<commit_before>extern crate rustyline;

use std::env;
use std::path::Path;
use std::fs::File;
use std::io::Read;

use rustyline::error::ReadlineError;
use rustyline::Editor;

/* Use the N64 module. */
mod n64;
use n64::N64;
use n64::N64_ROM_HEADER;
use n64::N64_ROM_HEADER_SIZE;

use std::str;

/* 'main()' function; loads N64 ROM and initializes emulator context. */
fn main() {
    /* Manage command line arguments using a vector. */
    let args: Vec<_> = env::args().collect();
    /* Ensure the proper arguments were provided, otherwise print usage information. */
    if args.len() < 3 {
        println!("r64: Another Nintendo 64 emulator; this time, written in Rust.\n\nOriginally authored by George Morgan. (george@george-morgan.com)\n\nusage: r64 [rom]");
        return;
    }

    /* Open the ROM file. */
    let path = Path::new(&args[1]);
    let mut rom_file = File::open(path).unwrap();

    /* Create the header. */
    let mut h_data = [0; N64_ROM_HEADER_SIZE];
    rom_file.read_exact(&mut h_data);
    let h_data_p: *const u8 = h_data.as_ptr();
    let h_p: *const N64_ROM_HEADER = h_data_p as *const _;
    let header: &N64_ROM_HEADER = unsafe { &*h_p };

    /* Load the cartridge ROM. */
    let mut rom_buf = Vec::new();
    rom_file.read_to_end(&mut rom_buf).unwrap();
    let crom = rom_buf.into_boxed_slice();

    /* Open the PIF ROM file. */
    let path = Path::new(&args[2]);
    let mut pif_file = File::open(path).unwrap();

    /* Load the PIF ROM. */
    let mut pif_data_buf = Vec::new();
    pif_file.read_to_end(&mut pif_data_buf).unwrap();
    let prom = pif_data_buf.into_boxed_slice();

    /* Print the name of the loaded ROM. */
    let name = str::from_utf8(&header.name).unwrap().trim();
    println!("The ROM is {:?}.", name);

    /* Create the N64. */
    let mut n64 = N64::new(crom, prom);

    let mut rl = Editor::<()>::new();
    loop {
        let readline = rl.readline("> ");
        match readline {
            Ok(line) => {
                rl.add_history_entry(&line);
                match line.as_ref() {
                    // /* Prints the CPU state. */
                    "print" | "p" => {
                        println!("{:?}", n64.cpu);
                    },
                    /* Steps into a single instruction. */
                    "step" | "s" | _ => {
                        n64.cycle();
                    },
                }
            },
            Err(ReadlineError::Interrupted) => {
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);
                break
            }
        }
    }
}
<commit_msg>allow quitting with 'q' or 'quit'<commit_after>extern crate rustyline;

use std::env;
use std::path::Path;
use std::fs::File;
use std::io::Read;

use rustyline::error::ReadlineError;
use rustyline::Editor;

/* Use the N64 module. */
mod n64;
use n64::N64;
use n64::N64_ROM_HEADER;
use n64::N64_ROM_HEADER_SIZE;

use std::str;

/* 'main()' function; loads N64 ROM and initializes emulator context. */
fn main() {
    /* Manage command line arguments using a vector. */
    let args: Vec<_> = env::args().collect();
    /* Ensure the proper arguments were provided, otherwise print usage information. */
    if args.len() < 3 {
        println!("r64: Another Nintendo 64 emulator; this time, written in Rust.\n\nOriginally authored by George Morgan. (george@george-morgan.com)\n\nusage: r64 [rom]");
        return;
    }

    /* Open the ROM file. */
    let path = Path::new(&args[1]);
    let mut rom_file = File::open(path).unwrap();

    /* Create the header. */
    let mut h_data = [0; N64_ROM_HEADER_SIZE];
    rom_file.read_exact(&mut h_data);
    let h_data_p: *const u8 = h_data.as_ptr();
    let h_p: *const N64_ROM_HEADER = h_data_p as *const _;
    let header: &N64_ROM_HEADER = unsafe { &*h_p };

    /* Load the cartridge ROM. */
    let mut rom_buf = Vec::new();
    rom_file.read_to_end(&mut rom_buf).unwrap();
    let crom = rom_buf.into_boxed_slice();

    /* Open the PIF ROM file. */
    let path = Path::new(&args[2]);
    let mut pif_file = File::open(path).unwrap();

    /* Load the PIF ROM. */
    let mut pif_data_buf = Vec::new();
    pif_file.read_to_end(&mut pif_data_buf).unwrap();
    let prom = pif_data_buf.into_boxed_slice();

    /* Print the name of the loaded ROM. */
    let name = str::from_utf8(&header.name).unwrap().trim();
    println!("The ROM is {:?}.", name);

    /* Create the N64. */
    let mut n64 = N64::new(crom, prom);

    let mut rl = Editor::<()>::new();
    'main_loop: loop {
        let readline = rl.readline("> ");
        match readline {
            Ok(line) => {
                rl.add_history_entry(&line);
                match line.as_ref() {
                    // /* Prints the CPU state. */
                    "print" | "p" => {
                        println!("{:?}", n64.cpu);
                    },
                    "quit" | "q" => {
                        break 'main_loop;
                    },
                    /* Steps into a single instruction. */
                    "step" | "s" | _ => {
                        n64.cycle();
                    },
                }
            },
            Err(ReadlineError::Interrupted) => {
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);
                break
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::io;

fn main() {
    println!("Guess the number!");

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Failed to read line");

    println!("You guessed: {}", guess);
}
<commit_msg>comment<commit_after>extern crate rand;

use std::io;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1,101);

    println!("The secret number is:{}", secret_number);

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Failed to read line");

    println!("You guessed: {}", guess);
}
<|endoftext|>


<commit_before>extern crate getopts;

use std::os;

static VERSION: &'static str = "0.0.1-shipoopi";

fn main () {
    let args = os::args();
    let ref program = args[0];

    let opts = [
        getopts::optflag("h", "help", "Show this message"),
        getopts::optflag("v", "version", "Show version"),
    ];

    let opt_matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m)  => m,
        Err(f) => { panic!(f.to_string()) }
    };

    if opt_matches.opt_present("help") {
        println!("selecta {}", VERSION);
        println!("");
        let usage = format!("Usage: {} [options]", program);
        println!("{}", getopts::usage(usage.as_slice(), &opts));
        return;
    }

    if opt_matches.opt_present("version") {
       println!("selecta version: {}", VERSION);
       return;
   }
}
<commit_msg>Remove not-working main<commit_after>fn main () {
}
<|endoftext|>


<commit_before>extern crate irc;

use irc::client::prelude::*;
use std::default::Default;

fn main() {
	let server = IrcServer::from_config(Config{
		owners   : Some(vec!["nabijaczleweli".to_string()]),
		nickname : Some("NabBot".to_string()),
		username : Some("NabBot".to_string()),
		realname : Some("наб's IRC bot".to_string()),
		server   : Some("chat.freenode.net".to_string()),
		use_ssl  : Some(true),
		channels : Some(vec!["#loungecpp".to_string()]),
		user_info: Some("наб's IRC bot".to_string()),
		..Default::default()
	}).unwrap();
	server.identify().unwrap();

	for message in server.iter() {
		if let Ok(message) = message {
			let source_nickname = message.get_source_nickname().map(String::from);

			if let Ok(Command::PRIVMSG(target, msg)) = Command::from_message_io(Ok(message)) {
				if (target == "NabBot" && msg == "Navaer") || msg == "Navaer, NabBot" {
					server.send_privmsg(&*&source_nickname.unwrap_or(target), "Mára mesta").unwrap();
					server.send_quit("Mára mesta").unwrap();
				} else if msg.contains("isn't") || msg.contains("is not") {
					println!("{}: {:?} -> Not your face", source_nickname.as_ref().unwrap_or(&"???".to_string()), msg);
					server.send_privmsg(&target, "Quite unlike your face").unwrap();
				} else if msg.contains("sucks") || msg.contains("is") {
					println!("{}: {:?} -> Your face", source_nickname.as_ref().unwrap_or(&"???".to_string()), msg);
					server.send_privmsg(&target, "Much like your face").unwrap();
				}
			}
		}
	}
}
<commit_msg>Remove like your face commands<commit_after>extern crate irc;

use irc::client::prelude::*;
use std::default::Default;

fn main() {
	let server = IrcServer::from_config(Config{
		owners   : Some(vec!["nabijaczleweli".to_string()]),
		nickname : Some("NabBot".to_string()),
		username : Some("NabBot".to_string()),
		realname : Some("наб's IRC bot".to_string()),
		server   : Some("chat.freenode.net".to_string()),
		use_ssl  : Some(true),
		channels : Some(vec!["#loungecpp".to_string()]),
		user_info: Some("наб's IRC bot".to_string()),
		..Default::default()
	}).unwrap();
	server.identify().unwrap();

	for message in server.iter() {
		if let Ok(message) = message {
			let sender = message.get_source_nickname().map(String::from);

			if let Ok(Command::PRIVMSG(target, msg)) = Command::from_message_io(Ok(message)) {
				if (target == "NabBot" && msg == "Navaer") || msg == "Navaer, NabBot" {
					server.send_privmsg(&*sender.as_ref().unwrap_or(&target), "Mára mesta").unwrap();
					server.send_quit("Mára mesta").unwrap();
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>use std::env;

use log::debug;
use structopt::StructOpt;
use yansi::Paint;

use cargo_modules::options::Options;

fn main() -> anyhow::Result<()> {
    env_logger::init();

    let args: Vec<_> = env::args().collect();
    debug!("Arguments: {:?}", args);

    if env::var("NO_COLOR").is_ok() {
        debug!("Disabling color output");
        Paint::disable()
    }

    let options = Options::from_args();

    options.command.run()
}
<commit_msg>Make `cargo_modules=warn` the `RUST_LOG` default<commit_after>use std::env;

use log::debug;
use structopt::StructOpt;
use yansi::Paint;

use cargo_modules::options::Options;

fn main() -> anyhow::Result<()> {
    env_logger::init_from_env({
        let env = env_logger::Env::default();
        let key = env_logger::DEFAULT_FILTER_ENV;
        let value = "cargo_modules=warn";
        env.filter_or(key, value)
    });

    let args: Vec<_> = env::args().collect();
    debug!("Arguments: {:?}", args);

    if env::var("NO_COLOR").is_ok() {
        debug!("Disabling color output");
        Paint::disable()
    }

    let options = Options::from_args();

    options.command.run()
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;

extern crate glium_sdl2;
extern crate sdl2;

use std::fmt;
use glium::{Surface, VertexBuffer, Program, index, uniforms};
use sdl2::event::Event;
use glium_sdl2::{DisplayBuild, SDL2Facade};

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 2],
}
implement_vertex!(Vertex, position);

impl fmt::Display for Vertex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.position[0], self.position[1])
    }
}

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();
    let display = video_subsystem.window("Tutorial 01", 800, 600).resizable().build_glium().unwrap();
    let v1 = Vertex { position: [-0.5, -0.5] };
    let v2 = Vertex { position: [ 0.0,  0.5] };
    let v3 = Vertex { position: [ 0.5, -0.25] };
    let shape = vec![v1, v2, v3];

    let vertex_buffer = VertexBuffer::new(&display, &shape).unwrap();
    let indices = index::NoIndices(index::PrimitiveType::TrianglesList);

    fn create_shaders(display: &SDL2Facade) -> Program {
        let vertex_shader_src = r#"
            #version 130

            in vec2 position;

            void main() {
                gl_Position = vec4(position, 0.0, 1.0);
            }
        "#;

        let fragment_shader_src = r#"
            #version 130

            out vec4 color;

            void main() {
                color = vec4(1.0, 0.0, 0.0, 1.0);
            }
        "#;

        Program::from_source(display, vertex_shader_src, fragment_shader_src, None).unwrap()
    }
    let program = create_shaders(&display);

    let mut running = true;
    let mut event_pump = sdl_context.event_pump().unwrap();

    while running {
        let mut target = display.draw();
        target.clear_color(0.0, 0.0, 1.0, 1.0);
        target.draw(&vertex_buffer, &indices, &program, &uniforms::EmptyUniforms,
                    &Default::default()).unwrap();
        target.finish().unwrap();

        for event in event_pump.poll_iter() {
            match event {
                Event::Quit { .. } => running = false,
                _ => ()
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::Vertex;

    #[test]
    fn test_vertex() {
        assert_eq!("(3, 5)", format!("{}", Vertex { position: [3.0, 5.0] }));
    }
}
<commit_msg>escape to quit<commit_after>#[macro_use]
extern crate glium;

extern crate glium_sdl2;
extern crate sdl2;

use std::fmt;
use glium::{Surface, VertexBuffer, Program, index, uniforms};
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use glium_sdl2::{DisplayBuild, SDL2Facade};

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 2],
}
implement_vertex!(Vertex, position);

impl fmt::Display for Vertex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.position[0], self.position[1])
    }
}

