<commit_before>//! Configuration for the zwreec compiler.
//!
//! Uses the `getopts` library to append a `getopts::Options` with compiler
//! specific flags and then creates a `Config` struct from `getopts::Matches`.
//!
//! # Usage
//!
//! This module depends on the [getopts](http://doc.rust-lang.org/getopts/getopts/index.html)
//! crate. To use it, you need to add `getopts` to your project. Read getopts'
//! [Usage](http://doc.rust-lang.org/getopts/getopts/index.html#usage) for more information.
//!
//! # Example
//!
//! The following example shows how to generate a `Config` struct from an empty
//! `getopts::Options`.
//!
//! ```
//! extern crate zwreec;
//! extern crate getopts;
//!
//! use zwreec::config;
//! use zwreec::config::Config;
//!
//!
//! fn main() {
//!     let args: Vec<String> = std::env::args().collect();
//!     let opts = config::zwreec_options(getopts::Options::new());
//!
//!     let matches = match opts.parse(&args[1..]) {
//!         Ok(m) => m,
//!         Err(f) => { panic!(f.to_string()) }
//!     };
//!
//!     let cfg = Config::from_matches(&matches);
//! }
//! ```
//!
//! # Appending this module (Development)
//!
//! To add new compiler flags for the compiler, you need to change three parts
//! in this module.
//!
//! 1. Appending the Struct
//!
//!     To store your new setting, you need to add it as a field to the `Config` struct. Here we
//!     add a new boolean `pub italics: bool` to control *italics*. Always add a field-comment.
//!
//!     ```ignore
//!     pub struct Config {
//!         /// Add easter egg to compiler
//!         pub easter_egg: bool,
//!         /// Instruct compiler to run these test-cases
//!         pub test_cases: Vec<TestCase>,
//!         /// Enables or disalbes Italics
//!         pub italics: bool,
//!     }
//!     ```
//!
//!     Now you also need to change `Config::default_config()` to provide the
//!     default value for your new field:
//!
//!     ```ignore
//!     pub fn default_config() -> Config {
//!         Config{
//!             easter_egg: true,
//!             test_cases: Vec::new(),
//!             italics: true,
//!         }
//!     }
//!     ```
//!
//! 2. Parse your flag in `from_matches()`
//!
//!     `from_matches` uses the Options `-F` and `-N` to enable or disable boolean flags.
//!     Therefore, if you added a new boolean flag, you can now simply add it to the match
//!     statement.
//!
//!     ```ignore
//!     for s in matches.opt_strs("F") {
//!         match s.as_ref() {
//!             "easter-egg" => {
//!                  cfg.easter_egg = true;
//!                  debug!("enabled easter-egg");
//!             },
//!             "italics" => {
//!                 cfg.italics = true;
//!                 debug!("enabbled italics");
//!             },
//!             _ => {
//!                 error!("Cannot enable feature {} - feature not known.", s);
//!             }
//!         }
//!     }
//!
//!     for s in matches.opt_strs("N") {
//!         match s.as_ref() {
//!             "easter-egg" => {
//!                 cfg.easter_egg = false;
//!                 debug!("disabled easter-egg");
//!             },
//!             "italics" => {
//!                 cfg.italics = false;
//!                 debug:("disalbed italics");
//!             }
//!             _ => {
//!                 error!("Cannot disable feature {} - feature not known.", s);
//!             }
//!         }
//!     }
//!     ```
//!
//! 3. Adding something that is not a boolean
//!
//!     If you need to add an option that is *not* a boolean, you will need to append the struct
//!     and `default_config()` accordingly (e.g. `pub notaflag: String,`). Then you need to add a new
//!     `getopts::Option` to `zwreec_options()`:
//!
//!     ```ignore
//! pub fn zwreec_options(mut opts: getopts::Options) -> getopts::Options {
//!     opts.optmulti("F", "feature", "", "FEAT");
//!     opts.optmulti("N", "no-feature", "enable or disable a feature (can occur multiple times).
//!                         List of supported features (default):
//!                             easter-egg (enabled)", "FEAT");
//!     opts.optflag("e", "generate-sample-zcode", "writes out a sample zcode file, input file is not used and can be omitted");
//!
//!     opts.optopt("n", "notaflag", "notaflag", "SOMETHING");
//!
//!     opts
//! }
//!     ```
//!
//!     Now you can append `Config::from_matches()` to analyse the provided matches for your new
//!     option and set the `Config` accordingly:
//!
//!     ```ignore
//!     if let s = matches.opt_str("n") {
//!         cfg.notaflag = s;
//!     }
//!     ```
//!
//! 4. Now you can use the new flag inside the compiler.
use getopts;

use std::vec::Vec;

/// Represents the configuration for the compiler.
///
/// This struct is created using either `config::default_config()` or
/// `config::parse_matches(matches: &getopts::Matches)`. It contains a series
/// of fields that can be used to control the behaviour of the compiler.
///
/// # Example Usage inside the compiler
///
/// ```
/// # use zwreec::config;
/// let cfg = config::Config::default_config();
///
/// if cfg.easter_egg {
///     println!("Egg!");
/// }
/// ```
pub struct Config {
    /// Force compilation despite errors
    pub force: bool,
    /// Add easter egg to compiler
    pub easter_egg: bool,
    pub force_unicode: bool,
    /// Instruct compiler to run these test-cases
    pub test_cases: Vec<TestCase>,
}

impl Config {
    /// Returns a `Config` struct with preset defaults
    ///
    /// # Example
    ///
    /// ```
    /// use zwreec::config::Config;
    /// let cfg = Config::default_config();
    /// ```
    pub fn default_config() -> Config {
        Config{
            force: false,
            easter_egg: true,
            force_unicode: false,
            test_cases: Vec::new(),
        }
    }

    /// Returns a `Config` struct by using `getopts::Matches` to set the fields.
    ///
    /// This method analyses a `getopts::Matches` for fields provided by
    /// `zwreec_options()`.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate getopts;
    /// # extern crate zwreec;
    /// let args: Vec<String> = std::env::args().collect();
    /// let opts = zwreec::config::zwreec_options(getopts::Options::new());
    ///
    /// let matches = match opts.parse(&args[1..]) {
    ///     Ok(m) => m,
    ///     Err(f) => { panic!(f.to_string()) }
    /// };
    ///
    /// let cfg = zwreec::config::Config::from_matches(&matches);
    /// ```
    pub fn from_matches(matches: &getopts::Matches) -> Config {
        // load defaults
        let mut cfg = Config::default_config();

        if matches.opt_present("generate-sample-zcode") {
            cfg.test_cases.push(TestCase::ZcodeBackend);
        }

        if matches.opt_present("f") {
            cfg.force = true;
        }

        // TODO: Find a way to make these two loops somewhat less.. repetitive
        for s in matches.opt_strs("F") {
            match s.as_ref() {
                "easter-egg" => {
                     cfg.easter_egg = true;
                     debug!("enabled easter-egg");
                },
                "force-unicode" => {
                     cfg.force_unicode = true;
                     debug!("enabled force-unicode");
                },
                _ => {
                    error!("Cannot enable feature {} - feature not known.", s);
                }
            }
        }

        for s in matches.opt_strs("N") {
            match s.as_ref() {
                "easter-egg" => {
                    cfg.easter_egg = false;
                    debug!("disabled easter-egg");
                },
                "force-unicode" => {
                     cfg.force_unicode = false;
                     debug!("enabled force-unicode");
                },
                _ => {
                    error!("Cannot disable feature {} - feature not known.", s);
                }
            }
        }

        cfg
    }
}

// TODO: If this stays only one Test Case, enum should be removed
/// The Type used to define backend tests for the compiler
#[derive(PartialEq)]
pub enum TestCase {
    /// Skips the normal compiler chain and builds an example zcode file by
    /// using every opcode.
    ZcodeBackend,
}

