<commit_before>//! Config used by the language server.
//!
//! We currently get this config from `initialize` LSP request, which is not the
//! best way to do it, but was the simplest thing we could implement.
//!
//! Of particular interest is the `feature_flags` hash map: while other fields
//! configure the server itself, feature flags are passed into analysis, and
//! tweak things like automatic insertion of `()` in completions.

use lsp_types::TextDocumentClientCapabilities;
use ra_flycheck::FlycheckConfig;
use ra_ide::{CompletionConfig, InlayHintsConfig};
use ra_project_model::CargoConfig;
use serde::Deserialize;

#[derive(Debug, Clone)]
pub struct Config {
    pub client_caps: ClientCapsConfig,

    pub with_sysroot: bool,
    pub publish_diagnostics: bool,
    pub lru_capacity: Option<usize>,
    pub proc_macro_srv: Option<(String, Vec<String>)>,
    pub files: FilesConfig,
    pub notifications: NotificationsConfig,

    pub cargo: CargoConfig,
    pub rustfmt: RustfmtConfig,
    pub check: Option<FlycheckConfig>,

    pub inlay_hints: InlayHintsConfig,
    pub completion: CompletionConfig,
    pub call_info_full: bool,
}

#[derive(Debug, Clone)]
pub struct FilesConfig {
    pub watcher: FilesWatcher,
    pub exclude: Vec<String>,
}

#[derive(Debug, Clone)]
pub enum FilesWatcher {
    Client,
    Notify,
}

#[derive(Debug, Clone)]
pub struct NotificationsConfig {
    pub workspace_loaded: bool,
    pub cargo_toml_not_found: bool,
}

#[derive(Debug, Clone)]
pub enum RustfmtConfig {
    Rustfmt {
        extra_args: Vec<String>,
    },
    #[allow(unused)]
    CustomCommand {
        command: String,
        args: Vec<String>,
    },
}

#[derive(Debug, Clone, Default)]
pub struct ClientCapsConfig {
    pub location_link: bool,
    pub line_folding_only: bool,
}

impl Default for Config {
    fn default() -> Self {
        Config {
            client_caps: ClientCapsConfig::default(),

            with_sysroot: true,
            publish_diagnostics: true,
            lru_capacity: None,
            proc_macro_srv: None,
            files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() },
            notifications: NotificationsConfig {
                workspace_loaded: true,
                cargo_toml_not_found: true,
            },

            cargo: CargoConfig::default(),
            rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() },
            check: Some(FlycheckConfig::CargoCommand {
                command: "check".to_string(),
                all_targets: true,
                extra_args: Vec::new(),
            }),

            inlay_hints: InlayHintsConfig {
                type_hints: true,
                parameter_hints: true,
                chaining_hints: true,
                max_length: None,
            },
            completion: CompletionConfig {
                enable_postfix_completions: true,
                add_call_parenthesis: true,
                add_call_argument_snippets: true,
            },
            call_info_full: true,
        }
    }
}

impl Config {
    #[rustfmt::skip]
    pub fn update(&mut self, value: &serde_json::Value) {
        log::info!("Config::update({:#})", value);

        let client_caps = self.client_caps.clone();
        *self = Default::default();
        self.client_caps = client_caps;

        set(value, "/withSysroot", &mut self.with_sysroot);
        set(value, "/featureFlags/lsp.diagnostics", &mut self.publish_diagnostics);
        set(value, "/lruCapacity", &mut self.lru_capacity);
        self.files.watcher = match get(value, "/files/watcher") {
            Some("client") => FilesWatcher::Client,
            Some("notify") | _ => FilesWatcher::Notify
        };
        set(value, "/notifications/workspaceLoaded", &mut self.notifications.workspace_loaded);
        set(value, "/notifications/cargoTomlNotFound", &mut self.notifications.cargo_toml_not_found);

        set(value, "/cargo/noDefaultFeatures", &mut self.cargo.no_default_features);
        set(value, "/cargo/allFeatures", &mut self.cargo.all_features);
        set(value, "/cargo/features", &mut self.cargo.features);
        set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check);

        match get::<bool>(value, "/procMacro/enabled") {
            Some(true) => {
                if let Ok(path) = std::env::current_exe() {
                    self.proc_macro_srv = Some((path.to_string_lossy().to_string(), vec!["proc-macro".to_string()]));
                }
            }
            _ => self.proc_macro_srv = None,
        }

        match get::<Vec<String>>(value, "/rustfmt/overrideCommand") {
            Some(mut args) if !args.is_empty() => {
                let command = args.remove(0);
                self.rustfmt = RustfmtConfig::CustomCommand {
                    command,
                    args,
                }
            }
            _ => {
                if let RustfmtConfig::Rustfmt { extra_args } = &mut self.rustfmt {
                    set(value, "/rustfmt/extraArgs", extra_args);
                }
            }
        };

        if let Some(false) = get(value, "/checkOnSave/enable") {
            // check is disabled
            self.check = None;
        } else {
            // check is enabled
            match get::<Vec<String>>(value, "/checkOnSave/overrideCommand") {
                // first see if the user has completely overridden the command
                Some(mut args) if !args.is_empty() => {
                    let command = args.remove(0);
                    self.check = Some(FlycheckConfig::CustomCommand {
                        command,
                        args,
                    });
                }
                // otherwise configure command customizations
                _ => {
                    if let Some(FlycheckConfig::CargoCommand { command, extra_args, all_targets })
                        = &mut self.check
                    {
                        set(value, "/checkOnSave/extraArgs", extra_args);
                        set(value, "/checkOnSave/command", command);
                        set(value, "/checkOnSave/allTargets", all_targets);
                    }
                }
            };
        }

        set(value, "/inlayHints/typeHints", &mut self.inlay_hints.type_hints);
        set(value, "/inlayHints/parameterHints", &mut self.inlay_hints.parameter_hints);
        set(value, "/inlayHints/chainingHints", &mut self.inlay_hints.chaining_hints);
        set(value, "/inlayHints/maxLength", &mut self.inlay_hints.max_length);
        set(value, "/completion/postfix/enable", &mut self.completion.enable_postfix_completions);
        set(value, "/completion/addCallParenthesis", &mut self.completion.add_call_parenthesis);
        set(value, "/completion/addCallArgumentSnippets", &mut self.completion.add_call_argument_snippets);
        set(value, "/callInfo/full", &mut self.call_info_full);

        log::info!("Config::update() = {:#?}", self);

        fn get<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str) -> Option<T> {
            value.pointer(pointer).and_then(|it| T::deserialize(it).ok())
        }

        fn set<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str, slot: &mut T) {
            if let Some(new_value) = get(value, pointer) {
                *slot = new_value
            }
        }
    }

    pub fn update_caps(&mut self, caps: &TextDocumentClientCapabilities) {
        if let Some(value) = caps.definition.as_ref().and_then(|it| it.link_support) {
            self.client_caps.location_link = value;
        }
        if let Some(value) = caps.folding_range.as_ref().and_then(|it| it.line_folding_only) {
            self.client_caps.line_folding_only = value
        }
    }
}
<commit_msg>Match implementation of diagnostics flag to the docs<commit_after>//! Config used by the language server.
//!
//! We currently get this config from `initialize` LSP request, which is not the
//! best way to do it, but was the simplest thing we could implement.
//!
//! Of particular interest is the `feature_flags` hash map: while other fields
//! configure the server itself, feature flags are passed into analysis, and
//! tweak things like automatic insertion of `()` in completions.

use lsp_types::TextDocumentClientCapabilities;
use ra_flycheck::FlycheckConfig;
use ra_ide::{CompletionConfig, InlayHintsConfig};
use ra_project_model::CargoConfig;
use serde::Deserialize;

#[derive(Debug, Clone)]
pub struct Config {
    pub client_caps: ClientCapsConfig,

    pub with_sysroot: bool,
    pub publish_diagnostics: bool,
    pub lru_capacity: Option<usize>,
    pub proc_macro_srv: Option<(String, Vec<String>)>,
    pub files: FilesConfig,
    pub notifications: NotificationsConfig,

    pub cargo: CargoConfig,
    pub rustfmt: RustfmtConfig,
    pub check: Option<FlycheckConfig>,

    pub inlay_hints: InlayHintsConfig,
    pub completion: CompletionConfig,
    pub call_info_full: bool,
}

#[derive(Debug, Clone)]
pub struct FilesConfig {
    pub watcher: FilesWatcher,
    pub exclude: Vec<String>,
}

#[derive(Debug, Clone)]
pub enum FilesWatcher {
    Client,
    Notify,
}

#[derive(Debug, Clone)]
pub struct NotificationsConfig {
    pub workspace_loaded: bool,
    pub cargo_toml_not_found: bool,
}

#[derive(Debug, Clone)]
pub enum RustfmtConfig {
    Rustfmt {
        extra_args: Vec<String>,
    },
    #[allow(unused)]
    CustomCommand {
        command: String,
        args: Vec<String>,
    },
}

#[derive(Debug, Clone, Default)]
pub struct ClientCapsConfig {
    pub location_link: bool,
    pub line_folding_only: bool,
}

impl Default for Config {
    fn default() -> Self {
        Config {
            client_caps: ClientCapsConfig::default(),

            with_sysroot: true,
            publish_diagnostics: true,
            lru_capacity: None,
            proc_macro_srv: None,
            files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() },
            notifications: NotificationsConfig {
                workspace_loaded: true,
                cargo_toml_not_found: true,
            },

            cargo: CargoConfig::default(),
            rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() },
            check: Some(FlycheckConfig::CargoCommand {
                command: "check".to_string(),
                all_targets: true,
                extra_args: Vec::new(),
            }),

            inlay_hints: InlayHintsConfig {
                type_hints: true,
                parameter_hints: true,
                chaining_hints: true,
                max_length: None,
            },
            completion: CompletionConfig {
                enable_postfix_completions: true,
                add_call_parenthesis: true,
                add_call_argument_snippets: true,
            },
            call_info_full: true,
        }
    }
}

impl Config {
    #[rustfmt::skip]
    pub fn update(&mut self, value: &serde_json::Value) {
        log::info!("Config::update({:#})", value);

        let client_caps = self.client_caps.clone();
        *self = Default::default();
        self.client_caps = client_caps;

        set(value, "/withSysroot", &mut self.with_sysroot);
        set(value, "/diagnostics/enable", &mut self.publish_diagnostics);
        set(value, "/lruCapacity", &mut self.lru_capacity);
        self.files.watcher = match get(value, "/files/watcher") {
            Some("client") => FilesWatcher::Client,
            Some("notify") | _ => FilesWatcher::Notify
        };
        set(value, "/notifications/workspaceLoaded", &mut self.notifications.workspace_loaded);
        set(value, "/notifications/cargoTomlNotFound", &mut self.notifications.cargo_toml_not_found);

        set(value, "/cargo/noDefaultFeatures", &mut self.cargo.no_default_features);
        set(value, "/cargo/allFeatures", &mut self.cargo.all_features);
        set(value, "/cargo/features", &mut self.cargo.features);
        set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check);

        match get::<bool>(value, "/procMacro/enabled") {
            Some(true) => {
                if let Ok(path) = std::env::current_exe() {
                    self.proc_macro_srv = Some((path.to_string_lossy().to_string(), vec!["proc-macro".to_string()]));
                }
            }
            _ => self.proc_macro_srv = None,
        }