fn handle_key(keycode: Keycode) -> bool {
    match keycode {
        Keycode::Escape => false,
        _ => true,
    }
}

fn main() {
    let sdl_context = sdl2::init()
        .unwrap();
    let video_subsystem = sdl_context
        . video()
        .unwrap();
    let display = video_subsystem
        .window("rustroam", 1024, 576)
        .resizable()
        .build_glium()
        .unwrap();

    let v1 = Vertex { position: [-0.5, -0.5] };
    let v2 = Vertex { position: [ 0.0,  0.5] };
    let v3 = Vertex { position: [ 0.5, -0.25] };
    let shape = vec![v1, v2, v3];

    let vertex_buffer = VertexBuffer::new(&display, &shape)
        .unwrap();
    let indices = index::NoIndices(index::PrimitiveType::TrianglesList);

    fn create_shaders(display: &SDL2Facade) -> Program {
        let vertex_shader_src = r#"
            #version 130

            in vec2 position;

            void main() {
                gl_Position = vec4(position, 0.0, 1.0);
            }
        "#;

        let fragment_shader_src = r#"
            #version 130

            out vec4 color;

            void main() {
                color = vec4(1.0, 0.6, 0.1, 1.0);
            }
        "#;

        Program::from_source(display, vertex_shader_src, fragment_shader_src, None).unwrap()
    }
    let program = create_shaders(&display);

    let mut running = true;
    let mut event_pump = sdl_context.event_pump().unwrap();

    while running {
        let mut target = display.draw();
        target.clear_color(0.05, 0.05, 0.05, 1.0);
        target.draw(&vertex_buffer,
                    &indices,
                    &program,
                    &uniforms::EmptyUniforms,
                    &Default::default())
            .unwrap();
        target
            .finish()
            .unwrap();

        for event in event_pump.poll_iter() {
            match event {
                Event::KeyDown { keycode, .. } => running = handle_key(keycode.unwrap()),
                Event::Quit { .. } => running = false,
                _ => ()
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::Vertex;

    #[test]
    fn test_vertex() {
        assert_eq!("(3, 5)", format!("{}", Vertex { position: [3.0, 5.0] }));
    }
}
<|endoftext|>


<commit_before>use disambiguation_map::Match;
use key::parse::parse;
use key::{MultiKey, Key};
use mode_map::ModeMap;
use op::{HasOperator, HasMotion, HasObject, PendingOp, ObjectOp, MotionOp,
         InsertOp, NormalOp, OperatorOp};
use ordered_vec_map::InsertionResult;
use state::NumericMap;
use typeahead::{RemapType, Typeahead};

impl HasOperator<MultiKey> for ModeMap<MultiKey, NormalOp> {
    fn insert_operator(
        &mut self,
        key: Vec<MultiKey>,
        op: OperatorOp,
    ) -> InsertionResult {
        self.insert_op(key, NormalOp::Operator(op))
    }
}

impl HasMotion<MultiKey> for ModeMap<MultiKey, NormalOp> {
    fn insert_motion(
        &mut self,
        key: Vec<MultiKey>,
        op: MotionOp,
    ) -> InsertionResult {
        self.insert_op(key, NormalOp::Motion(op))
    }
}

impl HasOperator<MultiKey> for ModeMap<MultiKey, PendingOp> {
    fn insert_operator(
        &mut self,
        key: Vec<MultiKey>,
        op: OperatorOp,
    ) -> InsertionResult {
        self.insert_op(key, PendingOp::Operator(op))
    }
}

impl HasMotion<MultiKey> for ModeMap<MultiKey, PendingOp> {
    fn insert_motion(
        &mut self,
        key: Vec<MultiKey>,
        op: MotionOp,
    ) -> InsertionResult {
        self.insert_op(key, PendingOp::Motion(op))
    }
}

impl HasObject<MultiKey> for ModeMap<MultiKey, PendingOp> {
    fn insert_object(
        &mut self,
        key: Vec<MultiKey>,
        op: ObjectOp,
    ) -> InsertionResult {
        self.insert_op(key, PendingOp::Object(op))
    }
}

fn add_operators<Op>(map: &mut ModeMap<MultiKey, Op>)
where
    Op: Copy,
    ModeMap<MultiKey, Op>: HasOperator<MultiKey>,
{
    use op::OperatorOp::*;
    map.insert_operator(parse("c"), Change);
    map.insert_operator(parse("d"), Delete);
    map.insert_operator(parse("y"), Yank);
    map.insert_operator(parse("g~"), SwapCase);
    map.insert_operator(parse("gu"), ToLower);
    map.insert_operator(parse("gU"), ToUpper);
    map.insert_operator(parse("!"), ExternalPrg);
    map.insert_operator(parse("="), EqualPrg);
    map.insert_operator(parse("gq"), TextFormat);
    map.insert_operator(parse("g?"), Rot13);
    map.insert_operator(parse(">"), ShiftRight);
    map.insert_operator(parse("<"), ShiftLeft);
    map.insert_operator(parse("<lt>"), ShiftLeft);
    map.insert_operator(parse("zf"), DefineFold);
    map.insert_operator(parse("g@"), OperatorFunc);
}

fn add_motions<Op>(map: &mut ModeMap<MultiKey, Op>)
where
    Op: Copy,
    ModeMap<MultiKey, Op>: HasMotion<MultiKey>,
{
    use op::MotionOp::*;
    map.insert_motion(parse("h"), Left);
    map.insert_motion(parse("l"), Right);
    map.insert_motion(parse("k"), Up);
    map.insert_motion(parse("j"), Down);
    map.insert_motion(parse("gg"), Top);
    map.insert_motion(parse("G"), Bottom);
    map.insert_motion(parse("w"), Word);
}

fn add_objects<Op>(map: &mut ModeMap<MultiKey, Op>)
where
    Op: Copy,
    ModeMap<MultiKey, Op>: HasObject<MultiKey>,
{
    use op::ObjectOp::*;
    map.insert_object(parse("aw"), AWord);
    map.insert_object(parse("iw"), InnerWord);
    map.insert_object(parse("aW"), AWORD);
    map.insert_object(parse("iW"), InnerWORD);
    map.insert_object(parse("as"), ASentence);
    map.insert_object(parse("is"), InnerSentence);
    map.insert_object(parse("ap"), AParagraph);
    map.insert_object(parse("ip"), InnerParagraph);
    map.insert_object(parse("a["), ASquareBlock);
    map.insert_object(parse("a]"), ASquareBlock);
    map.insert_object(parse("i["), InnerSquareBlock);
    map.insert_object(parse("i]"), InnerSquareBlock);
    map.insert_object(parse("a("), AParen);
    map.insert_object(parse("a)"), AParen);
    map.insert_object(parse("i("), InnerParen);
    map.insert_object(parse("i)"), InnerParen);
    map.insert_object(parse("a<"), AAngle);
    map.insert_object(parse("a>"), AAngle);
    map.insert_object(parse("i<"), InnerAngle);
    map.insert_object(parse("i>"), InnerAngle);
    map.insert_object(parse("at"), ATag);
    map.insert_object(parse("it"), InnerTag);
    map.insert_object(parse("a{"), ABrace);
    map.insert_object(parse("a}"), ABrace);
    map.insert_object(parse("i{"), InnerBrace);
    map.insert_object(parse("i}"), InnerBrace);
    map.insert_object(parse("a'"), ASingleQuote);
    map.insert_object(parse("i'"), InnerSingleQuote);
    map.insert_object(parse("a\""), ADoubleQuote);
    map.insert_object(parse("i\""), InnerDoubleQuote);
    map.insert_object(parse("a`"), ABackTick);
    map.insert_object(parse("i`"), InnerBackTick);
}

struct DecimalMap {}

impl NumericMap<MultiKey> for DecimalMap {
    /// Parses the front of the typeahead buffer for a non-negative decimal
    /// integer string.
    ///
    /// Returns
    /// * `Match::FullMatch(N)` if a non-empty numeric string of
    ///   value `N` was found, followed by a non-numeric character. The
    ///   non-numeric character implies the numeric string is complete.
    /// * `Match::PartialMatch` if the typeahead buffer contains only
    ///   decimal digits. This implies the numeric string might not be
    ///   complete.
    /// * `Match::NoMatch` if the first character in the typeahead buffer is
    ///   non-numeric.
    fn process(&self, typeahead: &mut Typeahead<MultiKey>) -> Match<i32> {
        let mut s = String::with_capacity(typeahead.len());
        let mut found_non_digit = false;
        for key in typeahead.value_iter() {
            match key {
                MultiKey::A(Key::Char(c)) => {
                    if c.is_digit(10) {
                        s.push(c);
                    } else {
                        found_non_digit = true;
                        break;
                    }
                }
                _ => {
                    found_non_digit = true;
                    break;
                }
            }
        }
        if found_non_digit {
            if s.is_empty() {
                return Match::NoMatch;
            } else {
                for i in 0..s.len() {
                    typeahead.pop_front();
                }
                return Match::FullMatch(s.parse::<i32>().unwrap());
            }
        }
        return Match::PartialMatch;
    }
}

pub fn numeric_map() -> Box<NumericMap<MultiKey>> {
    Box::new(DecimalMap {})
}

pub fn normal_mode_map() -> ModeMap<MultiKey, NormalOp> {
    use op::NormalOp::*;
    let mut map = ModeMap::new();
    map.insert_op(parse("<Esc>"), Cancel);
    map.insert_op(parse("i"), Insert);
    map.insert_op(parse("."), Repeat);
    add_operators(&mut map);
    add_motions(&mut map);
    return map;
}

pub fn pending_mode_map() -> ModeMap<MultiKey, PendingOp> {
    use op::PendingOp::*;
    let mut map = ModeMap::new();
    map.insert_op(parse("<Esc>"), Cancel);
    add_operators(&mut map);
    add_objects(&mut map);
    add_motions(&mut map);
    return map;
}

pub fn insert_mode_map() -> ModeMap<MultiKey, InsertOp> {
    use op::InsertOp::*;
    let mut map = ModeMap::new();
    map.insert_op(parse("<Esc>"), Cancel);
    return map;
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn parse_numeric_full_match() {
        let map = DecimalMap {};
        let mut typeahead = Typeahead::new();
        typeahead.put_front(&parse("12345g"), RemapType::Remap);
        let result = map.process(&mut typeahead);
        assert_eq!(Match::FullMatch(12345), result);
        assert_eq!(1, typeahead.len());
    }

    #[test]
    fn parse_numeric_partial_match() {
        let map = DecimalMap {};
        let mut typeahead = Typeahead::new();
        typeahead.put_front(&parse("12345"), RemapType::Remap);
        let result = map.process(&mut typeahead);
        assert_eq!(Match::PartialMatch, result);
        assert_eq!(5, typeahead.len());
    }

    #[test]
    fn parse_numeric_no_match() {
        let map = DecimalMap {};
        let mut typeahead = Typeahead::new();
        typeahead.put_front(&parse("g12345"), RemapType::Remap);
        let result = map.process(&mut typeahead);
        assert_eq!(Match::NoMatch, result);
        assert_eq!(6, typeahead.len());
    }
}
<commit_msg>lay groundwork to make numeric map statically dispatched<commit_after>use disambiguation_map::Match;
use key::parse::parse;
use key::{MultiKey, Key};
use mode_map::ModeMap;
use op::{HasOperator, HasMotion, HasObject, PendingOp, ObjectOp, MotionOp,
         InsertOp, NormalOp, OperatorOp};
use ordered_vec_map::InsertionResult;
use state::NumericMap;
use typeahead::{RemapType, Typeahead};

impl HasOperator<MultiKey> for ModeMap<MultiKey, NormalOp> {
    fn insert_operator(
        &mut self,
        key: Vec<MultiKey>,
        op: OperatorOp,
    ) -> InsertionResult {
        self.insert_op(key, NormalOp::Operator(op))
    }
}

impl HasMotion<MultiKey> for ModeMap<MultiKey, NormalOp> {
    fn insert_motion(
        &mut self,
        key: Vec<MultiKey>,
        op: MotionOp,
    ) -> InsertionResult {
        self.insert_op(key, NormalOp::Motion(op))
    }
}

impl HasOperator<MultiKey> for ModeMap<MultiKey, PendingOp> {
    fn insert_operator(
        &mut self,
        key: Vec<MultiKey>,
        op: OperatorOp,
    ) -> InsertionResult {
        self.insert_op(key, PendingOp::Operator(op))
    }
}

impl HasMotion<MultiKey> for ModeMap<MultiKey, PendingOp> {
    fn insert_motion(
        &mut self,
        key: Vec<MultiKey>,
        op: MotionOp,
    ) -> InsertionResult {
        self.insert_op(key, PendingOp::Motion(op))
    }
}

impl HasObject<MultiKey> for ModeMap<MultiKey, PendingOp> {
    fn insert_object(
        &mut self,
        key: Vec<MultiKey>,
        op: ObjectOp,
    ) -> InsertionResult {
        self.insert_op(key, PendingOp::Object(op))
    }
}

fn add_operators<Op>(map: &mut ModeMap<MultiKey, Op>)
where
    Op: Copy,
    ModeMap<MultiKey, Op>: HasOperator<MultiKey>,
{
    use op::OperatorOp::*;
    map.insert_operator(parse("c"), Change);
    map.insert_operator(parse("d"), Delete);
    map.insert_operator(parse("y"), Yank);
    map.insert_operator(parse("g~"), SwapCase);
    map.insert_operator(parse("gu"), ToLower);
    map.insert_operator(parse("gU"), ToUpper);
    map.insert_operator(parse("!"), ExternalPrg);
    map.insert_operator(parse("="), EqualPrg);
    map.insert_operator(parse("gq"), TextFormat);
    map.insert_operator(parse("g?"), Rot13);
    map.insert_operator(parse(">"), ShiftRight);
    map.insert_operator(parse("<"), ShiftLeft);
    map.insert_operator(parse("<lt>"), ShiftLeft);
    map.insert_operator(parse("zf"), DefineFold);
    map.insert_operator(parse("g@"), OperatorFunc);
}

fn add_motions<Op>(map: &mut ModeMap<MultiKey, Op>)
where
    Op: Copy,
    ModeMap<MultiKey, Op>: HasMotion<MultiKey>,
{
    use op::MotionOp::*;
    map.insert_motion(parse("h"), Left);
    map.insert_motion(parse("l"), Right);
    map.insert_motion(parse("k"), Up);
    map.insert_motion(parse("j"), Down);
    map.insert_motion(parse("gg"), Top);
    map.insert_motion(parse("G"), Bottom);
    map.insert_motion(parse("w"), Word);
}

fn add_objects<Op>(map: &mut ModeMap<MultiKey, Op>)
where
    Op: Copy,
    ModeMap<MultiKey, Op>: HasObject<MultiKey>,
{
    use op::ObjectOp::*;
    map.insert_object(parse("aw"), AWord);
    map.insert_object(parse("iw"), InnerWord);
    map.insert_object(parse("aW"), AWORD);
    map.insert_object(parse("iW"), InnerWORD);
    map.insert_object(parse("as"), ASentence);
    map.insert_object(parse("is"), InnerSentence);
    map.insert_object(parse("ap"), AParagraph);
    map.insert_object(parse("ip"), InnerParagraph);
    map.insert_object(parse("a["), ASquareBlock);
    map.insert_object(parse("a]"), ASquareBlock);
    map.insert_object(parse("i["), InnerSquareBlock);
    map.insert_object(parse("i]"), InnerSquareBlock);
    map.insert_object(parse("a("), AParen);
    map.insert_object(parse("a)"), AParen);
    map.insert_object(parse("i("), InnerParen);
    map.insert_object(parse("i)"), InnerParen);
    map.insert_object(parse("a<"), AAngle);
    map.insert_object(parse("a>"), AAngle);
    map.insert_object(parse("i<"), InnerAngle);
    map.insert_object(parse("i>"), InnerAngle);
    map.insert_object(parse("at"), ATag);
    map.insert_object(parse("it"), InnerTag);
    map.insert_object(parse("a{"), ABrace);
    map.insert_object(parse("a}"), ABrace);
    map.insert_object(parse("i{"), InnerBrace);
    map.insert_object(parse("i}"), InnerBrace);
    map.insert_object(parse("a'"), ASingleQuote);
    map.insert_object(parse("i'"), InnerSingleQuote);
    map.insert_object(parse("a\""), ADoubleQuote);
    map.insert_object(parse("i\""), InnerDoubleQuote);
    map.insert_object(parse("a`"), ABackTick);
    map.insert_object(parse("i`"), InnerBackTick);
}

struct DecimalMap {}

impl DecimalMap {
    fn decimal(key: MultiKey) -> Option<char> {
        match key {
            MultiKey::A(Key::Char(c)) => {
                if c.is_digit(10) {
                    return Some(c);
                } else {
                    return None;
                }
            }
            _ => None,
        }
    }
}

impl NumericMap<MultiKey> for DecimalMap {
    /// Parses the front of the typeahead buffer for a non-negative decimal
    /// integer string.
    ///
    /// Returns
    /// * `Match::FullMatch(N)` if a non-empty numeric string of
    ///   value `N` was found, followed by a non-numeric character. The
    ///   non-numeric character implies the numeric string is complete.
    /// * `Match::PartialMatch` if the typeahead buffer contains only
    ///   decimal digits. This implies the numeric string might not be
    ///   complete.
    /// * `Match::NoMatch` if the first character in the typeahead buffer is
    ///   non-numeric.
    fn process(&self, typeahead: &mut Typeahead<MultiKey>) -> Match<i32> {
        let mut s = String::with_capacity(typeahead.len());
        let mut full_match_found = false;
        for key in typeahead.value_iter() {
            match DecimalMap::decimal(key) {
                Some(c) => {
                    s.push(c);
                }
                None => {
                    if s.is_empty() {
                        return Match::NoMatch;
                    } else {
                        full_match_found = true;
                        break;
                    }
                }
            }
        }
        if full_match_found {
            for i in 0..s.len() {
                typeahead.pop_front();
            }
            return Match::FullMatch(s.parse::<i32>().unwrap());
        }
        return Match::PartialMatch;
    }
}

pub fn numeric_map() -> Box<NumericMap<MultiKey>> {
    Box::new(DecimalMap {})
}

pub fn normal_mode_map() -> ModeMap<MultiKey, NormalOp> {
    use op::NormalOp::*;
    let mut map = ModeMap::new();
    map.insert_op(parse("<Esc>"), Cancel);
    map.insert_op(parse("i"), Insert);
    map.insert_op(parse("."), Repeat);
    add_operators(&mut map);
    add_motions(&mut map);
    return map;
}

pub fn pending_mode_map() -> ModeMap<MultiKey, PendingOp> {
    use op::PendingOp::*;
    let mut map = ModeMap::new();
    map.insert_op(parse("<Esc>"), Cancel);
    add_operators(&mut map);
    add_objects(&mut map);
    add_motions(&mut map);
    return map;
}

pub fn insert_mode_map() -> ModeMap<MultiKey, InsertOp> {
    use op::InsertOp::*;
    let mut map = ModeMap::new();
    map.insert_op(parse("<Esc>"), Cancel);
    return map;
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn decimal_full_match() {
        let map = DecimalMap {};
        let mut typeahead = Typeahead::new();
        typeahead.put_front(&parse("12345g"), RemapType::Remap);
        let result = map.process(&mut typeahead);
        assert_eq!(Match::FullMatch(12345), result);
        assert_eq!(1, typeahead.len());
    }

    #[test]
    fn decimal_full_match_two() {
        let map = DecimalMap {};
        let mut typeahead = Typeahead::new();
        typeahead.put_front(&parse("12345gg1"), RemapType::Remap);
        let result = map.process(&mut typeahead);
        assert_eq!(Match::FullMatch(12345), result);
        assert_eq!(3, typeahead.len());
    }

    #[test]
    fn decimal_partial_match() {
        let map = DecimalMap {};
        let mut typeahead = Typeahead::new();
        typeahead.put_front(&parse("12345"), RemapType::Remap);
        let result = map.process(&mut typeahead);
        assert_eq!(Match::PartialMatch, result);
        assert_eq!(5, typeahead.len());
    }

    #[test]
    fn decimal_no_match() {
        let map = DecimalMap {};
        let mut typeahead = Typeahead::new();
        typeahead.put_front(&parse("g12345"), RemapType::Remap);
        let result = map.process(&mut typeahead);
        assert_eq!(Match::NoMatch, result);
        assert_eq!(6, typeahead.len());
    }
}
<|endoftext|>


<commit_before>pub use super::{Args, Command, CommandGroup, CommandOptions, CommandError};

use client::Context;
use model::{Message, Permissions};
use std::sync::Arc;

pub enum FnOrCommand {
    Fn(fn(&mut Context, &Message, Args) -> Result<(), CommandError>),
    Command(Arc<Command>),
}

pub struct CreateCommand(pub CommandOptions, pub FnOrCommand);

impl CreateCommand {
    /// Adds multiple aliases.
    pub fn batch_known_as<T: ToString, It: IntoIterator<Item=T>>(mut self, names: It) -> Self {
        self.0
            .aliases
            .extend(names.into_iter().map(|n| n.to_string()));

        self
    }

    /// Adds a ratelimit bucket.
    pub fn bucket(mut self, bucket: &str) -> Self {
        self.0.bucket = Some(bucket.to_string());

        self
    }

    /// Adds a "check" to a command, which checks whether or not the command's
    /// function should be called.
    ///
    /// These checks are bypassed for commands sent by the application owner.
    ///
    /// # Examples
    ///
    /// Ensure that the user who created a message, calling a "ping" command,
    /// is the owner.
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::EventHandler;
    /// # struct Handler;
    /// # impl EventHandler for Handler {}
    /// use serenity::client::{Client, Context};
    /// use serenity::framework::standard::{
    ///     Args,
    ///     CommandOptions,
    ///     CommandError,
    ///     StandardFramework,
    /// };
    /// use serenity::model::Message;
    /// use std::env;
    ///
    /// let token = env::var("DISCORD_TOKEN").unwrap();
    /// let mut client = Client::new(&token, Handler).unwrap();
    ///
    /// client.with_framework(StandardFramework::new()
    ///     .configure(|c| c.prefix("~"))
    ///     .command("ping", |c| c
    ///         .check(owner_check)
    ///         .desc("Replies to a ping with a pong")
    ///         .exec(ping)));
    ///
    /// fn ping(_context: &mut Context, message: &Message, _args: Args) -> Result<(),
    /// CommandError> {
    ///     message.channel_id.say("Pong!")?;
    ///
    ///     Ok(())
    /// }
    ///
    /// fn owner_check(_context: &mut Context, message: &Message, _: &mut Args, _:
    /// &CommandOptions) -> bool {
    ///     // replace with your user ID
    ///     message.author.id == 7
    /// }
    /// ```
    pub fn check<F>(mut self, check: F) -> Self
        where F: Fn(&mut Context, &Message, &mut Args, &CommandOptions) -> bool
                     + Send
                     + Sync
                     + 'static {
        self.0.checks.push(Box::new(check));

        self
    }

    /// Description, used by other commands.
    pub fn desc(mut self, desc: &str) -> Self {
        self.0.desc = Some(desc.to_string());

        self
    }

    /// Whether command can be used only privately or not.
    pub fn dm_only(mut self, dm_only: bool) -> Self {
        self.0.dm_only = dm_only;

        self
    }

    /// Example arguments, used by other commands.
    pub fn example(mut self, example: &str) -> Self {
        self.0.example = Some(example.to_string());

        self
    }

    /// A function that can be called when a command is received.
    /// You can return `Err(string)` if there's an error.
    pub fn exec(mut self, func: fn(&mut Context, &Message, Args) -> Result<(), CommandError>) -> Self {
        self.1 = FnOrCommand::Fn(func);

        self
    }

    /// Like [`exec`] but accepts a `Command` directly.
    ///
    /// [`exec`]: #method.exec
    pub fn cmd<C: Command + 'static>(mut self, c: C) -> Self {
        self.1 = FnOrCommand::Command(Arc::new(c));

        self
    }

    /// Whether command can be used only in guilds or not.
    pub fn guild_only(mut self, guild_only: bool) -> Self {
        self.0.guild_only = guild_only;

        self
    }

    /// Whether command should be displayed in help list or not, used by other commands.
    pub fn help_available(mut self, help_available: bool) -> Self {
        self.0.help_available = help_available;

        self
    }

    /// Adds an alias, allowing users to use the command under a different name.
    pub fn known_as(mut self, name: &str) -> Self {
        self.0.aliases.push(name.to_string());

        self
    }

    /// Maximum amount of arguments that can be passed.
    pub fn max_args(mut self, max_args: i32) -> Self {
        self.0.max_args = Some(max_args);

        self
    }

    /// Minumum amount of arguments that should be passed.
    pub fn min_args(mut self, min_args: i32) -> Self {
        self.0.min_args = Some(min_args);

        self
    }

    /// Exact number of arguments that should be passed.
    pub fn num_args(mut self, num_args: i32) -> Self {
        self.0.min_args = Some(num_args);
        self.0.max_args = Some(num_args);

        self
    }

    /// Whether command can be used only privately or not.
    pub fn owners_only(mut self, owners_only: bool) -> Self {
        self.0.owners_only = owners_only;

        self
    }

    /// The permissions that a user must have in the contextual channel in order
    /// for the command to be processed.
    pub fn required_permissions(mut self, permissions: Permissions) -> Self {
        self.0.required_permissions = permissions;

        self
    }

    /// Command usage schema, used by other commands.
    pub fn usage(mut self, usage: &str) -> Self {
        self.0.usage = Some(usage.to_string());

        self
    }

    /// Sets roles that are allowed to use the command.
    pub fn allowed_roles<T: ToString, It: IntoIterator<Item=T>>(mut self, allowed_roles: It) -> Self {
        self.0.allowed_roles = allowed_roles.into_iter().map(|x| x.to_string()).collect();

        self
    }

    pub(crate) fn finish(self) -> Arc<Command> {
        let CreateCommand(options, fc) = self;

        match fc {
            FnOrCommand::Fn(func) => {
                struct A(Arc<CommandOptions>, fn(&mut Context, &Message, Args) -> Result<(), CommandError>);

                impl Command for A {
                    fn execute(&self, c: &mut Context, m: &Message, a: Args) -> Result<(), CommandError> {
                        (self.1)(c, m, a)
                    }

                    fn options(&self) -> Arc<CommandOptions> { Arc::clone(&self.0) }
                }

                Arc::new(A(Arc::new(options), func))
            },
            FnOrCommand::Command(cmd) => {
                cmd.init();

                cmd
            },
        }
    }
}

<commit_msg>Actually remove the `init` call in `CreateCommand`<commit_after>pub use super::{Args, Command, CommandGroup, CommandOptions, CommandError};

use client::Context;
use model::{Message, Permissions};
use std::sync::Arc;

pub enum FnOrCommand {
    Fn(fn(&mut Context, &Message, Args) -> Result<(), CommandError>),
    Command(Arc<Command>),
}

pub struct CreateCommand(pub CommandOptions, pub FnOrCommand);

impl CreateCommand {
    /// Adds multiple aliases.
    pub fn batch_known_as<T: ToString, It: IntoIterator<Item=T>>(mut self, names: It) -> Self {
        self.0
            .aliases
            .extend(names.into_iter().map(|n| n.to_string()));

        self
    }

    /// Adds a ratelimit bucket.
    pub fn bucket(mut self, bucket: &str) -> Self {
        self.0.bucket = Some(bucket.to_string());

        self
    }

    /// Adds a "check" to a command, which checks whether or not the command's
    /// function should be called.
    ///
    /// These checks are bypassed for commands sent by the application owner.
    ///
    /// # Examples
    ///
    /// Ensure that the user who created a message, calling a "ping" command,
    /// is the owner.
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::EventHandler;
    /// # struct Handler;
    /// # impl EventHandler for Handler {}
    /// use serenity::client::{Client, Context};
    /// use serenity::framework::standard::{
    ///     Args,
    ///     CommandOptions,
    ///     CommandError,
    ///     StandardFramework,
    /// };
    /// use serenity::model::Message;
    /// use std::env;
    ///
    /// let token = env::var("DISCORD_TOKEN").unwrap();
    /// let mut client = Client::new(&token, Handler).unwrap();
    ///
    /// client.with_framework(StandardFramework::new()
    ///     .configure(|c| c.prefix("~"))
    ///     .command("ping", |c| c
    ///         .check(owner_check)
    ///         .desc("Replies to a ping with a pong")
    ///         .exec(ping)));
    ///
    /// fn ping(_context: &mut Context, message: &Message, _args: Args) -> Result<(),
    /// CommandError> {
    ///     message.channel_id.say("Pong!")?;
    ///
    ///     Ok(())
    /// }
    ///
    /// fn owner_check(_context: &mut Context, message: &Message, _: &mut Args, _:
    /// &CommandOptions) -> bool {
    ///     // replace with your user ID
    ///     message.author.id == 7
    /// }
    /// ```
    pub fn check<F>(mut self, check: F) -> Self
        where F: Fn(&mut Context, &Message, &mut Args, &CommandOptions) -> bool
                     + Send
                     + Sync
                     + 'static {
        self.0.checks.push(Box::new(check));

        self
    }

    /// Description, used by other commands.
    pub fn desc(mut self, desc: &str) -> Self {
        self.0.desc = Some(desc.to_string());

        self
    }

    /// Whether command can be used only privately or not.
    pub fn dm_only(mut self, dm_only: bool) -> Self {
        self.0.dm_only = dm_only;

        self
    }

    /// Example arguments, used by other commands.
    pub fn example(mut self, example: &str) -> Self {
        self.0.example = Some(example.to_string());

        self
    }

    /// A function that can be called when a command is received.
    /// You can return `Err(string)` if there's an error.
    pub fn exec(mut self, func: fn(&mut Context, &Message, Args) -> Result<(), CommandError>) -> Self {
        self.1 = FnOrCommand::Fn(func);

        self
    }

    /// Like [`exec`] but accepts a `Command` directly.
    ///
    /// [`exec`]: #method.exec
    pub fn cmd<C: Command + 'static>(mut self, c: C) -> Self {
        self.1 = FnOrCommand::Command(Arc::new(c));

        self
    }

    /// Whether command can be used only in guilds or not.
    pub fn guild_only(mut self, guild_only: bool) -> Self {
        self.0.guild_only = guild_only;

        self
    }

    /// Whether command should be displayed in help list or not, used by other commands.
    pub fn help_available(mut self, help_available: bool) -> Self {
        self.0.help_available = help_available;

        self
    }

    /// Adds an alias, allowing users to use the command under a different name.
    pub fn known_as(mut self, name: &str) -> Self {
        self.0.aliases.push(name.to_string());

        self
    }

    /// Maximum amount of arguments that can be passed.
    pub fn max_args(mut self, max_args: i32) -> Self {
        self.0.max_args = Some(max_args);

        self
    }

    /// Minumum amount of arguments that should be passed.
    pub fn min_args(mut self, min_args: i32) -> Self {
        self.0.min_args = Some(min_args);

        self
    }

    /// Exact number of arguments that should be passed.
    pub fn num_args(mut self, num_args: i32) -> Self {
        self.0.min_args = Some(num_args);
        self.0.max_args = Some(num_args);

        self
    }

    /// Whether command can be used only privately or not.
    pub fn owners_only(mut self, owners_only: bool) -> Self {
        self.0.owners_only = owners_only;

        self
    }

    /// The permissions that a user must have in the contextual channel in order
    /// for the command to be processed.
    pub fn required_permissions(mut self, permissions: Permissions) -> Self {
        self.0.required_permissions = permissions;

        self
    }

    /// Command usage schema, used by other commands.
    pub fn usage(mut self, usage: &str) -> Self {
        self.0.usage = Some(usage.to_string());

        self
    }

    /// Sets roles that are allowed to use the command.
    pub fn allowed_roles<T: ToString, It: IntoIterator<Item=T>>(mut self, allowed_roles: It) -> Self {
        self.0.allowed_roles = allowed_roles.into_iter().map(|x| x.to_string()).collect();

        self
    }

    pub(crate) fn finish(self) -> Arc<Command> {
        let CreateCommand(options, fc) = self;

        match fc {
            FnOrCommand::Fn(func) => {
                struct A(Arc<CommandOptions>, fn(&mut Context, &Message, Args) -> Result<(), CommandError>);

                impl Command for A {
                    fn execute(&self, c: &mut Context, m: &Message, a: Args) -> Result<(), CommandError> {
                        (self.1)(c, m, a)
                    }

                    fn options(&self) -> Arc<CommandOptions> { Arc::clone(&self.0) }
                }

                Arc::new(A(Arc::new(options), func))
            },
            FnOrCommand::Command(cmd) => cmd,
        }
    }
}

