<commit_before>use std::fmt;
use super::{Array, Dimension};

fn format_array<A, D: Dimension>(view: &Array<A, D>, f: &mut fmt::Formatter,
                                 format: |&mut fmt::Formatter, &A| -> fmt::Result)
                                -> fmt::Result
{
    let sz = view.dim.slice().len();
    if sz > 0 && f.width.is_none() {
        f.width = Some(4)
    }
    // None will be an empty iter.
    let mut last_index = match view.dim.first_index() {
        None => view.dim.clone(),
        Some(ix) => ix,
    };
    for _ in range(0, sz) {
        try!(write!(f, "["));
    }
    let mut first = true;
    // Simply use the indexed iterator, and take the index wraparounds
    // as cues for when to add []'s and how many to add.
    for (index, elt) in view.indexed_iter() {
        let mut update_index = false;
        for (i, (a, b)) in index.slice().iter().take(sz-1)
                        .zip(last_index.slice().iter())
                        .enumerate()
        {
            if a != b {
                // New row.
                // # of ['s needed
                let n = sz - i - 1;
                for _ in range(0, n) {
                    try!(write!(f, "]"));
                }
                try!(write!(f, ","));
                if f.flags & (1u << (fmt::rt::FlagAlternate as uint)) == 0 {
                    try!(write!(f, "\n"));
                }
                for _ in range(0, sz - n) {
                    try!(write!(f, " "));
                }
                for _ in range(0, n) {
                    try!(write!(f, "["));
                }
                first = true;
                update_index = true;
                break;
            }
        }
        if !first {
            try!(write!(f, ", "));
        }
        first = false;
        try!(format(f, elt));

        if update_index {
            last_index = index;
        }
    }
    for _ in range(0, sz) {
        try!(write!(f, "]"));
    }
    Ok(())
}

// NOTE: We can impl other fmt traits here
impl<'a, A: fmt::Show, D: Dimension> fmt::Show for Array<A, D>
{
    /// Format the array using `Show` and apply the formatting parameters used
    /// to each element.
    ///
    /// The array is shown in multiline style, unless the alternate form
    /// is used -- i.e. `{:#}`.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        format_array(self, f, |f, elt| elt.fmt(f))
    }
}

impl<'a, A: fmt::LowerExp, D: Dimension> fmt::LowerExp for Array<A, D>
{
    /// Format the array using `LowerExp` and apply the formatting parameters used
    /// to each element.
    ///
    /// The array is shown in multiline style, unless the alternate form
    /// is used -- i.e. `{:#e}`.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        format_array(self, f, |f, elt| elt.fmt(f))
    }
}

impl<'a, A: fmt::UpperExp, D: Dimension> fmt::UpperExp for Array<A, D>
{
    /// Format the array using `UpperExp` and apply the formatting parameters used
    /// to each element.
    ///
    /// The array is shown in multiline style, unless the alternate form
    /// is used -- i.e. `{:#E}`.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        format_array(self, f, |f, elt| elt.fmt(f))
    }
}

<commit_msg>arrayformat: Fix for private fields<commit_after>use std::fmt;
use super::{Array, Dimension};

fn format_array<A, D: Dimension>(view: &Array<A, D>, f: &mut fmt::Formatter,
                                 format: |&mut fmt::Formatter, &A| -> fmt::Result)
                                -> fmt::Result
{
    let sz = view.dim.slice().len();
    /* private nowadays
    if sz > 0 && f.width.is_none() {
        f.width = Some(4)
    }
    */
    // None will be an empty iter.
    let mut last_index = match view.dim.first_index() {
        None => view.dim.clone(),
        Some(ix) => ix,
    };
    for _ in range(0, sz) {
        try!(write!(f, "["));
    }
    let mut first = true;
    // Simply use the indexed iterator, and take the index wraparounds
    // as cues for when to add []'s and how many to add.
    for (index, elt) in view.indexed_iter() {
        let mut update_index = false;
        for (i, (a, b)) in index.slice().iter().take(sz-1)
                        .zip(last_index.slice().iter())
                        .enumerate()
        {
            if a != b {
                // New row.
                // # of ['s needed
                let n = sz - i - 1;
                for _ in range(0, n) {
                    try!(write!(f, "]"));
                }
                try!(write!(f, ","));
                if f.flags() & (1u << (fmt::rt::FlagAlternate as uint)) == 0 {
                    try!(write!(f, "\n"));
                }
                for _ in range(0, sz - n) {
                    try!(write!(f, " "));
                }
                for _ in range(0, n) {
                    try!(write!(f, "["));
                }
                first = true;
                update_index = true;
                break;
            }
        }
        if !first {
            try!(write!(f, ", "));
        }
        first = false;
        try!(format(f, elt));

        if update_index {
            last_index = index;
        }
    }
    for _ in range(0, sz) {
        try!(write!(f, "]"));
    }
    Ok(())
}

// NOTE: We can impl other fmt traits here
impl<'a, A: fmt::Show, D: Dimension> fmt::Show for Array<A, D>
{
    /// Format the array using `Show` and apply the formatting parameters used
    /// to each element.
    ///
    /// The array is shown in multiline style, unless the alternate form
    /// is used -- i.e. `{:#}`.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        format_array(self, f, |f, elt| elt.fmt(f))
    }
}

impl<'a, A: fmt::LowerExp, D: Dimension> fmt::LowerExp for Array<A, D>
{
    /// Format the array using `LowerExp` and apply the formatting parameters used
    /// to each element.
    ///
    /// The array is shown in multiline style, unless the alternate form
    /// is used -- i.e. `{:#e}`.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        format_array(self, f, |f, elt| elt.fmt(f))
    }
}

impl<'a, A: fmt::UpperExp, D: Dimension> fmt::UpperExp for Array<A, D>
{
    /// Format the array using `UpperExp` and apply the formatting parameters used
    /// to each element.
    ///
    /// The array is shown in multiline style, unless the alternate form
    /// is used -- i.e. `{:#E}`.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        format_array(self, f, |f, elt| elt.fmt(f))
    }
}

<|endoftext|>


<commit_before>use crowbook::Book;
use clap::{App, Arg, Format, ArgMatches, AppSettings};

use std::io::{self, Write};
use std::process::exit;
use std::fs;
use std::env;

/// Return the --lang option, if it is set
pub fn get_lang() -> Option<String> {
    let mut found = false;
    for arg in env::args() {
        if found {
            return Some(arg.clone());
        } else if arg == "--lang" || arg == "-L" {
            found = true;
        }
    }
    None
}

/// Prints an error on stderr and exit the program
pub fn print_error(s: &str) -> ! {
    writeln!(&mut io::stderr(),
             "{} {}",
             Format::Error(lformat!("Error:")),
             s)
        .unwrap();
    exit(0);
}

/// Gets the book options in a (key, value) list, or print an error
pub fn get_book_options<'a>(matches: &'a ArgMatches) -> Vec<(&'a str, &'a str)> {
    let mut output = vec![];
    if let Some(iter) = matches.values_of("set") {
        let v: Vec<_> = iter.collect();
        if v.len() % 2 != 0 {
            print_error(&lformat!("An odd number of arguments was passed to --set, but it takes \
                                   a list of key value pairs."));
        }

        for i in 0..v.len() / 2 {
            let key = v[i * 2];
            let value = v[i * 2 + 1];
            output.push((key, value));
        }
    }
    if matches.is_present("proofread") {
        output.push(("proofread", "true"));
    }
    output
}

/// Sets the book options according to command line arguments
/// Also print these options to a string, so it can be used at
/// the creation of a book to check that parameters are OK and t
/// then print them to file
pub fn set_book_options(book: &mut Book, matches: &ArgMatches) -> String {
    let mut output = String::new();
    let options = get_book_options(matches);

    for (key, value) in options {
        let res = book.options.set(key, value);
        if let Err(err) = res {
            print_error(&lformat!("Error in setting key {}: {}", key, err));
        }
        output.push_str(&format!("{}: {}\n", key, value));
    }
    output
}