        match get::<Vec<String>>(value, "/rustfmt/overrideCommand") {
            Some(mut args) if !args.is_empty() => {
                let command = args.remove(0);
                self.rustfmt = RustfmtConfig::CustomCommand {
                    command,
                    args,
                }
            }
            _ => {
                if let RustfmtConfig::Rustfmt { extra_args } = &mut self.rustfmt {
                    set(value, "/rustfmt/extraArgs", extra_args);
                }
            }
        };

        if let Some(false) = get(value, "/checkOnSave/enable") {
            // check is disabled
            self.check = None;
        } else {
            // check is enabled
            match get::<Vec<String>>(value, "/checkOnSave/overrideCommand") {
                // first see if the user has completely overridden the command
                Some(mut args) if !args.is_empty() => {
                    let command = args.remove(0);
                    self.check = Some(FlycheckConfig::CustomCommand {
                        command,
                        args,
                    });
                }
                // otherwise configure command customizations
                _ => {
                    if let Some(FlycheckConfig::CargoCommand { command, extra_args, all_targets })
                        = &mut self.check
                    {
                        set(value, "/checkOnSave/extraArgs", extra_args);
                        set(value, "/checkOnSave/command", command);
                        set(value, "/checkOnSave/allTargets", all_targets);
                    }
                }
            };
        }

        set(value, "/inlayHints/typeHints", &mut self.inlay_hints.type_hints);
        set(value, "/inlayHints/parameterHints", &mut self.inlay_hints.parameter_hints);
        set(value, "/inlayHints/chainingHints", &mut self.inlay_hints.chaining_hints);
        set(value, "/inlayHints/maxLength", &mut self.inlay_hints.max_length);
        set(value, "/completion/postfix/enable", &mut self.completion.enable_postfix_completions);
        set(value, "/completion/addCallParenthesis", &mut self.completion.add_call_parenthesis);
        set(value, "/completion/addCallArgumentSnippets", &mut self.completion.add_call_argument_snippets);
        set(value, "/callInfo/full", &mut self.call_info_full);

        log::info!("Config::update() = {:#?}", self);

        fn get<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str) -> Option<T> {
            value.pointer(pointer).and_then(|it| T::deserialize(it).ok())
        }

        fn set<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str, slot: &mut T) {
            if let Some(new_value) = get(value, pointer) {
                *slot = new_value
            }
        }
    }

    pub fn update_caps(&mut self, caps: &TextDocumentClientCapabilities) {
        if let Some(value) = caps.definition.as_ref().and_then(|it| it.link_support) {
            self.client_caps.location_link = value;
        }
        if let Some(value) = caps.folding_range.as_ref().and_then(|it| it.line_folding_only) {
            self.client_caps.line_folding_only = value
        }
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::io::Write;
use std::iter;
use std::path::Path;

/*
#[doc(hidden)]
#[macro_export]
macro_rules! count {
    () => { proc_macro_call_0!() };
    (!) => { proc_macro_call_1!() };
    (!!) => { proc_macro_call_2!() };
    ...
}
*/

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("count.rs");
    let mut f = File::create(&dest_path).unwrap();

    let mut content = String::new();
    content += "
        #[doc(hidden)]
        #[macro_export]
        macro_rules! count {
    ";
    for i in 0..=64 {
        let bangs = iter::repeat("!").take(i).collect::<String>();
        content += &format!("({}) => {{ proc_macro_call_{}!() }};", bangs, i);
    }
    content += "
            ($(!)+) => {
                compile_error!(\"this macro does not support >64 nested macro invocations\")
            };
        }
    ";

    f.write_all(content.as_bytes()).unwrap();
}
<commit_msg>Add rerun-if-changed to proc-macro-nested build script<commit_after>use std::env;
use std::fs::File;
use std::io::Write;
use std::iter;
use std::path::Path;

/*
#[doc(hidden)]
#[macro_export]
macro_rules! count {
    () => { proc_macro_call_0!() };
    (!) => { proc_macro_call_1!() };
    (!!) => { proc_macro_call_2!() };
    ...
}
*/

fn main() {
    // Tell Cargo not to rerun on src/lib.rs changes.
    println!("cargo:rerun-if-changed=build.rs");

    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("count.rs");
    let mut f = File::create(&dest_path).unwrap();

    let mut content = String::new();
    content += "
        #[doc(hidden)]
        #[macro_export]
        macro_rules! count {
    ";
    for i in 0..=64 {
        let bangs = iter::repeat("!").take(i).collect::<String>();
        content += &format!("({}) => {{ proc_macro_call_{}!() }};", bangs, i);
    }
    content += "
            ($(!)+) => {
                compile_error!(\"this macro does not support >64 nested macro invocations\")
            };
        }
    ";

    f.write_all(content.as_bytes()).unwrap();
}
<|endoftext|>


<commit_before>#![feature(conservative_impl_trait)]

#[macro_use]
extern crate lazy_static;

extern crate docopt;
extern crate lalrpop_intern;
extern crate graph_algorithms;
extern crate nll_repr;
extern crate rustc_serialize;

use docopt::Docopt;
use nll_repr::repr::*;
use std::env::args;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::process;

#[macro_use]
mod log;
mod borrowck;
mod env;
use self::env::Environment;
mod infer;
mod loans_in_scope;
mod liveness;
mod graph;
mod region;
mod regionck;
use self::graph::FuncGraph;

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.argv(args()).decode())
        .unwrap_or_else(|e| e.exit());

    for input in &args.arg_inputs {
        match process_input(&args, input) {
            Ok(()) => { }
            Err(err) => {
                println!("{}: {}", input, err);
                process::exit(1);
            }
        }
    }
}

fn process_input(args: &Args, input: &str) -> Result<(), Box<Error>> {
    let mut file_text = String::new();
    let mut file = try!(File::open(input));
    if file.read_to_string(&mut file_text).is_err() {
        return try!(Err(String::from("not UTF-8")));
    }
    let func = try!(Func::parse(&file_text));
    let graph = FuncGraph::new(func);
    graph::with_graph(&graph, || {
        let env = Environment::new(&graph);

        if args.flag_dominators {
            env.dump_dominators();
        }

        try!(regionck::region_check(&env));
        println!("{}: OK", input);
        Ok(())
    })
}

const USAGE: &'static str = "
Usage: nll [options] <inputs>...

Options:
  --help
  --dominators
  --post-dominators
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_inputs: Vec<String>,
    flag_dominators: bool,
    flag_post_dominators: bool,
    flag_help: bool,
}
<commit_msg>print what test was running when assertion fails<commit_after>#![feature(conservative_impl_trait)]

#[macro_use]
extern crate lazy_static;

extern crate docopt;
extern crate lalrpop_intern;
extern crate graph_algorithms;
extern crate nll_repr;
extern crate rustc_serialize;

use docopt::Docopt;
use nll_repr::repr::*;
use std::env::args;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::process;

#[macro_use]
mod log;
mod borrowck;
mod env;
use self::env::Environment;
mod infer;
mod loans_in_scope;
mod liveness;
mod graph;
mod region;
mod regionck;
use self::graph::FuncGraph;

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.argv(args()).decode())
        .unwrap_or_else(|e| e.exit());

    for input in &args.arg_inputs {
        match process_input(&args, input) {
            Ok(()) => { }
            Err(err) => {
                println!("{}: {}", input, err);
                process::exit(1);
            }
        }
    }
}

fn process_input(args: &Args, input: &str) -> Result<(), Box<Error>> {
    let mut file_text = String::new();
    let mut file = try!(File::open(input));
    if file.read_to_string(&mut file_text).is_err() {
        return try!(Err(String::from("not UTF-8")));
    }
    let func = try!(Func::parse(&file_text));
    let graph = FuncGraph::new(func);
    graph::with_graph(&graph, || {
        let env = Environment::new(&graph);

        if args.flag_dominators {
            env.dump_dominators();
        }

        println!("Testing `{}`...", input);
        try!(regionck::region_check(&env));
        Ok(())
    })
}

const USAGE: &'static str = "
Usage: nll [options] <inputs>...

Options:
  --help
  --dominators
  --post-dominators
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_inputs: Vec<String>,
    flag_dominators: bool,
    flag_post_dominators: bool,
    flag_help: bool,
}
<|endoftext|>


<commit_before>use crate::types::{
    *,
    flags::*,
    generation::*,
    parsing::*,
};

use nom::{
    combinator::{flat_map, map, map_opt},
    error::context,
};

use std::io::Write;

/// Protocol metadata
pub mod metadata {
    use super::*;

    /// The name of the protocol
    pub const NAME:          &str           = "{{protocol.name}}";
    /// The major version of the protocol
    pub const MAJOR_VERSION: ShortShortUInt = {{protocol.major_version}};
    /// The minor version of the protocol
    pub const MINOR_VERSION: ShortShortUInt = {{protocol.minor_version}};
    /// The revision (version) of the protocol
    pub const REVISION:      ShortShortUInt = {{protocol.revision}};
    /// The default port of the protocol
    pub const PORT:          LongUInt       = {{protocol.port}};
    /// The copyright holding the protocol
    pub const COPYRIGHT:     &str           = r#"{{protocol.copyright}}"#;
}

/// Protocol constants
pub mod constants {
    use super::*;

    {{#each protocol.constants as |constant| ~}}
    /// {{constant.name}} (Generated)
    pub const {{sanitize_name constant.name}}: {{constant.type}} = {{constant.value}};
    {{/each ~}}
}

/// An AMQP Error
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPError {
    /// A soft AMQP error
    Soft(AMQPSoftError),
    /// A hard AMQP error
    Hard(AMQPHardError),
}

impl AMQPError {
    /// Get the id of the error
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            AMQPError::Soft(ref s) => s.get_id(),
            AMQPError::Hard(ref h) => h.get_id(),
        }
    }

    /// Get the error corresponding to an id
    pub fn from_id(id: ShortUInt) -> Option<AMQPError> {
        AMQPSoftError::from_id(id).map(AMQPError::Soft).or_else(|| AMQPHardError::from_id(id).map(AMQPError::Hard))
    }
}