/// Appends a `getopts::Options` with compiler specific flags
///
/// The method `Config::from_matches()` looks for very specific `getopts::Matches`.
/// This function takes an `getopts::Options` to append it with Options required
/// by `from_matches`. It currently adds three fields:
///
/// ```ignore
/// opts.optmulti("F", "feature", "", "FEAT");
/// opts.optmulti("N", "no-feature", "enable or disable a feature (can occur multiple times).
///                     List of supported features (default):
///                         easter-egg (enabled)", "FEAT");
/// opts.optflag("e", "generate-sample-zcode", "writes out a sample zcode file, input file is not used and can be omitted");
/// ```
///
/// # Example
///
/// You can use this function to append your `getopts::Options`.
///
/// ```
/// # extern crate getopts;
/// # extern crate zwreec;
///
/// let mut opts = getopts::Options::new();
/// opts.optflag("h", "help", "print this message");
///
/// let opts = zwreec::config::zwreec_options(opts);
/// ```
///
/// Another useful example is to use it to gernerate a more compact usage by
/// having a function that only returns your options.
///
/// ```
/// # extern crate getopts;
/// # extern crate zwreec;
///
/// fn options() -> getopts::Options {
///     let mut opts = getopts::Options::new();
///     opts.optflag("h", "help", "display this help and exit");
///     opts.optflag("V", "version", "display version");
///
///     opts
/// }
///
/// fn print_usage(program: &str, verbose: bool) {
///     let brief = format!("Usage: {} [options]", program);
///
///     let opts = if verbose {
///         zwreec::config::zwreec_options(options())
///     } else {
///         options()
///     };
///
///     print!("{}", opts.usage(&brief));
/// }
/// ```
/// As you can see, `options()` returns your own command line options, which are then conditionally
/// expanded by using `zwreec_options()`.
pub fn zwreec_options(mut opts: getopts::Options) -> getopts::Options {
    opts.optflag("f", "force", "Force opening of output file");
    opts.optmulti("F", "feature", "", "FEAT");
    opts.optmulti("N", "no-feature", "Enable or disable a feature (can occur multiple times).
        For more information about the supported features run --help with -v and see the feature
        list at the end of the output", "FEAT");
    opts.optflag("e", "generate-sample-zcode", "Write out a sample zcode file, input file is not used and can be omitted");

    opts
}

pub fn zwreec_usage(verbose: bool, opts: getopts::Options, brief: &str) -> String {
    use std::fmt::format;
    let options = zwreec_options(opts);

    let options_usage = options.usage(brief);

    let features_usage = if verbose {
        "List of supported features (default value in parenthesis)
    easter-egg (enabled)
        Enables the generation of easter egg code. Enter the secret combination
        in your Z-Machine interpreter to activate the easter egg
    force-unicode (disabled)
        Force the generation of unicode print opcodes every time a unicode
        character is encountered. This disables the generation of the unicode
        translation table"
    } else {
        "Additional help:
    --help -v           Print the full set of options zwreec accepts"
    };

    format(format_args!("{}\n{}", options_usage, features_usage.to_string()))
}

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

    fn config_from_args(args: Vec<String>) -> Config {
        let opts = zwreec_options(getopts::Options::new());

        match opts.parse(&args) {
            Ok(m) => Config::from_matches(&m),
            Err(f) => { panic!(f.to_string()) }
        }
    }

    #[test]
    fn test_feature_easter_egg_true() {
        let cfg = config_from_args(vec!["-F".to_string(), "easter-egg".to_string()]);

        assert_eq!(cfg.easter_egg, true);
    }

    #[test]
    fn test_feature_easter_egg_false() {
        let cfg = config_from_args(vec!["-N".to_string(), "easter-egg".to_string()]);

        assert_eq!(cfg.easter_egg, false);
    }

    #[test]
    fn test_feature_easter_egg_both() {
        let cfg = config_from_args(vec![
                                   "-N".to_string(),
                                   "easter-egg".to_string(),
                                   "-F".to_string(),
                                   "easter-egg".to_string()]);

        assert_eq!(cfg.easter_egg, false);
    }

    #[test]
    fn test_generate_sample_zcode() {
        let cfg = config_from_args(vec!["-e".to_string()]);

        assert_eq!(cfg.test_cases.is_empty(), false);

        let mut contains = false;
        for tc in cfg.test_cases {
            if tc == TestCase::ZcodeBackend {
                contains = true;
            }
        }

        assert!(contains);
    }
}
<commit_msg>Usage: Add another newline to look like rustc --help<commit_after>//! Configuration for the zwreec compiler.
//!
//! Uses the `getopts` library to append a `getopts::Options` with compiler
//! specific flags and then creates a `Config` struct from `getopts::Matches`.
//!
//! # Usage
//!
//! This module depends on the [getopts](http://doc.rust-lang.org/getopts/getopts/index.html)
//! crate. To use it, you need to add `getopts` to your project. Read getopts'
//! [Usage](http://doc.rust-lang.org/getopts/getopts/index.html#usage) for more information.
//!
//! # Example
//!
//! The following example shows how to generate a `Config` struct from an empty
//! `getopts::Options`.
//!
//! ```
//! extern crate zwreec;
//! extern crate getopts;
//!
//! use zwreec::config;
//! use zwreec::config::Config;
//!
//!
//! fn main() {
//!     let args: Vec<String> = std::env::args().collect();
//!     let opts = config::zwreec_options(getopts::Options::new());
//!
//!     let matches = match opts.parse(&args[1..]) {
//!         Ok(m) => m,
//!         Err(f) => { panic!(f.to_string()) }
//!     };
//!
//!     let cfg = Config::from_matches(&matches);
//! }
//! ```
//!
//! # Appending this module (Development)
//!
//! To add new compiler flags for the compiler, you need to change three parts
//! in this module.
//!
//! 1. Appending the Struct
//!
//!     To store your new setting, you need to add it as a field to the `Config` struct. Here we
//!     add a new boolean `pub italics: bool` to control *italics*. Always add a field-comment.
//!
//!     ```ignore
//!     pub struct Config {
//!         /// Add easter egg to compiler
//!         pub easter_egg: bool,
//!         /// Instruct compiler to run these test-cases
//!         pub test_cases: Vec<TestCase>,
//!         /// Enables or disalbes Italics
//!         pub italics: bool,
//!     }
//!     ```
//!
//!     Now you also need to change `Config::default_config()` to provide the
//!     default value for your new field:
//!
//!     ```ignore
//!     pub fn default_config() -> Config {
//!         Config{
//!             easter_egg: true,
//!             test_cases: Vec::new(),
//!             italics: true,
//!         }
//!     }
//!     ```
//!
//! 2. Parse your flag in `from_matches()`
//!
//!     `from_matches` uses the Options `-F` and `-N` to enable or disable boolean flags.
//!     Therefore, if you added a new boolean flag, you can now simply add it to the match
//!     statement.
//!
//!     ```ignore
//!     for s in matches.opt_strs("F") {
//!         match s.as_ref() {
//!             "easter-egg" => {
//!                  cfg.easter_egg = true;
//!                  debug!("enabled easter-egg");
//!             },
//!             "italics" => {
//!                 cfg.italics = true;
//!                 debug!("enabbled italics");
//!             },
//!             _ => {
//!                 error!("Cannot enable feature {} - feature not known.", s);
//!             }
//!         }
//!     }
//!
//!     for s in matches.opt_strs("N") {
//!         match s.as_ref() {
//!             "easter-egg" => {
//!                 cfg.easter_egg = false;
//!                 debug!("disabled easter-egg");
//!             },
//!             "italics" => {
//!                 cfg.italics = false;
//!                 debug:("disalbed italics");
//!             }
//!             _ => {
//!                 error!("Cannot disable feature {} - feature not known.", s);
//!             }
//!         }
//!     }
//!     ```
//!
//! 3. Adding something that is not a boolean
//!
//!     If you need to add an option that is *not* a boolean, you will need to append the struct
//!     and `default_config()` accordingly (e.g. `pub notaflag: String,`). Then you need to add a new
//!     `getopts::Option` to `zwreec_options()`:
//!
//!     ```ignore
//! pub fn zwreec_options(mut opts: getopts::Options) -> getopts::Options {
//!     opts.optmulti("F", "feature", "", "FEAT");
//!     opts.optmulti("N", "no-feature", "enable or disable a feature (can occur multiple times).
//!                         List of supported features (default):
//!                             easter-egg (enabled)", "FEAT");
//!     opts.optflag("e", "generate-sample-zcode", "writes out a sample zcode file, input file is not used and can be omitted");
//!
//!     opts.optopt("n", "notaflag", "notaflag", "SOMETHING");
//!
//!     opts
//! }
//!     ```
//!
//!     Now you can append `Config::from_matches()` to analyse the provided matches for your new
//!     option and set the `Config` accordingly:
//!
//!     ```ignore
//!     if let s = matches.opt_str("n") {
//!         cfg.notaflag = s;
//!     }
//!     ```
//!
//! 4. Now you can use the new flag inside the compiler.
use getopts;

use std::vec::Vec;

/// Represents the configuration for the compiler.
///
/// This struct is created using either `config::default_config()` or
/// `config::parse_matches(matches: &getopts::Matches)`. It contains a series
/// of fields that can be used to control the behaviour of the compiler.
///
/// # Example Usage inside the compiler
///
/// ```
/// # use zwreec::config;
/// let cfg = config::Config::default_config();
///
/// if cfg.easter_egg {
///     println!("Egg!");
/// }
/// ```
pub struct Config {
    /// Force compilation despite errors
    pub force: bool,
    /// Add easter egg to compiler
    pub easter_egg: bool,
    pub force_unicode: bool,
    /// Instruct compiler to run these test-cases
    pub test_cases: Vec<TestCase>,
}

impl Config {
    /// Returns a `Config` struct with preset defaults
    ///
    /// # Example
    ///
    /// ```
    /// use zwreec::config::Config;
    /// let cfg = Config::default_config();
    /// ```
    pub fn default_config() -> Config {
        Config{
            force: false,
            easter_egg: true,
            force_unicode: false,
            test_cases: Vec::new(),
        }
    }

    /// Returns a `Config` struct by using `getopts::Matches` to set the fields.
    ///
    /// This method analyses a `getopts::Matches` for fields provided by
    /// `zwreec_options()`.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate getopts;
    /// # extern crate zwreec;
    /// let args: Vec<String> = std::env::args().collect();
    /// let opts = zwreec::config::zwreec_options(getopts::Options::new());
    ///
    /// let matches = match opts.parse(&args[1..]) {
    ///     Ok(m) => m,
    ///     Err(f) => { panic!(f.to_string()) }
    /// };
    ///
    /// let cfg = zwreec::config::Config::from_matches(&matches);
    /// ```
    pub fn from_matches(matches: &getopts::Matches) -> Config {
        // load defaults
        let mut cfg = Config::default_config();

        if matches.opt_present("generate-sample-zcode") {
            cfg.test_cases.push(TestCase::ZcodeBackend);
        }

        if matches.opt_present("f") {
            cfg.force = true;
        }

        // TODO: Find a way to make these two loops somewhat less.. repetitive
        for s in matches.opt_strs("F") {
            match s.as_ref() {
                "easter-egg" => {
                     cfg.easter_egg = true;
                     debug!("enabled easter-egg");
                },
                "force-unicode" => {
                     cfg.force_unicode = true;
                     debug!("enabled force-unicode");
                },
                _ => {
                    error!("Cannot enable feature {} - feature not known.", s);
                }
            }
        }

        for s in matches.opt_strs("N") {
            match s.as_ref() {
                "easter-egg" => {
                    cfg.easter_egg = false;
                    debug!("disabled easter-egg");
                },
                "force-unicode" => {
                     cfg.force_unicode = false;
                     debug!("enabled force-unicode");
                },
                _ => {
                    error!("Cannot disable feature {} - feature not known.", s);
                }
            }
        }

        cfg
    }
}