/// create a book file with the command line arguments
/// and exit the process at the end
pub fn create_book(matches: &ArgMatches) -> ! {
    let mut f: Box<Write> = if let Some(book) = matches.value_of("BOOK") {
        if fs::metadata(book).is_ok() {
            print_error(&lformat!("Could not create file {}: it already exists!", book));
        }
        Box::new(fs::File::create(book).unwrap())
    } else {
        Box::new(io::stdout())
    };

    if let Some(values) = matches.values_of("create") {
        if matches.is_present("set") {
            let mut book = Book::new();
            let s = set_book_options(&mut book, matches);
            f.write_all(s.as_bytes()).unwrap();
        } else {
            f.write_all(lformat!("author: Your name
title: Your title
lang: en

# Uncomment and fill to generate files
# output.html: some_file.html
# output.epub: some_file.epub
# output.pdf: some_file.pdf

# Uncomment and fill to set cover image (for Epub)
# cover: some_cover.png\n").as_bytes())
                .unwrap();
        }
        f.write_all(lformat!("\n# List of chapters\n").as_bytes()).unwrap();
        for file in values {
            f.write_all(format!("+ {}\n", file).as_bytes()).unwrap();
        }
        if let Some(s) = matches.value_of("BOOK") {
            println!("{}",
                     lformat!("Created {}, now you'll have to complete it!", s));
        }
        exit(0);
    } else {
        unreachable!(); // because Clap takes care of it
    }
}

pub fn create_matches<'a>() -> (ArgMatches<'a>, String, String) {
    lazy_static! {
        static ref HELP: String = lformat!("Print help information");
        static ref VERSION: String = lformat!("Print version information");
        static ref ABOUT: String = lformat!("Render a Markdown book in EPUB, PDF or HTML.");
        static ref SINGLE: String = lformat!("Use a single Markdown file instead of a book configuration file");
        static ref VERBOSE: String = lformat!("Print warnings in parsing/rendering");
        static ref QUIET: String = lformat!("Don't print info/error messages");
        static ref PROOFREAD: String = lformat!("Enable proofreading");
        static ref CREATE: String = lformat!("Create a new book with existing Markdown files");
        static ref OUTPUT: String = lformat!("Specify output file");
        static ref LANG: String = lformat!("Set the runtime language used by Crowbook");
        static ref TO: String = lformat!("Generate specific format");
        static ref SET: String = lformat!("Set a list of book options");
        static ref LIST_OPTIONS: String = lformat!("List all possible options");
        static ref LIST_OPTIONS_MD: String = lformat!("List all possible options, formatted in Markdown");
        static ref PRINT_TEMPLATE: String = lformat!("Prints the default content of a template");
        static ref BOOK: String = lformat!("File containing the book configuration file, or a Markdown file when called with --single");
        static ref STATS: String = lformat!("Print some project statistics");
        static ref TEMPLATE: String = lformat!("\
{{bin}} {{version}} by {{author}}
{{about}}

USAGE:
    {{usage}}

FLAGS:
{{flags}}

OPTIONS:
{{options}}

ARGS:
{{positionals}}
");
    }

    let app = App::new("crowbook")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Élisabeth Henry <liz.henry@ouvaton.org>")
        .setting(AppSettings::UnifiedHelpMessage)
        .setting(AppSettings::HidePossibleValuesInHelp)
        .about(ABOUT.as_str())
        .arg(Arg::from_usage("-s, --single").help(SINGLE.as_str()))
        .arg(Arg::from_usage("-v, --verbose").help(VERBOSE.as_str()))
        .arg(Arg::from_usage("-q, --quiet")
            .help(QUIET.as_str())
            .conflicts_with("verbose"))
        .arg(Arg::from_usage("-h, --help").help(HELP.as_str()))
        .arg(Arg::from_usage("-V, --version").help(VERSION.as_str()))
        .arg(Arg::from_usage("-p, --proofread").help(PROOFREAD.as_str()))
        .arg(Arg::from_usage("-c, --create [FILES]...").help(CREATE.as_str()))
        .arg(Arg::from_usage("-o, --output [FILE]")
            .help(OUTPUT.as_str())
            .requires("to"))
        .arg(Arg::from_usage("-t, --to [FORMAT]")
            .help(TO.as_str())
            .possible_values(&["epub",
                               "pdf",
                               "html",
                               "tex",
                               "odt",
                               "html.dir",
                               "proofread.html",
                               "proofread.html.dir",
                               "proofread.pdf",
                               "proofread.tex"]))
        .arg(Arg::from_usage("--set [KEY_VALUES]")
            .help(SET.as_str())
            .min_values(2))
        .arg(Arg::from_usage("-l --list-options").help(LIST_OPTIONS.as_str()))
        .arg(Arg::from_usage("--list-options-md")
            .help(LIST_OPTIONS_MD.as_str())
             .hidden(true))
        .arg(Arg::from_usage("-L --lang [LANG]")
             .help(LANG.as_str()))
        .arg(Arg::from_usage("--print-template [TEMPLATE]").help(PRINT_TEMPLATE.as_str()))
        .arg(Arg::from_usage("--stats -S").help(STATS.as_str()))
        .arg(Arg::with_name("BOOK")
            .index(1)
            .help(BOOK.as_str()))
        .template(TEMPLATE.as_str());

    // Write help and version now since it `app` is moved when `get_matches` is run
    let mut help = vec![];
    app.write_help(&mut help).unwrap();
    let help = String::from_utf8(help).unwrap();
    let mut version = vec![];
    app.write_version(&mut version).unwrap();
    let version = String::from_utf8(version).unwrap();

    let matches = app.get_matches();

    pre_check(&matches);
    (matches, help, version)
}

/// Pre-check the matches to see if there isn't illegal options not detected by clap
fn pre_check(matches: &ArgMatches) {
    if matches.is_present("files") && !matches.is_present("create") {
        print_error(&lformat!("A list of additional files is only valid with the --create \
                               option."));
    }
}
<commit_msg>Modified the create example<commit_after>use crowbook::Book;
use clap::{App, Arg, Format, ArgMatches, AppSettings};

use std::io::{self, Write};
use std::process::exit;
use std::fs;
use std::env;

/// Return the --lang option, if it is set
pub fn get_lang() -> Option<String> {
    let mut found = false;
    for arg in env::args() {
        if found {
            return Some(arg.clone());
        } else if arg == "--lang" || arg == "-L" {
            found = true;
        }
    }
    None
}

/// Prints an error on stderr and exit the program
pub fn print_error(s: &str) -> ! {
    writeln!(&mut io::stderr(),
             "{} {}",
             Format::Error(lformat!("Error:")),
             s)
        .unwrap();
    exit(0);
}

/// Gets the book options in a (key, value) list, or print an error
pub fn get_book_options<'a>(matches: &'a ArgMatches) -> Vec<(&'a str, &'a str)> {
    let mut output = vec![];
    if let Some(iter) = matches.values_of("set") {
        let v: Vec<_> = iter.collect();
        if v.len() % 2 != 0 {
            print_error(&lformat!("An odd number of arguments was passed to --set, but it takes \
                                   a list of key value pairs."));
        }

        for i in 0..v.len() / 2 {
            let key = v[i * 2];
            let value = v[i * 2 + 1];
            output.push((key, value));
        }
    }
    if matches.is_present("proofread") {
        output.push(("proofread", "true"));
    }
    output
}

/// Sets the book options according to command line arguments
/// Also print these options to a string, so it can be used at
/// the creation of a book to check that parameters are OK and t
/// then print them to file
pub fn set_book_options(book: &mut Book, matches: &ArgMatches) -> String {
    let mut output = String::new();
    let options = get_book_options(matches);

    for (key, value) in options {
        let res = book.options.set(key, value);
        if let Err(err) = res {
            print_error(&lformat!("Error in setting key {}: {}", key, err));
        }
        output.push_str(&format!("{}: {}\n", key, value));
    }
    output
}

/// create a book file with the command line arguments
/// and exit the process at the end
pub fn create_book(matches: &ArgMatches) -> ! {
    let mut f: Box<Write> = if let Some(book) = matches.value_of("BOOK") {
        if fs::metadata(book).is_ok() {
            print_error(&lformat!("Could not create file {}: it already exists!", book));
        }
        Box::new(fs::File::create(book).unwrap())
    } else {
        Box::new(io::stdout())
    };

    if let Some(values) = matches.values_of("create") {
        if matches.is_present("set") {
            let mut book = Book::new();
            let s = set_book_options(&mut book, matches);
            f.write_all(s.as_bytes()).unwrap();
        } else {
            f.write_all(lformat!("author: Your name
title: Your title
lang: en

## Output formats

# Uncomment and fill to generate files
# output.html: some_file.html
# output.epub: some_file.epub
# output.pdf: some_file.pdf

# Or uncomment the following to generate PDF, HTML and EPUB files based on this file's name
# output: [pdf, epub, html]

# Uncomment and fill to set cover image (for EPUB)
# cover: some_cover.png\n").as_bytes())
                .unwrap();
        }
        f.write_all(lformat!("\n## List of chapters\n").as_bytes()).unwrap();
        for file in values {
            f.write_all(format!("+ {}\n", file).as_bytes()).unwrap();
        }
        if let Some(s) = matches.value_of("BOOK") {
            println!("{}",
                     lformat!("Created {}, now you'll have to complete it!", s));
        }
        exit(0);
    } else {
        unreachable!(); // because Clap takes care of it
    }
}

pub fn create_matches<'a>() -> (ArgMatches<'a>, String, String) {
    lazy_static! {
        static ref HELP: String = lformat!("Print help information");
        static ref VERSION: String = lformat!("Print version information");
        static ref ABOUT: String = lformat!("Render a Markdown book in EPUB, PDF or HTML.");
        static ref SINGLE: String = lformat!("Use a single Markdown file instead of a book configuration file");
        static ref VERBOSE: String = lformat!("Print warnings in parsing/rendering");
        static ref QUIET: String = lformat!("Don't print info/error messages");
        static ref PROOFREAD: String = lformat!("Enable proofreading");
        static ref CREATE: String = lformat!("Create a new book with existing Markdown files");
        static ref OUTPUT: String = lformat!("Specify output file");
        static ref LANG: String = lformat!("Set the runtime language used by Crowbook");
        static ref TO: String = lformat!("Generate specific format");
        static ref SET: String = lformat!("Set a list of book options");
        static ref LIST_OPTIONS: String = lformat!("List all possible options");
        static ref LIST_OPTIONS_MD: String = lformat!("List all possible options, formatted in Markdown");
        static ref PRINT_TEMPLATE: String = lformat!("Prints the default content of a template");
        static ref BOOK: String = lformat!("File containing the book configuration file, or a Markdown file when called with --single");
        static ref STATS: String = lformat!("Print some project statistics");
        static ref TEMPLATE: String = lformat!("\
{{bin}} {{version}} by {{author}}
{{about}}

USAGE:
    {{usage}}

FLAGS:
{{flags}}

OPTIONS:
{{options}}

ARGS:
{{positionals}}
");
    }

    let app = App::new("crowbook")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Élisabeth Henry <liz.henry@ouvaton.org>")
        .setting(AppSettings::UnifiedHelpMessage)
        .setting(AppSettings::HidePossibleValuesInHelp)
        .about(ABOUT.as_str())
        .arg(Arg::from_usage("-s, --single").help(SINGLE.as_str()))
        .arg(Arg::from_usage("-v, --verbose").help(VERBOSE.as_str()))
        .arg(Arg::from_usage("-q, --quiet")
            .help(QUIET.as_str())
            .conflicts_with("verbose"))
        .arg(Arg::from_usage("-h, --help").help(HELP.as_str()))
        .arg(Arg::from_usage("-V, --version").help(VERSION.as_str()))
        .arg(Arg::from_usage("-p, --proofread").help(PROOFREAD.as_str()))
        .arg(Arg::from_usage("-c, --create [FILES]...").help(CREATE.as_str()))
        .arg(Arg::from_usage("-o, --output [FILE]")
            .help(OUTPUT.as_str())
            .requires("to"))
        .arg(Arg::from_usage("-t, --to [FORMAT]")
            .help(TO.as_str())
            .possible_values(&["epub",
                               "pdf",
                               "html",
                               "tex",
                               "odt",
                               "html.dir",
                               "proofread.html",
                               "proofread.html.dir",
                               "proofread.pdf",
                               "proofread.tex"]))
        .arg(Arg::from_usage("--set [KEY_VALUES]")
            .help(SET.as_str())
            .min_values(2))
        .arg(Arg::from_usage("-l --list-options").help(LIST_OPTIONS.as_str()))
        .arg(Arg::from_usage("--list-options-md")
            .help(LIST_OPTIONS_MD.as_str())
             .hidden(true))
        .arg(Arg::from_usage("-L --lang [LANG]")
             .help(LANG.as_str()))
        .arg(Arg::from_usage("--print-template [TEMPLATE]").help(PRINT_TEMPLATE.as_str()))
        .arg(Arg::from_usage("--stats -S").help(STATS.as_str()))
        .arg(Arg::with_name("BOOK")
            .index(1)
            .help(BOOK.as_str()))
        .template(TEMPLATE.as_str());

    // Write help and version now since it `app` is moved when `get_matches` is run
    let mut help = vec![];
    app.write_help(&mut help).unwrap();
    let help = String::from_utf8(help).unwrap();
    let mut version = vec![];
    app.write_version(&mut version).unwrap();
    let version = String::from_utf8(version).unwrap();

    let matches = app.get_matches();

    pre_check(&matches);
    (matches, help, version)
}

/// Pre-check the matches to see if there isn't illegal options not detected by clap
fn pre_check(matches: &ArgMatches) {
    if matches.is_present("files") && !matches.is_present("create") {
        print_error(&lformat!("A list of additional files is only valid with the --create \
                               option."));
    }
}
<|endoftext|>


<commit_before>extern crate askama_shared as shared;
#[macro_use]
extern crate nom;
extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate quote;
extern crate syn;

mod input;
mod generator;
mod parser;

use input::Print;
use proc_macro::TokenStream;

#[proc_macro_derive(Template, attributes(template))]
pub fn derive_template(input: TokenStream) -> TokenStream {
    let ast: syn::DeriveInput = syn::parse(input).unwrap();
    match ast.data {
        syn::Data::Struct(ref data) => data,
        _ => panic!("#[derive(Template)] can only be used with structs"),
    };
    build_template(&ast).parse().unwrap()
}

/// Takes a `syn::DeriveInput` and generates source code for it
///
/// Reads the metadata from the `template()` attribute to get the template
/// metadata, then fetches the source from the filesystem. The source is
/// parsed, and the parse tree is fed to the code generator. Will print
/// the parse tree and/or generated source according to the `print` key's
/// value as passed to the `template()` attribute.
fn build_template(ast: &syn::DeriveInput) -> String {
    let data = input::TemplateInput::new(ast);
    let nodes = parser::parse(data.source.as_ref());
    if data.meta.print == Print::Ast || data.meta.print == Print::All {
        println!("{:?}", nodes);
    }
    let code = generator::generate(&data, &nodes);
    if data.meta.print == Print::Code || data.meta.print == Print::All {
        println!("{}", code);
    }
    code
}
<commit_msg>Rename variable for consistency<commit_after>extern crate askama_shared as shared;
#[macro_use]
extern crate nom;
extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate quote;
extern crate syn;

mod input;
mod generator;
mod parser;

use input::Print;
use proc_macro::TokenStream;

#[proc_macro_derive(Template, attributes(template))]
pub fn derive_template(input: TokenStream) -> TokenStream {
    let ast: syn::DeriveInput = syn::parse(input).unwrap();
    match ast.data {
        syn::Data::Struct(ref data) => data,
        _ => panic!("#[derive(Template)] can only be used with structs"),
    };
    build_template(&ast).parse().unwrap()
}

/// Takes a `syn::DeriveInput` and generates source code for it
///
/// Reads the metadata from the `template()` attribute to get the template
/// metadata, then fetches the source from the filesystem. The source is
/// parsed, and the parse tree is fed to the code generator. Will print
/// the parse tree and/or generated source according to the `print` key's
/// value as passed to the `template()` attribute.
fn build_template(ast: &syn::DeriveInput) -> String {
    let input = input::TemplateInput::new(ast);
    let nodes = parser::parse(input.source.as_ref());
    if input.meta.print == Print::Ast || input.meta.print == Print::All {
        println!("{:?}", nodes);
    }
    let code = generator::generate(&input, &nodes);
    if input.meta.print == Print::Code || input.meta.print == Print::All {
        println!("{}", code);
    }
    code
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, WriteBytesExt};
use std::io::{self, Write};

use color;

const BITMAPFILEHEADER_SIZE: u32 = 14;
const BITMAPINFOHEADER_SIZE: u32 = 40;
const BITMAPV4HEADER_SIZE: u32 = 108;

/// The representation of a BMP encoder.
pub struct BMPEncoder<'a, W: 'a> {
    writer: &'a mut W,
}

impl<'a, W: Write + 'a> BMPEncoder<'a, W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: &'a mut W) -> Self {
        BMPEncoder { writer: w }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```.
    pub fn encode(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        c: color::ColorType,
    ) -> io::Result<()> {
        let bmp_header_size = BITMAPFILEHEADER_SIZE;

        let (dib_header_size, written_pixel_size, palette_color_count) = get_pixel_info(c)?;
        let row_pad_size = (4 - (width * written_pixel_size) % 4) % 4; // each row must be padded to a multiple of 4 bytes

        let image_size = width
            .checked_mul(height)
            .ok_or(io::Error::new(
                io::ErrorKind::InvalidInput,
                "Overflowing dimensions",
            ))?
            .checked_mul(written_pixel_size)
            .ok_or(io::Error::new(
                io::ErrorKind::InvalidInput,
                "Overflowing dimensions",
            ))?
            .checked_add(height * row_pad_size)
            .ok_or(io::Error::new(
                io::ErrorKind::InvalidInput,
                "Overflowing dimensions",
            ))?;
        let palette_size = palette_color_count * 4; // all palette colors are BGRA
        let file_size = bmp_header_size + dib_header_size + palette_size + image_size;

        // write BMP header
        self.writer.write_u8(b'B')?;
        self.writer.write_u8(b'M')?;
        self.writer.write_u32::<LittleEndian>(file_size)?; // file size
        self.writer.write_u16::<LittleEndian>(0)?; // reserved 1
        self.writer.write_u16::<LittleEndian>(0)?; // reserved 2
        self.writer
            .write_u32::<LittleEndian>(bmp_header_size + dib_header_size + palette_size)?; // image data offset

        // write DIB header
        self.writer.write_u32::<LittleEndian>(dib_header_size)?;
        self.writer.write_i32::<LittleEndian>(width as i32)?;
        self.writer.write_i32::<LittleEndian>(height as i32)?;
        self.writer.write_u16::<LittleEndian>(1)?; // color planes
        self.writer
            .write_u16::<LittleEndian>((written_pixel_size * 8) as u16)?; // bits per pixel
        if dib_header_size >= BITMAPV4HEADER_SIZE {
            // Assume BGRA32
            self.writer.write_u32::<LittleEndian>(3)?; // compression method - bitfields
        } else {
            self.writer.write_u32::<LittleEndian>(0)?; // compression method - no compression
        }
        self.writer.write_u32::<LittleEndian>(image_size)?;
        self.writer.write_i32::<LittleEndian>(0)?; // horizontal ppm
        self.writer.write_i32::<LittleEndian>(0)?; // vertical ppm
        self.writer.write_u32::<LittleEndian>(palette_color_count)?;
        self.writer.write_u32::<LittleEndian>(0)?; // all colors are important
        if dib_header_size >= BITMAPV4HEADER_SIZE {
            // Assume BGRA32
            self.writer.write_u32::<LittleEndian>(0xff << 16)?; // red mask
            self.writer.write_u32::<LittleEndian>(0xff << 8)?; // green mask
            self.writer.write_u32::<LittleEndian>(0xff << 0)?; // blue mask
            self.writer.write_u32::<LittleEndian>(0xff << 24)?; // alpha mask
            self.writer.write_u32::<LittleEndian>(0x73524742)?; // colorspace - sRGB

            // endpoints (3x3) and gamma (3)
            for _ in 0..12 {
                self.writer.write_u32::<LittleEndian>(0)?;
            }
        }

        // write image data
        match c {
            color::ColorType::RGB(8) => self.encode_rgb(image, width, height, row_pad_size, 3)?,
            color::ColorType::RGBA(8) => self.encode_rgba(image, width, height, row_pad_size, 4)?,
            color::ColorType::Gray(8) => self.encode_gray(image, width, height, row_pad_size, 1)?,
            color::ColorType::GrayA(8) => {
                self.encode_gray(image, width, height, row_pad_size, 2)?
            }
            _ => {
                return Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    &get_unsupported_error_message(c)[..],
                ))
            }
        }

        Ok(())
    }

    fn encode_rgb(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                let r = image[pixel_start];
                let g = image[pixel_start + 1];
                let b = image[pixel_start + 2];
                // written as BGR
                self.writer.write_u8(b)?;
                self.writer.write_u8(g)?;
                self.writer.write_u8(r)?;
                // alpha is never written as it's not widely supported
            }

            self.write_row_pad(row_pad_size)?;
        }

        Ok(())
    }

    fn encode_rgba(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                let r = image[pixel_start];
                let g = image[pixel_start + 1];
                let b = image[pixel_start + 2];
                let a = image[pixel_start + 3];
                // written as BGRA
                self.writer.write_u8(b)?;
                self.writer.write_u8(g)?;
                self.writer.write_u8(r)?;
                self.writer.write_u8(a)?;
            }

            self.write_row_pad(row_pad_size)?;
        }

        Ok(())
    }

    fn encode_gray(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        // write grayscale palette
        for val in 0..256 {
            // each color is written as BGRA, where A is always 0 and since only grayscale is being written, B = G = R = index
            let val = val as u8;
            self.writer.write_u8(val)?;
            self.writer.write_u8(val)?;
            self.writer.write_u8(val)?;
            self.writer.write_u8(0)?;
        }

        // write image data
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                // color value is equal to the palette index
                self.writer.write_u8(image[pixel_start])?;
                // alpha is never written as it's not widely supported
            }

            self.write_row_pad(row_pad_size)?;
        }

        Ok(())
    }

    fn write_row_pad(&mut self, row_pad_size: u32) -> io::Result<()> {
        for _ in 0..row_pad_size {
            self.writer.write_u8(0)?;
        }

        Ok(())
    }
}

fn get_unsupported_error_message(c: color::ColorType) -> String {
    format!(
        "Unsupported color type {:?}.  Supported types: RGB(8), RGBA(8), Gray(8), GrayA(8).",
        c
    )
}

/// Returns a tuple representing: (dib header size, written pixel size, palette color count).
fn get_pixel_info(c: color::ColorType) -> io::Result<(u32, u32, u32)> {
    let sizes = match c {
        color::ColorType::RGB(8) => (BITMAPINFOHEADER_SIZE, 3, 0),
        color::ColorType::RGBA(8) => (BITMAPV4HEADER_SIZE, 4, 0),
        color::ColorType::Gray(8) => (BITMAPINFOHEADER_SIZE, 1, 256),
        color::ColorType::GrayA(8) => (BITMAPINFOHEADER_SIZE, 1, 256),
        _ => {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                &get_unsupported_error_message(c)[..],
            ))
        }
    };

    Ok(sizes)
}

#[cfg(test)]
mod tests {
    use super::super::BMPDecoder;
    use super::BMPEncoder;
    use color::ColorType;
    use image::ImageDecoder;
    use std::io::Cursor;

    fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec<u8> {
        let mut encoded_data = Vec::new();
        {
            let mut encoder = BMPEncoder::new(&mut encoded_data);
            encoder
                .encode(&image, width, height, c)
                .expect("could not encode image");
        }

        let decoder = BMPDecoder::new(Cursor::new(&encoded_data)).expect("failed to decode");
        decoder.read_image().expect("failed to decode")
    }

    #[test]
    fn round_trip_single_pixel_rgb() {
        let image = [255u8, 0, 0]; // single red pixel
        let decoded = round_trip_image(&image, 1, 1, ColorType::RGB(8));
        assert_eq!(3, decoded.len());
        assert_eq!(255, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
    }

    #[test]
    fn huge_files_return_error() {
        let mut encoded_data = Vec::new();
        let image = vec![0u8; 3 * 40_000 * 40_000]; // 40_000x40_000 pixels, 3 bytes per pixel, allocated on the heap
        let mut encoder = BMPEncoder::new(&mut encoded_data);
        let result = encoder.encode(&image, 40_000, 40_000, ColorType::RGB(8));
        assert!(result.is_err());
    }

    #[test]
    fn round_trip_single_pixel_rgba() {
        let image = [1, 2, 3, 4];
        let decoded = round_trip_image(&image, 1, 1, ColorType::RGBA(8));
        assert_eq!(&decoded[..], &image[..]);
    }

    #[test]
    fn round_trip_3px_rgb() {
        let image = [0u8; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel
        let _decoded = round_trip_image(&image, 3, 3, ColorType::RGB(8));
    }

    #[test]
    fn round_trip_gray() {
        let image = [0u8, 1, 2]; // 3 pixels
        let decoded = round_trip_image(&image, 3, 1, ColorType::Gray(8));
        // should be read back as 3 RGB pixels
        assert_eq!(9, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(1, decoded[3]);
        assert_eq!(1, decoded[4]);
        assert_eq!(1, decoded[5]);
        assert_eq!(2, decoded[6]);
        assert_eq!(2, decoded[7]);
        assert_eq!(2, decoded[8]);
    }

    #[test]
    fn round_trip_graya() {
        let image = [0u8, 0, 1, 0, 2, 0]; // 3 pixels, each with an alpha channel
        let decoded = round_trip_image(&image, 1, 3, ColorType::GrayA(8));
        // should be read back as 3 RGB pixels
        assert_eq!(9, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(1, decoded[3]);
        assert_eq!(1, decoded[4]);
        assert_eq!(1, decoded[5]);
        assert_eq!(2, decoded[6]);
        assert_eq!(2, decoded[7]);
        assert_eq!(2, decoded[8]);
    }
}
<commit_msg>Updated to use ok_or_else.<commit_after>use byteorder::{LittleEndian, WriteBytesExt};
use std::io::{self, Write};

use color;

const BITMAPFILEHEADER_SIZE: u32 = 14;
const BITMAPINFOHEADER_SIZE: u32 = 40;
const BITMAPV4HEADER_SIZE: u32 = 108;

/// The representation of a BMP encoder.
pub struct BMPEncoder<'a, W: 'a> {
    writer: &'a mut W,
}

impl<'a, W: Write + 'a> BMPEncoder<'a, W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: &'a mut W) -> Self {
        BMPEncoder { writer: w }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```.
    pub fn encode(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        c: color::ColorType,
    ) -> io::Result<()> {
        let bmp_header_size = BITMAPFILEHEADER_SIZE;

        let (dib_header_size, written_pixel_size, palette_color_count) = get_pixel_info(c)?;
        let row_pad_size = (4 - (width * written_pixel_size) % 4) % 4; // each row must be padded to a multiple of 4 bytes

        let make_invalid_input_err =
            || io::Error::new(io::ErrorKind::InvalidInput, "Overflowing dimensions");
        let image_size = width
            .checked_mul(height)
            .ok_or_else(make_invalid_input_err)?
            .checked_mul(written_pixel_size)
            .ok_or_else(make_invalid_input_err)?
            .checked_add(height * row_pad_size)
            .ok_or_else(make_invalid_input_err)?;
        let palette_size = palette_color_count * 4; // all palette colors are BGRA
        let file_size = bmp_header_size + dib_header_size + palette_size + image_size;

        // write BMP header
        self.writer.write_u8(b'B')?;
        self.writer.write_u8(b'M')?;
        self.writer.write_u32::<LittleEndian>(file_size)?; // file size
        self.writer.write_u16::<LittleEndian>(0)?; // reserved 1
        self.writer.write_u16::<LittleEndian>(0)?; // reserved 2
        self.writer
            .write_u32::<LittleEndian>(bmp_header_size + dib_header_size + palette_size)?; // image data offset

        // write DIB header
        self.writer.write_u32::<LittleEndian>(dib_header_size)?;
        self.writer.write_i32::<LittleEndian>(width as i32)?;
        self.writer.write_i32::<LittleEndian>(height as i32)?;
        self.writer.write_u16::<LittleEndian>(1)?; // color planes
        self.writer
            .write_u16::<LittleEndian>((written_pixel_size * 8) as u16)?; // bits per pixel
        if dib_header_size >= BITMAPV4HEADER_SIZE {
            // Assume BGRA32
            self.writer.write_u32::<LittleEndian>(3)?; // compression method - bitfields
        } else {
            self.writer.write_u32::<LittleEndian>(0)?; // compression method - no compression
        }
        self.writer.write_u32::<LittleEndian>(image_size)?;
        self.writer.write_i32::<LittleEndian>(0)?; // horizontal ppm
        self.writer.write_i32::<LittleEndian>(0)?; // vertical ppm
        self.writer.write_u32::<LittleEndian>(palette_color_count)?;
        self.writer.write_u32::<LittleEndian>(0)?; // all colors are important
        if dib_header_size >= BITMAPV4HEADER_SIZE {
            // Assume BGRA32
            self.writer.write_u32::<LittleEndian>(0xff << 16)?; // red mask
            self.writer.write_u32::<LittleEndian>(0xff << 8)?; // green mask
            self.writer.write_u32::<LittleEndian>(0xff << 0)?; // blue mask
            self.writer.write_u32::<LittleEndian>(0xff << 24)?; // alpha mask
            self.writer.write_u32::<LittleEndian>(0x73524742)?; // colorspace - sRGB

            // endpoints (3x3) and gamma (3)
            for _ in 0..12 {
                self.writer.write_u32::<LittleEndian>(0)?;
            }
        }

        // write image data
        match c {
            color::ColorType::RGB(8) => self.encode_rgb(image, width, height, row_pad_size, 3)?,
            color::ColorType::RGBA(8) => self.encode_rgba(image, width, height, row_pad_size, 4)?,
            color::ColorType::Gray(8) => self.encode_gray(image, width, height, row_pad_size, 1)?,
            color::ColorType::GrayA(8) => {
                self.encode_gray(image, width, height, row_pad_size, 2)?
            }
            _ => {
                return Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    &get_unsupported_error_message(c)[..],
                ))
            }
        }

        Ok(())
    }

    fn encode_rgb(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                let r = image[pixel_start];
                let g = image[pixel_start + 1];
                let b = image[pixel_start + 2];
                // written as BGR
                self.writer.write_u8(b)?;
                self.writer.write_u8(g)?;
                self.writer.write_u8(r)?;
                // alpha is never written as it's not widely supported
            }

            self.write_row_pad(row_pad_size)?;
        }

        Ok(())
    }

    fn encode_rgba(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                let r = image[pixel_start];
                let g = image[pixel_start + 1];
                let b = image[pixel_start + 2];
                let a = image[pixel_start + 3];
                // written as BGRA
                self.writer.write_u8(b)?;
                self.writer.write_u8(g)?;
                self.writer.write_u8(r)?;
                self.writer.write_u8(a)?;
            }

            self.write_row_pad(row_pad_size)?;
        }

        Ok(())
    }

    fn encode_gray(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        // write grayscale palette
        for val in 0..256 {
            // each color is written as BGRA, where A is always 0 and since only grayscale is being written, B = G = R = index
            let val = val as u8;
            self.writer.write_u8(val)?;
            self.writer.write_u8(val)?;
            self.writer.write_u8(val)?;
            self.writer.write_u8(0)?;
        }

        // write image data
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                // color value is equal to the palette index
                self.writer.write_u8(image[pixel_start])?;
                // alpha is never written as it's not widely supported
            }

            self.write_row_pad(row_pad_size)?;
        }

        Ok(())
    }

    fn write_row_pad(&mut self, row_pad_size: u32) -> io::Result<()> {
        for _ in 0..row_pad_size {
            self.writer.write_u8(0)?;
        }

        Ok(())
    }
}