<|endoftext|>


<commit_before>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types and traits for working with the [Matrix](https://matrix.org) protocol.
//!
//! This crate re-exports things from all of the other ruma crates so you don't
//! have to manually keep all the versions in sync.
//!
//! Which crates are re-exported can be configured through cargo features.
//!
//! > ⚠ Some details might be missing because rustdoc has trouble with re-exports so you may need
//!   to refer to other crates' documentations.
//!
//! # API features
//!
//! Depending on which parts of Matrix are relevant to you, activate the following features:
//!
//! * `appservice-api` -- Application Service API.
//! * `client-api` -- Client-Server API.
//! * `federation-api` -- Server-Server (Federation) API.
//! * `identity-service-api` -- Identity Service API.
//! * `push-gateway-api` -- Push Gateway API.
//!
//! These features have `client`- and `server`-optimized variants that are enabled respectively
//! with the `-c` and `-s` suffixes. For example:
//!   * `client-api-c` -- The Client-Server API optimized for the client side.
//!   * `client-api-s` -- The Client-Server API optimized for the server side.
//!
//! # Compatibility feature
//!
//! * `compat` increases compatibility with other parts of the Matrix ecosystem, at the expense of
//! deviating from the specification.
//!
//! # Convenience features
//!
//! These features are only useful if you want to use a method that requires it:
//!
//! * `either`
//! * `rand`
//! * `markdown`
//!
//! # Unstable features
//!
//! By using these features, you opt out of all semver guarantees Ruma otherwise provides:
//!
//! * `unstable-exhaustive-types` -- Most types in Ruma are marked as non-exhaustive to avoid
//!   breaking changes when new fields are added in the specification. This feature compiles all
//!   types as exhaustive.
//! * `unstable-pre-spec` -- Upcoming Matrix features that may be subject to change or removal.
//! * `unstable-synapse-quirks` -- Fix issues for clients expecting to connect to Synapse
//!   homeservers, at the expense of being less compatible with other homeservers.
//!
//! # Common features
//!
//! These submodules are usually activated by the API features when needed:
//!
//! * `api`
//! * `events`
//! * `signatures`
//!
//! If you are viewing this on `docs.rs`, you can have a look at the feature dependencies by
//! clicking **Feature flags** in the toolbar at the top.

#![deny(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]

#[doc(no_inline)]
pub use assign::assign;
#[doc(no_inline)]
pub use js_int::{int, uint, Int, UInt};

pub use ruma_common::*;
#[doc(inline)]
pub use ruma_identifiers as identifiers;
#[doc(inline)]
pub use ruma_serde as serde;

pub use ruma_serde::Outgoing;

#[allow(deprecated)] // Allow re-export of deprecated items
pub use ruma_identifiers::{
    device_id, device_key_id, event_id, mxc_uri, room_alias_id, room_id, room_version_id,
    server_key_id, server_name, server_signing_key_id, user_id, DeviceId, DeviceKeyAlgorithm,
    DeviceKeyId, EventId, MxcUri, RoomAliasId, RoomId, RoomIdOrAliasId, RoomVersionId, ServerName,
    ServerSigningKeyId, SigningKeyAlgorithm, UserId,
};

#[cfg(feature = "events")]
#[cfg_attr(docsrs, doc(cfg(feature = "events")))]
#[doc(inline)]
pub use ruma_events as events;
#[cfg(feature = "signatures")]
#[cfg_attr(docsrs, doc(cfg(feature = "signatures")))]
#[doc(inline)]
pub use ruma_signatures as signatures;

/// (De)serializable types for various [Matrix APIs][apis] requests and responses and abstractions
/// for them.
///
/// [apis]: https://matrix.org/docs/spec/#matrix-apis
#[cfg(feature = "api")]
#[cfg_attr(docsrs, doc(cfg(feature = "api")))]
pub mod api {
    pub use ruma_api::*;

    #[cfg(feature = "ruma-appservice-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "appservice-api",
            feature = "appservice-api-c",
            feature = "appservice-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_appservice_api as appservice;
    #[cfg(feature = "ruma-client-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "client-api",
            feature = "client-api-c",
            feature = "client-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_client_api as client;
    #[cfg(feature = "ruma-federation-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "federation-api",
            feature = "federation-api-c",
            feature = "federation-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_federation_api as federation;
    #[cfg(feature = "ruma-identity-service-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "identity-service-api",
            feature = "identity-service-api-c",
            feature = "identity-service-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_identity_service_api as identity_service;
    #[cfg(feature = "ruma-push-gateway-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "push-gateway-api",
            feature = "push-gateway-api-c",
            feature = "push-gateway-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_push_gateway_api as push_gateway;
}
<commit_msg>ruma: Re-export all types from ruma-identifiers, except Error<commit_after>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types and traits for working with the [Matrix](https://matrix.org) protocol.
//!
//! This crate re-exports things from all of the other ruma crates so you don't
//! have to manually keep all the versions in sync.
//!
//! Which crates are re-exported can be configured through cargo features.
//!
//! > ⚠ Some details might be missing because rustdoc has trouble with re-exports so you may need
//!   to refer to other crates' documentations.
//!
//! # API features
//!
//! Depending on which parts of Matrix are relevant to you, activate the following features:
//!
//! * `appservice-api` -- Application Service API.
//! * `client-api` -- Client-Server API.
//! * `federation-api` -- Server-Server (Federation) API.
//! * `identity-service-api` -- Identity Service API.
//! * `push-gateway-api` -- Push Gateway API.
//!
//! These features have `client`- and `server`-optimized variants that are enabled respectively
//! with the `-c` and `-s` suffixes. For example:
//!   * `client-api-c` -- The Client-Server API optimized for the client side.
//!   * `client-api-s` -- The Client-Server API optimized for the server side.
//!
//! # Compatibility feature
//!
//! * `compat` increases compatibility with other parts of the Matrix ecosystem, at the expense of
//! deviating from the specification.
//!
//! # Convenience features
//!
//! These features are only useful if you want to use a method that requires it:
//!
//! * `either`
//! * `rand`
//! * `markdown`
//!
//! # Unstable features
//!
//! By using these features, you opt out of all semver guarantees Ruma otherwise provides:
//!
//! * `unstable-exhaustive-types` -- Most types in Ruma are marked as non-exhaustive to avoid
//!   breaking changes when new fields are added in the specification. This feature compiles all
//!   types as exhaustive.
//! * `unstable-pre-spec` -- Upcoming Matrix features that may be subject to change or removal.
//! * `unstable-synapse-quirks` -- Fix issues for clients expecting to connect to Synapse
//!   homeservers, at the expense of being less compatible with other homeservers.
//!
//! # Common features
//!
//! These submodules are usually activated by the API features when needed:
//!
//! * `api`
//! * `events`
//! * `signatures`
//!
//! If you are viewing this on `docs.rs`, you can have a look at the feature dependencies by
//! clicking **Feature flags** in the toolbar at the top.

#![deny(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]

#[doc(no_inline)]
pub use assign::assign;
#[doc(no_inline)]
pub use js_int::{int, uint, Int, UInt};

pub use ruma_common::*;
#[doc(inline)]
pub use ruma_identifiers as identifiers;
#[doc(inline)]
pub use ruma_serde as serde;

pub use ruma_serde::Outgoing;

#[allow(deprecated)] // Allow re-export of deprecated items
pub use ruma_identifiers::{
    device_id, device_key_id, event_id, mxc_uri, room_alias_id, room_id, room_version_id,
    server_key_id, server_name, server_signing_key_id, user_id, DeviceId, DeviceIdBox,
    DeviceKeyAlgorithm, DeviceKeyId, DeviceSignatures, DeviceSigningKeyId, EntitySignatures,
    EventEncryptionAlgorithm, EventId, KeyId, KeyName, KeyNameBox, MxcUri, RoomAliasId, RoomId,
    RoomIdOrAliasId, RoomVersionId, ServerName, ServerNameBox, ServerSignatures,
    ServerSigningKeyId, Signatures, SigningKeyAlgorithm, UserId,
};

#[cfg(feature = "events")]
#[cfg_attr(docsrs, doc(cfg(feature = "events")))]
#[doc(inline)]
pub use ruma_events as events;
#[cfg(feature = "signatures")]
#[cfg_attr(docsrs, doc(cfg(feature = "signatures")))]
#[doc(inline)]
pub use ruma_signatures as signatures;

/// (De)serializable types for various [Matrix APIs][apis] requests and responses and abstractions
/// for them.
///
/// [apis]: https://matrix.org/docs/spec/#matrix-apis
#[cfg(feature = "api")]
#[cfg_attr(docsrs, doc(cfg(feature = "api")))]
pub mod api {
    pub use ruma_api::*;

    #[cfg(feature = "ruma-appservice-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "appservice-api",
            feature = "appservice-api-c",
            feature = "appservice-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_appservice_api as appservice;
    #[cfg(feature = "ruma-client-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "client-api",
            feature = "client-api-c",
            feature = "client-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_client_api as client;
    #[cfg(feature = "ruma-federation-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "federation-api",
            feature = "federation-api-c",
            feature = "federation-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_federation_api as federation;
    #[cfg(feature = "ruma-identity-service-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "identity-service-api",
            feature = "identity-service-api-c",
            feature = "identity-service-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_identity_service_api as identity_service;
    #[cfg(feature = "ruma-push-gateway-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "push-gateway-api",
            feature = "push-gateway-api-c",
            feature = "push-gateway-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_push_gateway_api as push_gateway;
}
<|endoftext|>


<commit_before>use diesel::prelude::*;

use crate::git;
use crate::util::errors::{cargo_err, AppResult};

use crate::models::{Crate, Version};
use crate::schema::*;
use crate::views::EncodableCrateDependency;

pub const WILDCARD_ERROR_MESSAGE: &str = "wildcard (`*`) dependency constraints are not allowed \
     on crates.io. See https://doc.rust-lang.org/cargo/faq.html#can-\
     libraries-use--as-a-version-for-their-dependencies for more \
     information";

#[derive(Identifiable, Associations, Debug, Queryable, QueryableByName)]
#[belongs_to(Version)]
#[belongs_to(Crate)]
#[table_name = "dependencies"]
pub struct Dependency {
    pub id: i32,
    pub version_id: i32,
    pub crate_id: i32,
    pub req: String,
    pub optional: bool,
    pub default_features: bool,
    pub features: Vec<String>,
    pub target: Option<String>,
    pub kind: DependencyKind,
}

#[derive(Debug, QueryableByName)]
pub struct ReverseDependency {
    #[diesel(embed)]
    pub dependency: Dependency,
    #[sql_type = "::diesel::sql_types::Integer"]
    pub crate_downloads: i32,
    #[sql_type = "::diesel::sql_types::Text"]
    #[column_name = "crate_name"]
    pub name: String,
}

#[derive(Copy, Clone, Serialize, Deserialize, Debug, FromSqlRow)]
#[serde(rename_all = "lowercase")]
#[repr(u32)]
pub enum DependencyKind {
    Normal = 0,
    Build = 1,
    Dev = 2,
    // if you add a kind here, be sure to update `from_row` below.
}

pub fn add_dependencies(
    conn: &PgConnection,
    deps: &[EncodableCrateDependency],
    target_version_id: i32,
) -> AppResult<Vec<git::Dependency>> {
    use self::dependencies::dsl::*;
    use diesel::insert_into;

    let git_and_new_dependencies = deps
        .iter()
        .map(|dep| {
            if let Some(registry) = &dep.registry {
                if !registry.is_empty() {
                    return Err(cargo_err(&format_args!("Dependency `{}` is hosted on another registry. Cross-registry dependencies are not permitted on crates.io.", &*dep.name)));
                }
            }

            // Match only identical names to ensure the index always references the original crate name
            let krate:Crate = Crate::by_exact_name(&dep.name)
                .first(&*conn)
                .map_err(|_| cargo_err(&format_args!("no known crate named `{}`", &*dep.name)))?;
            if semver::VersionReq::parse(&dep.version_req.0) == semver::VersionReq::parse("*") {
                return Err(cargo_err(WILDCARD_ERROR_MESSAGE));
            }

            // If this dependency has an explicit name in `Cargo.toml` that
            // means that the `name` we have listed is actually the package name
            // that we're depending on. The `name` listed in the index is the
            // Cargo.toml-written-name which is what cargo uses for
            // `--extern foo=...`
            let (name, package) = match &dep.explicit_name_in_toml {
                Some(explicit) => (explicit.to_string(), Some(dep.name.to_string())),
                None => (dep.name.to_string(), None),
            };

            Ok((
                git::Dependency {
                    name,
                    req: dep.version_req.to_string(),
                    features: dep.features.iter().map(|s| s.0.to_string()).collect(),
                    optional: dep.optional,
                    default_features: dep.default_features,
                    target: dep.target.clone(),
                    kind: dep.kind.or(Some(DependencyKind::Normal)),
                    package,
                },
                (
                    version_id.eq(target_version_id),
                    crate_id.eq(krate.id),
                    req.eq(dep.version_req.to_string()),
                    dep.kind.map(|k| kind.eq(k as i32)),
                    optional.eq(dep.optional),
                    default_features.eq(dep.default_features),
                    features.eq(&dep.features),
                    target.eq(dep.target.as_deref()),
                ),
            ))
        })
        .collect::<Result<Vec<_>, _>>()?;

    let (git_deps, new_dependencies): (Vec<_>, Vec<_>) =
        git_and_new_dependencies.into_iter().unzip();

    insert_into(dependencies)
        .values(&new_dependencies)
        .execute(conn)?;

    Ok(git_deps)
}

use diesel::deserialize::{self, FromSql};
use diesel::pg::Pg;
use diesel::sql_types::Integer;

impl FromSql<Integer, Pg> for DependencyKind {
    fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
        match <i32 as FromSql<Integer, Pg>>::from_sql(bytes)? {
            0 => Ok(DependencyKind::Normal),
            1 => Ok(DependencyKind::Build),
            2 => Ok(DependencyKind::Dev),
            n => Err(format!("unknown kind: {}", n).into()),
        }
    }
}
<commit_msg>models/dependency: Move imports to the top<commit_after>use diesel::deserialize::{self, FromSql};
use diesel::pg::Pg;
use diesel::prelude::*;
use diesel::sql_types::Integer;

use crate::git;
use crate::util::errors::{cargo_err, AppResult};

use crate::models::{Crate, Version};
use crate::schema::*;
use crate::views::EncodableCrateDependency;

pub const WILDCARD_ERROR_MESSAGE: &str = "wildcard (`*`) dependency constraints are not allowed \
     on crates.io. See https://doc.rust-lang.org/cargo/faq.html#can-\
     libraries-use--as-a-version-for-their-dependencies for more \
     information";

#[derive(Identifiable, Associations, Debug, Queryable, QueryableByName)]
#[belongs_to(Version)]
#[belongs_to(Crate)]
#[table_name = "dependencies"]
pub struct Dependency {
    pub id: i32,
    pub version_id: i32,
    pub crate_id: i32,
    pub req: String,
    pub optional: bool,
    pub default_features: bool,
    pub features: Vec<String>,
    pub target: Option<String>,
    pub kind: DependencyKind,
}

#[derive(Debug, QueryableByName)]
pub struct ReverseDependency {
    #[diesel(embed)]
    pub dependency: Dependency,
    #[sql_type = "::diesel::sql_types::Integer"]
    pub crate_downloads: i32,
    #[sql_type = "::diesel::sql_types::Text"]
    #[column_name = "crate_name"]
    pub name: String,
}

#[derive(Copy, Clone, Serialize, Deserialize, Debug, FromSqlRow)]
#[serde(rename_all = "lowercase")]
#[repr(u32)]
pub enum DependencyKind {
    Normal = 0,
    Build = 1,
    Dev = 2,
    // if you add a kind here, be sure to update `from_row` below.
}

pub fn add_dependencies(
    conn: &PgConnection,
    deps: &[EncodableCrateDependency],
    target_version_id: i32,
) -> AppResult<Vec<git::Dependency>> {
    use self::dependencies::dsl::*;
    use diesel::insert_into;

    let git_and_new_dependencies = deps
        .iter()
        .map(|dep| {
            if let Some(registry) = &dep.registry {
                if !registry.is_empty() {
                    return Err(cargo_err(&format_args!("Dependency `{}` is hosted on another registry. Cross-registry dependencies are not permitted on crates.io.", &*dep.name)));
                }
            }

            // Match only identical names to ensure the index always references the original crate name
            let krate:Crate = Crate::by_exact_name(&dep.name)
                .first(&*conn)
                .map_err(|_| cargo_err(&format_args!("no known crate named `{}`", &*dep.name)))?;
            if semver::VersionReq::parse(&dep.version_req.0) == semver::VersionReq::parse("*") {
                return Err(cargo_err(WILDCARD_ERROR_MESSAGE));
            }

            // If this dependency has an explicit name in `Cargo.toml` that
            // means that the `name` we have listed is actually the package name
            // that we're depending on. The `name` listed in the index is the
            // Cargo.toml-written-name which is what cargo uses for
            // `--extern foo=...`
            let (name, package) = match &dep.explicit_name_in_toml {
                Some(explicit) => (explicit.to_string(), Some(dep.name.to_string())),
                None => (dep.name.to_string(), None),
            };

            Ok((
                git::Dependency {
                    name,
                    req: dep.version_req.to_string(),
                    features: dep.features.iter().map(|s| s.0.to_string()).collect(),
                    optional: dep.optional,
                    default_features: dep.default_features,
                    target: dep.target.clone(),
                    kind: dep.kind.or(Some(DependencyKind::Normal)),
                    package,
                },
                (
                    version_id.eq(target_version_id),
                    crate_id.eq(krate.id),
                    req.eq(dep.version_req.to_string()),
                    dep.kind.map(|k| kind.eq(k as i32)),
                    optional.eq(dep.optional),
                    default_features.eq(dep.default_features),
                    features.eq(&dep.features),
                    target.eq(dep.target.as_deref()),
                ),
            ))
        })
        .collect::<Result<Vec<_>, _>>()?;

    let (git_deps, new_dependencies): (Vec<_>, Vec<_>) =
        git_and_new_dependencies.into_iter().unzip();

    insert_into(dependencies)
        .values(&new_dependencies)
        .execute(conn)?;

    Ok(git_deps)
}

impl FromSql<Integer, Pg> for DependencyKind {
    fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
        match <i32 as FromSql<Integer, Pg>>::from_sql(bytes)? {
            0 => Ok(DependencyKind::Normal),
            1 => Ok(DependencyKind::Build),
            2 => Ok(DependencyKind::Dev),
            n => Err(format!("unknown kind: {}", n).into()),
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use protobuf;
use protobuf::compiler_plugin;
use protobuf::descriptor::*;
use protobuf::descriptorx::*;
use protobuf::Message;
use protobuf_codegen::code_writer::CodeWriter;

/// Adjust method name to follow Rust style.
fn snake_name(name: &str) -> String {
    let mut snake_method_name = String::with_capacity(name.len());
    let mut chars = name.chars();
    // initial char can be any char except '_'.
    let mut last_char = '.';
    'outer: while let Some(c) = chars.next() {
        // Please note that '_' is neither uppercase nor lowercase.
        if !c.is_uppercase() {
            last_char = c;
            snake_method_name.push(c);
            continue;
        }
        let mut can_append_underscore = false;
        // check if it's the first char.
        if !snake_method_name.is_empty() && last_char != '_' {
            snake_method_name.push('_');
        }
        last_char = c;
        // find all continous upper case char and append an underscore before
        // last upper case char if neccessary.
        #[allow(clippy::while_let_on_iterator)]
        while let Some(c) = chars.next() {
            if !c.is_uppercase() {
                if can_append_underscore && c != '_' {
                    snake_method_name.push('_');
                }
                snake_method_name.extend(last_char.to_lowercase());
                snake_method_name.push(c);
                last_char = c;
                continue 'outer;
            }
            snake_method_name.extend(last_char.to_lowercase());
            last_char = c;
            can_append_underscore = true;
        }
        snake_method_name.extend(last_char.to_lowercase());
    }
    snake_method_name
}

struct MethodGen<'a> {
    proto: &'a MethodDescriptorProto,
    service_path: String,
    root_scope: &'a RootScope<'a>,
}

impl<'a> MethodGen<'a> {
    fn new(
        proto: &'a MethodDescriptorProto,
        service_path: String,
        root_scope: &'a RootScope<'a>,
    ) -> MethodGen<'a> {
        MethodGen {
            proto,
            service_path,
            root_scope,
        }
    }

    fn snake_name(&self) -> String {
        snake_name(self.proto.get_name())
    }

    fn input_empty(&self) -> bool {
        self.root_scope
            .find_message(self.proto.get_input_type())
            .message
            == protobuf::well_known_types::Empty::descriptor_static().get_proto()
    }

    fn output_empty(&self) -> bool {
        self.root_scope
            .find_message(self.proto.get_output_type())
            .message
            == protobuf::well_known_types::Empty::descriptor_static().get_proto()
    }

    fn input_message(&self) -> String {
        let msg = self.root_scope.find_message(self.proto.get_input_type());
        let empty = protobuf::well_known_types::Empty::descriptor_static();
        if msg.message == empty.get_proto() {
            "()".to_string()
        } else {
            format!("super::{}", msg.rust_fq_name())
        }
    }

    fn output_message(&self) -> String {
        let msg = self.root_scope.find_message(self.proto.get_output_type());
        let empty = protobuf::well_known_types::Empty::descriptor_static();
        if msg.message == empty.get_proto() {
            "()".to_string()
        } else {
            format!("super::{}", msg.rust_fq_name())
        }
    }

    fn server_req_type(&self) -> String {
        if self.proto.get_client_streaming() {
            // TODO: better streaming
            format!("Vec<{}>", self.input_message())
        } else {
            self.input_message().to_string()
        }
    }

    fn server_resp_type(&self) -> String {
        if self.proto.get_server_streaming() {
            "".to_string()
        } else {
            format!(" -> grpc::Result<{}>", self.output_message())
        }
    }

    fn server_sig(&self) -> String {
        let arg = if self.input_empty() {
            "".to_string()
        } else {
            format!(
                ", {}: {}",
                if self.proto.get_client_streaming() {
                    "reqs"
                } else {
                    "req"
                },
                self.server_req_type(),
            )
        };
        let arg2 = if self.proto.get_server_streaming() {
            ", writer: grpc::ChannelResponseWriter".to_string()
        } else {
            "".to_string()
        };
        format!(
            "{}(&mut self{}{}){}",
            self.snake_name(),
            arg,
            arg2,
            self.server_resp_type()
        )
    }

    fn write_server_intf(&self, w: &mut CodeWriter) {
        w.fn_def(&self.server_sig())
    }

    fn write_dispatch(&self, w: &mut CodeWriter) {
        // TODO: rather than explicitly generating dispatch() boilerplate, instead
        // invoke a generic method that accepts the relevant request/response types.
        let param_in;
        if self.input_empty() {
            param_in = "";
        } else if self.proto.get_client_streaming() {
            param_in = "rr";
            w.write_line("let rr = vec![protobuf::parse_from_bytes(&req).unwrap()];")
        } else {
            param_in = "r";
            w.write_line("let r = protobuf::parse_from_bytes(&req).unwrap();")
        }
        if self.output_empty() {
            w.block(
                &format!("match node.{}({}) {{", self.snake_name(), param_in),
                "}",
                |w| {
                    w.write_line("Ok(_) => writer.write_empty(grpc::WriteMode::Close),");
                    w.write_line("Err(status) => writer.close(Err(status)),");
                },
            );
        } else if self.proto.get_server_streaming() {
            w.write_line(format!("node.{}({}, writer)", self.snake_name(), param_in));
        } else {
            w.block(
                &format!("match node.{}({}) {{", self.snake_name(), param_in),
                "}",
                |w| {
                    w.write_line("Ok(rsp) => writer.write(rsp, grpc::WriteMode::Close),");
                    w.write_line("Err(status) => writer.close(Err(status)),");
                },
            );
        }
    }
}