// TODO: If this stays only one Test Case, enum should be removed
/// The Type used to define backend tests for the compiler
#[derive(PartialEq)]
pub enum TestCase {
    /// Skips the normal compiler chain and builds an example zcode file by
    /// using every opcode.
    ZcodeBackend,
}

/// Appends a `getopts::Options` with compiler specific flags
///
/// The method `Config::from_matches()` looks for very specific `getopts::Matches`.
/// This function takes an `getopts::Options` to append it with Options required
/// by `from_matches`. It currently adds three fields:
///
/// ```ignore
/// opts.optmulti("F", "feature", "", "FEAT");
/// opts.optmulti("N", "no-feature", "enable or disable a feature (can occur multiple times).
///                     List of supported features (default):
///                         easter-egg (enabled)", "FEAT");
/// opts.optflag("e", "generate-sample-zcode", "writes out a sample zcode file, input file is not used and can be omitted");
/// ```
///
/// # Example
///
/// You can use this function to append your `getopts::Options`.
///
/// ```
/// # extern crate getopts;
/// # extern crate zwreec;
///
/// let mut opts = getopts::Options::new();
/// opts.optflag("h", "help", "print this message");
///
/// let opts = zwreec::config::zwreec_options(opts);
/// ```
///
/// Another useful example is to use it to gernerate a more compact usage by
/// having a function that only returns your options.
///
/// ```
/// # extern crate getopts;
/// # extern crate zwreec;
///
/// fn options() -> getopts::Options {
///     let mut opts = getopts::Options::new();
///     opts.optflag("h", "help", "display this help and exit");
///     opts.optflag("V", "version", "display version");
///
///     opts
/// }
///
/// fn print_usage(program: &str, verbose: bool) {
///     let brief = format!("Usage: {} [options]", program);
///
///     let opts = if verbose {
///         zwreec::config::zwreec_options(options())
///     } else {
///         options()
///     };
///
///     print!("{}", opts.usage(&brief));
/// }
/// ```
/// As you can see, `options()` returns your own command line options, which are then conditionally
/// expanded by using `zwreec_options()`.
pub fn zwreec_options(mut opts: getopts::Options) -> getopts::Options {
    opts.optflag("f", "force", "Force opening of output file");
    opts.optmulti("F", "feature", "", "FEAT");
    opts.optmulti("N", "no-feature", "Enable or disable a feature (can occur multiple times).
        For more information about the supported features run --help with -v and see the feature
        list at the end of the output", "FEAT");
    opts.optflag("e", "generate-sample-zcode", "Write out a sample zcode file, input file is not used and can be omitted");

    opts
}

pub fn zwreec_usage(verbose: bool, opts: getopts::Options, brief: &str) -> String {
    use std::fmt::format;
    let options = zwreec_options(opts);

    let options_usage = options.usage(brief);

    let features_usage = if verbose {
        "List of supported features (default value in parenthesis)
    easter-egg (enabled)
        Enables the generation of easter egg code. Enter the secret combination
        in your Z-Machine interpreter to activate the easter egg
    force-unicode (disabled)
        Force the generation of unicode print opcodes every time a unicode
        character is encountered. This disables the generation of the unicode
        translation table"
    } else {
        "Additional help:
    --help -v           Print the full set of options zwreec accepts"
    };

    format(format_args!("{}\n{}\n", options_usage, features_usage.to_string()))
}

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

    fn config_from_args(args: Vec<String>) -> Config {
        let opts = zwreec_options(getopts::Options::new());

        match opts.parse(&args) {
            Ok(m) => Config::from_matches(&m),
            Err(f) => { panic!(f.to_string()) }
        }
    }

    #[test]
    fn test_feature_easter_egg_true() {
        let cfg = config_from_args(vec!["-F".to_string(), "easter-egg".to_string()]);

        assert_eq!(cfg.easter_egg, true);
    }

    #[test]
    fn test_feature_easter_egg_false() {
        let cfg = config_from_args(vec!["-N".to_string(), "easter-egg".to_string()]);

        assert_eq!(cfg.easter_egg, false);
    }

    #[test]
    fn test_feature_easter_egg_both() {
        let cfg = config_from_args(vec![
                                   "-N".to_string(),
                                   "easter-egg".to_string(),
                                   "-F".to_string(),
                                   "easter-egg".to_string()]);

        assert_eq!(cfg.easter_egg, false);
    }

    #[test]
    fn test_generate_sample_zcode() {
        let cfg = config_from_args(vec!["-e".to_string()]);

        assert_eq!(cfg.test_cases.is_empty(), false);

        let mut contains = false;
        for tc in cfg.test_cases {
            if tc == TestCase::ZcodeBackend {
                contains = true;
            }
        }

        assert!(contains);
    }
}
<|endoftext|>


<commit_before>#![feature(proc_macro)]
#![recursion_limit = "128"]

extern crate proc_macro;
extern crate proc_macro2;
extern crate syn;

use std::str::FromStr;
use proc_macro::TokenStream;
use syn::*;

#[proc_macro_attribute]
pub fn snapshot(attribute: TokenStream, function: TokenStream) -> TokenStream {
    let src = function.to_string();
    let function = proc_macro2::TokenStream::from(function);
    let Item { attrs, node } = function.into();
    let ItemFn {
        ident, // TODO get the function name out of this bad boy
        unsafety,
        constness,
        abi,
        block,
        decl,
        ..
    } = match node {
        ItemKind::Fn(item) => item,
        _ => panic!("#[snapshot] can only be applied to functions"),
    };
    let FnDecl {
        inputs,
        output,
        variadic,
        generics,
        ..
    } = {
        *decl
    };

    // TODO get the function name!!!!
    panic!("haha we're finding the function name");

    <TokenStream as FromStr>::from_str(&src).unwrap()
}
<commit_msg>Finding the function name from the macro attribute.<commit_after>#![feature(proc_macro)]
#![recursion_limit = "128"]

extern crate proc_macro;
extern crate proc_macro2;
extern crate syn;

use std::str::FromStr;
use proc_macro::TokenStream;
use syn::*;

#[proc_macro_attribute]
pub fn snapshot(attribute: TokenStream, function: TokenStream) -> TokenStream {
    let src = function.to_string();
    let function = proc_macro2::TokenStream::from(function);
    let Item { attrs, node } = function.into();
    let ItemFn {
        ident, // TODO get the function name out of this bad boy
        unsafety,
        constness,
        abi,
        block,
        decl,
        ..
    } = match node {
        ItemKind::Fn(item) => item,
        _ => panic!("#[snapshot] can only be applied to functions"),
    };
    let FnDecl {
        inputs,
        output,
        variadic,
        generics,
        ..
    } = {
        *decl
    };

    // TODO get the function name!!!!
    panic!("haha function name is {}", ident);

    <TokenStream as FromStr>::from_str(&src).unwrap()
}
<|endoftext|>


<commit_before>extern crate core;

#[test]
fn empty()
{
	let translator = core::Translator::new();

	assert_eq!("", translator.translate(""));
	assert_eq!(" ", translator.translate(" "));
	assert_eq!("  ", translator.translate("  "));
	assert_eq!("   ", translator.translate("   "));
}

#[test]
fn letters()
{
	let translator = core::Translator::new();

	assert_eq!("а", translator.translate("a"));
	assert_eq!("б", translator.translate("b"));
	assert_eq!("в", translator.translate("v"));
	assert_eq!("г", translator.translate("g"));
	assert_eq!("д", translator.translate("d"));
	assert_eq!("е", translator.translate("e"));
	assert_eq!("ё", translator.translate("jo"));
	assert_eq!("ж", translator.translate("zh"));
	assert_eq!("з", translator.translate("z"));
	assert_eq!("и", translator.translate("i"));
	assert_eq!("й", translator.translate("j"));
	assert_eq!("к", translator.translate("k"));
	assert_eq!("л", translator.translate("l"));
	assert_eq!("м", translator.translate("m"));
	assert_eq!("н", translator.translate("n"));
	assert_eq!("о", translator.translate("o"));
	assert_eq!("п", translator.translate("p"));
	assert_eq!("р", translator.translate("r"));
	assert_eq!("с", translator.translate("s"));
	assert_eq!("т", translator.translate("t"));
	assert_eq!("у", translator.translate("u"));
	assert_eq!("ф", translator.translate("f"));
	assert_eq!("х", translator.translate("h"));
	assert_eq!("ц", translator.translate("c"));
	assert_eq!("ч", translator.translate("ch"));
	assert_eq!("ш", translator.translate("sh"));
	assert_eq!("щ", translator.translate("shh"));
	assert_eq!("ъ", translator.translate("#"));
	assert_eq!("ы", translator.translate("y"));
	assert_eq!("ь", translator.translate("'"));
	assert_eq!("э", translator.translate("je"));
	assert_eq!("ю", translator.translate("ju"));
	assert_eq!("я", translator.translate("ja"));
}

fn capital_letters()
{
	let translator = core::Translator::new();

	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
	assert_eq!("а", translator.translate(""));
}

#[test]
fn words()
{
}

<commit_msg>Capital letters test<commit_after>extern crate core;

#[test]
fn empty()
{
	let translator = core::Translator::new();

	assert_eq!("", translator.translate(""));
	assert_eq!(" ", translator.translate(" "));
	assert_eq!("  ", translator.translate("  "));
	assert_eq!("   ", translator.translate("   "));
}