fn get_unsupported_error_message(c: color::ColorType) -> String {
    format!(
        "Unsupported color type {:?}.  Supported types: RGB(8), RGBA(8), Gray(8), GrayA(8).",
        c
    )
}

/// Returns a tuple representing: (dib header size, written pixel size, palette color count).
fn get_pixel_info(c: color::ColorType) -> io::Result<(u32, u32, u32)> {
    let sizes = match c {
        color::ColorType::RGB(8) => (BITMAPINFOHEADER_SIZE, 3, 0),
        color::ColorType::RGBA(8) => (BITMAPV4HEADER_SIZE, 4, 0),
        color::ColorType::Gray(8) => (BITMAPINFOHEADER_SIZE, 1, 256),
        color::ColorType::GrayA(8) => (BITMAPINFOHEADER_SIZE, 1, 256),
        _ => {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                &get_unsupported_error_message(c)[..],
            ))
        }
    };

    Ok(sizes)
}

#[cfg(test)]
mod tests {
    use super::super::BMPDecoder;
    use super::BMPEncoder;
    use color::ColorType;
    use image::ImageDecoder;
    use std::io::Cursor;

    fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec<u8> {
        let mut encoded_data = Vec::new();
        {
            let mut encoder = BMPEncoder::new(&mut encoded_data);
            encoder
                .encode(&image, width, height, c)
                .expect("could not encode image");
        }

        let decoder = BMPDecoder::new(Cursor::new(&encoded_data)).expect("failed to decode");
        decoder.read_image().expect("failed to decode")
    }