struct ServiceGen<'a> {
    proto: &'a ServiceDescriptorProto,
    _root_scope: &'a RootScope<'a>,
    methods: Vec<MethodGen<'a>>,
    _package: String,
}

impl<'a> ServiceGen<'a> {
    fn new(
        proto: &'a ServiceDescriptorProto,
        file: &FileDescriptorProto,
        root_scope: &'a RootScope,
    ) -> ServiceGen<'a> {
        let service_path = if file.get_package().is_empty() {
            format!("/{}", proto.get_name())
        } else {
            format!("/{}.{}", file.get_package(), proto.get_name())
        };
        let methods = proto
            .get_method()
            .iter()
            .map(|m| MethodGen::new(m, service_path.clone(), root_scope))
            .collect();

        ServiceGen {
            proto,
            _root_scope: root_scope,
            methods,
            _package: file.get_package().to_string(),
        }
    }

    // trait name
    fn server_intf_name(&self) -> String {
        format!("{}Node", self.proto.get_name())
    }

    fn write_server_intf(&self, w: &mut CodeWriter) {
        w.pub_trait(&self.server_intf_name(), |w| {
            for (i, method) in self.methods.iter().enumerate() {
                if i != 0 {
                    w.write_line("");
                }

                method.write_server_intf(w);
            }
        });
    }

    fn write_dispatcher(&self, w: &mut CodeWriter) {
        w.pub_fn(&format!("dispatch(node: &mut dyn {}, method: &str, req: &[u8], mut writer: grpc::ChannelResponseWriter)", self.server_intf_name()), |w| {
            w.block("match method {", "};", |w| {
                for method in &self.methods {
                    let full_path = format!("{}/{}", method.service_path, method.proto.get_name());
                    w.block(&format!("\"{}\" => {{", full_path), "}", |w| {
                        method.write_dispatch(w);
                    });
                }
                w.block("_ => {", "}", |w| {
                    w.write_line("writeln!(oak::logging_channel(), \"unknown method name: {}\", method).unwrap();");
                    w.write_line("panic!(\"unknown method name\");");
                });
            });
        });
    }

    fn write(&self, w: &mut CodeWriter) {
        w.write_line("use oak::grpc;");
        w.write_line("use protobuf::Message;");
        w.write_line("use std::io::Write;");
        w.write_line("");
        w.comment("Oak Node server interface");
        self.write_server_intf(w);
        w.write_line("");
        w.comment("Oak Node gRPC method dispatcher");
        self.write_dispatcher(w);
    }
}