#[test]
fn letters()
{
	let translator = core::Translator::new();

	assert_eq!("а", translator.translate("a"));
	assert_eq!("б", translator.translate("b"));
	assert_eq!("в", translator.translate("v"));
	assert_eq!("г", translator.translate("g"));
	assert_eq!("д", translator.translate("d"));
	assert_eq!("е", translator.translate("e"));
	assert_eq!("ё", translator.translate("jo"));
	assert_eq!("ж", translator.translate("zh"));
	assert_eq!("з", translator.translate("z"));
	assert_eq!("и", translator.translate("i"));
	assert_eq!("й", translator.translate("j"));
	assert_eq!("к", translator.translate("k"));
	assert_eq!("л", translator.translate("l"));
	assert_eq!("м", translator.translate("m"));
	assert_eq!("н", translator.translate("n"));
	assert_eq!("о", translator.translate("o"));
	assert_eq!("п", translator.translate("p"));
	assert_eq!("р", translator.translate("r"));
	assert_eq!("с", translator.translate("s"));
	assert_eq!("т", translator.translate("t"));
	assert_eq!("у", translator.translate("u"));
	assert_eq!("ф", translator.translate("f"));
	assert_eq!("х", translator.translate("h"));
	assert_eq!("ц", translator.translate("c"));
	assert_eq!("ч", translator.translate("ch"));
	assert_eq!("ш", translator.translate("sh"));
	assert_eq!("щ", translator.translate("shh"));
	assert_eq!("ъ", translator.translate("#"));
	assert_eq!("ы", translator.translate("y"));
	assert_eq!("ь", translator.translate("'"));
	assert_eq!("э", translator.translate("je"));
	assert_eq!("ю", translator.translate("ju"));
	assert_eq!("я", translator.translate("ja"));
}

fn capital_letters()
{
	let translator = core::Translator::new();

	assert_eq!("А", translator.translate(""));
	assert_eq!("Б", translator.translate(""));
	assert_eq!("В", translator.translate(""));
	assert_eq!("Г", translator.translate(""));
	assert_eq!("Д", translator.translate(""));
	assert_eq!("Е", translator.translate(""));
	assert_eq!("Ё", translator.translate(""));
	assert_eq!("Ж", translator.translate(""));
	assert_eq!("З", translator.translate(""));
	assert_eq!("И", translator.translate(""));
	assert_eq!("Й", translator.translate(""));
	assert_eq!("К", translator.translate(""));
	assert_eq!("Л", translator.translate(""));
	assert_eq!("М", translator.translate(""));
	assert_eq!("Н", translator.translate(""));
	assert_eq!("О", translator.translate(""));
	assert_eq!("П", translator.translate(""));
	assert_eq!("Р", translator.translate(""));
	assert_eq!("С", translator.translate(""));
	assert_eq!("Т", translator.translate(""));
	assert_eq!("У", translator.translate(""));
	assert_eq!("Ф", translator.translate(""));
	assert_eq!("Х", translator.translate(""));
	assert_eq!("Ц", translator.translate(""));
	assert_eq!("Ч", translator.translate(""));
	assert_eq!("Ш", translator.translate(""));
	assert_eq!("Щ", translator.translate(""));
	assert_eq!("Ъ", translator.translate(""));
	assert_eq!("Ы", translator.translate(""));
	assert_eq!("Ь", translator.translate(""));
	assert_eq!("Э", translator.translate(""));
	assert_eq!("Ю", translator.translate(""));
	assert_eq!("Я", translator.translate(""));
}

#[test]
fn words()
{
}

<|endoftext|>


<commit_before>extern crate desync;
extern crate futures;

use desync::*;
use futures::stream;

use std::sync::*;

#[test]
fn pipe_in_simple_stream() {
    // Create a stream
    let stream  = vec![1, 2, 3];
    let stream  = stream::iter_ok(stream);

    // Create an object for the stream to be piped into
    let obj     = Arc::new(Desync::new(vec![]));

    // Pipe the stream into the object
    pipe_in(Arc::clone(&obj), stream, |core: &mut Vec<Result<i32, ()>>, item| core.push(item));

    // Once the stream is drained, the core should contain Ok(1), Ok(2), Ok(3)
    assert!(obj.sync(|core| core.clone()) == vec![Ok(1), Ok(2), Ok(3)])
}
<commit_msg>Test pipe_in with a mpsc receiver<commit_after>extern crate desync;
extern crate futures;

use desync::*;
use futures::stream;
use futures::executor;
use futures::sync::mpsc;

use std::sync::*;
use std::thread;
use std::time::Duration;

#[test]
fn pipe_in_simple_stream() {
    // Create a stream
    let stream  = vec![1, 2, 3];
    let stream  = stream::iter_ok(stream);

    // Create an object for the stream to be piped into
    let obj     = Arc::new(Desync::new(vec![]));

    // Pipe the stream into the object
    pipe_in(Arc::clone(&obj), stream, |core: &mut Vec<Result<i32, ()>>, item| core.push(item));

    // Once the stream is drained, the core should contain Ok(1), Ok(2), Ok(3)
    assert!(obj.sync(|core| core.clone()) == vec![Ok(1), Ok(2), Ok(3)])
}

#[test]
fn pipe_in_mpsc_receiver() {
    // Create a channel to send to the object
    let (sender, receiver) = mpsc::channel(10);

    // Create an object
    let obj = Arc::new(Desync::new(vec![]));

    // Add anything received to the vector via a pipe
    pipe_in(Arc::clone(&obj), receiver, |core: &mut Vec<i32>, item| core.push(item.unwrap()));

    // Initially empty
    assert!(obj.sync(|core| core.clone()) == vec![]);

    // Send some values
    let mut sender = executor::spawn(sender);
    sender.wait_send(1).unwrap();
    sender.wait_send(2).unwrap();

    // Should arrive after a short delay
    thread::sleep(Duration::from_millis(10));
    assert!(obj.sync(|core| core.clone()) == vec![1, 2]);
}
<|endoftext|>


<commit_before>use mio::net::*;

#[test]
#[cfg(unix)]
#[cfg(not(debug_assertions))]
fn assert_size() {
    use std::mem::size_of;

    // Without debug assertions enabled `TcpListener`, `TcpStream` and `UdpSocket` should have the
    // same size as the system specific socket, i.e. just a file descriptor on Unix platforms.
    assert_eq!(size_of::<TcpListener>(), size_of::<std::net::TcpListener>());
    assert_eq!(size_of::<TcpStream>(), size_of::<std::net::TcpStream>());
    assert_eq!(size_of::<UdpSocket>(), size_of::<std::net::UdpSocket>());
}
<commit_msg>fix clippy<commit_after>#[test]
#[cfg(unix)]
#[cfg(not(debug_assertions))]
fn assert_size() {
    use mio::net::*;
    use std::mem::size_of;

    // Without debug assertions enabled `TcpListener`, `TcpStream` and `UdpSocket` should have the
    // same size as the system specific socket, i.e. just a file descriptor on Unix platforms.
    assert_eq!(size_of::<TcpListener>(), size_of::<std::net::TcpListener>());
    assert_eq!(size_of::<TcpStream>(), size_of::<std::net::TcpStream>());
    assert_eq!(size_of::<UdpSocket>(), size_of::<std::net::UdpSocket>());
}
<|endoftext|>


<commit_before>use super::{ASTNode, SymbolTable, SymbolAnnotation};
use ::position::Position;

use std::rc::Rc;
use std::borrow::Borrow;
use std::hash::Hash;
use std::ops;
use std::marker::PhantomData;

// pub type STCell<'a> = Rc<RefCell<SymbolTable<'a>>>;

//==-----------------------------------------------------==
//      Warning: evil typesystem hacking to follow
//==-----------------------------------------------------==
// This is basically a reimplementation of the typestate
// system that Rust briefly had.
pub trait ScopednessTypestate { fn is_scoped() -> bool; }
pub struct Scoped;
pub struct Unscoped;
impl ScopednessTypestate for Scoped { fn is_scoped() -> bool {true} }
impl ScopednessTypestate for Unscoped { fn is_scoped() -> bool {false} }
//==------- exiting typesystem danger zone --------------==

/// An AST node which has been annotated with position &
/// (possibly) scope information.
pub struct Annotated<'a, T, S>
where S: ScopednessTypestate,
      T: ASTNode {
    pub node: T,
    pub position: Position,
    scope: Option<SymbolTable<'a>>,
    my_typestate: PhantomData<S>
}

/// Due to Evil Typesystem Hacking reasons, this impl only exists
/// for annotations which are in the Scoped typestate.
impl<'a, T> Annotated<'a, T, Scoped>
where T: ASTNode {

    /// Get the type signature associated with the given name.
    ///
    /// This returns a borrowed reference to the type signature
    /// associated with that name in the current scope. The argument
    /// can be any type `Q` such that `String: Borrow<Q>` (i.e.
    /// you can pass an `&str` to this function).
    pub fn get_type<Q: ?Sized>(&self, name: &Q) -> Option<&SymbolAnnotation>
    where String: Borrow<Q>,
          Q: Hash + Eq {
        self.scope
            .expect("VERY FATAL ERROR: Node in scoped typestate had no scope")
            .get(name)
    }

    /// Check if the given name is defined in this scope.
    ///
    /// The argument can be any type `Q` such that `String: Borrow<Q>`
    /// (i.e. you can pass an `&str` to this function).
    pub fn is_defined_here<Q: ?Sized>(&self, name: &Q) -> bool
    where String: Borrow<Q>,
          Q: Hash + Eq {
        self.scope
            .expect("VERY FATAL ERROR: Node in scoped typestate had no scope")
            .contains_key(name)
    }

}