    #[test]
    fn round_trip_single_pixel_rgb() {
        let image = [255u8, 0, 0]; // single red pixel
        let decoded = round_trip_image(&image, 1, 1, ColorType::RGB(8));
        assert_eq!(3, decoded.len());
        assert_eq!(255, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
    }

    #[test]
    fn huge_files_return_error() {
        let mut encoded_data = Vec::new();
        let image = vec![0u8; 3 * 40_000 * 40_000]; // 40_000x40_000 pixels, 3 bytes per pixel, allocated on the heap
        let mut encoder = BMPEncoder::new(&mut encoded_data);
        let result = encoder.encode(&image, 40_000, 40_000, ColorType::RGB(8));
        assert!(result.is_err());
    }

    #[test]
    fn round_trip_single_pixel_rgba() {
        let image = [1, 2, 3, 4];
        let decoded = round_trip_image(&image, 1, 1, ColorType::RGBA(8));
        assert_eq!(&decoded[..], &image[..]);
    }

    #[test]
    fn round_trip_3px_rgb() {
        let image = [0u8; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel
        let _decoded = round_trip_image(&image, 3, 3, ColorType::RGB(8));
    }

    #[test]
    fn round_trip_gray() {
        let image = [0u8, 1, 2]; // 3 pixels
        let decoded = round_trip_image(&image, 3, 1, ColorType::Gray(8));
        // should be read back as 3 RGB pixels
        assert_eq!(9, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(1, decoded[3]);
        assert_eq!(1, decoded[4]);
        assert_eq!(1, decoded[5]);
        assert_eq!(2, decoded[6]);
        assert_eq!(2, decoded[7]);
        assert_eq!(2, decoded[8]);
    }

    #[test]
    fn round_trip_graya() {
        let image = [0u8, 0, 1, 0, 2, 0]; // 3 pixels, each with an alpha channel
        let decoded = round_trip_image(&image, 1, 3, ColorType::GrayA(8));
        // should be read back as 3 RGB pixels
        assert_eq!(9, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(1, decoded[3]);
        assert_eq!(1, decoded[4]);
        assert_eq!(1, decoded[5]);
        assert_eq!(2, decoded[6]);
        assert_eq!(2, decoded[7]);
        assert_eq!(2, decoded[8]);
    }
}
<|endoftext|>


<commit_before>use lazy_static::lazy_static;
use regex::Regex;
use serde::{
    de::{self, Deserializer},
    ser::Serializer,
    Deserialize, Serialize,
};
use snafu::Snafu;

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct KeyValue(pub(crate) Option<String>);

impl<'de> Deserialize<'de> for KeyValue {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let x: &str = Deserialize::deserialize(deserializer)?;
        Ok(KeyValue(deserialize(x).map_err(de::Error::custom)?))
    }
}

impl Serialize for KeyValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let KeyValue(v) = self;
        serializer.serialize_str(&serialize(v))
    }
}

pub fn deserialize(input: &str) -> Result<Option<String>, Error> {
    if input == r"\u{0}" {
        Ok(None)
    } else {
        Ok(Some(decode_unicode_escapes(input)?))
    }
}

pub fn serialize(input: &Option<String>) -> String {
    if let Some(input) = input {
        input
            .chars()
            .map(|c| {
                let char_category = unic_ucd_category::GeneralCategory::of(c);

                if char_category.is_other()
                    || char_category.is_separator()
                    || char_category.is_mark()
                {
                    input.escape_unicode().to_string()
                } else {
                    input.to_string()
                }
            })
            .collect()
    } else {
        String::from(r"\u{0}")
    }
}

fn decode_unicode_escapes(input: &str) -> Result<String, Error> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"\\u\{([0-9A-Fa-f]{1,6})\}").expect("valid regex");
    }

    let new = RE.replace_all(input, |hex: &regex::Captures| {
        let number = u32::from_str_radix(hex.get(1).unwrap().as_str(), 16).unwrap();
        std::char::from_u32(number).unwrap().to_string()
    });

    Ok(new.to_string())
}