fn gen_file(
    file: &FileDescriptorProto,
    root_scope: &RootScope,
) -> Option<compiler_plugin::GenResult> {
    if file.get_service().is_empty() {
        return None;
    }

    let base = protobuf::descriptorx::proto_path_to_rust_mod(file.get_name());

    let mut v = Vec::new();
    {
        let mut w = CodeWriter::new(&mut v);
        w.write_generated();
        w.write_line("");

        for service in file.get_service() {
            w.write_line("");
            ServiceGen::new(service, file, root_scope).write(&mut w);
        }
    }

    Some(compiler_plugin::GenResult {
        name: base + "_grpc.rs",
        content: v,
    })
}

pub fn gen(
    file_descriptors: &[FileDescriptorProto],
    files_to_generate: &[String],
) -> Vec<compiler_plugin::GenResult> {
    let files_map: HashMap<&str, &FileDescriptorProto> =
        file_descriptors.iter().map(|f| (f.get_name(), f)).collect();

    let root_scope = RootScope { file_descriptors };

    let mut results = Vec::new();

    for file_name in files_to_generate {
        let file = files_map[&file_name[..]];

        if file.get_service().is_empty() {
            continue;
        }

        results.extend(gen_file(file, &root_scope).into_iter());
    }

    results
}

pub fn protoc_gen_grpc_rust_main() {
    compiler_plugin::plugin_main(gen);
}