impl<'a, T> Annotated<'a, T, Unscoped>
where T: ASTNode {

    /// Consume this unscoped annotation to produce a new
    /// annotation in the scoped typestate with the given
    /// scope.
    pub fn with_scope(self, scope: SymbolTable<'a>)
        -> Annotated<'a, T, Scoped> {
        Annotated {
            node: self.node,
            position: self.position,
            scope: Some(scope),
            my_typestate: PhantomData
        }
    }
}

impl<'a, T, S> ops::Deref for Annotated<'a, T, S>
where S: ScopednessTypestate,
      T: ASTNode {
    type Target = T;
    fn deref(&self) -> &T { &self.node }
}

#[derive(Debug, Clone)]
pub enum Type {
    /// Reference types
    Ref(Reference),
    /// Primitive types
    Prim(Primitive),
    /// An algebraic data type.
    ///
    /// Represented as a vector of variants.
    Algebraic(Vec<Type>),
    /// A function.
    ///
    /// Represented as a vector of parameters and a return type.
    Function { params: Vec<Type>
             , rt: Rc<Type> },
    /// A unique symbol type (`'symbol` syntax)
    Symbol(String)
}

/// Reference types (pointers)
///
/// TODO: how will lifetime analysis actually work?
#[derive(Debug, Clone)]
pub enum Reference {
    /// A reference borrowed from another scope.
    ///
    /// Semantically similar to Rust's `&`-pointers.
    ///
    /// TODO: should this track where it was borrowed from?
    /// (can we even perform this analysis at this stage?)
    Borrowed(Rc<Type>),
    /// A moved reference from another scope
    ///
    /// TODO: should this track where it was moved from?
    /// (can we even perform this analysis at this stage?)
    Moved(Rc<Type>),
    /// A unique (i.e. boxed) reference.
    Unique(Rc<Type>),
    /// A raw (unsafe) reference.
    ///
    /// Unfortunately we have to have this because of
    /// reasons (i.e, FFI).
    Raw(Rc<Type>)
}

/// Language primitive types
///
/// TODO: add some form of provable-refinement (i.e. we know that some value
/// is not just a bool at compile time but that it's true/false, or we know
/// some value is not just a number but the number 1382, or whatever).
#[derive(Debug, Clone, Copy)]
pub enum Primitive { Int
                   , Uint
                   , Byte
                   , Char
                   , Str
                   , Bool
                   , Float
                   , Double
                   // TODO: finish
                   }
<commit_msg>Operations on Annotated pointers in Scoped typestate work now<commit_after>use super::{ASTNode, SymbolTable, SymbolAnnotation};
use ::position::Position;

use std::rc::Rc;
use std::borrow::Borrow;
use std::hash::Hash;
use std::ops;
use std::marker::PhantomData;

// pub type STCell<'a> = Rc<RefCell<SymbolTable<'a>>>;

//==-----------------------------------------------------==
//      Warning: evil typesystem hacking to follow
//==-----------------------------------------------------==
// This is basically a reimplementation of the typestate
// system that Rust briefly had.
macro_rules! scope_typestate_err {
    ($err_site:expr) => {
        panic!("VERY TRAGIC ERROR: Typestate assertion failed during {}.\n \
            A node in the scoped typestate had no scope. Something has gone \
            terribly, terribly wrong. Contact the Mnemosyne implementors.",
            $err_site
        )}
}

pub trait ScopednessTypestate { fn is_scoped() -> bool; }
pub struct Scoped;
pub struct Unscoped;
impl ScopednessTypestate for Scoped { fn is_scoped() -> bool {true} }
impl ScopednessTypestate for Unscoped { fn is_scoped() -> bool {false} }
//==------- exiting typesystem danger zone --------------==

/// An AST node which has been annotated with position &
/// (possibly) scope information.
pub struct Annotated<'a, T, S>
where S: ScopednessTypestate,
      T: ASTNode {
    pub node: T,
    pub position: Position,
    scope: Option<SymbolTable<'a>>,
    my_typestate: PhantomData<S>
}