#[derive(Debug, Snafu)]
pub enum Error {
    #[snafu(display("std failed to parse `{}` as char: {}", input, source))]
    CharParseError {
        input: String,
        source: std::char::ParseCharError,
        backtrace: snafu::Backtrace,
    },
    #[snafu(display("Error parsing `{}` as char: {}", input, description))]
    CharFromStrError { input: String, description: String },
}

#[cfg(test)]
mod tests {
    use super::{decode_unicode_escapes, deserialize, serialize};
    use proptest::prelude::*;

    #[test]
    fn test_unicode_escapes() {
        assert_eq!("\u{35}", decode_unicode_escapes(r"\u{35}").unwrap());
        assert_eq!("5", decode_unicode_escapes(r"\u{35}").unwrap());

        assert_eq!("\u{5}", decode_unicode_escapes(r"\u{5}").unwrap());
    }

    #[test]
    fn roundtrips() {
        let x = r"0 1 2 3 4 5 6 7 8 9 0 \u{1F} = \
            \u{11} \u{17} \u{5} \u{12} \u{14} \u{19} \u{15} \u{9} \u{F} \u{10} \u{1B} \u{1D} \
            \u{1} \u{13} \u{4} \u{6} \u{7} \u{8} \u{A} \u{B} \u{C} ; ' \u{1C} \
            ` \u{1A} \u{18} \u{3} \u{16} \u{2} \u{E} \u{D} , . /";

        for s in x.split_whitespace() {
            assert_eq!(s.to_lowercase(), serialize(&deserialize(&s).unwrap()));
        }
    }

    proptest! {
        #[test]
        fn doesnt_crash(s in ".") {
            serialize(&deserialize(&s).unwrap())
        }
    }
}
<commit_msg>Add roundrip proptests for consistency<commit_after>use lazy_static::lazy_static;
use regex::Regex;
use serde::{
    de::{self, Deserializer},
    ser::Serializer,
    Deserialize, Serialize,
};
use snafu::Snafu;

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct KeyValue(pub(crate) Option<String>);

impl<'de> Deserialize<'de> for KeyValue {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let x: &str = Deserialize::deserialize(deserializer)?;
        Ok(KeyValue(deserialize(x).map_err(de::Error::custom)?))
    }
}

impl Serialize for KeyValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let KeyValue(v) = self;
        serializer.serialize_str(&serialize(v))
    }
}

pub fn deserialize(input: &str) -> Result<Option<String>, Error> {
    if input == r"\u{0}" {
        Ok(None)
    } else {
        Ok(Some(decode_unicode_escapes(input)?))
    }
}

pub fn serialize(input: &Option<String>) -> String {
    if let Some(input) = input {
        input
            .chars()
            .map(|c| {
                let char_category = unic_ucd_category::GeneralCategory::of(c);

                if char_category.is_other()
                    || char_category.is_separator()
                    || char_category.is_mark()
                {
                    input.escape_unicode().to_string()
                } else {
                    input.to_string()
                }
            })
            .collect()
    } else {
        String::from(r"\u{0}")
    }
}

fn decode_unicode_escapes(input: &str) -> Result<String, Error> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"\\u\{([0-9A-Fa-f]{1,6})\}").expect("valid regex");
    }

    let new = RE.replace_all(input, |hex: &regex::Captures| {
        let number = u32::from_str_radix(hex.get(1).unwrap().as_str(), 16).unwrap();
        std::char::from_u32(number).unwrap().to_string()
    });

    Ok(new.to_string())
}

#[derive(Debug, Snafu)]
pub enum Error {
    #[snafu(display("std failed to parse `{}` as char: {}", input, source))]
    CharParseError {
        input: String,
        source: std::char::ParseCharError,
        backtrace: snafu::Backtrace,
    },
    #[snafu(display("Error parsing `{}` as char: {}", input, description))]
    CharFromStrError { input: String, description: String },
}

#[cfg(test)]
mod tests {
    use super::{decode_unicode_escapes, deserialize, serialize};
    use proptest::prelude::*;

    #[test]
    fn test_unicode_escapes() {
        assert_eq!("\u{35}", decode_unicode_escapes(r"\u{35}").unwrap());
        assert_eq!("5", decode_unicode_escapes(r"\u{35}").unwrap());

        assert_eq!("\u{5}", decode_unicode_escapes(r"\u{5}").unwrap());
    }

    #[test]
    fn roundtrips() {
        let x = r"0 1 2 3 4 5 6 7 8 9 0 \u{1F} = \
            \u{11} \u{17} \u{5} \u{12} \u{14} \u{19} \u{15} \u{9} \u{F} \u{10} \u{1B} \u{1D} \
            \u{1} \u{13} \u{4} \u{6} \u{7} \u{8} \u{A} \u{B} \u{C} ; ' \u{1C} \
            ` \u{1A} \u{18} \u{3} \u{16} \u{2} \u{E} \u{D} , . /";

        for s in x.split_whitespace() {
            assert_eq!(s.to_lowercase(), serialize(&deserialize(&s).unwrap()));
        }
    }

    proptest! {
        #[test]
        fn doesnt_crash(s in ".") {
            serialize(&deserialize(&s).unwrap())
        }

        #[test]
        fn escape_unicode_rountrip(c: char) {
            prop_assume!(c != '\u{0}');
            let esc = c.escape_unicode().to_string();
            assert_eq!(c.to_string(), deserialize(&esc).unwrap().unwrap());
        }

        #[test]
        fn unescape_unicode_rountrip(c: char) {
            prop_assume!(c != '\u{0}');
            assert_eq!(c.to_string(), deserialize(&serialize(&Some(c.to_string()))).unwrap().unwrap());
        }
    }
}
<|endoftext|>


<commit_before>use super::*;
use pact_matching::models::*;
use pact_matching::models::matchingrules::*;
use pact_matching::models::generators::*;
use std::str::FromStr;
use std::collections::hash_map::HashMap;
use std::io::Read;
use tokio::runtime::Runtime;
use hyper::client::Client;
use hyper::client::connect::HttpConnector;
use hyper::{Request as HyperRequest, Response as HyperResponse};
use hyper::http::request::{Builder as RequestBuilder};
use hyper::Body;
use hyper::error::Error as HyperError;
use hyper::Method;
use hyper::http::header::HeaderName;
use hyper::http::header::CONTENT_TYPE;

pub fn join_paths(base: &String, path: String) -> String {
    let mut full_path = s!(base.trim_right_matches("/"));
    full_path.push('/');
    full_path.push_str(path.trim_left_matches("/"));
    full_path
}

fn setup_headers(builder: &mut RequestBuilder, headers: &Option<HashMap<String, String>>) -> Result<(), Box<Error>> {
    let mut hyper_headers = builder.headers_mut().unwrap();
    match headers {
        Some(header_map) => {
            for (k, v) in header_map {
                // FIXME?: Headers are not sent in "raw" mode.
                // Names are converted to lower case and values are parsed.
                hyper_headers.insert(
                    HeaderName::from_bytes(k.as_bytes())?,
                    v.parse()?
                );
            }

            if !header_map.keys().any(|k| k.to_lowercase() == "content-type") {
                hyper_headers.insert(CONTENT_TYPE, "application/json".parse()?);
            }
        }
    }
    Ok(())
}

fn make_request(base_url: &String, request: &Request, runtime: &mut Runtime) -> Result<HyperResponse<Body>, Box<Error>> {
    match Method::from_str(&request.method) {
        Ok(method) => {
            let mut url = join_paths(base_url, request.path.clone());
            if request.query.is_some() {
                url.push('?');
                url.push_str(&build_query_string(request.query.clone().unwrap()));
            }
            debug!("Making request to '{}'", url);
            let mut builder = HyperRequest::builder()
                .method(method)
                .uri(url);
            setup_headers(&mut builder, &request.headers())?;

            let mut hyper_request = builder
                .body(match request.body {
                    OptionalBody::Present(ref s) => Body::from(s.clone()),
                    OptionalBody::Null => {
                        if request.content_type() == "application/json" {
                            Body::from("null")
                        } else {
                            Body::empty()
                        }
                    },
                    _ => Body::empty()
                })?;

            runtime.block_on(
                Client::new().request(hyper_request)
            ).map_err(|err| err.into())

            /*
            let hyper_request = client.request(method, &url)
                .headers(setup_headers(&request.headers.clone()));
            match request.body {
                OptionalBody::Present(ref s) => hyper_request.body(s.as_slice()),
                OptionalBody::Null => {
                    if request.content_type() == "application/json" {
                        hyper_request.body("null")
                    } else {
                        hyper_request
                    }
                },
                _ => hyper_request
            }.send()
            */

        },
        Err(err) => Err(err.into())
    }
}

fn extract_headers(headers: &Headers) -> Option<HashMap<String, String>> {
    if headers.len() > 0 {
        Some(headers.iter().map(|h| (s!(h.name()), h.value_string()) ).collect())
    } else {
        None
    }
}

pub fn extract_body(response: &mut HyperResponse<Body>) -> OptionalBody {
    let mut buffer = Vec::new();
    match response.read_to_end(&mut buffer) {
        Ok(size) => if size > 0 {
                OptionalBody::Present(buffer)
            } else {
                OptionalBody::Empty
            },
        Err(err) => {
            warn!("Failed to read request body: {}", err);
            OptionalBody::Missing
        }
    }
}