#[cfg(test)]
mod test {
    #[test]
    fn test_snake_name() {
        let cases = vec![
            ("AsyncRequest", "async_request"),
            ("asyncRequest", "async_request"),
            ("async_request", "async_request"),
            ("createID", "create_id"),
            ("CreateIDForReq", "create_id_for_req"),
            ("Create_ID_For_Req", "create_id_for_req"),
            ("ID", "id"),
            ("id", "id"),
        ];

        for (origin, exp) in cases {
            let res = super::snake_name(&origin);
            assert_eq!(res, exp);
        }
    }
}
<commit_msg>Generate code that uses oak::grpc generic functions<commit_after>use std::collections::HashMap;

use protobuf;
use protobuf::compiler_plugin;
use protobuf::descriptor::*;
use protobuf::descriptorx::*;
use protobuf::Message;
use protobuf_codegen::code_writer::CodeWriter;

/// Adjust method name to follow Rust style.
fn snake_name(name: &str) -> String {
    let mut snake_method_name = String::with_capacity(name.len());
    let mut chars = name.chars();
    // initial char can be any char except '_'.
    let mut last_char = '.';
    'outer: while let Some(c) = chars.next() {
        // Please note that '_' is neither uppercase nor lowercase.
        if !c.is_uppercase() {
            last_char = c;
            snake_method_name.push(c);
            continue;
        }
        let mut can_append_underscore = false;
        // check if it's the first char.
        if !snake_method_name.is_empty() && last_char != '_' {
            snake_method_name.push('_');
        }
        last_char = c;
        // find all continous upper case char and append an underscore before
        // last upper case char if neccessary.
        #[allow(clippy::while_let_on_iterator)]
        while let Some(c) = chars.next() {
            if !c.is_uppercase() {
                if can_append_underscore && c != '_' {
                    snake_method_name.push('_');
                }
                snake_method_name.extend(last_char.to_lowercase());
                snake_method_name.push(c);
                last_char = c;
                continue 'outer;
            }
            snake_method_name.extend(last_char.to_lowercase());
            last_char = c;
            can_append_underscore = true;
        }
        snake_method_name.extend(last_char.to_lowercase());
    }
    snake_method_name
}