/// Due to Evil Typesystem Hacking reasons, this impl only exists
/// for annotations which are in the Scoped typestate.
impl<'a, T> Annotated<'a, T, Scoped>
where T: ASTNode {

    /// Get the type signature associated with the given name.
    ///
    /// This returns a borrowed reference to the type signature
    /// associated with that name in the current scope. The argument
    /// can be any type `Q` such that `String: Borrow<Q>` (i.e.
    /// you can pass an `&str` to this function).
    pub fn get_type<Q: ?Sized>(&self, name: &'a Q) -> Option<&SymbolAnnotation>
    where String: Borrow<Q>,
          Q: Hash + Eq {
        match self.scope {
            Some(ref table) => table.get(name),
            None => scope_typestate_err!("get_type()")
        }
    }

    /// Check if the given name is defined in this scope.
    ///
    /// The argument can be any type `Q` such that `String: Borrow<Q>`
    /// (i.e. you can pass an `&str` to this function).
    pub fn is_defined_here<Q: ?Sized>(&self, name: &Q) -> bool
    where String: Borrow<Q>,
          Q: Hash + Eq {
        match self.scope {
            Some(ref table) => table.contains_key(name),
            None => scope_typestate_err!("is_defined_here()")
        }
    }

}

impl<'a, T> Annotated<'a, T, Unscoped>
where T: ASTNode {

    /// Consume this unscoped annotation to produce a new
    /// annotation in the scoped typestate with the given
    /// scope.
    pub fn with_scope(self, scope: SymbolTable<'a>)
        -> Annotated<'a, T, Scoped> {
        Annotated {
            node: self.node,
            position: self.position,
            scope: Some(scope),
            my_typestate: PhantomData
        }
    }
}

impl<'a, T, S> ops::Deref for Annotated<'a, T, S>
where S: ScopednessTypestate,
      T: ASTNode {
    type Target = T;
    fn deref(&self) -> &T { &self.node }
}

#[derive(Debug, Clone)]
pub enum Type {
    /// Reference types
    Ref(Reference),
    /// Primitive types
    Prim(Primitive),
    /// An algebraic data type.
    ///
    /// Represented as a vector of variants.
    Algebraic(Vec<Type>),
    /// A function.
    ///
    /// Represented as a vector of parameters and a return type.
    Function { params: Vec<Type>
             , rt: Rc<Type> },
    /// A unique symbol type (`'symbol` syntax)
    Symbol(String)
}

/// Reference types (pointers)
///
/// TODO: how will lifetime analysis actually work?
#[derive(Debug, Clone)]
pub enum Reference {
    /// A reference borrowed from another scope.
    ///
    /// Semantically similar to Rust's `&`-pointers.
    ///
    /// TODO: should this track where it was borrowed from?
    /// (can we even perform this analysis at this stage?)
    Borrowed(Rc<Type>),
    /// A moved reference from another scope
    ///
    /// TODO: should this track where it was moved from?
    /// (can we even perform this analysis at this stage?)
    Moved(Rc<Type>),
    /// A unique (i.e. boxed) reference.
    Unique(Rc<Type>),
    /// A raw (unsafe) reference.
    ///
    /// Unfortunately we have to have this because of
    /// reasons (i.e, FFI).
    Raw(Rc<Type>)
}

/// Language primitive types
///
/// TODO: add some form of provable-refinement (i.e. we know that some value
/// is not just a bool at compile time but that it's true/false, or we know
/// some value is not just a number but the number 1382, or whatever).
#[derive(Debug, Clone, Copy)]
pub enum Primitive { Int
                   , Uint
                   , Byte
                   , Char
                   , Str
                   , Bool
                   , Float
                   , Double
                   // TODO: finish
                   }
<|endoftext|>


<commit_before>use backend::obj::*;
use std::f32::consts;
use core::color;
use core::color::ToRgb;
use core::geometry::*;
use backend::world::segment;
use backend::world::segment::*;
use backend::world::agent;
use backend::world::agent::Agent;
use backend::world::gen::*;
use cgmath;
use cgmath::EuclideanVector;

pub trait Phenotype {
	fn develop(gen: &mut Genome, id: Id, transform: Transform, motion: Option<Motion>, charge: f32) -> agent::Agent;
}

pub struct Resource {}
pub struct Minion {}
pub struct Spore {}

impl Phenotype for Resource {
	fn develop(gen: &mut Genome, id: Id, transform: Transform, motion: Option<Motion>, charge: f32) -> agent::Agent {

		let albedo = color::YPbPr::new(0.5, gen.next_float(-0.5, 0.5), gen.next_float(-0.5, 0.5));
		let body = gen.eq_triangle();
		let mut builder = AgentBuilder::new(id,
		                                    Material { density: 1.0, ..Default::default() },
		                                    Livery { albedo: albedo.to_rgba(), ..Default::default() },
		                                    gen.dna(),
		                                    segment::State::with_charge(charge, 0., charge));
		builder.start(Transform::with_position(transform.position), motion, &body).build()
	}
}

impl Phenotype for Minion {
	fn develop(gen: &mut Genome, id: Id, transform: Transform, motion: Option<Motion>, charge: f32) -> agent::Agent {
		let albedo = color::Hsl::new(gen.next_float(0., 1.), 0.5, 0.5);
		let mut builder = AgentBuilder::new(id,
		                                    Material { density: 0.2, ..Default::default() },
		                                    Livery { albedo: albedo.to_rgba(), ..Default::default() },
		                                    gen.dna(),
		                                    segment::State::with_charge(0., charge, charge));
		let torso_shape = gen.npoly(5, true);
		let torso = builder.start(transform, motion, &torso_shape).index();
		let arm_shape = gen.star();
		let leg_shape = gen.star();
		let head_shape = gen.iso_triangle();
		let tail_shape = gen.vbar();
		builder.addr(torso, 2, &arm_shape, ARM | JOINT | ACTUATOR | RUDDER)
			.addl(torso, -2, &arm_shape, ARM | JOINT | ACTUATOR | RUDDER);

		let head = builder.add(torso, 0, &head_shape, HEAD | SENSOR).index();
		builder.addr(head, 1, &head_shape, HEAD | ACTUATOR | RUDDER)
			.addl(head, 2, &head_shape, HEAD | ACTUATOR | RUDDER);

		let mut belly = torso;
		let mut belly_mid = torso_shape.mid();
		for _ in 0..gen.next_integer(0, 4) {
			let belly_shape = gen.poly(true);

			belly = builder.add(belly, belly_mid, &belly_shape, BELLY | JOINT).index();
			belly_mid = belly_shape.mid();
			if gen.next_integer(0, 4) == 0 {
				builder.addr(belly, 2, &arm_shape, ARM | ACTUATOR | RUDDER)
					.addl(belly, -2, &arm_shape, ARM | ACTUATOR | RUDDER);
			}
		}

		builder.addr(belly, belly_mid - 1, &leg_shape, LEG | ACTUATOR | THRUSTER)
			.addl(belly,
			      -(belly_mid - 1),
			      &leg_shape,
			      LEG | ACTUATOR | THRUSTER)
			.add(belly, belly_mid, &tail_shape, TAIL | ACTUATOR | BRAKE)
			.build()
	}
}

impl Phenotype for Spore {
	fn develop(gen: &mut Genome, id: Id, transform: Transform, motion: Option<Motion>, charge: f32) -> agent::Agent {
		let albedo = color::Hsl::new(gen.next_float(0., 1.), 0.5, 0.5);
		let mut builder = AgentBuilder::new(id,
		                                    Material { density: 0.2, ..Default::default() },
		                                    Livery { albedo: albedo.to_rgba(), ..Default::default() },
		                                    gen.dna(),
		                                    segment::State::with_charge(0., charge, charge));
		builder.start(transform, motion, &gen.ball()).build()
	}
}

pub struct AgentBuilder {
	id: Id,
	material: Material,
	livery: Livery,
	dna: Dna,
	state: segment::State,
	segments: Vec<Segment>,
}

impl AgentBuilder {
	pub fn new(id: Id, material: Material, livery: Livery, dna: &Dna, state: segment::State) -> Self {
		AgentBuilder {
			id: id,
			material: material,
			livery: livery,
			state: state,
			dna: dna.clone(),
			segments: Vec::new(),
		}
	}

	pub fn start(&mut self, transform: Transform, initial_vel: Option<Motion>, shape: &Shape) -> &mut Self {
		let segment = self.new_segment(shape,
		                               Winding::CW,
		                               transform,
		                               initial_vel,
		                               None,
		                               segment::TORSO | segment::MIDDLE);
		self.segments.clear();
		self.segments.push(segment);
		self
	}

	#[inline]
	pub fn add(&mut self,
	           parent_index: SegmentIndex,
	           attachment_index_offset: isize,
	           shape: &Shape,
	           flags: segment::Flags)
	           -> &mut Self {
		self.addw(parent_index,
		          attachment_index_offset,
		          shape,
		          Winding::CW,
		          flags | segment::MIDDLE)
	}
	#[inline]
	pub fn addl(&mut self,
	            parent_index: SegmentIndex,
	            attachment_index_offset: isize,
	            shape: &Shape,
	            flags: segment::Flags)
	            -> &mut Self {
		self.addw(parent_index,
		          attachment_index_offset,
		          shape,
		          Winding::CCW,
		          flags | segment::LEFT)
	}
	#[inline]
	pub fn addr(&mut self,
	            parent_index: SegmentIndex,
	            attachment_index_offset: isize,
	            shape: &Shape,
	            flags: segment::Flags)
	            -> &mut Self {
		self.addw(parent_index,
		          attachment_index_offset,
		          shape,
		          Winding::CW,
		          flags | segment::RIGHT)
	}

	pub fn addw(&mut self,
	            parent_index: SegmentIndex,
	            attachment_index_offset: isize,
	            shape: &Shape,
	            winding: Winding,
	            flags: segment::Flags)
	            -> &mut Self {
		let parent = self.segments[parent_index as usize].clone();//urgh!;
		let parent_pos = parent.transform.position;
		let parent_angle = parent.transform.angle;
		let parent_length = parent.mesh.shape.length() as isize;
		let attachment_index = ((attachment_index_offset + parent_length) % parent_length) as usize;
		let p0 = cgmath::Matrix2::from_angle(cgmath::rad(parent_angle)) * parent.mesh.vertices[attachment_index];
		let angle = f32::atan2(p0.y, p0.x);
		let r0 = p0.length() * parent.mesh.shape.radius();
		let r1 = shape.radius();
		let segment = self.new_segment(shape,
		                               winding,
		                               Transform::new(parent_pos + (p0 * (r0 + r1)), consts::PI / 2. + angle),
		                               None,
		                               parent.new_attachment(attachment_index as AttachmentIndex),
		                               flags);
		self.segments.push(segment);
		self
	}

	pub fn index(&self) -> SegmentIndex {
		match self.segments.len() {
			0 => 0,
			n => (n - 1) as SegmentIndex,
		}
	}

	fn new_segment(&mut self,
	               shape: &Shape,
	               winding: Winding,
	               transform: Transform,
	               motion: Option<Motion>,
	               attachment: Option<segment::Attachment>,
	               flags: segment::Flags)
	               -> segment::Segment {
		segment::Segment {
			index: self.segments.len() as SegmentIndex,
			transform: transform,
			motion: motion,
			mesh: Mesh::from_shape(shape.clone(), winding),
			material: self.material.clone(),
			livery: self.livery.clone(),
			state: self.state.clone(),
			attached_to: attachment,
			flags: flags,
		}
	}

	pub fn build(&self) -> Agent {
		let order = self.segments.len() as f32;
		let d0 = 2. * order;

		Agent::new(self.id,
		           d0,
		           order,
		           &self.dna,
		           self.segments.clone().into_boxed_slice())
	}
}
<commit_msg>Antenna phenotype decoupled<commit_after>use backend::obj::*;
use std::f32::consts;
use core::color;
use core::color::ToRgb;
use core::geometry::*;
use backend::world::segment;
use backend::world::segment::*;
use backend::world::agent;
use backend::world::agent::Agent;
use backend::world::gen::*;
use cgmath;
use cgmath::EuclideanVector;

pub trait Phenotype {
	fn develop(gen: &mut Genome, id: Id, transform: Transform, motion: Option<Motion>, charge: f32) -> agent::Agent;
}

pub struct Resource {}
pub struct Minion {}
pub struct Spore {}

impl Phenotype for Resource {
	fn develop(gen: &mut Genome, id: Id, transform: Transform, motion: Option<Motion>, charge: f32) -> agent::Agent {

		let albedo = color::YPbPr::new(0.5, gen.next_float(-0.5, 0.5), gen.next_float(-0.5, 0.5));
		let body = gen.eq_triangle();
		let mut builder = AgentBuilder::new(id,
		                                    Material { density: 1.0, ..Default::default() },
		                                    Livery { albedo: albedo.to_rgba(), ..Default::default() },
		                                    gen.dna(),
		                                    segment::State::with_charge(charge, 0., charge));
		builder.start(Transform::with_position(transform.position), motion, &body).build()
	}
}

impl Phenotype for Minion {
	fn develop(gen: &mut Genome, id: Id, transform: Transform, motion: Option<Motion>, charge: f32) -> agent::Agent {
		let albedo = color::Hsl::new(gen.next_float(0., 1.), 0.5, 0.5);
		let mut builder = AgentBuilder::new(id,
		                                    Material { density: 0.2, ..Default::default() },
		                                    Livery { albedo: albedo.to_rgba(), ..Default::default() },
		                                    gen.dna(),
		                                    segment::State::with_charge(0., charge, charge));
		let torso_shape = gen.npoly(5, true);
		let torso = builder.start(transform, motion, &torso_shape).index();
		let arm_shape = gen.star();
		let leg_shape = gen.star();
		let head_shape = gen.iso_triangle();
		let antenna_shape = gen.triangle();
		let tail_shape = gen.vbar();
		builder.addr(torso, 2, &arm_shape, ARM | JOINT | ACTUATOR | RUDDER)
			.addl(torso, -2, &arm_shape, ARM | JOINT | ACTUATOR | RUDDER);

		let head = builder.add(torso, 0, &head_shape, HEAD | SENSOR).index();
		builder.addr(head, 1, &antenna_shape, HEAD | ACTUATOR | RUDDER)
			.addl(head, 2, &antenna_shape, HEAD | ACTUATOR | RUDDER);

		let mut belly = torso;
		let mut belly_mid = torso_shape.mid();
		for _ in 0..gen.next_integer(0, 4) {
			let belly_shape = gen.poly(true);

			belly = builder.add(belly, belly_mid, &belly_shape, BELLY | JOINT).index();
			belly_mid = belly_shape.mid();
			if gen.next_integer(0, 4) == 0 {
				builder.addr(belly, 2, &arm_shape, ARM | ACTUATOR | RUDDER)
					.addl(belly, -2, &arm_shape, ARM | ACTUATOR | RUDDER);
			}
		}

		builder.addr(belly, belly_mid - 1, &leg_shape, LEG | ACTUATOR | THRUSTER)
			.addl(belly,
			      -(belly_mid - 1),
			      &leg_shape,
			      LEG | ACTUATOR | THRUSTER)
			.add(belly, belly_mid, &tail_shape, TAIL | ACTUATOR | BRAKE)
			.build()
	}
}

impl Phenotype for Spore {
	fn develop(gen: &mut Genome, id: Id, transform: Transform, motion: Option<Motion>, charge: f32) -> agent::Agent {
		let albedo = color::Hsl::new(gen.next_float(0., 1.), 0.5, 0.5);
		let mut builder = AgentBuilder::new(id,
		                                    Material { density: 0.5, ..Default::default() },
		                                    Livery { albedo: albedo.to_rgba(), ..Default::default() },
		                                    gen.dna(),
		                                    segment::State::with_charge(0., charge, charge));
		builder.start(transform, motion, &gen.ball()).build()
	}
}

pub struct AgentBuilder {
	id: Id,
	material: Material,
	livery: Livery,
	dna: Dna,
	state: segment::State,
	segments: Vec<Segment>,
}

impl AgentBuilder {
	pub fn new(id: Id, material: Material, livery: Livery, dna: &Dna, state: segment::State) -> Self {
		AgentBuilder {
			id: id,
			material: material,
			livery: livery,
			state: state,
			dna: dna.clone(),
			segments: Vec::new(),
		}
	}

	pub fn start(&mut self, transform: Transform, initial_vel: Option<Motion>, shape: &Shape) -> &mut Self {
		let segment = self.new_segment(shape,
		                               Winding::CW,
		                               transform,
		                               initial_vel,
		                               None,
		                               segment::TORSO | segment::MIDDLE);
		self.segments.clear();
		self.segments.push(segment);
		self
	}

	#[inline]
	pub fn add(&mut self,
	           parent_index: SegmentIndex,
	           attachment_index_offset: isize,
	           shape: &Shape,
	           flags: segment::Flags)
	           -> &mut Self {
		self.addw(parent_index,
		          attachment_index_offset,
		          shape,
		          Winding::CW,
		          flags | segment::MIDDLE)
	}
	#[inline]
	pub fn addl(&mut self,
	            parent_index: SegmentIndex,
	            attachment_index_offset: isize,
	            shape: &Shape,
	            flags: segment::Flags)
	            -> &mut Self {
		self.addw(parent_index,
		          attachment_index_offset,
		          shape,
		          Winding::CCW,
		          flags | segment::LEFT)
	}
	#[inline]
	pub fn addr(&mut self,
	            parent_index: SegmentIndex,
	            attachment_index_offset: isize,
	            shape: &Shape,
	            flags: segment::Flags)
	            -> &mut Self {
		self.addw(parent_index,
		          attachment_index_offset,
		          shape,
		          Winding::CW,
		          flags | segment::RIGHT)
	}

	pub fn addw(&mut self,
	            parent_index: SegmentIndex,
	            attachment_index_offset: isize,
	            shape: &Shape,
	            winding: Winding,
	            flags: segment::Flags)
	            -> &mut Self {
		let parent = self.segments[parent_index as usize].clone();//urgh!;
		let parent_pos = parent.transform.position;
		let parent_angle = parent.transform.angle;
		let parent_length = parent.mesh.shape.length() as isize;
		let attachment_index = ((attachment_index_offset + parent_length) % parent_length) as usize;
		let p0 = cgmath::Matrix2::from_angle(cgmath::rad(parent_angle)) * parent.mesh.vertices[attachment_index];
		let angle = f32::atan2(p0.y, p0.x);
		let r0 = p0.length() * parent.mesh.shape.radius();
		let r1 = shape.radius();
		let segment = self.new_segment(shape,
		                               winding,
		                               Transform::new(parent_pos + (p0 * (r0 + r1)), consts::PI / 2. + angle),
		                               None,
		                               parent.new_attachment(attachment_index as AttachmentIndex),
		                               flags);
		self.segments.push(segment);
		self
	}

	pub fn index(&self) -> SegmentIndex {
		match self.segments.len() {
			0 => 0,
			n => (n - 1) as SegmentIndex,
		}
	}

	fn new_segment(&mut self,
	               shape: &Shape,
	               winding: Winding,
	               transform: Transform,
	               motion: Option<Motion>,
	               attachment: Option<segment::Attachment>,
	               flags: segment::Flags)
	               -> segment::Segment {
		segment::Segment {
			index: self.segments.len() as SegmentIndex,
			transform: transform,
			motion: motion,
			mesh: Mesh::from_shape(shape.clone(), winding),
			material: self.material.clone(),
			livery: self.livery.clone(),
			state: self.state.clone(),
			attached_to: attachment,
			flags: flags,
		}
	}

	pub fn build(&self) -> Agent {
		let order = self.segments.len() as f32;
		let d0 = 2. * order;

		Agent::new(self.id,
		           d0,
		           order,
		           &self.dna,
		           self.segments.clone().into_boxed_slice())
	}
}
<|endoftext|>


<commit_before>use itertools::Itertools;
use regex::Regex;
use reqwest;
use rust_htslib::bcf;
use rust_htslib::bcf::Read;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::str;

#[derive(Serialize, Deserialize, Debug)]
struct Dgidb {
    #[serde(rename = "matchedTerms")]
    matched_terms: Vec<MatchedTerm>,
}

#[derive(Serialize, Deserialize, Debug)]
struct MatchedTerm {
    #[serde(rename = "geneName")]
    gene_name: String,
    interactions: Vec<Interaction>,
}

#[derive(Serialize, Deserialize, Debug)]
struct Interaction {
    #[serde(rename = "drugName")]
    drug_name: String,
    #[serde(rename = "interactionTypes")]
    interaction_types: Vec<String>,
}

pub fn annotate_dgidb(
    vcf_path: &str,
    api_path: String,
    field_name: &str,
) -> Result<(), Box<dyn Error>> {
    let gene_drug_interactions = request_interaction_drugs(vcf_path, api_path)?;
    modify_vcf_entries(vcf_path, gene_drug_interactions, field_name)
}

fn request_interaction_drugs(
    vcf_path: &str,
    mut api_path: String,
) -> Result<HashMap<String, Vec<(String, Vec<String>)>>, Box<dyn Error>> {
    let mut genes = collect_genes(vcf_path)?;
    api_path.push_str(genes.drain().join(",").as_str());
    let res: Dgidb = reqwest::get(&api_path)?.json()?;

    let mut gene_drug_interactions: HashMap<String, Vec<(String, Vec<String>)>> = HashMap::new();
    for term in res.matched_terms {
        if !term.interactions.is_empty() {
            gene_drug_interactions.insert(
                term.gene_name,
                term.interactions
                    .iter()
                    .map(|interaction| {
                        (
                            interaction.drug_name.clone(),
                            interaction.interaction_types.clone(),
                        )
                    })
                    .collect(),
            );
        }
    }
    Ok(gene_drug_interactions)
}

//TODO Remove split by ',' when updating to latest htslib release
fn collect_genes(vcf_path: &str) -> Result<HashSet<String>, Box<dyn Error>> {
    let mut total_genes = HashSet::new();
    let mut reader = bcf::Reader::from_path(vcf_path)?;
    //let all_genes = HashSet::new();
    for result in reader.records() {
        let mut rec = result?;
        let genes_opt = extract_genes(&mut rec)?;
        match genes_opt {
            Some(genes) => {
                for gene in genes {
                    total_genes.insert(gene);
                }
            }
            None => {}
        }
    }
    Ok(total_genes)
}

//TODO Remove split by ',' when updating to latest htslib release
fn extract_genes<'a>(
    rec: &'a mut bcf::Record,
) -> Result<Option<impl Iterator<Item = String> + 'a>, Box<dyn Error>> {
    let annotation = rec.info("ANN".as_bytes()).string()?;
    match annotation {
        Some(transcripts) => Ok(Some(transcripts[0].split(|c| *c == b',').map(
            |transcript| {
                str::from_utf8(transcript.split(|c| *c == b'|').nth(3).unwrap())
                    .unwrap()
                    .to_owned()
            },
        ))),
        None => Ok(None),
    }
}