/// The available soft AMQP errors
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPSoftError {
    {{#each protocol.soft_errors as |constant| ~}}
    /// {{{constant.name}}} (Generated)
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPSoftError {
    /// Get the id of the soft error
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.soft_errors as |constant| ~}}
            AMQPSoftError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    /// Get the soft error corresponding to an id
    pub fn from_id(id: ShortUInt) -> Option<AMQPSoftError> {
        match id {
            {{#each protocol.soft_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPSoftError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}

/// The available hard AMQP errors
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPHardError {
    {{#each protocol.hard_errors as |constant| ~}}
    /// {{{constant.name}}} (Generated)
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPHardError {
    /// Get the id of the hard error
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.hard_errors as |constant| ~}}
            AMQPHardError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    /// Get the hard error corresponding to an id
    pub fn from_id(id: ShortUInt) -> Option<AMQPHardError> {
        match id {
            {{#each protocol.hard_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPHardError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}

{{#each protocol.classes as |class| ~}}
use self::{{snake class.name}}::parse_{{snake class.name}};
{{/each ~}}

/// Parse an AMQP class
pub fn parse_class(i: &[u8]) -> ParserResult<'_, AMQPClass> {
    context("parse_class", map_opt(flat_map(parse_id, |id| move |i| match id {
        {{#each protocol.classes as |class| ~}}
        {{class.id}} => map(map(parse_{{snake class.name false}}, AMQPClass::{{camel class.name}}), Some)(i),
        {{/each ~}}
        _ => Ok((i, None)),
    }), std::convert::identity))(i)
}

/// Serialize an AMQP class
pub fn gen_class<'a, W: Write + BackToTheBuffer + 'a>(class: &'a AMQPClass) -> impl SerializeFn<W> + 'a {
    move |input| match *class {
        {{#each protocol.classes as |class| ~}}
        AMQPClass::{{camel class.name}}(ref {{snake class.name}}) => {{snake class.name}}::gen_{{snake class.name false}}({{snake class.name}})(input),
        {{/each ~}}
    }
}

/// The available AMQP classes
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPClass {
    {{#each protocol.classes as |class| ~}}
    /// {{class.name}} (Generated)
    {{camel class.name}}({{snake class.name}}::AMQPMethod),
    {{/each ~}}
}

impl AMQPClass {
    /// Get the AMQP class id (Generated)
    pub fn get_amqp_class_id(&self) -> u16 {
        match self {
            {{#each protocol.classes as |class| ~}}
            AMQPClass::{{camel class.name}}(_) => {{class.id}},
            {{/each ~}}
        }
    }
}

{{#each protocol.classes as |class|}}
/// {{class.name}} (generated)
pub mod {{snake class.name}} {
    use super::*;

    /// Parse {{class.name}} (Generated)
    pub fn parse_{{snake class.name false}}(i: &[u8]) -> ParserResult<'_, {{snake class.name}}::AMQPMethod> {
        context("parse_{{snake class.name false}}", map_opt(flat_map(parse_id, |id| move |i| match id {
            {{#each class.methods as |method| ~}}
            {{method.id}} => context("parse_{{snake method.name false}}", map(map(parse_{{snake method.name false}}, AMQPMethod::{{camel method.name}}), Some))(i),
            {{/each ~}}
            _ => Ok((i, None)),
        }), std::convert::identity))(i)
    }

    /// Serialize {{class.name}} (Generated)
    pub fn gen_{{snake class.name false}}<'a, W: Write + BackToTheBuffer + 'a>(method: &'a AMQPMethod) -> impl SerializeFn<W> + 'a {
        cookie_factory::sequence::pair(
            gen_id({{class.id}}),
            move |input| match *method {
                {{#each class.methods as |method| ~}}
                AMQPMethod::{{camel method.name}}(ref {{snake method.name}}) => {
                    gen_{{snake method.name false}}({{snake method.name}})(input)
                },
                {{/each ~}}
            }
        )
    }

    /// The available methods in {{class.name}}
    #[derive(Clone, Debug, PartialEq)]
    pub enum AMQPMethod {
        {{#each class.methods as |method| ~}}
        /// {{method.name}} (Generated)
        {{camel method.name}}({{camel method.name}}),
        {{/each ~}}
    }

    {{#each class.methods as |method|}}
    /// {{method.name}} (Generated)
    #[derive(Clone, Debug, Default, PartialEq)]
    pub struct {{camel method.name}} {
        {{#each_argument method.arguments as |argument| ~}}
        {{#if @argument_is_value ~}}
        {{#unless argument.force_default ~}}
        /// {{argument.name}} (Generated)
        pub {{snake argument.name}}: {{argument.type}},
        {{/unless ~}}
        {{else}}
        {{#unless argument.ignore_flags ~}}
        {{#each argument.flags as |flag| ~}}
        {{#unless flag.force_default ~}}
        /// {{flag.name}} (Generated)
        pub {{snake flag.name}}: Boolean,
        {{/unless ~}}
        {{/each ~}}
        {{/unless ~}}
        {{/if ~}}
        {{/each_argument ~}}
    }

    impl {{camel method.name}} {
        /// Get the AMQP class id for {{method.name}} (Generated)
        pub fn get_amqp_class_id(&self) -> u16 {
            {{class.id}}
        }

        /// Get the AMQP method id for {{method.name}} (Generated)
        pub fn get_amqp_method_id(&self) -> u16 {
            {{method.id}}
        }
    }

    /// Parse {{method.name}} (Generated)
    pub fn parse_{{snake method.name false}}(i: &[u8]) -> ParserResult<'_, {{camel method.name}}> {
        {{#each_argument method.arguments as |argument| ~}}
        {{#if @argument_is_value ~}}
        let (i, {{#if argument.force_default ~}}_{{else}}{{snake argument.name}}{{/if ~}}) = parse_{{snake_type argument.type}}(i)?;
        {{else}}
        let (i, {{#if argument.ignore_flags ~}}_{{else}}flags{{/if ~}}) = parse_flags(i, &[
            {{#each argument.flags as |flag| ~}}
            "{{flag.name}}",
            {{/each ~}}
        ])?;
        {{/if ~}}
        {{/each_argument ~}}
        Ok((i, {{camel method.name}} {
            {{#each_argument method.arguments as |argument| ~}}
            {{#if @argument_is_value ~}}
            {{#unless argument.force_default ~}}
            {{snake argument.name}},
            {{/unless ~}}
            {{else}}
            {{#unless argument.ignore_flags ~}}
            {{#each argument.flags as |flag| ~}}
            {{#unless flag.force_default ~}}
            {{snake flag.name}}: flags.get_flag("{{snake flag.name}}").unwrap_or({{flag.default_value}}),
            {{/unless ~}}
            {{/each ~}}
            {{/unless ~}}
            {{/if ~}}
            {{/each_argument ~}}
        }))
    }

    /// Serialize {{method.name}} (Generated)
    pub fn gen_{{snake method.name false}}<'a, W: Write + BackToTheBuffer + 'a>({{#if method.arguments ~}}{{#if method.ignore_args ~}}_{{/if ~}}method{{else}}_{{/if ~}}: &'a {{camel method.name}}) -> impl SerializeFn<W> + 'a {
        move |mut input| {
            {{#each_argument method.arguments as |argument| ~}}
            {{#unless @argument_is_value ~}}
            let mut flags = AMQPFlags::default();
            {{#each argument.flags as |flag| ~}}
            flags.add_flag("{{snake flag.name}}".to_string(), {{#if flag.force_default ~}}{{flag.default_value}}{{else}}method.{{snake flag.name}}{{/if ~}});
            {{/each ~}}
            {{/unless ~}}
            {{/each_argument ~}}
            input = gen_id({{method.id}})(input)?;
            {{#each_argument method.arguments as |argument| ~}}
            {{#if @argument_is_value ~}}
            {{#if argument.force_default ~}}
            {{/if ~}}
            input = gen_{{snake_type argument.type}}({{#if (and (pass_by_ref argument.type) (not (use_str_ref argument.type))) ~}}&{{/if ~}}{{#if argument.force_default ~}}{{amqp_value_ref argument.default_value}}{{else}}method.{{snake argument.name}}{{#if (use_str_ref argument.type) ~}}.as_str(){{/if ~}}{{/if ~}})(input)?;
            {{else}}
            input = gen_flags(&flags)(input)?;
            {{/if ~}}
            {{/each_argument ~}}
            Ok(input)
        }
    }
    {{/each ~}}
    {{#if class.properties ~}}
    /// {{class.name}} properties (Generated)
    #[derive(Clone, Debug, PartialEq)]
    pub struct AMQPProperties {
        {{#each class.properties as |property| ~}}
        {{snake property.name}}: Option<{{property.type}}>,
        {{/each ~}}
    }

    impl Default for AMQPProperties {
        fn default() -> AMQPProperties {
            AMQPProperties {
                {{#each class.properties as |property| ~}}
                {{snake property.name}}: None,
                {{/each ~}}
            }
        }
    }

    impl AMQPProperties {
        {{#each class.properties as |property| ~}}
        /// Set {{property.name}} (Generated)
        pub fn with_{{snake property.name false}}(mut self, value: {{property.type}}) -> AMQPProperties {
            self.{{snake property.name}} = Some(value);
            self
        }
        {{/each ~}}

        {{#each class.properties as |property| ~}}
        /// Get {{property.name}} (Generated)
        pub fn {{snake property.name}}(&self) -> &Option<{{property.type}}> {
            &self.{{snake property.name}}
        }
        {{/each ~}}

        /// Get the bitpask for serialization (Generated)
        #[allow(clippy::identity_op)]
        pub fn bitmask(&self) -> ShortUInt {
            {{#each class.properties as |property| ~}}
            (if self.{{snake property.name}}.is_some() { 1 << (15 - {{@index}}) } else { 0 }) {{#unless @last ~}} + {{/unless ~}}
            {{/each ~}}
        }
    }

    /// Parse {{class.name}} properties (Generated)
    #[allow(clippy::identity_op)]
    pub fn parse_properties(i: &[u8]) -> ParserResult<'_, AMQPProperties> {
        let (i, flags) = parse_short_uint(i)?;
        {{#each class.properties as |property| ~}}
        let (i, {{snake property.name}}) = if flags & (1 << (15 - {{@index}})) != 0 { map(parse_{{snake_type property.type}}, Some)(i)? } else { (i, None) };
        {{/each ~}}
        Ok((i, AMQPProperties {
            {{#each class.properties as |property| ~}}
            {{snake property.name}},
            {{/each ~}}
        }))
    }

    /// Serialize {{class.name}} properties (Generated)
    pub fn gen_properties<'a, W: Write + BackToTheBuffer + 'a>(props: &'a AMQPProperties) -> impl SerializeFn<W> + 'a {
        cookie_factory::sequence::pair(
            gen_short_uint(props.bitmask()),
            move |mut input| {
                {{#each class.properties as |property| ~}}
                if let Some(prop) = props.{{snake property.name}}{{#if (pass_by_ref property.type) ~}}.as_ref(){{/if ~}} {
                    input = gen_{{snake_type property.type}}(prop{{#if (use_str_ref property.type) ~}}.as_str(){{/if ~}})(input)?;
                }
                {{/each ~}}
                Ok(input)
            }
        )
    }
    {{/if ~}}
}
{{/each ~}}
<commit_msg>impl Error for AMQPError<commit_after>use crate::types::{
    *,
    flags::*,
    generation::*,
    parsing::*,
};

use nom::{
    combinator::{flat_map, map, map_opt},
    error::context,
};

use std::{error, fmt, io::Write};

/// Protocol metadata
pub mod metadata {
    use super::*;

    /// The name of the protocol
    pub const NAME:          &str           = "{{protocol.name}}";
    /// The major version of the protocol
    pub const MAJOR_VERSION: ShortShortUInt = {{protocol.major_version}};
    /// The minor version of the protocol
    pub const MINOR_VERSION: ShortShortUInt = {{protocol.minor_version}};
    /// The revision (version) of the protocol
    pub const REVISION:      ShortShortUInt = {{protocol.revision}};
    /// The default port of the protocol
    pub const PORT:          LongUInt       = {{protocol.port}};
    /// The copyright holding the protocol
    pub const COPYRIGHT:     &str           = r#"{{protocol.copyright}}"#;
}

/// Protocol constants
pub mod constants {
    use super::*;

    {{#each protocol.constants as |constant| ~}}
    /// {{constant.name}} (Generated)
    pub const {{sanitize_name constant.name}}: {{constant.type}} = {{constant.value}};
    {{/each ~}}
}

/// An AMQP Error
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPError {
    /// A soft AMQP error
    Soft(AMQPSoftError),
    /// A hard AMQP error
    Hard(AMQPHardError),
}

impl AMQPError {
    /// Get the id of the error
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            AMQPError::Soft(ref s) => s.get_id(),
            AMQPError::Hard(ref h) => h.get_id(),
        }
    }

    /// Get the error corresponding to an id
    pub fn from_id(id: ShortUInt) -> Option<AMQPError> {
        AMQPSoftError::from_id(id).map(AMQPError::Soft).or_else(|| AMQPHardError::from_id(id).map(AMQPError::Hard))
    }
}

impl fmt::Display for AMQPError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            AMQPError::Soft(err) => write!(f, "AMQP soft error: {}", err),
            AMQPError::Hard(err) => write!(f, "AMQP hard error: {}", err),
        }
    }
}

impl error::Error for AMQPError {}

/// The available soft AMQP errors
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPSoftError {
    {{#each protocol.soft_errors as |constant| ~}}
    /// {{{constant.name}}} (Generated)
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPSoftError {
    /// Get the id of the soft error
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.soft_errors as |constant| ~}}
            AMQPSoftError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    /// Get the soft error corresponding to an id
    pub fn from_id(id: ShortUInt) -> Option<AMQPSoftError> {
        match id {
            {{#each protocol.soft_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPSoftError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}

impl fmt::Display for AMQPSoftError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            {{#each protocol.soft_errors as |constant| ~}}
            AMQPSoftError::{{camel constant.name}} => write!(f, "{{{constant.name}}}"),
            {{/each ~}}
        }
    }
}

impl error::Error for AMQPSoftError {}

/// The available hard AMQP errors
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPHardError {
    {{#each protocol.hard_errors as |constant| ~}}
    /// {{{constant.name}}} (Generated)
    {{camel constant.name}},
    {{/each ~}}
}

impl AMQPHardError {
    /// Get the id of the hard error
    pub fn get_id(&self) -> ShortUInt {
        match *self {
            {{#each protocol.hard_errors as |constant| ~}}
            AMQPHardError::{{camel constant.name}} => {{constant.value}},
            {{/each ~}}
        }
    }

    /// Get the hard error corresponding to an id
    pub fn from_id(id: ShortUInt) -> Option<AMQPHardError> {
        match id {
            {{#each protocol.hard_errors as |constant| ~}}
            {{constant.value}} => Some(AMQPHardError::{{camel constant.name}}),
            {{/each ~}}
            _                  => None,
        }
    }
}

impl fmt::Display for AMQPHardError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            {{#each protocol.hard_errors as |constant| ~}}
            AMQPHardError::{{camel constant.name}} => write!(f, "{{{constant.name}}}"),
            {{/each ~}}
        }
    }
}

impl error::Error for AMQPHardError {}

{{#each protocol.classes as |class| ~}}
use self::{{snake class.name}}::parse_{{snake class.name}};
{{/each ~}}

/// Parse an AMQP class
pub fn parse_class(i: &[u8]) -> ParserResult<'_, AMQPClass> {
    context("parse_class", map_opt(flat_map(parse_id, |id| move |i| match id {
        {{#each protocol.classes as |class| ~}}
        {{class.id}} => map(map(parse_{{snake class.name false}}, AMQPClass::{{camel class.name}}), Some)(i),
        {{/each ~}}
        _ => Ok((i, None)),
    }), std::convert::identity))(i)
}

/// Serialize an AMQP class
pub fn gen_class<'a, W: Write + BackToTheBuffer + 'a>(class: &'a AMQPClass) -> impl SerializeFn<W> + 'a {
    move |input| match *class {
        {{#each protocol.classes as |class| ~}}
        AMQPClass::{{camel class.name}}(ref {{snake class.name}}) => {{snake class.name}}::gen_{{snake class.name false}}({{snake class.name}})(input),
        {{/each ~}}
    }
}

/// The available AMQP classes
#[derive(Clone, Debug, PartialEq)]
pub enum AMQPClass {
    {{#each protocol.classes as |class| ~}}
    /// {{class.name}} (Generated)
    {{camel class.name}}({{snake class.name}}::AMQPMethod),
    {{/each ~}}
}

impl AMQPClass {
    /// Get the AMQP class id (Generated)
    pub fn get_amqp_class_id(&self) -> u16 {
        match self {
            {{#each protocol.classes as |class| ~}}
            AMQPClass::{{camel class.name}}(_) => {{class.id}},
            {{/each ~}}
        }
    }
}

{{#each protocol.classes as |class|}}
/// {{class.name}} (generated)
pub mod {{snake class.name}} {
    use super::*;

    /// Parse {{class.name}} (Generated)
    pub fn parse_{{snake class.name false}}(i: &[u8]) -> ParserResult<'_, {{snake class.name}}::AMQPMethod> {
        context("parse_{{snake class.name false}}", map_opt(flat_map(parse_id, |id| move |i| match id {
            {{#each class.methods as |method| ~}}
            {{method.id}} => context("parse_{{snake method.name false}}", map(map(parse_{{snake method.name false}}, AMQPMethod::{{camel method.name}}), Some))(i),
            {{/each ~}}
            _ => Ok((i, None)),
        }), std::convert::identity))(i)
    }

    /// Serialize {{class.name}} (Generated)
    pub fn gen_{{snake class.name false}}<'a, W: Write + BackToTheBuffer + 'a>(method: &'a AMQPMethod) -> impl SerializeFn<W> + 'a {
        cookie_factory::sequence::pair(
            gen_id({{class.id}}),
            move |input| match *method {
                {{#each class.methods as |method| ~}}
                AMQPMethod::{{camel method.name}}(ref {{snake method.name}}) => {
                    gen_{{snake method.name false}}({{snake method.name}})(input)
                },
                {{/each ~}}
            }
        )
    }

    /// The available methods in {{class.name}}
    #[derive(Clone, Debug, PartialEq)]
    pub enum AMQPMethod {
        {{#each class.methods as |method| ~}}
        /// {{method.name}} (Generated)
        {{camel method.name}}({{camel method.name}}),
        {{/each ~}}
    }

    {{#each class.methods as |method|}}
    /// {{method.name}} (Generated)
    #[derive(Clone, Debug, Default, PartialEq)]
    pub struct {{camel method.name}} {
        {{#each_argument method.arguments as |argument| ~}}
        {{#if @argument_is_value ~}}
        {{#unless argument.force_default ~}}
        /// {{argument.name}} (Generated)
        pub {{snake argument.name}}: {{argument.type}},
        {{/unless ~}}
        {{else}}
        {{#unless argument.ignore_flags ~}}
        {{#each argument.flags as |flag| ~}}
        {{#unless flag.force_default ~}}
        /// {{flag.name}} (Generated)
        pub {{snake flag.name}}: Boolean,
        {{/unless ~}}
        {{/each ~}}
        {{/unless ~}}
        {{/if ~}}
        {{/each_argument ~}}
    }

    impl {{camel method.name}} {
        /// Get the AMQP class id for {{method.name}} (Generated)
        pub fn get_amqp_class_id(&self) -> u16 {
            {{class.id}}
        }

        /// Get the AMQP method id for {{method.name}} (Generated)
        pub fn get_amqp_method_id(&self) -> u16 {
            {{method.id}}
        }
    }

    /// Parse {{method.name}} (Generated)
    pub fn parse_{{snake method.name false}}(i: &[u8]) -> ParserResult<'_, {{camel method.name}}> {
        {{#each_argument method.arguments as |argument| ~}}
        {{#if @argument_is_value ~}}
        let (i, {{#if argument.force_default ~}}_{{else}}{{snake argument.name}}{{/if ~}}) = parse_{{snake_type argument.type}}(i)?;
        {{else}}
        let (i, {{#if argument.ignore_flags ~}}_{{else}}flags{{/if ~}}) = parse_flags(i, &[
            {{#each argument.flags as |flag| ~}}
            "{{flag.name}}",
            {{/each ~}}
        ])?;
        {{/if ~}}
        {{/each_argument ~}}
        Ok((i, {{camel method.name}} {
            {{#each_argument method.arguments as |argument| ~}}
            {{#if @argument_is_value ~}}
            {{#unless argument.force_default ~}}
            {{snake argument.name}},
            {{/unless ~}}
            {{else}}
            {{#unless argument.ignore_flags ~}}
            {{#each argument.flags as |flag| ~}}
            {{#unless flag.force_default ~}}
            {{snake flag.name}}: flags.get_flag("{{snake flag.name}}").unwrap_or({{flag.default_value}}),
            {{/unless ~}}
            {{/each ~}}
            {{/unless ~}}
            {{/if ~}}
            {{/each_argument ~}}
        }))
    }

    /// Serialize {{method.name}} (Generated)
    pub fn gen_{{snake method.name false}}<'a, W: Write + BackToTheBuffer + 'a>({{#if method.arguments ~}}{{#if method.ignore_args ~}}_{{/if ~}}method{{else}}_{{/if ~}}: &'a {{camel method.name}}) -> impl SerializeFn<W> + 'a {
        move |mut input| {
            {{#each_argument method.arguments as |argument| ~}}
            {{#unless @argument_is_value ~}}
            let mut flags = AMQPFlags::default();
            {{#each argument.flags as |flag| ~}}
            flags.add_flag("{{snake flag.name}}".to_string(), {{#if flag.force_default ~}}{{flag.default_value}}{{else}}method.{{snake flag.name}}{{/if ~}});
            {{/each ~}}
            {{/unless ~}}
            {{/each_argument ~}}
            input = gen_id({{method.id}})(input)?;
            {{#each_argument method.arguments as |argument| ~}}
            {{#if @argument_is_value ~}}
            {{#if argument.force_default ~}}
            {{/if ~}}
            input = gen_{{snake_type argument.type}}({{#if (and (pass_by_ref argument.type) (not (use_str_ref argument.type))) ~}}&{{/if ~}}{{#if argument.force_default ~}}{{amqp_value_ref argument.default_value}}{{else}}method.{{snake argument.name}}{{#if (use_str_ref argument.type) ~}}.as_str(){{/if ~}}{{/if ~}})(input)?;
            {{else}}
            input = gen_flags(&flags)(input)?;
            {{/if ~}}
            {{/each_argument ~}}
            Ok(input)
        }
    }
    {{/each ~}}
    {{#if class.properties ~}}
    /// {{class.name}} properties (Generated)
    #[derive(Clone, Debug, PartialEq)]
    pub struct AMQPProperties {
        {{#each class.properties as |property| ~}}
        {{snake property.name}}: Option<{{property.type}}>,
        {{/each ~}}
    }

    impl Default for AMQPProperties {
        fn default() -> AMQPProperties {
            AMQPProperties {
                {{#each class.properties as |property| ~}}
                {{snake property.name}}: None,
                {{/each ~}}
            }
        }
    }

    impl AMQPProperties {
        {{#each class.properties as |property| ~}}
        /// Set {{property.name}} (Generated)
        pub fn with_{{snake property.name false}}(mut self, value: {{property.type}}) -> AMQPProperties {
            self.{{snake property.name}} = Some(value);
            self
        }
        {{/each ~}}

        {{#each class.properties as |property| ~}}
        /// Get {{property.name}} (Generated)
        pub fn {{snake property.name}}(&self) -> &Option<{{property.type}}> {
            &self.{{snake property.name}}
        }
        {{/each ~}}

        /// Get the bitpask for serialization (Generated)
        #[allow(clippy::identity_op)]
        pub fn bitmask(&self) -> ShortUInt {
            {{#each class.properties as |property| ~}}
            (if self.{{snake property.name}}.is_some() { 1 << (15 - {{@index}}) } else { 0 }) {{#unless @last ~}} + {{/unless ~}}
            {{/each ~}}
        }
    }

    /// Parse {{class.name}} properties (Generated)
    #[allow(clippy::identity_op)]
    pub fn parse_properties(i: &[u8]) -> ParserResult<'_, AMQPProperties> {
        let (i, flags) = parse_short_uint(i)?;
        {{#each class.properties as |property| ~}}
        let (i, {{snake property.name}}) = if flags & (1 << (15 - {{@index}})) != 0 { map(parse_{{snake_type property.type}}, Some)(i)? } else { (i, None) };
        {{/each ~}}
        Ok((i, AMQPProperties {
            {{#each class.properties as |property| ~}}
            {{snake property.name}},
            {{/each ~}}
        }))
    }

    /// Serialize {{class.name}} properties (Generated)
    pub fn gen_properties<'a, W: Write + BackToTheBuffer + 'a>(props: &'a AMQPProperties) -> impl SerializeFn<W> + 'a {
        cookie_factory::sequence::pair(
            gen_short_uint(props.bitmask()),
            move |mut input| {
                {{#each class.properties as |property| ~}}
                if let Some(prop) = props.{{snake property.name}}{{#if (pass_by_ref property.type) ~}}.as_ref(){{/if ~}} {
                    input = gen_{{snake_type property.type}}(prop{{#if (use_str_ref property.type) ~}}.as_str(){{/if ~}})(input)?;
                }
                {{/each ~}}
                Ok(input)
            }
        )
    }
    {{/if ~}}
}
{{/each ~}}
<|endoftext|>


<commit_before>use core::cmp::{Eq, Ord};
use std::list;
use std::list::{List, Cons, Nil};

/**
 * A purely functional Pairing Heap [FSST86]
 *
 * Our implementation uses Linked List (cons cells) so may not be the
 * fastest way to implement this in Rust.
 *
 * This implementation is a port of the Standard ML found in Okasaki's
 * Purely Functional Data Structures.
 */
pub enum PairingHeap<E: Copy Eq Ord> {
  Empty_,
  PairingHeap_(@{
    head: E,
    rest: @List<PairingHeap<E>>
  })
}

pub trait Heap<E: Copy Eq Ord> {
  // returns true if the Heap is empty.
  pure fn is_empty(&self) -> bool;

  // returns a new Heap with the element inserted.
  pure fn insert(elem: E) -> self;

  // returns the minimum element without a modified heap
  pure fn find_min() -> Option<E>;

  // returns the minimum element and a new Heap without that element.
  pure fn delete_min() -> (Option<E>, self);
}

pure fn Empty<E: Copy Eq Ord>() -> PairingHeap<E> {
  return Empty_;
}

pure fn PairingHeap<E: Copy Eq Ord>(initial_value: E) -> PairingHeap<E> {
  return PairingHeap_(@{
    head: initial_value,
    rest: @Nil
  });
}

impl<E: Copy Eq Ord> PairingHeap<E> : Eq {
  pure fn eq(other: &PairingHeap<E>) -> bool {
    match (self, *other) {
      (Empty_, Empty_) => {true}
      (PairingHeap_(heapA), PairingHeap_(heapB)) => {
        return (heapA.head == heapB.head) && (heapA.rest == heapB.rest);
      }
      //(Empty_, PairingHeap_(_)) => {false} // why are these unreachable?
      //(PairingHeap_(_), Empty) => {false}
      (_, _) => {false}
    }
  }

  pure fn ne(other: &PairingHeap<E>) -> bool { !(self).eq(other) }
}

impl<E: Copy Eq Ord> PairingHeap<E> : Heap<E> {
  pure fn is_empty(&self) -> bool {
    *self == Empty_
  }

  pure fn insert(e: E) -> PairingHeap<E> {
    return self.merge(PairingHeap(e));
  }

  pure fn find_min() -> Option<E> {
    match self {
      Empty_ => { None }
      PairingHeap_(heap) => { Some(heap.head) }
    }
  }

  pure fn delete_min() -> (Option<E>, PairingHeap<E>) {
    match self {
      Empty_ => {(None, self)}
      PairingHeap_(heap) => {(Some(heap.head), self.merge_pairs(heap.rest))}
    }
  }

  pure fn merge(other: PairingHeap<E>) -> PairingHeap<E> {
    match (self, other) {
      (Empty_, b) => { return b; }
      (a, Empty_) => { return a; }
      (x@PairingHeap_(heapA), y@PairingHeap_(heapB)) => {
        if (heapA.head.le(&heapB.head)) {
          return PairingHeap_(@{
            head: heapA.head,
            rest: @Cons(y, heapA.rest)
          });
        } else {
          return PairingHeap_(@{
            head: heapB.head,
            rest: @Cons(x, heapB.rest)
          });
        }
      }
    }
  }

  pure fn merge_pairs(heaps: @List<PairingHeap<E>>) -> PairingHeap<E> {
    match heaps {
      // Why are @-signs required for pattern matching here?
      @Cons(a, @Cons(b, xs)) => {a.merge(b).merge(self.merge_pairs(xs))}
      @Cons(elem, @Nil) => {elem}
      @Nil => {Empty()}
    }
  }
}

#[test]
fn test_heap_create() {
  let heap = PairingHeap(1);
  assert(!heap.is_empty());

  // inference fails on this without a type declaration.
  let heap : PairingHeap<()> = Empty();
  assert(heap.is_empty());
}

#[test]
fn test_heap_insert() {
  let v1 = PairingHeap(10);
  let v2 = v1.insert(1);
  let (one, v3) = v2.delete_min();
  let (ten, v4) = v3.delete_min();
  let (e, v5) = v4.delete_min();

  assert(one == Some(1));
  assert(ten == Some(10));
  assert(v4 == Empty_);
  assert(e == None);
  assert(v5 == Empty_);
}

#[test]
fn test_heap_insert_delete_interleved() {
  let v1 = PairingHeap(10);
  let (a, v2) = v1.delete_min();
  assert(a == Some(10));
  assert(v2 == Empty_);

  let v3 = v2.insert(9);
  let v4 = v3.insert(8);
  let v5 = v4.insert(11);

  let (b, v6) = v5.delete_min();
  assert(b == Some(8));

  let v7 = v6.insert(7);
  let v8 = v7.insert(12);

  let x = v8.find_min();
  assert(x == Some(7));

  let (c, v9) = v8.delete_min();
  assert(c == Some(7));

  let (d, v10) = v9.delete_min();
  assert(d == Some(9));

  let (e, v11) = v10.delete_min();
  assert(e == Some(11));

  let (f, v12) = v11.delete_min();
  assert(f == Some(12));

  let (g, v13) = v12.delete_min();
  assert(g == None);
  assert(v13 == Empty_);
}

#[test]
fn test_immutable_heap() {
  let heap = PairingHeap(10);
  let x1 = heap.insert(1);

  assert(x1.find_min() == Some(1));
  assert(heap.find_min() == Some(10));

  let (a, v1) = heap.delete_min();
  assert(a == Some(10));
  assert(v1 == Empty_);

  let (b, x2) = x1.delete_min();
  assert(b == Some(1));
  assert(x2 != Empty_);
}

<commit_msg>killing returns<commit_after>use core::cmp::{Eq, Ord};
use std::list;
use std::list::{List, Cons, Nil};

/**
 * A purely functional Pairing Heap [FSST86]
 *
 * Our implementation uses Linked List (cons cells) so may not be the
 * fastest way to implement this in Rust.
 *
 * This implementation is a port of the Standard ML found in Okasaki's
 * Purely Functional Data Structures.
 */
pub enum PairingHeap<E: Copy Eq Ord> {
  Empty_,
  PairingHeap_(@{
    head: E,
    rest: @List<PairingHeap<E>>
  })
}

pub trait Heap<E: Copy Eq Ord> {
  // returns true if the Heap is empty.
  pure fn is_empty(&self) -> bool;

  // returns a new Heap with the element inserted.
  pure fn insert(elem: E) -> self;

  // returns the minimum element without a modified heap
  pure fn find_min() -> Option<E>;

  // returns the minimum element and a new Heap without that element.
  pure fn delete_min() -> (Option<E>, self);
}

pure fn Empty<E: Copy Eq Ord>() -> PairingHeap<E> {
  Empty_
}

pure fn PairingHeap<E: Copy Eq Ord>(initial_value: E) -> PairingHeap<E> {
  PairingHeap_(@{
    head: initial_value,
    rest: @Nil
  })
}

impl<E: Copy Eq Ord> PairingHeap<E> : Eq {
  pure fn eq(other: &PairingHeap<E>) -> bool {
    match (self, *other) {
      (Empty_, Empty_) => {true}
      (PairingHeap_(heapA), PairingHeap_(heapB)) => {
        (heapA.head == heapB.head) && (heapA.rest == heapB.rest)
      }
      //(Empty_, PairingHeap_(_)) => {false} // why are these unreachable?
      //(PairingHeap_(_), Empty) => {false}
      (_, _) => {false}
    }
  }

  pure fn ne(other: &PairingHeap<E>) -> bool { !(self).eq(other) }
}

impl<E: Copy Eq Ord> PairingHeap<E> : Heap<E> {
  pure fn is_empty(&self) -> bool {
    *self == Empty_
  }

  pure fn insert(e: E) -> PairingHeap<E> {
    self.merge(PairingHeap(e))
  }

  pure fn find_min() -> Option<E> {
    match self {
      Empty_ => { None }
      PairingHeap_(heap) => { Some(heap.head) }
    }
  }

  pure fn delete_min() -> (Option<E>, PairingHeap<E>) {
    match self {
      Empty_ => {(None, self)}
      PairingHeap_(heap) => {(Some(heap.head), self.merge_pairs(heap.rest))}
    }
  }

  pure fn merge(other: PairingHeap<E>) -> PairingHeap<E> {
    match (self, other) {
      (Empty_, b) => { b }
      (a, Empty_) => { a }
      (x@PairingHeap_(heapA), y@PairingHeap_(heapB)) => {
        if (heapA.head.le(&heapB.head)) {
          PairingHeap_(@{
            head: heapA.head,
            rest: @Cons(y, heapA.rest)
          })
        } else {
          PairingHeap_(@{
            head: heapB.head,
            rest: @Cons(x, heapB.rest)
          })
        }
      }
    }
  }

  pure fn merge_pairs(heaps: @List<PairingHeap<E>>) -> PairingHeap<E> {
    match heaps {
      // Why are @-signs required for pattern matching here?
      @Cons(a, @Cons(b, xs)) => {a.merge(b).merge(self.merge_pairs(xs))}
      @Cons(elem, @Nil) => {elem}
      @Nil => {Empty()}
    }
  }
}

#[test]
fn test_heap_create() {
  let heap = PairingHeap(1);
  assert(!heap.is_empty());

  // inference fails on this without a type declaration.
  let heap : PairingHeap<()> = Empty();
  assert(heap.is_empty());
}

#[test]
fn test_heap_insert() {
  let v1 = PairingHeap(10);
  let v2 = v1.insert(1);
  let (one, v3) = v2.delete_min();
  let (ten, v4) = v3.delete_min();
  let (e, v5) = v4.delete_min();

  assert(one == Some(1));
  assert(ten == Some(10));
  assert(v4 == Empty_);
  assert(e == None);
  assert(v5 == Empty_);
}

#[test]
fn test_heap_insert_delete_interleved() {
  let v1 = PairingHeap(10);
  let (a, v2) = v1.delete_min();
  assert(a == Some(10));
  assert(v2 == Empty_);

  let v3 = v2.insert(9);
  let v4 = v3.insert(8);
  let v5 = v4.insert(11);

  let (b, v6) = v5.delete_min();
  assert(b == Some(8));

  let v7 = v6.insert(7);
  let v8 = v7.insert(12);

  let x = v8.find_min();
  assert(x == Some(7));

  let (c, v9) = v8.delete_min();
  assert(c == Some(7));

  let (d, v10) = v9.delete_min();
  assert(d == Some(9));

  let (e, v11) = v10.delete_min();
  assert(e == Some(11));

  let (f, v12) = v11.delete_min();
  assert(f == Some(12));

  let (g, v13) = v12.delete_min();
  assert(g == None);
  assert(v13 == Empty_);
}

#[test]
fn test_immutable_heap() {
  let heap = PairingHeap(10);
  let x1 = heap.insert(1);

  assert(x1.find_min() == Some(1));
  assert(heap.find_min() == Some(10));

  let (a, v1) = heap.delete_min();
  assert(a == Some(10));
  assert(v1 == Empty_);

  let (b, x2) = x1.delete_min();
  assert(b == Some(1));
  assert(x2 != Empty_);
}

<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::link;
use super::write;
use rustc::session::{mod, config};
use llvm;
use llvm::archive_ro::ArchiveRO;
use llvm::{ModuleRef, TargetMachineRef, True, False};
use rustc::metadata::cstore;
use rustc::util::common::time;

use libc;
use flate;

use std::iter;
use std::mem;
use std::num::Int;

pub fn run(sess: &session::Session, llmod: ModuleRef,
           tm: TargetMachineRef, reachable: &[String]) {
    if sess.opts.cg.prefer_dynamic {
        sess.err("cannot prefer dynamic linking when performing LTO");
        sess.note("only 'staticlib' and 'bin' outputs are supported with LTO");
        sess.abort_if_errors();
    }

    // Make sure we actually can run LTO
    for crate_type in sess.crate_types.borrow().iter() {
        match *crate_type {
            config::CrateTypeExecutable | config::CrateTypeStaticlib => {}
            _ => {
                sess.fatal("lto can only be run for executables and \
                            static library outputs");
            }
        }
    }

    // For each of our upstream dependencies, find the corresponding rlib and
    // load the bitcode from the archive. Then merge it into the current LLVM
    // module that we've got.
    let crates = sess.cstore.get_used_crates(cstore::RequireStatic);
    for (cnum, path) in crates.into_iter() {
        let name = sess.cstore.get_crate_data(cnum).name.clone();
        let path = match path {
            Some(p) => p,
            None => {
                sess.fatal(format!("could not find rlib for: `{}`",
                                   name).as_slice());
            }
        };

        let archive = ArchiveRO::open(&path).expect("wanted an rlib");
        let file = path.filename_str().unwrap();
        let file = file.slice(3, file.len() - 5); // chop off lib/.rlib
        debug!("reading {}", file);
        for i in iter::count(0u, 1) {
            let bc_encoded = time(sess.time_passes(),
                                  format!("check for {}.{}.bytecode.deflate", name, i).as_slice(),
                                  (),
                                  |_| {
                                      archive.read(format!("{}.{}.bytecode.deflate",
                                                           file, i).as_slice())
                                  });
            let bc_encoded = match bc_encoded {
                Some(data) => data,
                None => {
                    if i == 0 {
                        // No bitcode was found at all.
                        sess.fatal(format!("missing compressed bytecode in {}",
                                           path.display()).as_slice());
                    }
                    // No more bitcode files to read.
                    break;
                },
            };
            let bc_extractor = if is_versioned_bytecode_format(bc_encoded) {
                |_| {
                    // Read the version
                    let version = extract_bytecode_format_version(bc_encoded);

                    if version == 1 {
                        // The only version existing so far
                        let data_size = extract_compressed_bytecode_size_v1(bc_encoded);
                        let compressed_data = bc_encoded[
                            link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET..
                            link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as uint];

                        match flate::inflate_bytes(compressed_data) {
                            Some(inflated) => inflated,
                            None => {
                                sess.fatal(format!("failed to decompress bc of `{}`",
                                                   name).as_slice())
                            }
                        }
                    } else {
                        sess.fatal(format!("Unsupported bytecode format version {}",
                                           version).as_slice())
                    }
                }
            } else {
                // the object must be in the old, pre-versioning format, so simply
                // inflate everything and let LLVM decide if it can make sense of it
                |_| {
                    match flate::inflate_bytes(bc_encoded) {
                        Some(bc) => bc,
                        None => {
                            sess.fatal(format!("failed to decompress bc of `{}`",
                                               name).as_slice())
                        }
                    }
                }
            };

            let bc_decoded = time(sess.time_passes(),
                                  format!("decode {}.{}.bc", file, i).as_slice(),
                                  (),
                                  bc_extractor);

            let ptr = bc_decoded.as_slice().as_ptr();
            debug!("linking {}, part {}", name, i);
            time(sess.time_passes(),
                 format!("ll link {}.{}", name, i).as_slice(),
                 (),
                 |()| unsafe {
                if !llvm::LLVMRustLinkInExternalBitcode(llmod,
                                                        ptr as *const libc::c_char,
                                                        bc_decoded.len() as libc::size_t) {
                    write::llvm_err(sess.diagnostic().handler(),
                                    format!("failed to load bc of `{}`",
                                            name.as_slice()));
                }
            });
        }
    }

    // Internalize everything but the reachable symbols of the current module
    let cstrs: Vec<::std::c_str::CString> =
        reachable.iter().map(|s| s.to_c_str()).collect();
    let arr: Vec<*const i8> = cstrs.iter().map(|c| c.as_ptr()).collect();
    let ptr = arr.as_ptr();
    unsafe {
        llvm::LLVMRustRunRestrictionPass(llmod,
                                         ptr as *const *const libc::c_char,
                                         arr.len() as libc::size_t);
    }

    if sess.no_landing_pads() {
        unsafe {
            llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
        }
    }

    // Now we have one massive module inside of llmod. Time to run the
    // LTO-specific optimization passes that LLVM provides.
    //
    // This code is based off the code found in llvm's LTO code generator:
    //      tools/lto/LTOCodeGenerator.cpp
    debug!("running the pass manager");
    unsafe {
        let pm = llvm::LLVMCreatePassManager();
        llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
        "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s));

        let builder = llvm::LLVMPassManagerBuilderCreate();
        llvm::LLVMPassManagerBuilderPopulateLTOPassManager(builder, pm,
            /* Internalize = */ False,
            /* RunInliner = */ True);
        llvm::LLVMPassManagerBuilderDispose(builder);

        "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s));

        time(sess.time_passes(), "LTO passes", (), |()|
             llvm::LLVMRunPassManager(pm, llmod));

        llvm::LLVMDisposePassManager(pm);
    }
    debug!("lto done");
}

fn is_versioned_bytecode_format(bc: &[u8]) -> bool {
    let magic_id_byte_count = link::RLIB_BYTECODE_OBJECT_MAGIC.len();
    return bc.len() > magic_id_byte_count &&
           bc[..magic_id_byte_count] == link::RLIB_BYTECODE_OBJECT_MAGIC;
}

fn extract_bytecode_format_version(bc: &[u8]) -> u32 {
    return read_from_le_bytes::<u32>(bc, link::RLIB_BYTECODE_OBJECT_VERSION_OFFSET);
}

fn extract_compressed_bytecode_size_v1(bc: &[u8]) -> u64 {
    return read_from_le_bytes::<u64>(bc, link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET);
}

fn read_from_le_bytes<T: Int>(bytes: &[u8], position_in_bytes: uint) -> T {
    let byte_data = bytes[position_in_bytes..
                          position_in_bytes + mem::size_of::<T>()];
    let data = unsafe {
        *(byte_data.as_ptr() as *const T)
    };

    Int::from_le(data)
}

<commit_msg>librustc_trans: fix fallout<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::link;
use super::write;
use rustc::session::{mod, config};
use llvm;
use llvm::archive_ro::ArchiveRO;
use llvm::{ModuleRef, TargetMachineRef, True, False};
use rustc::metadata::cstore;
use rustc::util::common::time;

use libc;
use flate;

use std::iter;
use std::mem;
use std::num::Int;

pub fn run(sess: &session::Session, llmod: ModuleRef,
           tm: TargetMachineRef, reachable: &[String]) {
    if sess.opts.cg.prefer_dynamic {
        sess.err("cannot prefer dynamic linking when performing LTO");
        sess.note("only 'staticlib' and 'bin' outputs are supported with LTO");
        sess.abort_if_errors();
    }

    // Make sure we actually can run LTO
    for crate_type in sess.crate_types.borrow().iter() {
        match *crate_type {
            config::CrateTypeExecutable | config::CrateTypeStaticlib => {}
            _ => {
                sess.fatal("lto can only be run for executables and \
                            static library outputs");
            }
        }
    }

    // For each of our upstream dependencies, find the corresponding rlib and
    // load the bitcode from the archive. Then merge it into the current LLVM
    // module that we've got.
    let crates = sess.cstore.get_used_crates(cstore::RequireStatic);
    for (cnum, path) in crates.into_iter() {
        let name = sess.cstore.get_crate_data(cnum).name.clone();
        let path = match path {
            Some(p) => p,
            None => {
                sess.fatal(format!("could not find rlib for: `{}`",
                                   name).as_slice());
            }
        };

        let archive = ArchiveRO::open(&path).expect("wanted an rlib");
        let file = path.filename_str().unwrap();
        let file = file.slice(3, file.len() - 5); // chop off lib/.rlib
        debug!("reading {}", file);
        for i in iter::count(0u, 1) {
            let bc_encoded = time(sess.time_passes(),
                                  format!("check for {}.{}.bytecode.deflate", name, i).as_slice(),
                                  (),
                                  |_| {
                                      archive.read(format!("{}.{}.bytecode.deflate",
                                                           file, i).as_slice())
                                  });
            let bc_encoded = match bc_encoded {
                Some(data) => data,
                None => {
                    if i == 0 {
                        // No bitcode was found at all.
                        sess.fatal(format!("missing compressed bytecode in {}",
                                           path.display()).as_slice());
                    }
                    // No more bitcode files to read.
                    break;
                },
            };

            let bc_decoded = if is_versioned_bytecode_format(bc_encoded) {
                time(sess.time_passes(), format!("decode {}.{}.bc", file, i).as_slice(), (), |_| {
                    // Read the version
                    let version = extract_bytecode_format_version(bc_encoded);

                    if version == 1 {
                        // The only version existing so far
                        let data_size = extract_compressed_bytecode_size_v1(bc_encoded);
                        let compressed_data = bc_encoded[
                            link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET..
                            link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as uint];

                        match flate::inflate_bytes(compressed_data) {
                            Some(inflated) => inflated,
                            None => {
                                sess.fatal(format!("failed to decompress bc of `{}`",
                                                   name).as_slice())
                            }
                        }
                    } else {
                        sess.fatal(format!("Unsupported bytecode format version {}",
                                           version).as_slice())
                    }
                })
            } else {
                time(sess.time_passes(), format!("decode {}.{}.bc", file, i).as_slice(), (), |_| {
                // the object must be in the old, pre-versioning format, so simply
                // inflate everything and let LLVM decide if it can make sense of it
                    match flate::inflate_bytes(bc_encoded) {
                        Some(bc) => bc,
                        None => {
                            sess.fatal(format!("failed to decompress bc of `{}`",
                                               name).as_slice())
                        }
                    }
                })
            };

            let ptr = bc_decoded.as_slice().as_ptr();
            debug!("linking {}, part {}", name, i);
            time(sess.time_passes(),
                 format!("ll link {}.{}", name, i).as_slice(),
                 (),
                 |()| unsafe {
                if !llvm::LLVMRustLinkInExternalBitcode(llmod,
                                                        ptr as *const libc::c_char,
                                                        bc_decoded.len() as libc::size_t) {
                    write::llvm_err(sess.diagnostic().handler(),
                                    format!("failed to load bc of `{}`",
                                            name.as_slice()));
                }
            });
        }
    }

    // Internalize everything but the reachable symbols of the current module
    let cstrs: Vec<::std::c_str::CString> =
        reachable.iter().map(|s| s.to_c_str()).collect();
    let arr: Vec<*const i8> = cstrs.iter().map(|c| c.as_ptr()).collect();
    let ptr = arr.as_ptr();
    unsafe {
        llvm::LLVMRustRunRestrictionPass(llmod,
                                         ptr as *const *const libc::c_char,
                                         arr.len() as libc::size_t);
    }

    if sess.no_landing_pads() {
        unsafe {
            llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
        }
    }

    // Now we have one massive module inside of llmod. Time to run the
    // LTO-specific optimization passes that LLVM provides.
    //
    // This code is based off the code found in llvm's LTO code generator:
    //      tools/lto/LTOCodeGenerator.cpp
    debug!("running the pass manager");
    unsafe {
        let pm = llvm::LLVMCreatePassManager();
        llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
        "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s));

        let builder = llvm::LLVMPassManagerBuilderCreate();
        llvm::LLVMPassManagerBuilderPopulateLTOPassManager(builder, pm,
            /* Internalize = */ False,
            /* RunInliner = */ True);
        llvm::LLVMPassManagerBuilderDispose(builder);

        "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s));

        time(sess.time_passes(), "LTO passes", (), |()|
             llvm::LLVMRunPassManager(pm, llmod));

        llvm::LLVMDisposePassManager(pm);
    }
    debug!("lto done");
}

fn is_versioned_bytecode_format(bc: &[u8]) -> bool {
    let magic_id_byte_count = link::RLIB_BYTECODE_OBJECT_MAGIC.len();
    return bc.len() > magic_id_byte_count &&
           bc[..magic_id_byte_count] == link::RLIB_BYTECODE_OBJECT_MAGIC;
}

fn extract_bytecode_format_version(bc: &[u8]) -> u32 {
    return read_from_le_bytes::<u32>(bc, link::RLIB_BYTECODE_OBJECT_VERSION_OFFSET);
}

fn extract_compressed_bytecode_size_v1(bc: &[u8]) -> u64 {
    return read_from_le_bytes::<u64>(bc, link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET);
}

fn read_from_le_bytes<T: Int>(bytes: &[u8], position_in_bytes: uint) -> T {
    let byte_data = bytes[position_in_bytes..
                          position_in_bytes + mem::size_of::<T>()];
    let data = unsafe {
        *(byte_data.as_ptr() as *const T)
    };

    Int::from_le(data)
}

<|endoftext|>


<commit_before>// Hound -- A WAV encoding and decoding library in Rust
// Copyright (C) 2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 3 of the License only.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// This example shows how to play a wav file using the cpal crate.

extern crate hound;
extern crate cpal;

use std::env;

fn main() {
    // Make a WavReader that reads the file provided as program argument.
    let fname = env::args().nth(1).expect("no file given");
    let mut reader = hound::WavReader::open(fname).unwrap();
    let spec = reader.spec().clone(); // TODO: by value might be better in this case.

    // A voice in cpal is used for playback.
    let mut voice = cpal::Voice::new();

    let mut append_data = |voice: &mut cpal::Voice| {
        let mut buffer: cpal::Buffer<u16> =
            voice.append_data(spec.channels,
                              cpal::SamplesRate(spec.sample_rate),
                              1024); // TODO: Do I know the number of samples?
        // Fill the cpal buffer with data from the wav file.
        for (dest, src) in buffer.iter_mut().zip(reader.samples::<i16>()) {
            // TODO: Without the cast, there are a lot of artefacts. This
            // suggests that samples are actually unsigned. We can find out by
            // computing the mean: if it is around 0i16, then samples are signed.
            // If it is around 32000u16, then samples are unsigned.
            *dest = src.unwrap() as u16;
        }
        // TODO: check when reader is done, then exit.
    };

    // The voice must have some data before playing for the first time.
    append_data(&mut voice);
    voice.play();

    // Then we keep providing new data until the end of the audio.
    loop {
        append_data(&mut voice); // TODO exit when done
    }
}
<commit_msg>update cpal example<commit_after>// Hound -- A WAV encoding and decoding library in Rust
// Copyright (C) 2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 3 of the License only.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// This example shows how to play a wav file using the cpal crate.

extern crate hound;
extern crate cpal;

use std::env;
use std::thread;

fn main() {
    // Make a WavReader that reads the file provided as program argument.
    let fname = env::args().nth(1).expect("no file given");
    let mut reader = hound::WavReader::open(fname).unwrap();
    let spec = reader.spec().clone(); // TODO: by value might be better in this case.

    // A voice in cpal is used for playback.
    let mut voice = cpal::Voice::new();

    let mut append_data = |voice: &mut cpal::Voice| {
        let mut samples = reader.samples::<i16>();
        let samples_left = samples.size_hint().0; // TODO: add method to reader?

        if samples_left == 0 { return false; }

        println!("still going, {} samples left", samples_left);

        let mut buffer: cpal::Buffer<u16> =
            voice.append_data(spec.channels,
                              cpal::SamplesRate(spec.sample_rate),
                              samples_left);
        // Fill the cpal buffer with data from the wav file.
        for (dest, src) in buffer.iter_mut().zip(&mut samples) {
            // TODO: There is a bug in cpal that handles signed samples in the
            // wrong manner, so we cast it to `u16` for now.
            *dest = src.unwrap() as u16;
        }

        // Probably not done, loop again.
        true
    };

    // The voice must have some data before playing for the first time.
    append_data(&mut voice);
    voice.play();

    // Then we keep providing new data until the end of the audio.
    while append_data(&mut voice) { }

    // TODO: Cpal has no function (yet) to wait for playback to complete, so
    // sleep manually.
    thread::sleep_ms(1000);
}
<|endoftext|>


<commit_before>//! An "hello world" echo server with tokio-core
//!
//! This server will create a TCP listener, accept connections in a loop, and
//! simply write back everything that's read off of each TCP connection. Each
//! TCP connection is processed concurrently with all other TCP connections, and
//! each connection will have its own buffer that it's reading in/out of.
//!
//! To see this server in action, you can run this in one terminal:
//!
//!     cargo run --example echo
//!
//! and in another terminal you can run:
//!
//!     cargo run --example connect 127.0.0.1:8080
//!
//! Each line you type in to the `connect` terminal should be echo'd back to
//! you! If you open up multiple terminals running the `connect` example you
//! should be able to see them all make progress simultaneously.

extern crate futures;
extern crate tokio_core;

use std::env;
use std::net::SocketAddr;

use futures::Future;
use futures::stream::Stream;
use tokio_core::io::{copy, Io};
use tokio_core::net::TcpListener;
use tokio_core::reactor::Core;

fn main() {
    // Allow passing an address to listen on as the first argument of this
    // program, but otherwise we'll just set up our TCP listener on
    // 127.0.0.1:8080 for connections.
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse::<SocketAddr>().unwrap();

    // First up we'll create the event loop that's going to drive this server.
    // This is done by creating an instance of the `Core` type, tokio-core's
    // event loop. Most functions in tokio-core return an `io::Result`, and
    // `Core::new` is no exception. For this example, though, we're mostly just
    // ignoring errors, so we unwrap the return value.
    //
    // After the event loop is created we acquire a handle to it through the
    // `handle` method. With this handle we'll then later be able to create I/O
    // objects and spawn futures.
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    // Next up we create a TCP listener which will listen for incoming
    // connections. This TCP listener is bound to the address we determined
    // above and must be associated with an event loop, so we pass in a handle
    // to our event loop. After the socket's created we inform that we're ready
    // to go and start accepting connections.
    let socket = TcpListener::bind(&addr, &handle).unwrap();
    println!("Listening on: {}", addr);

    // Here we convert the `TcpListener` to a stream of incoming connections
    // with the `incoming` method. We then define how to process each element in
    // the stream with the `for_each` method.
    //
    // This combinator, defined on the `Stream` trait, will allow us to define a
    // computation to happen for all items on the stream (in this case TCP
    // connections made to the server).  The return value of the `for_each`
    // method is itself a future representing processing the entire stream of
    // connections, and ends up being our server.
    let done = socket.incoming().for_each(move |(socket, addr)| {

        // Once we're inside this closure this represents an accepted client
        // from our server. The `socket` is the client connection and `addr` is
        // the remote address of the client (similar to how the standard library
        // operates).
        //
        // We just want to copy all data read from the socket back onto the
        // socket itself (e.g. "echo"). We can use the standard `io::copy`
        // combinator in the `tokio-core` crate to do precisely this!
        //
        // The `copy` function takes two arguments, where to read from and where
        // to write to. We only have one argument, though, with `socket`.
        // Luckily there's a method, `Io::split`, which will split an Read/Write
        // stream into its two halves. This operation allows us to work with
        // each stream independently, such as pass them as two arguments to the
        // `copy` function.
        //
        // The `copy` function then returns a future, and this future will be
        // resolved when the copying operation is complete, resolving to the
        // amount of data that was copied.
        let (reader, writer) = socket.split();
        let amt = copy(reader, writer);

        // After our copy operation is complete we just print out some helpful
        // information.
        let msg = amt.then(move |result| {
            match result {
                Ok(amt) => println!("wrote {} bytes to {}", amt, addr),
                Err(e) => println!("error on {}: {}", addr, e),
            }

            Ok(())
        });

        // And this is where much of the magic of this server happens. We
        // crucially want all clients to make progress concurrently, rather than
        // blocking one on completion of another. To achieve this was use the
        // `spawn` function on `Handle` to essentially execute some work in the
        // background.
        //
        // This function will transfer ownership of the future (`msg` in this
        // case) to the event loop that `handle` points to. The event loop will
        // then drive the future to completion.
        //
        // Essentially here we're spawning a new task to run concurrently, which
        // will allow all of our clients to be processed concurrently.
        handle.spawn(msg);

        Ok(())
    });

    // And finally now that we've define what our server is, we run it! We
    // didn't actually do much I/O up to this point and this `Core::run` method
    // is responsible for driving the entire server to completion.
    //
    // The `run` method will return the result of the future that it's running,
    // but in our case the `done` future won't ever finish because a TCP
    // listener is never done accepting clients. That basically just means that
    // we're going to be running the server until it's killed (e.g. ctrl-c).
    core.run(done).unwrap();
}
<commit_msg>Fix typo.<commit_after>//! An "hello world" echo server with tokio-core
//!
//! This server will create a TCP listener, accept connections in a loop, and
//! simply write back everything that's read off of each TCP connection. Each
//! TCP connection is processed concurrently with all other TCP connections, and
//! each connection will have its own buffer that it's reading in/out of.
//!
//! To see this server in action, you can run this in one terminal:
//!
//!     cargo run --example echo
//!
//! and in another terminal you can run:
//!
//!     cargo run --example connect 127.0.0.1:8080
//!
//! Each line you type in to the `connect` terminal should be echo'd back to
//! you! If you open up multiple terminals running the `connect` example you
//! should be able to see them all make progress simultaneously.

extern crate futures;
extern crate tokio_core;

use std::env;
use std::net::SocketAddr;

use futures::Future;
use futures::stream::Stream;
use tokio_core::io::{copy, Io};
use tokio_core::net::TcpListener;
use tokio_core::reactor::Core;

fn main() {
    // Allow passing an address to listen on as the first argument of this
    // program, but otherwise we'll just set up our TCP listener on
    // 127.0.0.1:8080 for connections.
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse::<SocketAddr>().unwrap();

    // First up we'll create the event loop that's going to drive this server.
    // This is done by creating an instance of the `Core` type, tokio-core's
    // event loop. Most functions in tokio-core return an `io::Result`, and
    // `Core::new` is no exception. For this example, though, we're mostly just
    // ignoring errors, so we unwrap the return value.
    //
    // After the event loop is created we acquire a handle to it through the
    // `handle` method. With this handle we'll then later be able to create I/O
    // objects and spawn futures.
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    // Next up we create a TCP listener which will listen for incoming
    // connections. This TCP listener is bound to the address we determined
    // above and must be associated with an event loop, so we pass in a handle
    // to our event loop. After the socket's created we inform that we're ready
    // to go and start accepting connections.
    let socket = TcpListener::bind(&addr, &handle).unwrap();
    println!("Listening on: {}", addr);

    // Here we convert the `TcpListener` to a stream of incoming connections
    // with the `incoming` method. We then define how to process each element in
    // the stream with the `for_each` method.
    //
    // This combinator, defined on the `Stream` trait, will allow us to define a
    // computation to happen for all items on the stream (in this case TCP
    // connections made to the server).  The return value of the `for_each`
    // method is itself a future representing processing the entire stream of
    // connections, and ends up being our server.
    let done = socket.incoming().for_each(move |(socket, addr)| {

        // Once we're inside this closure this represents an accepted client
        // from our server. The `socket` is the client connection and `addr` is
        // the remote address of the client (similar to how the standard library
        // operates).
        //
        // We just want to copy all data read from the socket back onto the
        // socket itself (e.g. "echo"). We can use the standard `io::copy`
        // combinator in the `tokio-core` crate to do precisely this!
        //
        // The `copy` function takes two arguments, where to read from and where
        // to write to. We only have one argument, though, with `socket`.
        // Luckily there's a method, `Io::split`, which will split an Read/Write
        // stream into its two halves. This operation allows us to work with
        // each stream independently, such as pass them as two arguments to the
        // `copy` function.
        //
        // The `copy` function then returns a future, and this future will be
        // resolved when the copying operation is complete, resolving to the
        // amount of data that was copied.
        let (reader, writer) = socket.split();
        let amt = copy(reader, writer);

        // After our copy operation is complete we just print out some helpful
        // information.
        let msg = amt.then(move |result| {
            match result {
                Ok(amt) => println!("wrote {} bytes to {}", amt, addr),
                Err(e) => println!("error on {}: {}", addr, e),
            }

            Ok(())
        });

        // And this is where much of the magic of this server happens. We
        // crucially want all clients to make progress concurrently, rather than
        // blocking one on completion of another. To achieve this we use the
        // `spawn` function on `Handle` to essentially execute some work in the
        // background.
        //
        // This function will transfer ownership of the future (`msg` in this
        // case) to the event loop that `handle` points to. The event loop will
        // then drive the future to completion.
        //
        // Essentially here we're spawning a new task to run concurrently, which
        // will allow all of our clients to be processed concurrently.
        handle.spawn(msg);

        Ok(())
    });

    // And finally now that we've define what our server is, we run it! We
    // didn't actually do much I/O up to this point and this `Core::run` method
    // is responsible for driving the entire server to completion.
    //
    // The `run` method will return the result of the future that it's running,
    // but in our case the `done` future won't ever finish because a TCP
    // listener is never done accepting clients. That basically just means that
    // we're going to be running the server until it's killed (e.g. ctrl-c).
    core.run(done).unwrap();
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate ndarray;

use ndarray::{
    Array,
    Ix,
};

type Ix2 = (Ix, Ix);

const INPUT: &'static [u8] = include_bytes!("life.txt");
//const INPUT: &'static [u8] = include_bytes!("lifelite.txt");

const N: usize = 100;
//const N: usize = 8;

type Board = Array<u8, Ix2>;

fn parse(x: &[u8]) -> Board {
    // make a border of 0 cells
    let mut map = Array::from_elem(((N + 2) as Ix, (N + 2) as Ix), 0);
    let a: Array<u8, Ix> = x.iter().filter_map(|&b| match b {
        b'#' => Some(1),
        b'.' => Some(0),
        _ => None,
    }).collect();

    let a = a.reshape((N as Ix, N as Ix));
    map.slice_mut(s![1..-1, 1..-1]).assign(&a);
    map
}

// Rules
//
// 2 or 3 neighbors: stay alive
// 3 neighbors: birth
// otherwise: death

fn iterate(z: &mut Board, scratch: &mut Board) {
    // compute number of neighbors
    let mut neigh = scratch.view_mut();
    neigh.assign_scalar(&0);
    let neigh = neigh
    + z.slice(s![0..-2, 0..-2])
    + z.slice(s![0..-2, 1..-1])
    + z.slice(s![0..-2, 2..  ])

    + z.slice(s![1..-1, 0..-2])
    + z.slice(s![1..-1, 2..  ])

    + z.slice(s![2..  , 0..-2])
    + z.slice(s![2..  , 1..-1])
    + z.slice(s![2..  , 2..  ]);

    // birth where n = 3 and z[i] = 0,
    // survive where n = 2 || n = 3 and z[i] = 1
    {
        let mut zv = z.slice_mut(s![1..-1, 1..-1]);

        for row in 0..zv.shape()[0] {
            let row = row as Ix;
            for (i, &n) in neigh.row_iter(row).enumerate() {
                let i = i as Ix;
                if n == 3 {
                    zv[(row, i)] = 1;
                } else if n == 2 {
                    /* survive */
                } else {
                    zv[(row, i)] = 0;
                }
            }
        }
    }
}

fn turn_on_corners(z: &mut Board) {
    z.slice_mut(s![1..2, 1..2]).assign_scalar(&1);
    z.slice_mut(s![1..2, -2..-1]).assign_scalar(&1);
    z.slice_mut(s![-2..-1, 1..2]).assign_scalar(&1);
    z.slice_mut(s![-2..-1, -2..-1]).assign_scalar(&1);
}

fn render(a: &Board) {
    for row in 0..a.shape()[0] {
        for &x in a.row_iter(row) {
            if x > 0 {
                print!("#");
            } else {
                print!(".");
            }
        }
        println!("");
    }
}

fn main() {
    let mut a = parse(INPUT);
    let mut scratch = Board::zeros((N as Ix, N as Ix));
    let steps = 100;
    turn_on_corners(&mut a);
    for _ in 0..steps {
        iterate(&mut a, &mut scratch);
        turn_on_corners(&mut a);
        //render(&a);
    }
    let alive = a.iter().filter(|&&x| x > 0).count();
    println!("After {} steps there are {} cells alive", steps, alive);
}
<commit_msg>Fix warning in example<commit_after>#[macro_use]
extern crate ndarray;

use ndarray::{
    Array,
    Ix,
};

type Ix2 = (Ix, Ix);

const INPUT: &'static [u8] = include_bytes!("life.txt");
//const INPUT: &'static [u8] = include_bytes!("lifelite.txt");

const N: usize = 100;
//const N: usize = 8;

type Board = Array<u8, Ix2>;

fn parse(x: &[u8]) -> Board {
    // make a border of 0 cells
    let mut map = Array::from_elem(((N + 2) as Ix, (N + 2) as Ix), 0);
    let a: Array<u8, Ix> = x.iter().filter_map(|&b| match b {
        b'#' => Some(1),
        b'.' => Some(0),
        _ => None,
    }).collect();

    let a = a.reshape((N as Ix, N as Ix));
    map.slice_mut(s![1..-1, 1..-1]).assign(&a);
    map
}

// Rules
//
// 2 or 3 neighbors: stay alive
// 3 neighbors: birth
// otherwise: death

fn iterate(z: &mut Board, scratch: &mut Board) {
    // compute number of neighbors
    let mut neigh = scratch.view_mut();
    neigh.assign_scalar(&0);
    let neigh = neigh
    + z.slice(s![0..-2, 0..-2])
    + z.slice(s![0..-2, 1..-1])
    + z.slice(s![0..-2, 2..  ])

    + z.slice(s![1..-1, 0..-2])
    + z.slice(s![1..-1, 2..  ])

    + z.slice(s![2..  , 0..-2])
    + z.slice(s![2..  , 1..-1])
    + z.slice(s![2..  , 2..  ]);

    // birth where n = 3 and z[i] = 0,
    // survive where n = 2 || n = 3 and z[i] = 1
    {
        let mut zv = z.slice_mut(s![1..-1, 1..-1]);

        for row in 0..zv.shape()[0] {
            let row = row as Ix;
            for (i, &n) in neigh.row_iter(row).enumerate() {
                let i = i as Ix;
                if n == 3 {
                    zv[(row, i)] = 1;
                } else if n == 2 {
                    /* survive */
                } else {
                    zv[(row, i)] = 0;
                }
            }
        }
    }
}

fn turn_on_corners(z: &mut Board) {
    z.slice_mut(s![1..2, 1..2]).assign_scalar(&1);
    z.slice_mut(s![1..2, -2..-1]).assign_scalar(&1);
    z.slice_mut(s![-2..-1, 1..2]).assign_scalar(&1);
    z.slice_mut(s![-2..-1, -2..-1]).assign_scalar(&1);
}

fn render(a: &Board) {
    for row in 0..a.shape()[0] {
        for &x in a.row_iter(row) {
            if x > 0 {
                print!("#");
            } else {
                print!(".");
            }
        }
        println!("");
    }
}

fn main() {
    let mut a = parse(INPUT);
    let mut scratch = Board::zeros((N as Ix, N as Ix));
    let steps = 100;
    turn_on_corners(&mut a);
    for _ in 0..steps {
        iterate(&mut a, &mut scratch);
        turn_on_corners(&mut a);
        //render(&a);
    }
    render(&a);
    let alive = a.iter().filter(|&&x| x > 0).count();
    println!("After {} steps there are {} cells alive", steps, alive);
}
<|endoftext|>