struct MethodGen<'a> {
    proto: &'a MethodDescriptorProto,
    service_path: String,
    root_scope: &'a RootScope<'a>,
}

impl<'a> MethodGen<'a> {
    fn new(
        proto: &'a MethodDescriptorProto,
        service_path: String,
        root_scope: &'a RootScope<'a>,
    ) -> MethodGen<'a> {
        MethodGen {
            proto,
            service_path,
            root_scope,
        }
    }

    fn snake_name(&self) -> String {
        snake_name(self.proto.get_name())
    }

    fn input_message(&self) -> String {
        let msg = self.root_scope.find_message(self.proto.get_input_type());
        let empty = protobuf::well_known_types::Empty::descriptor_static();
        if msg.message == empty.get_proto() {
            "protobuf::well_known_types::Empty".to_string()
        } else {
            format!("super::{}", msg.rust_fq_name())
        }
    }

    fn output_message(&self) -> String {
        let msg = self.root_scope.find_message(self.proto.get_output_type());
        let empty = protobuf::well_known_types::Empty::descriptor_static();
        if msg.message == empty.get_proto() {
            "protobuf::well_known_types::Empty".to_string()
        } else {
            format!("super::{}", msg.rust_fq_name())
        }
    }

    fn server_req_type(&self) -> String {
        if self.proto.get_client_streaming() {
            // TODO(#97): better client-side streaming
            format!("Vec<{}>", self.input_message())
        } else {
            self.input_message().to_string()
        }
    }

    fn server_resp_type(&self) -> String {
        if self.proto.get_server_streaming() {
            "".to_string()
        } else {
            format!(" -> grpc::Result<{}>", self.output_message())
        }
    }

    fn server_sig(&self) -> String {
        let arg = format!(
            ", {}: {}",
            if self.proto.get_client_streaming() {
                "reqs"
            } else {
                "req"
            },
            self.server_req_type(),
        );
        let arg2 = if self.proto.get_server_streaming() {
            ", writer: grpc::ChannelResponseWriter".to_string()
        } else {
            "".to_string()
        };
        format!(
            "{}(&mut self{}{}){}",
            self.snake_name(),
            arg,
            arg2,
            self.server_resp_type()
        )
    }

    fn write_server_intf(&self, w: &mut CodeWriter) {
        w.fn_def(&self.server_sig())
    }

    fn dispatch_method(&self) -> String {
        // Figure out which generic function applies
        let (gen_fn, lambda_params) = if self.proto.get_client_streaming() {
            if self.proto.get_server_streaming() {
                ("grpc::handle_stream_stream", "rr, w")
            } else {
                ("grpc::handle_stream_rsp", "rr")
            }
        } else if self.proto.get_server_streaming() {
            ("grpc::handle_req_stream", "r, w")
        } else {
            ("grpc::handle_req_rsp", "r")
        };
        format!(
            "{}(|{}| node.{}({}), req, writer)",
            gen_fn,
            lambda_params,
            self.snake_name(),
            lambda_params
        )
    }
}