fn modify_vcf_entries(
    vcf_path: &str,
    gene_drug_interactions: HashMap<String, Vec<(String, Vec<String>)>>,
    field_name: &str,
) -> Result<(), Box<dyn Error>> {
    let mut reader = bcf::Reader::from_path(vcf_path)?;
    let mut header = bcf::header::Header::from_template(reader.header());
    header.push_record(format!("##INFO=<ID={},Number=.,Type=String,Description=\"Combination of gene, drug, interaction types extracted from dgiDB. Each combination is pipe-seperated annotated as GENE|DRUG|TYPE\">", field_name).as_bytes());
    let mut writer = bcf::Writer::from_stdout(&header, true, true)?;

    for result in reader.records() {
        let mut rec = result?;
        writer.translate(&mut rec);
        let genes = extract_genes(&mut rec)?.map(|genes| genes.collect_vec());
        if let Some(genes) = genes {
            let field_entries = build_dgidb_field(&gene_drug_interactions, genes)?;
            let field_entries: Vec<&[u8]> = field_entries.iter().map(|v| v.as_slice()).collect();
            rec.push_info_string(field_name.as_bytes(), &field_entries[..])?;
        }
        writer.write(&rec)?;
    }
    Ok(())
}

fn build_dgidb_field(
    gene_drug_interactions: &HashMap<String, Vec<(String, Vec<String>)>>,
    genes: Vec<String>,
) -> Result<Vec<Vec<u8>>, Box<dyn Error>> {
    let mut field_entries: Vec<Vec<u8>> = Vec::new();
    let re = Regex::new(r"\s\(\w+\)").unwrap();
    for gene in genes.iter() {
        match gene_drug_interactions.get(gene) {
            Some(drug_interactions) => {
                drug_interactions
                    .iter()
                    .for_each(|(drug, interaction_types)| {
                        interaction_types.iter().for_each(|interaction_type| {
                            field_entries.push(
                                format!(
                                    "{g}|{d}|{t}",
                                    g = gene,
                                    d = re.replace(drug, ""),
                                    t = interaction_type
                                )
                                .as_bytes()
                                .to_vec(),
                            )
                        })
                    });
            }
            None => field_entries.push(format!("{g}|.|.", g = gene).as_bytes().to_vec()),
        }
    }
    Ok(field_entries)
}
<commit_msg>Fixed bug skipping drugs without interaction types<commit_after>use itertools::Itertools;
use regex::Regex;
use reqwest;
use rust_htslib::bcf;
use rust_htslib::bcf::Read;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::str;