fn hyper_response_to_pact_response(response: &mut HyperResponse<Body>) -> Response {
    Response {
        status: response.status().as_u16(),
        headers: extract_headers(&response.headers()),
        body: extract_body(response),
        matching_rules: MatchingRules::default(),
        generators: Generators::default()
    }
}

pub fn make_provider_request(provider: &ProviderInfo, request: &Request, runtime: &mut Runtime) -> Result<Response, Box<Error>> {
    debug!("Sending {:?} to provider", request);
    match make_request(&format!("{}://{}:{}{}", provider.protocol, provider.host, provider.port,
        provider.path), request, &mut runtime) {
        Ok(ref mut response) => {
            debug!("Received response: {:?}", response);
            Ok(hyper_response_to_pact_response(response))
        },
        Err(err) => {
            debug!("Request failed: {}", err);
            Err(err)
        }
    }
}

pub fn make_state_change_request(provider: &ProviderInfo, request: &Request) -> Result<(), String> {
    debug!("Sending {:?} to state change handler", request);
    let client = Client::new();
    match make_request(&provider.state_change_url.clone().unwrap(), request, &client) {
        Ok(ref mut response) => {
            debug!("Received response: {:?}", response);
            if response.status.is_success() {
                Ok(())
            } else {
                debug!("Request failed: {}", response.status);
                Err(format!("State change request failed: {}", response.status))
            }
        },
        Err(err) => {
            debug!("Request failed: {}", err);
            Err(format!("State change request failed: {}", err))
        }
    }
}

#[cfg(test)]
mod tests {
    use expectest::prelude::*;
    use super::join_paths;

    #[test]
    fn join_paths_test() {
        expect!(join_paths(&s!(""), s!(""))).to(be_equal_to(s!("/")));
        expect!(join_paths(&s!("/"), s!(""))).to(be_equal_to(s!("/")));
        expect!(join_paths(&s!(""), s!("/"))).to(be_equal_to(s!("/")));
        expect!(join_paths(&s!("/"), s!("/"))).to(be_equal_to(s!("/")));
        expect!(join_paths(&s!("/a/b"), s!("/c/d"))).to(be_equal_to(s!("/a/b/c/d")));
    }

}
<commit_msg>More work on futures<commit_after>use super::*;
use pact_matching::models::*;
use pact_matching::models::matchingrules::*;
use pact_matching::models::generators::*;
use std::str::FromStr;
use std::collections::hash_map::HashMap;
use std::io::Read;
use tokio::runtime::Runtime;
use hyper::client::Client;
use hyper::{Request as HyperRequest, Response as HyperResponse};
use hyper::http::request::{Builder as RequestBuilder};
use hyper::Body;
use hyper::error::Error as HyperError;
use hyper::client::ResponseFuture;
use hyper::Method;
use hyper::http::header::{HeaderMap, HeaderName};
use hyper::http::header::CONTENT_TYPE;
use hyper::rt::{Future, Stream};

pub fn join_paths(base: &String, path: String) -> String {
    let mut full_path = s!(base.trim_right_matches("/"));
    full_path.push('/');
    full_path.push_str(path.trim_left_matches("/"));
    full_path
}

fn setup_headers(builder: &mut RequestBuilder, headers: &Option<HashMap<String, String>>) -> Result<(), Box<Error>> {
    let mut hyper_headers = builder.headers_mut().unwrap();
    match headers {
        Some(header_map) => {
            for (k, v) in header_map {
                // FIXME?: Headers are not sent in "raw" mode.
                // Names are converted to lower case and values are parsed.
                hyper_headers.insert(
                    HeaderName::from_bytes(k.as_bytes())?,
                    v.parse()?
                );
            }

            if !header_map.keys().any(|k| k.to_lowercase() == "content-type") {
                hyper_headers.insert(CONTENT_TYPE, "application/json".parse()?);
            }
        }
    }
    Ok(())
}

fn make_request(base_url: &String, request: &Request) -> Result<ResponseFuture, Box<Error>> {
    match Method::from_str(&request.method) {
        Ok(method) => {
            let mut url = join_paths(base_url, request.path.clone());
            if request.query.is_some() {
                url.push('?');
                url.push_str(&build_query_string(request.query.clone().unwrap()));
            }
            debug!("Making request to '{}'", url);
            let mut builder = HyperRequest::builder()
                .method(method)
                .uri(url);
            setup_headers(&mut builder, &request.headers())?;

            let mut hyper_request = builder
                .body(match request.body {
                    OptionalBody::Present(ref s) => Body::from(s.clone()),
                    OptionalBody::Null => {
                        if request.content_type() == "application/json" {
                            Body::from("null")
                        } else {
                            Body::empty()
                        }
                    },
                    _ => Body::empty()
                })?;

            Ok(Client::new().request(hyper_request))
        },
        Err(err) => Err(err.into())
    }
}

fn extract_headers(headers: &HeaderMap) -> Option<HashMap<String, String>> {
    if headers.len() > 0 {
        Some(headers.iter()
            .map(|(name, value)| {
                (name.as_str().into(), value.to_str().unwrap().into())
            })
            .collect()
        )
    } else {
        None
    }
}

pub fn extract_body(hyper_body: Result<hyper::Chunk, HyperError>) -> Result<OptionalBody, HyperError> {
    match hyper_body {
        Ok(chunk) => {
            let bytes = chunk.into_bytes();
            if bytes.len() > 0 {
                Ok(OptionalBody::Present(bytes.to_vec()))
            } else {
                Ok(OptionalBody::Empty)
            }
        },
        Err(err) => {
            warn!("Failed to read request body: {}", err);
            Ok(OptionalBody::Missing)
        }
    }
}

fn hyper_response_to_pact_response(response: HyperResponse<Body>) -> impl Future<Item = Response, Error = HyperError> {
    debug!("Received response: {:?}", response);

    let status = response.status().as_u16();
    let headers = extract_headers(response.headers());

    response.into_body()
        .concat2()
        .then(extract_body)
        .map(|body| {
            Response {
                status: status,
                headers: headers,
                body: body,
                matching_rules: MatchingRules::default(),
                generators: Generators::default()
            }
        })
}

pub fn make_provider_request(provider: &ProviderInfo, request: &Request, runtime: &mut Runtime) -> Result<Response, Box<Error>> {
    debug!("Sending {:?} to provider", request);
    match make_request(&format!("{}://{}:{}{}", provider.protocol, provider.host, provider.port,
        provider.path), request) {
        Ok(ref mut response_future) => {
            let pact_response_future = response_future
                .and_then(hyper_response_to_pact_response);

            runtime.block_on(pact_response_future)
                .map_err(|err| err.into())
        },
        Err(err) => {
            debug!("Request failed: {}", err);
            Err(err)
        }
    }
}

pub fn make_state_change_request(provider: &ProviderInfo, request: &Request, runtime: &mut Runtime) -> Result<(), String> {
    debug!("Sending {:?} to state change handler", request);
    let client = Client::new();
    match make_request(&provider.state_change_url.clone().unwrap(), request) {
        Ok(ref mut response) => {
            debug!("Received response: {:?}", response);
            if response.status.is_success() {
                Ok(())
            } else {
                debug!("Request failed: {}", response.status);
                Err(format!("State change request failed: {}", response.status))
            }
        },
        Err(err) => {
            debug!("Request failed: {}", err);
            Err(format!("State change request failed: {}", err))
        }
    }
}

#[cfg(test)]
mod tests {
    use expectest::prelude::*;
    use super::join_paths;

    #[test]
    fn join_paths_test() {
        expect!(join_paths(&s!(""), s!(""))).to(be_equal_to(s!("/")));
        expect!(join_paths(&s!("/"), s!(""))).to(be_equal_to(s!("/")));
        expect!(join_paths(&s!(""), s!("/"))).to(be_equal_to(s!("/")));
        expect!(join_paths(&s!("/"), s!("/"))).to(be_equal_to(s!("/")));
        expect!(join_paths(&s!("/a/b"), s!("/c/d"))).to(be_equal_to(s!("/a/b/c/d")));
    }

}
<|endoftext|>


<commit_before>//! Gamepad utility functions.
//!
//! This is going to be a bit of a work-in-progress as gamepad input
//! gets fleshed out.  The `gilrs` crate needs help to add better
//! cross-platform support.  Why not give it a hand?
use gilrs::ConnectedGamepadsIterator;
use std::fmt;

pub use gilrs::{self, Event, Gamepad, Gilrs};

/// A unique identifier for a particular GamePad
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct GamepadId(pub(crate) gilrs::GamepadId);

use crate::context::Context;
use crate::error::GameResult;

/// Trait object defining a gamepad/joystick context.
pub trait GamepadContext {
    /// Returns a gamepad event.
    fn next_event(&mut self) -> Option<Event>;

    /// returns the `Gamepad` associated with an id.
    fn gamepad(&self, id: GamepadId) -> Gamepad;

    /// returns an iterator over the connected `Gamepad`s.
    fn gamepads(&self) -> GamepadsIterator;
}

/// A structure that contains gamepad state using `gilrs`.
pub struct GilrsGamepadContext {
    pub(crate) gilrs: Gilrs,
}

impl fmt::Debug for GilrsGamepadContext {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<GilrsGamepadContext: {:p}>", self)
    }
}

impl GilrsGamepadContext {
    pub(crate) fn new() -> GameResult<Self> {
        let gilrs = Gilrs::new()?;
        Ok(GilrsGamepadContext { gilrs })
    }

    /// Returns a `GilrsGamepadContext` with the entered Gilrs
    pub fn from(custom_gilrs: Gilrs) -> Self {
        GilrsGamepadContext {
            gilrs: custom_gilrs,
        }
    }
}

impl GamepadContext for GilrsGamepadContext {
    fn next_event(&mut self) -> Option<Event> {
        self.gilrs.next_event()
    }

    fn gamepad(&self, id: GamepadId) -> Gamepad {
        self.gilrs.gamepad(id.0)
    }

    fn gamepads(&self) -> GamepadsIterator {
        GamepadsIterator {
            wrapped: self.gilrs.gamepads(),
        }
    }
}

/// An iterator of the connected gamepads
pub struct GamepadsIterator<'a> {
    wrapped: ConnectedGamepadsIterator<'a>,
}

impl<'a> fmt::Debug for GamepadsIterator<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<GamepadsIterator: {:p}>", self)
    }
}

impl<'a> Iterator for GamepadsIterator<'a> {
    type Item = (GamepadId, Gamepad<'a>);

    fn next(&mut self) -> Option<(GamepadId, Gamepad<'a>)> {
        match self.wrapped.next() {
            Some((id, gp)) => Some((GamepadId(id), gp)),
            None => None,
        }
    }
}

/// A structure that implements [`GamepadContext`](trait.GamepadContext.html)
/// but does nothing; a stub for when you don't need it or are
/// on a platform that `gilrs` doesn't support.
#[derive(Debug, Clone, Copy, Default)]
pub(crate) struct NullGamepadContext {}

impl GamepadContext for NullGamepadContext {
    fn next_event(&mut self) -> Option<Event> {
        panic!("Gamepad module disabled")
    }

    fn gamepad(&self, _id: GamepadId) -> Gamepad {
        panic!("Gamepad module disabled")
    }