struct ServiceGen<'a> {
    proto: &'a ServiceDescriptorProto,
    _root_scope: &'a RootScope<'a>,
    methods: Vec<MethodGen<'a>>,
    _package: String,
}

impl<'a> ServiceGen<'a> {
    fn new(
        proto: &'a ServiceDescriptorProto,
        file: &FileDescriptorProto,
        root_scope: &'a RootScope,
    ) -> ServiceGen<'a> {
        let service_path = if file.get_package().is_empty() {
            format!("/{}", proto.get_name())
        } else {
            format!("/{}.{}", file.get_package(), proto.get_name())
        };
        let methods = proto
            .get_method()
            .iter()
            .map(|m| MethodGen::new(m, service_path.clone(), root_scope))
            .collect();

        ServiceGen {
            proto,
            _root_scope: root_scope,
            methods,
            _package: file.get_package().to_string(),
        }
    }

    // trait name
    fn server_intf_name(&self) -> String {
        format!("{}Node", self.proto.get_name())
    }

    fn write_server_intf(&self, w: &mut CodeWriter) {
        w.pub_trait(&self.server_intf_name(), |w| {
            for method in &self.methods {
                method.write_server_intf(w);
            }
        });
    }

    fn write_dispatcher(&self, w: &mut CodeWriter) {
        w.pub_fn(&format!("dispatch(node: &mut dyn {}, method: &str, req: &[u8], writer: grpc::ChannelResponseWriter)", self.server_intf_name()), |w| {
            w.block("match method {", "};", |w| {
                for method in &self.methods {
                    let full_path = format!("{}/{}", method.service_path, method.proto.get_name());
                    w.write_line(format!("\"{}\" => {},", full_path, method.dispatch_method()));
                }
                w.block("_ => {", "}", |w| {
                    w.write_line("writeln!(oak::logging_channel(), \"unknown method name: {}\", method).unwrap();");
                    w.write_line("panic!(\"unknown method name\");");
                });
            });
        });
    }

    fn write(&self, w: &mut CodeWriter) {
        w.write_line("use oak::grpc;");
        w.write_line("use protobuf::Message;");
        w.write_line("use std::io::Write;");
        w.write_line("");
        w.comment("Oak Node server interface");
        self.write_server_intf(w);
        w.write_line("");
        w.comment("Oak Node gRPC method dispatcher");
        self.write_dispatcher(w);
    }
}

fn gen_file(
    file: &FileDescriptorProto,
    root_scope: &RootScope,
) -> Option<compiler_plugin::GenResult> {
    if file.get_service().is_empty() {
        return None;
    }

    let base = protobuf::descriptorx::proto_path_to_rust_mod(file.get_name());

    let mut v = Vec::new();
    {
        let mut w = CodeWriter::new(&mut v);
        w.write_generated();
        w.write_line("");

        for service in file.get_service() {
            w.write_line("");
            ServiceGen::new(service, file, root_scope).write(&mut w);
        }
    }

    Some(compiler_plugin::GenResult {
        name: base + "_grpc.rs",
        content: v,
    })
}

pub fn gen(
    file_descriptors: &[FileDescriptorProto],
    files_to_generate: &[String],
) -> Vec<compiler_plugin::GenResult> {
    let files_map: HashMap<&str, &FileDescriptorProto> =
        file_descriptors.iter().map(|f| (f.get_name(), f)).collect();
    let root_scope = RootScope { file_descriptors };
    let mut results = Vec::new();

    for file_name in files_to_generate {
        let file = files_map[&file_name[..]];
        if file.get_service().is_empty() {
            continue;
        }
        results.extend(gen_file(file, &root_scope).into_iter());
    }

    results
}

pub fn protoc_gen_grpc_rust_main() {
    compiler_plugin::plugin_main(gen);
}

#[cfg(test)]
mod test {
    #[test]
    fn test_snake_name() {
        let cases = vec![
            ("AsyncRequest", "async_request"),
            ("asyncRequest", "async_request"),
            ("async_request", "async_request"),
            ("createID", "create_id"),
            ("CreateIDForReq", "create_id_for_req"),
            ("Create_ID_For_Req", "create_id_for_req"),
            ("ID", "id"),
            ("id", "id"),
        ];

        for (origin, exp) in cases {
            let res = super::snake_name(&origin);
            assert_eq!(res, exp);
        }
    }
}
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::cell::UnsafeCell;

/// A mutable memory location that can be set only once.
pub struct OnceCell<T>(UnsafeCell<Option<T>>);

impl<T> OnceCell<T> {
    /// Creates a new `OnceCell` that may already be initialized.
    ///
    /// # Example
    ///
    /// ```
    /// use mitochondria::OnceCell;
    ///
    /// let c = OnceCell::new(Some("Hello vesicle!".to_owned()));
    /// ```
    #[inline]
    pub fn new(value: Option<T>) -> Self {
        OnceCell(UnsafeCell::new(value))
    }

    /// Performs an initialization routine once and only once. The given closure
    /// will be executed if this is the first time `init_once` has been called,
    /// and otherwise the routine will *not* be invoked.
    ///
    /// The result of the given closure is then used to set the contents of this
    /// cell and borrowed as the return value of this method.
    ///
    /// # Examples
    ///
    /// ```
    /// use mitochondria::OnceCell;
    ///
    /// let c = OnceCell::new(None);
    ///
    /// let greeting: &str = c.init_once(|| "Hello ribosome!".to_owned());
    /// ```
    ///
    /// ```
    /// use mitochondria::OnceCell;
    ///
    /// let c = OnceCell::new(Some("Hello reticulum!".to_owned()));
    ///
    /// // Calls to `init_once` on already-initialized cells are ignored.
    /// assert_eq!(c.init_once(|| "Goodbye!".to_owned()), "Hello reticulum!");
    /// ```
    pub fn init_once<F: FnOnce() -> T>(&self, f: F) -> &T {
        let mut cell = unsafe { &mut *self.0.get() };
        if cell.is_none() {
            let value = f();
            // f() may have initialised the value already.
            if cell.is_none() {
                *cell = Some(value);
            }
        }
        cell.as_ref().unwrap().borrow()
    }

    /// Borrows the contained value, if initialized.
    ///
    /// # Examples
    ///
    /// ```
    /// use mitochondria::OnceCell;
    ///
    /// let c = OnceCell::new(None);
    ///
    /// assert!(c.borrow().is_none());
    ///
    /// let greeting = c.init_once(|| "Hello nucleus!".to_owned());
    /// assert_eq!(c.borrow(), Some(greeting));
    /// ```
    #[inline]
    pub fn borrow(&self) -> Option<&T> {
        unsafe { (*self.0.get()).as_ref() }
    }
}
<commit_msg>Test for reentrancy<commit_after>use std::borrow::Borrow;
use std::cell::UnsafeCell;

/// A mutable memory location that can be set only once.
pub struct OnceCell<T>(UnsafeCell<Option<T>>);

impl<T> OnceCell<T> {
    /// Creates a new `OnceCell` that may already be initialized.
    ///
    /// # Example
    ///
    /// ```
    /// use mitochondria::OnceCell;
    ///
    /// let c = OnceCell::new(Some("Hello vesicle!".to_owned()));
    /// ```
    #[inline]
    pub fn new(value: Option<T>) -> Self {
        OnceCell(UnsafeCell::new(value))
    }

    /// Performs an initialization routine once and only once. The given closure
    /// will be executed if this is the first time `init_once` has been called,
    /// and otherwise the routine will *not* be invoked.
    ///
    /// The result of the given closure is then used to set the contents of this
    /// cell and borrowed as the return value of this method.
    ///
    /// # Examples
    ///
    /// ```
    /// use mitochondria::OnceCell;
    ///
    /// let c = OnceCell::new(None);
    ///
    /// let greeting: &str = c.init_once(|| "Hello ribosome!".to_owned());
    /// ```
    ///
    /// ```
    /// use mitochondria::OnceCell;
    ///
    /// let c = OnceCell::new(Some("Hello reticulum!".to_owned()));
    ///
    /// // Calls to `init_once` on already-initialized cells are ignored.
    /// assert_eq!(c.init_once(|| "Goodbye!".to_owned()), "Hello reticulum!");
    /// ```
    pub fn init_once<F: FnOnce() -> T>(&self, f: F) -> &T {
        let mut cell = unsafe { &mut *self.0.get() };
        if cell.is_none() {
            let value = f();
            // f() may have initialised the value already.
            if cell.is_none() {
                *cell = Some(value);
            }
        }
        cell.as_ref().unwrap().borrow()
    }

    /// Borrows the contained value, if initialized.
    ///
    /// # Examples
    ///
    /// ```
    /// use mitochondria::OnceCell;
    ///
    /// let c = OnceCell::new(None);
    ///
    /// assert!(c.borrow().is_none());
    ///
    /// let greeting = c.init_once(|| "Hello nucleus!".to_owned());
    /// assert_eq!(c.borrow(), Some(greeting));
    /// ```
    #[inline]
    pub fn borrow(&self) -> Option<&T> {
        unsafe { (*self.0.get()).as_ref() }
    }
}

#[cfg(test)]
mod tests {
    use OnceCell;

    #[test]
    fn reentrancy() {
        let c = OnceCell::new(None);

        let value = *c.init_once(|| {
            c.init_once(|| "ribosome");
            "nucleolus"
        });

        assert_eq!(value, "ribosome");
    }
}
<|endoftext|>


<commit_before>use std;

pub struct Path {
  opaque: *mut std::libc::c_void
}

impl std::ops::Drop for Path {
  fn drop(&mut self) {
    unsafe {
      cairo_path_destroy(self.opaque);
    }
  }
}

extern {
  fn cairo_path_destroy(self_value: *mut std::libc::c_void);
}

<commit_msg>Copied comments for path<commit_after>//! Creating paths and manipulating path data

use std;

///  A data structure for holding a path. This data structure serves as the return value for cairo_copy_path() and cairo_copy_path_flat() as well the input value for cairo_append_path().
///
/// See cairo_path_data_t for hints on how to iterate over the actual data within the path.
///
/// The num_data member gives the number of elements in the data array. This number is larger than the number of independent path portions (defined in cairo_path_data_type_t), since the data includes both headers and coordinates for each portion.
///
/// cairo_status_t status; the current error status
///
/// cairo_path_data_t *data; the elements in the path
///
/// int num_data; the number of elements in the data array
///
/// Since 1.0
pub struct Path {
  opaque: *mut std::libc::c_void
}

impl std::ops::Drop for Path {
  fn drop(&mut self) {
    unsafe {
      cairo_path_destroy(self.opaque);
    }
  }
}

extern {
  fn cairo_path_destroy(self_value: *mut std::libc::c_void);
}

<|endoftext|>