#[derive(Serialize, Deserialize, Debug)]
struct Dgidb {
    #[serde(rename = "matchedTerms")]
    matched_terms: Vec<MatchedTerm>,
}

#[derive(Serialize, Deserialize, Debug)]
struct MatchedTerm {
    #[serde(rename = "geneName")]
    gene_name: String,
    interactions: Vec<Interaction>,
}

#[derive(Serialize, Deserialize, Debug)]
struct Interaction {
    #[serde(rename = "drugName")]
    drug_name: String,
    #[serde(rename = "interactionTypes")]
    interaction_types: Vec<String>,
}

pub fn annotate_dgidb(
    vcf_path: &str,
    api_path: String,
    field_name: &str,
) -> Result<(), Box<dyn Error>> {
    let gene_drug_interactions = request_interaction_drugs(vcf_path, api_path)?;
    modify_vcf_entries(vcf_path, gene_drug_interactions, field_name)
}

fn request_interaction_drugs(
    vcf_path: &str,
    mut api_path: String,
) -> Result<HashMap<String, Vec<(String, Vec<String>)>>, Box<dyn Error>> {
    let mut genes = collect_genes(vcf_path)?;
    api_path.push_str(genes.drain().join(",").as_str());
    let res: Dgidb = reqwest::get(&api_path)?.json()?;

    let mut gene_drug_interactions: HashMap<String, Vec<(String, Vec<String>)>> = HashMap::new();
    for term in res.matched_terms {
        if !term.interactions.is_empty() {
            gene_drug_interactions.insert(
                term.gene_name,
                term.interactions
                    .iter()
                    .map(|interaction| {
                        (
                            interaction.drug_name.clone(),
                            interaction.interaction_types.clone(),
                        )
                    })
                    .collect(),
            );
        }
    }
    Ok(gene_drug_interactions)
}

//TODO Remove split by ',' when updating to latest htslib release
fn collect_genes(vcf_path: &str) -> Result<HashSet<String>, Box<dyn Error>> {
    let mut total_genes = HashSet::new();
    let mut reader = bcf::Reader::from_path(vcf_path)?;
    //let all_genes = HashSet::new();
    for result in reader.records() {
        let mut rec = result?;
        let genes_opt = extract_genes(&mut rec)?;
        match genes_opt {
            Some(genes) => {
                for gene in genes {
                    total_genes.insert(gene);
                }
            }
            None => {}
        }
    }
    Ok(total_genes)
}

//TODO Remove split by ',' when updating to latest htslib release
fn extract_genes<'a>(
    rec: &'a mut bcf::Record,
) -> Result<Option<impl Iterator<Item = String> + 'a>, Box<dyn Error>> {
    let annotation = rec.info("ANN".as_bytes()).string()?;
    match annotation {
        Some(transcripts) => Ok(Some(transcripts[0].split(|c| *c == b',').map(
            |transcript| {
                str::from_utf8(transcript.split(|c| *c == b'|').nth(3).unwrap())
                    .unwrap()
                    .to_owned()
            },
        ))),
        None => Ok(None),
    }
}

fn modify_vcf_entries(
    vcf_path: &str,
    gene_drug_interactions: HashMap<String, Vec<(String, Vec<String>)>>,
    field_name: &str,
) -> Result<(), Box<dyn Error>> {
    let mut reader = bcf::Reader::from_path(vcf_path)?;
    let mut header = bcf::header::Header::from_template(reader.header());
    header.push_record(format!("##INFO=<ID={},Number=.,Type=String,Description=\"Combination of gene, drug, interaction types extracted from dgiDB. Each combination is pipe-seperated annotated as GENE|DRUG|TYPE\">", field_name).as_bytes());
    let mut writer = bcf::Writer::from_stdout(&header, true, true)?;

    for result in reader.records() {
        let mut rec = result?;
        writer.translate(&mut rec);
        let genes = extract_genes(&mut rec)?.map(|genes| genes.collect_vec());
        if let Some(genes) = genes {
            let field_entries = build_dgidb_field(&gene_drug_interactions, genes)?;
            let field_entries: Vec<&[u8]> = field_entries.iter().map(|v| v.as_slice()).collect();
            rec.push_info_string(field_name.as_bytes(), &field_entries[..])?;
        }
        writer.write(&rec)?;
    }
    Ok(())
}

fn build_dgidb_field(
    gene_drug_interactions: &HashMap<String, Vec<(String, Vec<String>)>>,
    genes: Vec<String>,
) -> Result<Vec<Vec<u8>>, Box<dyn Error>> {
    let mut field_entries: Vec<Vec<u8>> = Vec::new();
    let re = Regex::new(r"\s\(\w+\)").unwrap();
    dbg!(&gene_drug_interactions);
    for gene in genes.iter() {
        match gene_drug_interactions.get(gene) {
            Some(drug_interactions) => {
                drug_interactions
                    .iter()
                    .for_each(|(drug, interaction_types)| {
                        if !interaction_types.is_empty(){
                        interaction_types.iter().for_each(|interaction_type| {
                            field_entries.push(
                                format!(
                                    "{g}|{d}|{t}",
                                    g = gene,
                                    d = re.replace(drug, ""),
                                    t = interaction_type
                                )
                                .as_bytes()
                                .to_vec(),
                            )
                        })} else {
                            field_entries.push(
                                format!(
                                    "{g}|{d}|.",
                                    g = gene,
                                    d = re.replace(drug, "")
                                )
                                .as_bytes()
                                .to_vec(),
                            )
                        }

                    });
            }
            None => field_entries.push(format!("{g}|.|.", g = gene).as_bytes().to_vec()),
        }
    }
    Ok(field_entries)
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use std::process;

use cargo::util::{CliResult, Config};
use rustc_serialize::json;
use toml;

pub type Error = HashMap<String, String>;

#[derive(RustcDecodable)]
struct Flags {
    flag_manifest_path: String,
    flag_verbose: bool,
    flag_quiet: bool,
    flag_color: Option<String>,
}

pub const USAGE: &'static str = "
Usage:
    cargo verify-project [options] --manifest-path PATH
    cargo verify-project -h | --help

Options:
    -h, --help              Print this message
    --manifest-path PATH    Path to the manifest to verify
    -v, --verbose           Use verbose output
    -q, --quiet             No output printed to stdout
    --color WHEN            Coloring: auto, always, never
";

pub fn execute(args: Flags, config: &Config) -> CliResult<Option<Error>> {
    try!(config.shell().set_verbosity(args.flag_verbose, args.flag_quiet));
    try!(config.shell().set_color_config(args.flag_color.as_ref().map(|s| &s[..])));

    let mut contents = String::new();
    let file = File::open(&args.flag_manifest_path);
    match file.and_then(|mut f| f.read_to_string(&mut contents)) {
        Ok(_) => {},
        Err(e) => fail("invalid", &format!("error reading file: {}", e))
    };
    match toml::Parser::new(&contents).parse() {
        None => fail("invalid", "invalid-format"),
        Some(..) => {}
    };

    let mut h = HashMap::new();
    h.insert("success".to_string(), "true".to_string());
    Ok(Some(h))
}

fn fail(reason: &str, value: &str) -> ! {
    let mut h = HashMap::new();
    h.insert(reason.to_string(), value.to_string());
    println!("{}", json::encode(&h).unwrap());
    process::exit(1)
}
<commit_msg>Make verify-project able to verify the current working dir project<commit_after>use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use std::process;

use cargo::util::{CliResult, Config};
use rustc_serialize::json;
use toml;

pub type Error = HashMap<String, String>;

#[derive(RustcDecodable)]
struct Flags {
    flag_manifest_path: Option<String>,
    flag_verbose: bool,
    flag_quiet: bool,
    flag_color: Option<String>,
}

pub const USAGE: &'static str = "
Usage:
    cargo verify-project [options]
    cargo verify-project -h | --help

Options:
    -h, --help              Print this message
    --manifest-path PATH    Path to the manifest to verify
    -v, --verbose           Use verbose output
    -q, --quiet             No output printed to stdout
    --color WHEN            Coloring: auto, always, never
";

pub fn execute(args: Flags, config: &Config) -> CliResult<Option<Error>> {
    try!(config.shell().set_verbosity(args.flag_verbose, args.flag_quiet));
    try!(config.shell().set_color_config(args.flag_color.as_ref().map(|s| &s[..])));

    let mut contents = String::new();
    let filename = args.flag_manifest_path.unwrap_or("Cargo.toml".into());
    let file = File::open(&filename);
    match file.and_then(|mut f| f.read_to_string(&mut contents)) {
        Ok(_) => {},
        Err(e) => fail("invalid", &format!("error reading file: {}", e))
    };
    match toml::Parser::new(&contents).parse() {
        None => fail("invalid", "invalid-format"),
        Some(..) => {}
    };

    let mut h = HashMap::new();
    h.insert("success".to_string(), "true".to_string());
    Ok(Some(h))
}

fn fail(reason: &str, value: &str) -> ! {
    let mut h = HashMap::new();
    h.insert(reason.to_string(), value.to_string());
    println!("{}", json::encode(&h).unwrap());
    process::exit(1)
}
<|endoftext|>