    fn gamepads(&self) -> GamepadsIterator {
        panic!("Gamepad module disabled")
    }
}

/// Returns the `Gamepad` associated with an `id`.
pub fn gamepad(ctx: &Context, id: GamepadId) -> Gamepad {
    ctx.gamepad_context.gamepad(id)
}

/// Return an iterator of all the `Gamepads` that are connected.
pub fn gamepads(ctx: &Context) -> GamepadsIterator {
    ctx.gamepad_context.gamepads()
}

// Properties gamepads might want:
// Number of buttons
// Number of axes
// Name/ID
// Is it connected?  (For consoles?)
// Whether or not they support vibration

/*
/// Lists all gamepads.  With metainfo, maybe?
pub fn list_gamepads() {
    unimplemented!()
}

/// Returns the state of the given axis on a gamepad.
pub fn axis() {
    unimplemented!()
}

/// Returns the state of the given button on a gamepad.
pub fn button_pressed() {
    unimplemented!()
}
*/

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

    #[test]
    fn gilrs_init() {
        assert!(GilrsGamepadContext::new().is_ok());
    }
}
<commit_msg>implement as a trait as opposed to a method<commit_after>//! Gamepad utility functions.
//!
//! This is going to be a bit of a work-in-progress as gamepad input
//! gets fleshed out.  The `gilrs` crate needs help to add better
//! cross-platform support.  Why not give it a hand?
use gilrs::ConnectedGamepadsIterator;
use std::fmt;

pub use gilrs::{self, Event, Gamepad, Gilrs};

/// A unique identifier for a particular GamePad
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct GamepadId(pub(crate) gilrs::GamepadId);

use crate::context::Context;
use crate::error::GameResult;

/// Trait object defining a gamepad/joystick context.
pub trait GamepadContext {
    /// Returns a gamepad event.
    fn next_event(&mut self) -> Option<Event>;

    /// returns the `Gamepad` associated with an id.
    fn gamepad(&self, id: GamepadId) -> Gamepad;

    /// returns an iterator over the connected `Gamepad`s.
    fn gamepads(&self) -> GamepadsIterator;
}

/// A structure that contains gamepad state using `gilrs`.
pub struct GilrsGamepadContext {
    pub(crate) gilrs: Gilrs,
}

impl fmt::Debug for GilrsGamepadContext {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<GilrsGamepadContext: {:p}>", self)
    }
}

impl GilrsGamepadContext {
    pub(crate) fn new() -> GameResult<Self> {
        let gilrs = Gilrs::new()?;
        Ok(GilrsGamepadContext { gilrs })
    }
}

impl From<Gilrs> for GilrsGamepadContext {
    /// Converts from a `Gilrs` custom instance to a `GilrsGamepadContext`
    fn from(gilrs: Gilrs) -> Self {
        Self { gilrs }
    }
}

impl GamepadContext for GilrsGamepadContext {
    fn next_event(&mut self) -> Option<Event> {
        self.gilrs.next_event()
    }

    fn gamepad(&self, id: GamepadId) -> Gamepad {
        self.gilrs.gamepad(id.0)
    }

    fn gamepads(&self) -> GamepadsIterator {
        GamepadsIterator {
            wrapped: self.gilrs.gamepads(),
        }
    }
}

/// An iterator of the connected gamepads
pub struct GamepadsIterator<'a> {
    wrapped: ConnectedGamepadsIterator<'a>,
}

impl<'a> fmt::Debug for GamepadsIterator<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<GamepadsIterator: {:p}>", self)
    }
}

impl<'a> Iterator for GamepadsIterator<'a> {
    type Item = (GamepadId, Gamepad<'a>);

    fn next(&mut self) -> Option<(GamepadId, Gamepad<'a>)> {
        match self.wrapped.next() {
            Some((id, gp)) => Some((GamepadId(id), gp)),
            None => None,
        }
    }
}

/// A structure that implements [`GamepadContext`](trait.GamepadContext.html)
/// but does nothing; a stub for when you don't need it or are
/// on a platform that `gilrs` doesn't support.
#[derive(Debug, Clone, Copy, Default)]
pub(crate) struct NullGamepadContext {}

impl GamepadContext for NullGamepadContext {
    fn next_event(&mut self) -> Option<Event> {
        panic!("Gamepad module disabled")
    }

    fn gamepad(&self, _id: GamepadId) -> Gamepad {
        panic!("Gamepad module disabled")
    }

    fn gamepads(&self) -> GamepadsIterator {
        panic!("Gamepad module disabled")
    }
}

/// Returns the `Gamepad` associated with an `id`.
pub fn gamepad(ctx: &Context, id: GamepadId) -> Gamepad {
    ctx.gamepad_context.gamepad(id)
}

/// Return an iterator of all the `Gamepads` that are connected.
pub fn gamepads(ctx: &Context) -> GamepadsIterator {
    ctx.gamepad_context.gamepads()
}

// Properties gamepads might want:
// Number of buttons
// Number of axes
// Name/ID
// Is it connected?  (For consoles?)
// Whether or not they support vibration

/*
/// Lists all gamepads.  With metainfo, maybe?
pub fn list_gamepads() {
    unimplemented!()
}

/// Returns the state of the given axis on a gamepad.
pub fn axis() {
    unimplemented!()
}

/// Returns the state of the given button on a gamepad.
pub fn button_pressed() {
    unimplemented!()
}
*/

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

    #[test]
    fn gilrs_init() {
        assert!(GilrsGamepadContext::new().is_ok());
    }
}
<|endoftext|>


<commit_before>
use byteorder::{BigEndian, WriteBytesExt};
use serializer::encoder::*;
use klv::ul::Ul;

pub struct Tag {
  pub id: [u8; 2],
  pub data: Vec<u8>
}

#[derive(Debug, Clone, PartialEq)]
pub struct DynamicTagList {
  pub tag: u16,
  pub identifier: Ul
}

impl Encoder for Tag {
  fn serialise(&self) -> Vec<u8> {
    let mut result = vec![];
    let mut t = self.data.clone();
    result.push(self.id[0]);
    result.push(self.id[1]);

    result.write_u16::<BigEndian>(t.len() as u16).unwrap();
    result.append(&mut t);
    result
  }
}

// pub fn parse_tag<R: Read>(stream: &mut R) -> Result<Option<Tag>, String> {
//   let mut data = vec![0; 2];
//   try!(stream.read_exact(&mut data).map_err(|e| e.to_string()));

//   match (data[0], data[1]) {
//     (0x00, 0x00) => {
//       println!("TAG");
//     },
//     _ => {
//       println!("Unknown TAG");
//     }
//   }
// }
<commit_msg>remove some commented code<commit_after>
use byteorder::{BigEndian, WriteBytesExt};
use serializer::encoder::*;
use klv::ul::Ul;

pub struct Tag {
  pub id: [u8; 2],
  pub data: Vec<u8>
}

#[derive(Debug, Clone, PartialEq)]
pub struct DynamicTagList {
  pub tag: u16,
  pub identifier: Ul
}

impl Encoder for Tag {
  fn serialise(&self) -> Vec<u8> {
    let mut result = vec![];
    let mut t = self.data.clone();
    result.push(self.id[0]);
    result.push(self.id[1]);

    result.write_u16::<BigEndian>(t.len() as u16).unwrap();
    result.append(&mut t);
    result
  }
}
<|endoftext|>


<commit_before>use metrics::{Metric, MetricValue};
use std::sync::{Mutex, MutexGuard};
use time::{get_time, Timespec};
use utils::EWMA;

const WINDOW: [f64; 3] = [1.0, 5.0, 15.0];

// A MeterSnapshot
#[derive(Debug)]
pub struct MeterSnapshot {
    pub count: i64,
    pub rates: [f64; 3],
    pub mean: f64,
}

// A StdMeter struct
#[derive(Debug)]
pub struct StdMeter {
    data: Mutex<MeterSnapshot>,
    ewma: [EWMA; 3],
    start: Timespec,
}

// A Meter trait
pub trait Meter: Metric {
    fn get_meter(&self) -> MeterSnapshot {
        self.snapshot()
    }

    fn export_metric(&self) -> MetricValue;

    fn snapshot(&self) -> MeterSnapshot;

    fn mark(&self, n: i64);

    fn tick(&mut self);

    fn rate(&self, rate: f64) -> f64;

    fn mean(&self) -> f64;

    fn count(&self) -> i64;
}

impl Meter for StdMeter {
    fn export_metric(&self) -> MetricValue {
        MetricValue::Meter(self.snapshot())
    }

    fn snapshot(&self) -> MeterSnapshot {
        let s = self.data.lock().unwrap();

        MeterSnapshot {
            count: s.count,
            rates: s.rates,
            mean: s.mean,
        }
    }

    fn mark(&self, n: i64) {
        let mut s = self.data.lock().unwrap();

        s.count += n;

        for i in 0..WINDOW.len() {
            self.ewma[i].update(n as usize);
        }

        self.update_snapshot(s);
    }

    fn tick(&mut self) {
        let s = self.data.lock().unwrap();

        for i in 0..WINDOW.len() {
            self.ewma[i].tick();
        }

        self.update_snapshot(s);
    }

    /// Return the given EWMA for a rate like 1, 5, 15 minutes
    fn rate(&self, rate: f64) -> f64 {
        let s = self.data.lock().unwrap();

        if let Some(pos) = WINDOW.iter().position(|w| *w == rate) {
            return s.rates[pos];
        }
        0.0
    }
    /// Return the mean rate
    fn mean(&self) -> f64 {
        let s = self.data.lock().unwrap();

        s.mean
    }

    fn count(&self) -> i64 {
        let s = self.data.lock().unwrap();

        s.count
    }
}

impl Metric for StdMeter {
    fn export_metric(&self) -> MetricValue {
        MetricValue::Meter(self.snapshot())
    }
}

impl Default for StdMeter {
    fn default() -> Self {
        StdMeter::new()
    }
}

impl StdMeter {
    fn update_snapshot(&self, mut s: MutexGuard<MeterSnapshot>) {
        for i in 0..WINDOW.len() {
            s.rates[i] = self.ewma[i].rate();
        }

        let diff = get_time() - self.start;
        s.mean = s.count as f64 / diff.num_seconds() as f64;
    }

    pub fn new() -> Self {
        let data: MeterSnapshot = MeterSnapshot {
            count: 0,
            rates: [0.0, 0.0, 0.0],
            mean: 0.0,
        };

        let ewma: [EWMA; 3] = [EWMA::new(1.0), EWMA::new(5.0), EWMA::new(15.0)];

        StdMeter {
            data: Mutex::new(data),
            ewma: ewma,
            start: get_time(),
        }
    }
}

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

    #[test]
    fn zero() {
        let m: StdMeter = StdMeter::new();
        let s: MeterSnapshot = m.snapshot();

        assert_eq!(s.count, 0);
    }

    #[test]
    fn non_zero() {
        let m: StdMeter = StdMeter::new();
        m.mark(3);

        let s: MeterSnapshot = m.snapshot();

        assert_eq!(s.count, 3);
    }

    #[test]
    fn snapshot() {
        let m: StdMeter = StdMeter::new();
        m.mark(1);
        m.mark(1);

        let s = m.snapshot();

        m.mark(1);

        assert_eq!(s.count, 2);
        assert_eq!(m.snapshot().count, 3);
    }

    // Test that decay works correctly
    #[test]
    fn decay() {
        let mut m: StdMeter = StdMeter::new();

        m.tick();
    }
}
<commit_msg>Remove unused Meter methods.<commit_after>use metrics::{Metric, MetricValue};
use std::sync::{Mutex, MutexGuard};
use time::{get_time, Timespec};
use utils::EWMA;

const WINDOW: [f64; 3] = [1.0, 5.0, 15.0];

// A MeterSnapshot
#[derive(Debug)]
pub struct MeterSnapshot {
    pub count: i64,
    pub rates: [f64; 3],
    pub mean: f64,
}

// A StdMeter struct
#[derive(Debug)]
pub struct StdMeter {
    data: Mutex<MeterSnapshot>,
    ewma: [EWMA; 3],
    start: Timespec,
}

// A Meter trait
pub trait Meter: Metric {
    fn snapshot(&self) -> MeterSnapshot;

    fn mark(&self, n: i64);

    fn tick(&mut self);

    fn rate(&self, rate: f64) -> f64;

    fn mean(&self) -> f64;

    fn count(&self) -> i64;
}

impl Meter for StdMeter {
    fn snapshot(&self) -> MeterSnapshot {
        let s = self.data.lock().unwrap();

        MeterSnapshot {
            count: s.count,
            rates: s.rates,
            mean: s.mean,
        }
    }

    fn mark(&self, n: i64) {
        let mut s = self.data.lock().unwrap();

        s.count += n;

        for i in 0..WINDOW.len() {
            self.ewma[i].update(n as usize);
        }

        self.update_snapshot(s);
    }

    fn tick(&mut self) {
        let s = self.data.lock().unwrap();

        for i in 0..WINDOW.len() {
            self.ewma[i].tick();
        }

        self.update_snapshot(s);
    }

    /// Return the given EWMA for a rate like 1, 5, 15 minutes
    fn rate(&self, rate: f64) -> f64 {
        let s = self.data.lock().unwrap();

        if let Some(pos) = WINDOW.iter().position(|w| *w == rate) {
            return s.rates[pos];
        }
        0.0
    }
    /// Return the mean rate
    fn mean(&self) -> f64 {
        let s = self.data.lock().unwrap();

        s.mean
    }

    fn count(&self) -> i64 {
        let s = self.data.lock().unwrap();

        s.count
    }
}

impl Metric for StdMeter {
    fn export_metric(&self) -> MetricValue {
        MetricValue::Meter(self.snapshot())
    }
}

impl Default for StdMeter {
    fn default() -> Self {
        StdMeter::new()
    }
}

impl StdMeter {
    fn update_snapshot(&self, mut s: MutexGuard<MeterSnapshot>) {
        for i in 0..WINDOW.len() {
            s.rates[i] = self.ewma[i].rate();
        }

        let diff = get_time() - self.start;
        s.mean = s.count as f64 / diff.num_seconds() as f64;
    }

    pub fn new() -> Self {
        let data: MeterSnapshot = MeterSnapshot {
            count: 0,
            rates: [0.0, 0.0, 0.0],
            mean: 0.0,
        };

        let ewma: [EWMA; 3] = [EWMA::new(1.0), EWMA::new(5.0), EWMA::new(15.0)];

        StdMeter {
            data: Mutex::new(data),
            ewma: ewma,
            start: get_time(),
        }
    }
}

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

    #[test]
    fn zero() {
        let m: StdMeter = StdMeter::new();
        let s: MeterSnapshot = m.snapshot();

        assert_eq!(s.count, 0);
    }

    #[test]
    fn non_zero() {
        let m: StdMeter = StdMeter::new();
        m.mark(3);

        let s: MeterSnapshot = m.snapshot();

        assert_eq!(s.count, 3);
    }

    #[test]
    fn snapshot() {
        let m: StdMeter = StdMeter::new();
        m.mark(1);
        m.mark(1);

        let s = m.snapshot();

        m.mark(1);

        assert_eq!(s.count, 2);
        assert_eq!(m.snapshot().count, 3);
    }

    // Test that decay works correctly
    #[test]
    fn decay() {
        let mut m: StdMeter = StdMeter::new();

        m.tick();
    }
}
<|endoftext|>


<commit_before>use autograd::Variable;
use tensor::NumLimits;
use nn::_functions::{Conv2dFArgs, ConvNdArgs, ConvNd, Dropout1d, Dropout2d, Threshold, LogSoftmax,
                     NLLLoss, LinearF, MaxPool2d};
pub use nn::_functions::{MaxPool2dArgs, DropoutArgs, NLLLossArgs};

pub fn max_pool2d<T: NumLimits>(input: Variable<T>,
                                kernel_size: (u32, u32),
                                args: &MaxPool2dArgs)
                                -> Variable<T> {
    let mut pool_args = args.v.clone();
    pool_args.kernel_size = vec![kernel_size.0, kernel_size.1];
    MaxPool2d::new(&pool_args)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn dropout<T: NumLimits>(input: Variable<T>, args: &DropoutArgs) -> Variable<T> {
    if args.training == false {
        return input.clone();
    }
    Dropout1d::new(args)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn dropout_<T: NumLimits>(input: Variable<T>, args: &DropoutArgs) -> Variable<T> {
    if args.training == false {
        return input.clone();
    }
    Dropout1d::new(args)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn dropout2d<T: NumLimits>(input: Variable<T>, args: &DropoutArgs) -> Variable<T> {
    if args.training == false {
        return input.clone();
    }
    Dropout2d::new(args)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn dropout2d_<T: NumLimits>(input: Variable<T>, args: &DropoutArgs) -> Variable<T> {
    if args.training == false {
        return input.clone();
    }
    Dropout2d::new(args)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn conv2d<T: NumLimits>(input: &mut Variable<T>,
                            weight: &mut Variable<T>,
                            mut bias_: Option<&mut Variable<T>>,
                            args: &mut Conv2dFArgs)
                            -> Variable<T> {
    let mut v = match bias_ {
        Some(ref mut bias) => {
            vec![input.clone().into(),
                 weight.clone().into(),
                 bias.clone().into()]
        }
        None => vec![input.clone().into(), weight.clone().into()],
    };
    ConvNd::new(&ConvNdArgs::from(args))
        .f(&mut v)
        .remove(0)
        .into()
}

pub fn linear<T: NumLimits>(input: &Variable<T>,
                            weight: &mut Variable<T>,
                            bias_: Option<&mut Variable<T>>)
                            -> Variable<T> {
    let v = if let Some(bias) = bias_ {
        vec![input.clone(), weight.clone(), bias.clone()]
    } else {
        vec![input.clone(), weight.clone()]
    };
    let mut v = v.into_iter().map(|v| v.into()).collect();
    LinearF::new().f(&mut v).remove(0).into()
}

pub fn relu<T: NumLimits>(input: Variable<T>) -> Variable<T> {
    Threshold::new(0., 0., false)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn relu_<T: NumLimits>(input: Variable<T>) -> Variable<T> {
    Threshold::new(0., 0., true)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn log_softmax<T: NumLimits>(input: Variable<T>) -> Variable<T> {
    LogSoftmax::new()
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn nll_loss<T: NumLimits>(input: Variable<T>,
                              target: Variable<i64>,
                              args: &NLLLossArgs)
                              -> Variable<T> {
    let mut kind_input = vec![input.clone().into(), target.clone().into()];
    NLLLoss::new(args).f(&mut kind_input).remove(0).into()

}
<commit_msg>kernel params are i32<commit_after>use autograd::Variable;
use tensor::NumLimits;
use nn::_functions::{Conv2dFArgs, ConvNdArgs, ConvNd, Dropout1d, Dropout2d, Threshold, LogSoftmax,
                     NLLLoss, LinearF, MaxPool2d};
pub use nn::_functions::{MaxPool2dArgs, DropoutArgs, NLLLossArgs};

pub fn max_pool2d<T: NumLimits>(input: Variable<T>,
                                kernel_size: (i32, i32),
                                args: &MaxPool2dArgs)
                                -> Variable<T> {
    let mut pool_args = args.v.clone();
    pool_args.kernel_size = vec![kernel_size.0, kernel_size.1];
    MaxPool2d::new(&pool_args)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn dropout<T: NumLimits>(input: Variable<T>, args: &DropoutArgs) -> Variable<T> {
    if args.training == false {
        return input.clone();
    }
    Dropout1d::new(args)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn dropout_<T: NumLimits>(input: Variable<T>, args: &DropoutArgs) -> Variable<T> {
    if args.training == false {
        return input.clone();
    }
    Dropout1d::new(args)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn dropout2d<T: NumLimits>(input: Variable<T>, args: &DropoutArgs) -> Variable<T> {
    if args.training == false {
        return input.clone();
    }
    Dropout2d::new(args)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn dropout2d_<T: NumLimits>(input: Variable<T>, args: &DropoutArgs) -> Variable<T> {
    if args.training == false {
        return input.clone();
    }
    Dropout2d::new(args)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn conv2d<T: NumLimits>(input: &mut Variable<T>,
                            weight: &mut Variable<T>,
                            mut bias_: Option<&mut Variable<T>>,
                            args: &mut Conv2dFArgs)
                            -> Variable<T> {
    let mut v = match bias_ {
        Some(ref mut bias) => {
            vec![input.clone().into(),
                 weight.clone().into(),
                 bias.clone().into()]
        }
        None => vec![input.clone().into(), weight.clone().into()],
    };
    ConvNd::new(&ConvNdArgs::from(args))
        .f(&mut v)
        .remove(0)
        .into()
}

pub fn linear<T: NumLimits>(input: &Variable<T>,
                            weight: &mut Variable<T>,
                            bias_: Option<&mut Variable<T>>)
                            -> Variable<T> {
    let v = if let Some(bias) = bias_ {
        vec![input.clone(), weight.clone(), bias.clone()]
    } else {
        vec![input.clone(), weight.clone()]
    };
    let mut v = v.into_iter().map(|v| v.into()).collect();
    LinearF::new().f(&mut v).remove(0).into()
}

pub fn relu<T: NumLimits>(input: Variable<T>) -> Variable<T> {
    Threshold::new(0., 0., false)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn relu_<T: NumLimits>(input: Variable<T>) -> Variable<T> {
    Threshold::new(0., 0., true)
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn log_softmax<T: NumLimits>(input: Variable<T>) -> Variable<T> {
    LogSoftmax::new()
        .f(&mut vec![input.clone().into()])
        .remove(0)
        .into()
}

pub fn nll_loss<T: NumLimits>(input: Variable<T>,
                              target: Variable<i64>,
                              args: &NLLLossArgs)
                              -> Variable<T> {
    let mut kind_input = vec![input.clone().into(), target.clone().into()];
    NLLLoss::new(args).f(&mut kind_input).remove(0).into()

}
<|endoftext|>