<commit_before>extern crate ansi_term;
extern crate hyper;
extern crate hyper_openssl;
extern crate pbr;
extern crate rayon;

use std::sync::{Arc, Mutex};

#[macro_use]
pub mod logs;

pub mod authorization;
pub mod bench;
pub mod cargo_helper;
pub mod client;
pub mod contentlength;
pub mod download;
pub mod filesize;
pub mod http_version;
pub mod response;
pub mod util;
pub mod write;

pub static mut SSL_SUPPORT: bool = false;

/// Represents a number of bytes, as `u64`.
pub type Bytes = u64;
/// Represents a 'chunk', which is just a piece of bytes.
type Chunk = Vec<u8>;
/// Represents a list of chunks
pub type Chunks = Vec<Chunk>;
/// Represents a shared mutable reference of chunks
pub type SChunks = Arc<Mutex<Chunks>>;
/// Represents an URL
pub type URL<'a> = &'a str;
/// MirrorsList is an alias that contain fast URLs to download the file
type MirrorsList<'a> = Vec<URL<'a>>;
<commit_msg>Remove mutable static variable<commit_after>extern crate ansi_term;
extern crate hyper;
extern crate hyper_openssl;
extern crate pbr;
extern crate rayon;

use std::sync::{Arc, Mutex};

#[macro_use]
pub mod logs;

pub mod authorization;
pub mod bench;
pub mod cargo_helper;
pub mod client;
pub mod contentlength;
pub mod download;
pub mod filesize;
pub mod http_version;
pub mod response;
pub mod util;
pub mod write;

/// Represents a number of bytes, as `u64`.
pub type Bytes = u64;
/// Represents a 'chunk', which is just a piece of bytes.
type Chunk = Vec<u8>;
/// Represents a list of chunks
pub type Chunks = Vec<Chunk>;
/// Represents a shared mutable reference of chunks
pub type SChunks = Arc<Mutex<Chunks>>;
/// Represents an URL
pub type URL<'a> = &'a str;
/// MirrorsList is an alias that contain fast URLs to download the file
type MirrorsList<'a> = Vec<URL<'a>>;
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::borrow::Borrow;
use std::hash::{Hash,Hasher};

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Param {
    Short(char),
    Long(String),
}

impl Borrow<str> for Param {
    fn borrow(&self) -> &str {
        if let Param::Long(ref string) = *self {
            string
        } else {
            ""
        }
    }
}

impl Borrow<char> for Param {
    fn borrow(&self) -> &char {
        if let Param::Short(ref ch) = *self {
            ch
        } else {
            const CH: &'static char = &'\0';
            CH
        }
    }
}

impl Hash for Param {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match *self {
            Param::Short(ref c) => c.hash(state),
            Param::Long(ref s) => s.hash(state)
        }
    }
}

#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
struct Rhs<T> {
    value: T,
    occurrences: usize,
}

impl<T> Rhs<T> {
    fn new<U: Into<T>>(value: U) -> Self {
        Rhs { value: value.into(), occurrences: 0 }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
enum OptRhs {
    With(Rhs<String>, bool),
    Empty,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
enum Value {
    Flag(Rhs<bool>),
    Opt(OptRhs),
}

/// Our homebrewed Arg Parser
#[derive(Clone, Debug, Default)]
pub struct ArgParser {
    params: HashMap<Param, Value>,
    invalid: Vec<Param>,
    pub args: Vec<String>,
}

impl ArgParser {
    /// Create a new ArgParser object
    ///
    /// The capacity specifies the initial capacity of the number parameters.
    /// Always good to set it at the number of flags and opts total.
    pub fn new(capacity: usize) -> Self {
        ArgParser {
            params: HashMap::with_capacity(capacity),
            invalid: Vec::new(),
            args: Vec::new(),
        }
    }

    /// Builder method for adding both short and long flags
    ///
    /// Flags are just parameters that have no assigned values. They are used
    /// for when certain features or options have been enabled for the application
    ///
    /// For example
    /// > ls -l --human-readable
    ///   ^  ^  ^
    ///   |  |  |
    ///   |  |  `-- A long flag to enable human readable numbers.
    ///   |  `-- A short flag to enable the long format.
    ///   `-- The command to list files.
    pub fn add_flag(mut self, short: &str, long: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.params.insert(Param::Short(short), Value::Flag(Rhs::default()));
        }
        if !long.is_empty() {
            self.params.insert(Param::Long(long.to_owned()), Value::Flag(Rhs::default()));
        }
        self
    }

    /// Builder method for adding both short and long opts
    ///
    /// Opts are parameters that hold assigned values. They are used
    /// for when certain features or options have been enabled for the application
    ///
    /// For example
    /// > ls -T 4 --color=always
    ///   ^  ^    ^
    ///   |  |    |
    ///   |  |    `-- A long opt to enable the use of color with value `always`.
    ///   |  `-- A short opt to set tab size to the value `4`.
    ///   `-- The command to list files.
    pub fn add_opt(mut self, short: &str, long: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.params.insert(Param::Short(short), Value::Opt(OptRhs::Empty));
        }
        if !long.is_empty() {
            self.params.insert(Param::Long(long.to_owned()), Value::Opt(OptRhs::Empty));
        }
        self
    }

    pub fn add_opt_default(mut self, short: &str, long: &str, default: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.params.insert(Param::Short(short), Value::Opt(OptRhs::With(Rhs::new(default), false)));
        }
        if !long.is_empty() {
            self.params.insert(Param::Long(long.to_owned()), Value::Opt(OptRhs::With(Rhs::new(default), false)));
        }
        self
    }

    /// Start parsing user inputted args for which flags and opts are used at
    /// runtime. The rest of the args that are not associated to opts get added
    /// to `ArgParser.args`.
    pub fn initialize<A: Iterator<Item=String>>(&mut self, args: A) {
        let mut args = args.skip(1);
        while let Some(arg) = args.next() {
            if arg.starts_with("--") {
                // Remove both dashes
                let arg = &arg[2..];
                if arg.is_empty() {
                    //Arg `--` means we are done parsing args, collect the rest
                    self.args.extend(args);
                    break;
                }
                if let Some(i) = arg.find('=') {
                    let (lhs, rhs) = arg.split_at(i);
                    let rhs = &rhs[1..]; // slice off the `=` char
                    match self.params.get_mut(lhs) {
                        Some(&mut Value::Opt(ref mut value)) => {
                            match value {
                                &mut OptRhs::With(ref mut opt_rhs, ref mut found) => {
                                    opt_rhs.value.clear();
                                    opt_rhs.value.push_str(rhs);
                                    opt_rhs.occurrences += 1;
                                    *found = true;
                                }
                                &mut OptRhs::Empty => {
                                    let mut rhs = Rhs::new(rhs);
                                    rhs.occurrences = 1;
                                    *value = OptRhs::With(rhs, true);
                                }
                            }
                        }
                        _ => self.invalid.push(Param::Long(lhs.to_owned())),
                    }
                }
                else {
                    match self.params.get_mut(arg) {
                        Some(&mut Value::Flag(ref mut rhs)) => {
                            rhs.value = true;
                            rhs.occurrences += 1;
                        }
                        Some(&mut Value::Opt(OptRhs::With(ref mut rhs, ref mut found))) => {
                            rhs.occurrences += 1;
                            *found = true;
                        }
                        _ => self.invalid.push(Param::Long(arg.to_owned())),
                    }
                }
            }
            else if arg.starts_with("-") {
                let mut chars = arg[1..].chars();
                while let Some(ch) = chars.next() {
                    match self.params.get_mut(&ch) {
                        Some(&mut Value::Flag(ref mut rhs)) => {
                            rhs.value = true;
                            rhs.occurrences += 1;
                        }
                        Some(&mut Value::Opt(ref mut opt_rhs)) => {
                            let rest: String = chars.collect();
                            if !rest.is_empty() {
                                *opt_rhs = OptRhs::With(Rhs::new(rest), true);
                            } else {
                                *opt_rhs = args.next().map(|a| OptRhs::With(Rhs::new(a), true)).unwrap_or(OptRhs::Empty);
                            }
                            break;
                        }
                        None => self.invalid.push(Param::Short(ch)),
                    }
                }
            }
            else {
                self.args.push(arg);
            }
        }
    }

    /// Check the number of time a Flag or Opt has been found after initialization.
    pub fn count
(&self, name: &P) -> usize
        where Param: Borrow

    {
        match self.params.get(name) {
            Some(&Value::Flag(ref rhs)) => rhs.occurrences,
            Some(&Value::Opt(OptRhs::With(ref rhs, _))) => rhs.occurrences,
            _ => 0,
        }
    }

    /// Check if a Flag or Opt has been found after initialization.
    pub fn flagged
(&self, name: &P) -> bool
        where Param: Borrow

    {
        match self.params.get(name) {
            Some(&Value::Flag(ref rhs)) => rhs.value,
            Some(&Value::Opt(OptRhs::With(_, found))) => found,
            _ => false,
        }
    }

    /// Modify the state of a flag. Use `true` if the flag is to be enabled. Use `false` to
    /// disable its use.
    pub fn set_flag<F: Hash + Eq + ?Sized>(&mut self, flag: &F, state: bool)
        where Param: Borrow<F>
    {
        if let Some(&mut Value::Flag(ref mut rhs)) = self.params.get_mut(flag) {
            rhs.value = state;
        }
    }

    /// Modify the state value of an opt. Use `Some(String)` to set if the opt is to be enabled and
    /// has been assigned a value from `String`. Use `None` to disable the opt's use.
    pub fn set_opt<O: Hash + Eq + ?Sized>(&mut self, opt: &O, state: Option<String>)
        where Param: Borrow<O>
    {
        if let Some(&mut Value::Opt(OptRhs::With(ref mut rhs, ref mut found))) = self.params.get_mut(opt) {
            match state {
                Some(input) => {
                    rhs.value = input;
                    *found = true;
                }
                None => *found = false,
            }
        }
    }

    /// Get the value of an Opt. If it has been set or defaulted, it will return a `Some(String)`
    /// value otherwise it will return None.
    pub fn get_opt<O: Hash + Eq + ?Sized>(&self, opt: &O) -> Option<String>
        where Param: Borrow<O>
    {
        if let Some(&Value::Opt(OptRhs::With(ref rhs, _))) = self.params.get(opt) {
            return Some(rhs.value.clone());
        }
        None
    }

    pub fn flagged_invalid(&self) -> Result<(), String> {
        if self.invalid.is_empty() {
            return Ok(());
        }

        let mut and: bool = false;
        let mut output =
            if self.invalid.len() == 1 {
                "Invalid parameter"
            } else {
                and = true;
                "Invalid parameters"
            }.to_owned();

        let mut iter = self.invalid.iter().peekable();
        while let Some(param) = iter.next() {
            match param {
                &Param::Short(ch) => {
                    output += " '-";
                    output.push(ch);
                    output.push('\'');
                }
                &Param::Long(ref s) => {
                    output += " '--";
                    output += s;
                    output.push('\'');
                }
            }
            if and && iter.peek().is_some() {
                output += " and";
            }
        }
        output.push('\n');
        Err(output)
    }
}

pub fn to_human_readable_string(size: u64) -> String {
    if size < 1024 {
        return format!("{}", size);
    }

    static UNITS: [&'static str; 7] = ["", "K", "M", "G", "T", "P", "E"];

    let sizef = size as f64;
    let digit_groups = (sizef.log10() / 1024f64.log10()) as i32;
    format!("{:.1}{}",
            sizef / 1024f64.powf(digit_groups as f64),
            UNITS[digit_groups as usize])
}

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

    #[test]
    fn stop_parsing() {
        let args = vec![String::from("binname"), String::from("-a"), String::from("--"), String::from("-v")];
        let mut parser = ArgParser::new(2);
        parser = parser.add_flag("a", "")
                       .add_flag("v", "");
        parser.initialize(args.into_iter());
        assert!(parser.flagged(&'a'));
        assert!(!parser.flagged(&'v'));
        assert!(parser.args[0] == "-v");
    }

    #[test]
    fn short_opts() {
        let args = vec![String::from("binname"), String::from("-asdf"), String::from("-f"), String::from("foo")];
        let mut parser = ArgParser::new(4);
        parser = parser.add_flag("a", "")
                       .add_flag("d", "")
                       .add_opt("s", "")
                       .add_opt("f", "");
        parser.initialize(args.into_iter());
        assert!(parser.flagged(&'a'));
        assert!(!parser.flagged(&'d'));
        assert!(parser.get_opt(&'s') == Some(String::from("df")));
        assert!(parser.get_opt(&'f') == Some(String::from("foo")));
    }

    #[test]
    fn long_opts() {
        let args = vec![String::from("binname"), String::from("--foo=bar")];
        let mut parser = ArgParser::new(4);
        parser = parser.add_opt("", "foo");
        parser.initialize(args.into_iter());
        assert!(parser.get_opt("foo") == Some(String::from("bar")));
    }
}
<commit_msg>Cleanup and remove `OptRhs`<commit_after>use std::collections::HashMap;
use std::borrow::Borrow;
use std::hash::{Hash,Hasher};

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Param {
    Short(char),
    Long(String),
}

impl Borrow<str> for Param {
    fn borrow(&self) -> &str {
        if let Param::Long(ref string) = *self {
            string
        } else {
            ""
        }
    }
}

impl Borrow<char> for Param {
    fn borrow(&self) -> &char {
        if let Param::Short(ref ch) = *self {
            ch
        } else {
            const CH: &'static char = &'\0';
            CH
        }
    }
}

impl Hash for Param {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match *self {
            Param::Short(ref c) => c.hash(state),
            Param::Long(ref s) => s.hash(state)
        }
    }
}

#[derive(Clone, Debug, Default, Eq, PartialEq)]
struct Rhs<T> {
    value: T,
    occurrences: usize,
}

impl<T> Rhs<T> {
    fn new<U: Into<T>>(value: U) -> Self {
        Rhs { value: value.into(), occurrences: 0 }
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Value {
    Flag(Rhs<bool>),
    Opt {
        rhs: Rhs<String>,
        found: bool,
    },
}

impl Value {
    fn new_opt() -> Self {
        Value::Opt { rhs: Rhs::new(""), found: false }
    }
    fn new_opt_default(value: &str) -> Self {
        Value::Opt { rhs: Rhs::new(value), found: false }
    }
}

/// Our homebrewed Arg Parser
#[derive(Clone, Debug, Default)]
pub struct ArgParser {
    params: HashMap<Param, Value>,
    invalid: Vec<Param>,
    pub args: Vec<String>,
}

impl ArgParser {
    /// Create a new ArgParser object
    ///
    /// The capacity specifies the initial capacity of the number parameters.
    /// Always good to set it at the number of flags and opts total.
    pub fn new(capacity: usize) -> Self {
        ArgParser {
            params: HashMap::with_capacity(capacity),
            invalid: Vec::new(),
            args: Vec::new(),
        }
    }

    /// Builder method for adding both short and long flags
    ///
    /// Flags are just parameters that have no assigned values. They are used
    /// for when certain features or options have been enabled for the application
    ///
    /// For example
    /// > ls -l --human-readable
    ///   ^  ^  ^
    ///   |  |  |
    ///   |  |  `-- A long flag to enable human readable numbers.
    ///   |  `-- A short flag to enable the long format.
    ///   `-- The command to list files.
    pub fn add_flag(mut self, short: &str, long: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.params.insert(Param::Short(short), Value::Flag(Rhs::default()));
        }
        if !long.is_empty() {
            self.params.insert(Param::Long(long.to_owned()), Value::Flag(Rhs::default()));
        }
        self
    }

    /// Builder method for adding both short and long opts
    ///
    /// Opts are parameters that hold assigned values. They are used
    /// for when certain features or options have been enabled for the application
    ///
    /// For example
    /// > ls -T 4 --color=always
    ///   ^  ^    ^
    ///   |  |    |
    ///   |  |    `-- A long opt to enable the use of color with value `always`.
    ///   |  `-- A short opt to set tab size to the value `4`.
    ///   `-- The command to list files.
    pub fn add_opt(mut self, short: &str, long: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.params.insert(Param::Short(short), Value::new_opt());
        }
        if !long.is_empty() {
            self.params.insert(Param::Long(long.to_owned()), Value::new_opt());
        }
        self
    }

    pub fn add_opt_default(mut self, short: &str, long: &str, default: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.params.insert(Param::Short(short), Value::new_opt_default(default));
        }
        if !long.is_empty() {
            self.params.insert(Param::Long(long.to_owned()), Value::new_opt_default(default));
        }
        self
    }

    /// Start parsing user inputted args for which flags and opts are used at
    /// runtime. The rest of the args that are not associated to opts get added
    /// to `ArgParser.args`.
    pub fn initialize<A: Iterator<Item=String>>(&mut self, args: A) {
        let mut args = args.skip(1);
        while let Some(arg) = args.next() {
            if arg.starts_with("--") {
                // Remove both dashes
                let arg = &arg[2..];
                if arg.is_empty() {
                    //Arg `--` means we are done parsing args, collect the rest
                    self.args.extend(args);
                    break;
                }
                if let Some(i) = arg.find('=') {
                    let (lhs, rhs) = arg.split_at(i);
                    let rhs = &rhs[1..]; // slice off the `=` char
                    match self.params.get_mut(lhs) {
                        Some(&mut Value::Opt { rhs: ref mut opt_rhs, ref mut found }) => {
                            if opt_rhs.value.is_empty() {
                                opt_rhs.occurrences = 1;
                            }
                            else {
                                opt_rhs.occurrences += 1;
                            }
                            opt_rhs.value.clear();
                            opt_rhs.value.push_str(rhs);
                            *found = true;
                        }
                        _ => self.invalid.push(Param::Long(lhs.to_owned())),
                    }
                }
                else {
                    match self.params.get_mut(arg) {
                        Some(&mut Value::Flag(ref mut rhs)) => {
                            rhs.value = true;
                            rhs.occurrences += 1;
                        }
                        Some(&mut Value::Opt { ref mut rhs, ref mut found }) => {
                            rhs.occurrences += 1;
                            *found = true;
                        }
                        _ => self.invalid.push(Param::Long(arg.to_owned())),
                    }
                }
            }
            else if arg.starts_with("-") {
                let mut chars = arg[1..].chars();
                while let Some(ch) = chars.next() {
                    match self.params.get_mut(&ch) {
                        Some(&mut Value::Flag(ref mut rhs)) => {
                            rhs.value = true;
                            rhs.occurrences += 1;
                        }
                        Some(&mut Value::Opt { ref mut rhs, ref mut found }) => {
                            let rest: String = chars.collect();
                            if !rest.is_empty() {
                                rhs.value = rest;
                                *found = true;
                            } else {
                                rhs.value = args.next().map(|a| {*found = true; a}).unwrap_or("".to_owned());
                            }
                            break;
                        }
                        None => self.invalid.push(Param::Short(ch)),
                    }
                }
            }
            else {
                self.args.push(arg);
            }
        }
    }

    /// Check the number of time a Flag or Opt has been found after initialization.
    pub fn count
(&self, name: &P) -> usize
        where Param: Borrow

    {
        match self.params.get(name) {
            Some(&Value::Flag(ref rhs)) => rhs.occurrences,
            Some(&Value::Opt { ref rhs, .. }) => rhs.occurrences,
            _ => 0,
        }
    }

    /// Check if a Flag or Opt has been found after initialization.
    pub fn flagged
(&self, name: &P) -> bool
        where Param: Borrow

    {
        match self.params.get(name) {
            Some(&Value::Flag(ref rhs)) => rhs.value,
            Some(&Value::Opt { found, .. }) => found,
            _ => false,
        }
    }

    /// Modify the state of a flag. Use `true` if the flag is to be enabled. Use `false` to
    /// disable its use.
    pub fn set_flag<F: Hash + Eq + ?Sized>(&mut self, flag: &F, state: bool)
        where Param: Borrow<F>
    {
        if let Some(&mut Value::Flag(ref mut rhs)) = self.params.get_mut(flag) {
            rhs.value = state;
        }
    }

    /// Modify the state value of an opt. Use `Some(String)` to set if the opt is to be enabled and
    /// has been assigned a value from `String`. Use `None` to disable the opt's use.
    pub fn set_opt<O: Hash + Eq + ?Sized>(&mut self, opt: &O, state: Option<String>)
        where Param: Borrow<O>
    {
        if let Some(&mut Value::Opt { ref mut rhs, ref mut found }) = self.params.get_mut(opt) {
            match state {
                Some(input) => {
                    rhs.value = input;
                    *found = true;
                }
                None => *found = false,
            }
        }
    }

    /// Get the value of an Opt. If it has been set or defaulted, it will return a `Some(String)`
    /// value otherwise it will return None.
    pub fn get_opt<O: Hash + Eq + ?Sized>(&self, opt: &O) -> Option<String>
        where Param: Borrow<O>
    {
        if let Some(&Value::Opt { ref rhs, .. }) = self.params.get(opt) {
            return Some(rhs.value.clone());
        }
        None
    }

    pub fn flagged_invalid(&self) -> Result<(), String> {
        if self.invalid.is_empty() {
            return Ok(());
        }

        let mut and: bool = false;
        let mut output =
            if self.invalid.len() == 1 {
                "Invalid parameter"
            } else {
                and = true;
                "Invalid parameters"
            }.to_owned();

        let mut iter = self.invalid.iter().peekable();
        while let Some(param) = iter.next() {
            match param {
                &Param::Short(ch) => {
                    output += " '-";
                    output.push(ch);
                    output.push('\'');
                }
                &Param::Long(ref s) => {
                    output += " '--";
                    output += s;
                    output.push('\'');
                }
            }
            if and && iter.peek().is_some() {
                output += " and";
            }
        }
        output.push('\n');
        Err(output)
    }
}

pub fn to_human_readable_string(size: u64) -> String {
    if size < 1024 {
        return format!("{}", size);
    }

    static UNITS: [&'static str; 7] = ["", "K", "M", "G", "T", "P", "E"];

    let sizef = size as f64;
    let digit_groups = (sizef.log10() / 1024f64.log10()) as i32;
    format!("{:.1}{}",
            sizef / 1024f64.powf(digit_groups as f64),
            UNITS[digit_groups as usize])
}

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

    #[test]
    fn stop_parsing() {
        let args = vec![String::from("binname"), String::from("-a"), String::from("--"), String::from("-v")];
        let mut parser = ArgParser::new(2);
        parser = parser.add_flag("a", "")
                       .add_flag("v", "");
        parser.initialize(args.into_iter());
        assert!(parser.flagged(&'a'));
        assert!(!parser.flagged(&'v'));
        assert!(parser.args[0] == "-v");
    }

    #[test]
    fn short_opts() {
        let args = vec![String::from("binname"), String::from("-asdf"), String::from("-f"), String::from("foo")];
        let mut parser = ArgParser::new(4);
        parser = parser.add_flag("a", "")
                       .add_flag("d", "")
                       .add_opt("s", "")
                       .add_opt("f", "");
        parser.initialize(args.into_iter());
        assert!(parser.flagged(&'a'));
        assert!(!parser.flagged(&'d'));
        assert!(parser.get_opt(&'s') == Some(String::from("df")));
        assert!(parser.get_opt(&'f') == Some(String::from("foo")));
    }

    #[test]
    fn long_opts() {
        let args = vec![String::from("binname"), String::from("--foo=bar")];
        let mut parser = ArgParser::new(4);
        parser = parser.add_opt("", "foo");
        parser.initialize(args.into_iter());
        assert!(parser.get_opt("foo") == Some(String::from("bar")));
    }
}
<|endoftext|>


<commit_before>#![feature(vec_push_all)]

pub struct JsonEncoder {
    buffer: Vec<u8>
}

impl JsonEncoder {
    pub fn new() -> JsonEncoder {
        JsonEncoder{buffer: Vec::new()}
    }

    #[inline(always)]
    pub fn encode_raw(&mut self, raw: &[u8]) {
        self.buffer.push_all(raw);
    }

    pub fn into_vec(self) -> Vec<u8> {
        self.buffer
    }

    pub fn with_buf<F>(&mut self, f: F) where F: Fn(&mut Vec<u8>) {
        f(&mut self.buffer);
    }

    #[inline(always)]
    pub fn encode_str_noescape(&mut self, raw_str: &str) {
        self.buffer.push(b'"');
        self.buffer.push_all(raw_str.as_bytes());
        self.buffer.push(b'"');
    }

    fn escape_bytes(&mut self, bytes: &[u8]) {
        let mut start = 0;

        for (i, byte) in bytes.iter().enumerate() {
            let escaped = match *byte {
                b'"' => b"\\\"",
                b'\\' => b"\\\\",
                b'\x08' => b"\\b",
                b'\x0c' => b"\\f",
                b'\n' => b"\\n",
                b'\r' => b"\\r",
                b'\t' => b"\\t",
                _ => {
                    continue;
                }
            };

            if start < i {
                self.encode_raw(&bytes[start..i]);
            }

            self.encode_raw(escaped);

            start = i + 1;
        }

        if start != bytes.len() {
            self.encode_raw(&bytes[start..]);
        }
    }

    pub fn encode_decimal_str(&mut self, value: u64) {
        self.buffer.push(b'"');
        self.encode_u64_decimal(value);
        self.buffer.push(b'"');
    }

    // encodes as decimal string
    #[inline(always)]
    fn encode_u64_decimal(&mut self, value: u64) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 20;

        if value == 0 {
            self.buffer.push(b'0');
            return;
        }

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    #[inline(always)]
    pub fn encode_str(&mut self, s: &str) {
        self.buffer.push(b'"');
        self.escape_bytes(s.as_bytes());
        self.buffer.push(b'"');
    }

    #[inline(always)]
    pub fn encode_i32(&mut self, value: i32) {
        if value == 0 {
            self.buffer.push(b'0');
        } else if value > 0 {
            self.encode_u31(value as u32);
        } else {
            self.buffer.push(b'-');
            self.encode_u31((-value) as u32);
        }
    }

    // encodes a 31-bit unsigned integer != 0
    fn encode_u31(&mut self, value: u32) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 10;
        debug_assert!(value != 0);

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    pub fn encode_obj<F>(&mut self, f: F) where F: Fn(&mut JsonObjectEncoder) {
        self.buffer.push(b'{');
        {
            f(&mut JsonObjectEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b'}');
    }

    pub fn encode_array<F>(&mut self, f: F) where F: Fn(&mut JsonArrayEncoder) {
        self.buffer.push(b'[');
        {
            f(&mut JsonArrayEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b']');
    }

}

pub struct JsonObjectEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonObjectEncoder<'a> {
    // XXX: name MAY NOT include escapable characters
    #[inline(always)]
    pub fn encode_field<F:Fn(&mut JsonEncoder)>(&mut self, name: &str, f: F) {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        self.js.encode_str_noescape(name);
        self.js.buffer.push(b':');

        f(self.js);
    }

    #[inline(always)]
    pub fn encode_field_array<F:Fn(&mut JsonArrayEncoder)>(&mut self, name: &str, f: F) {
        self.encode_field(name, |js| js.encode_array(|jsa| f(jsa)));
    }

    #[inline(always)]
    pub fn encode_field_i32(&mut self, name: &str, val: i32) {
        self.encode_field(name, |js| js.encode_i32(val));
    }

    #[inline(always)]
    pub fn encode_field_str(&mut self, name: &str, s: &str) {
        self.encode_field(name, |js| js.encode_str(s));
    }

}

pub struct JsonArrayEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonArrayEncoder<'a> {
    #[inline(always)]
    pub fn encode_elm<F:Fn(&mut JsonEncoder)>(&mut self, f: F) {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        f(self.js);
    }

    #[inline(always)]
    pub fn encode_elm_i32(&mut self, val: i32) {
        self.encode_elm(|j| j.encode_i32(val));
    }

    #[inline(always)]
    pub fn encode_elm_str(&mut self, s: &str) {
        self.encode_elm(|j| j.encode_str(s));
    }
}

#[test]
fn test_json_obj_encoder() {
    use std::str;

    let mut js = JsonEncoder::new();
    js.encode_obj(|_|{});
    assert_eq!(b"{}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
    });
    assert_eq!(b"{\"total\":31}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
    });
    assert_eq!(b"{\"total\":31,\"next\":\"abc\"}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
        jso.encode_field("tags", |js| {
                js.encode_array(|jsa| {
                        jsa.encode_elm(|js| js.encode_i32(1));
                        jsa.encode_elm(|js| js.encode_i32(2));
                });
        });
    });
    assert_eq!("{\"total\":31,\"next\":\"abc\",\"tags\":[1,2]}", str::from_utf8(&js.into_vec()[..]).unwrap());
}
<commit_msg>Add helper method<commit_after>#![feature(vec_push_all)]

pub struct JsonEncoder {
    buffer: Vec<u8>
}

impl JsonEncoder {
    pub fn new() -> JsonEncoder {
        JsonEncoder{buffer: Vec::new()}
    }

    #[inline(always)]
    pub fn encode_raw(&mut self, raw: &[u8]) {
        self.buffer.push_all(raw);
    }

    pub fn into_vec(self) -> Vec<u8> {
        self.buffer
    }

    pub fn with_buf<F>(&mut self, f: F) where F: Fn(&mut Vec<u8>) {
        f(&mut self.buffer);
    }

    #[inline(always)]
    pub fn encode_str_noescape(&mut self, raw_str: &str) {
        self.buffer.push(b'"');
        self.buffer.push_all(raw_str.as_bytes());
        self.buffer.push(b'"');
    }

    fn escape_bytes(&mut self, bytes: &[u8]) {
        let mut start = 0;

        for (i, byte) in bytes.iter().enumerate() {
            let escaped = match *byte {
                b'"' => b"\\\"",
                b'\\' => b"\\\\",
                b'\x08' => b"\\b",
                b'\x0c' => b"\\f",
                b'\n' => b"\\n",
                b'\r' => b"\\r",
                b'\t' => b"\\t",
                _ => {
                    continue;
                }
            };

            if start < i {
                self.encode_raw(&bytes[start..i]);
            }

            self.encode_raw(escaped);

            start = i + 1;
        }

        if start != bytes.len() {
            self.encode_raw(&bytes[start..]);
        }
    }

    pub fn encode_decimal_str(&mut self, value: u64) {
        self.buffer.push(b'"');
        self.encode_u64_decimal(value);
        self.buffer.push(b'"');
    }

    // encodes as decimal string
    #[inline(always)]
    fn encode_u64_decimal(&mut self, value: u64) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 20;

        if value == 0 {
            self.buffer.push(b'0');
            return;
        }

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    #[inline(always)]
    pub fn encode_str(&mut self, s: &str) {
        self.buffer.push(b'"');
        self.escape_bytes(s.as_bytes());
        self.buffer.push(b'"');
    }

    #[inline(always)]
    pub fn encode_i32(&mut self, value: i32) {
        if value == 0 {
            self.buffer.push(b'0');
        } else if value > 0 {
            self.encode_u31(value as u32);
        } else {
            self.buffer.push(b'-');
            self.encode_u31((-value) as u32);
        }
    }

    // encodes a 31-bit unsigned integer != 0
    fn encode_u31(&mut self, value: u32) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 10;
        debug_assert!(value != 0);

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    pub fn encode_obj<F>(&mut self, f: F) where F: Fn(&mut JsonObjectEncoder) {
        self.buffer.push(b'{');
        {
            f(&mut JsonObjectEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b'}');
    }

    pub fn encode_array<F>(&mut self, f: F) where F: Fn(&mut JsonArrayEncoder) {
        self.buffer.push(b'[');
        {
            f(&mut JsonArrayEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b']');
    }

}

pub struct JsonObjectEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonObjectEncoder<'a> {
    // XXX: name MAY NOT include escapable characters
    #[inline(always)]
    pub fn encode_field<F:Fn(&mut JsonEncoder)>(&mut self, name: &str, f: F) {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        self.js.encode_str_noescape(name);
        self.js.buffer.push(b':');

        f(self.js);
    }

    #[inline(always)]
    pub fn encode_field_array<F:Fn(&mut JsonArrayEncoder)>(&mut self, name: &str, f: F) {
        self.encode_field(name, |js| js.encode_array(|jsa| f(jsa)));
    }

    #[inline(always)]
    pub fn encode_field_i32(&mut self, name: &str, val: i32) {
        self.encode_field(name, |js| js.encode_i32(val));
    }

    #[inline(always)]
    pub fn encode_field_str(&mut self, name: &str, s: &str) {
        self.encode_field(name, |js| js.encode_str(s));
    }

}

pub struct JsonArrayEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonArrayEncoder<'a> {
    #[inline(always)]
    pub fn encode_elm<F:Fn(&mut JsonEncoder)>(&mut self, f: F) {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        f(self.js);
    }

    #[inline(always)]
    pub fn encode_elm_i32(&mut self, val: i32) {
        self.encode_elm(|js| js.encode_i32(val));
    }

    #[inline(always)]
    pub fn encode_elm_str(&mut self, s: &str) {
        self.encode_elm(|js| js.encode_str(s));
    }

    #[inline(always)]
    pub fn encode_elm_obj<F:Fn(&mut JsonObjectEncoder)>(&mut self, f: F) {
        self.encode_elm(|js| js.encode_obj(|jso| f(jso)));
    }
}

#[test]
fn test_json_obj_encoder() {
    use std::str;

    let mut js = JsonEncoder::new();
    js.encode_obj(|_|{});
    assert_eq!(b"{}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
    });
    assert_eq!(b"{\"total\":31}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
    });
    assert_eq!(b"{\"total\":31,\"next\":\"abc\"}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
        jso.encode_field("tags", |js| {
                js.encode_array(|jsa| {
                        jsa.encode_elm(|js| js.encode_i32(1));
                        jsa.encode_elm(|js| js.encode_i32(2));
                });
        });
    });
    assert_eq!("{\"total\":31,\"next\":\"abc\",\"tags\":[1,2]}", str::from_utf8(&js.into_vec()[..]).unwrap());
}
<|endoftext|>


<commit_before>#![feature(proc_macro_lib)]

extern crate proc_macro;

#[doc(hidden)]
pub use proc_macro::TokenStream;

#[macro_export]
macro_rules! proc_macro_expr_decl {
    ($name:ident ! => $name_impl:ident) => {
        #[derive(ProcMacroHackExpr)]
        #[allow(unused)]
        enum $name {
            $name_impl
        }
    }
}

#[macro_export]
macro_rules! proc_macro_item_decl {
    ($name:ident ! => $name_impl:ident) => {
        #[derive(ProcMacroHackItem)]
        #[allow(unused)]
        enum $name {
            $name_impl
        }
    }
}

#[macro_export]
macro_rules! proc_macro_expr_impl {
    ($(
        $( #[$attr:meta] )*
        pub fn $func:ident($input:ident: &str ) -> Result<String, String> $body:block
    )+) => {
        $(
            $( #[$attr] )*
            #[proc_macro_derive($func)]
            pub fn $func(input: $crate::TokenStream) -> $crate::TokenStream {
                let source = input.to_string();

                let prefix = "#[allow(unused)]\nenum ProcMacroHack { Input = { stringify!(";
                let suffix = "); 0 }, }\n";
                if !(source.starts_with(prefix) && source.ends_with(suffix)) {
                    panic!("`{}` procedural macro failed", stringify!($func));
                }

                let tokens = &source[prefix.len() .. source.len() - suffix.len()];

                fn func($input: &str) -> Result<String, String> $body

                let wrap = match func(tokens) {
                    Ok(expr) => {
                        format!("
                            macro_rules! proc_macro_call {{
                                ($($tt:tt)*) => {{
                                    {}
                                }}
                            }}
                        ", expr)
                    }
                    Err(msg) => panic!(msg)
                };

                wrap.parse().unwrap()
            }
        )+
    }
}

#[macro_export]
macro_rules! proc_macro_item_impl {
    ($(
        $( #[$attr:meta] )*
        pub fn $func:ident($input:ident: &str ) -> Result<String, String> $body:block
    )+) => {
        $(
            $( #[$attr] )*
            #[proc_macro_derive($func)]
            pub fn $func(input: $crate::TokenStream) -> $crate::TokenStream {
                let source = input.to_string();

                let prefix = "#[allow(unused)]\nenum ProcMacroHack { Input = { stringify!(";
                let suffix = "); 0 }, }\n";
                if !(source.starts_with(prefix) && source.ends_with(suffix)) {
                    panic!("`{}` procedural macro failed", stringify!($func));
                }

                let tokens = &source[prefix.len() .. source.len() - suffix.len()];

                fn func($input: &str) -> Result<String, String> $body

                func(tokens).unwrap_or_else(|msg| panic!(msg)).parse().unwrap()
            }
        )+
    }
}
<commit_msg>Remove unneeded macro args<commit_after>#![feature(proc_macro_lib)]

extern crate proc_macro;

#[doc(hidden)]
pub use proc_macro::TokenStream;

#[macro_export]
macro_rules! proc_macro_expr_decl {
    ($name:ident ! => $name_impl:ident) => {
        #[derive(ProcMacroHackExpr)]
        #[allow(unused)]
        enum $name {
            $name_impl
        }
    }
}

#[macro_export]
macro_rules! proc_macro_item_decl {
    ($name:ident ! => $name_impl:ident) => {
        #[derive(ProcMacroHackItem)]
        #[allow(unused)]
        enum $name {
            $name_impl
        }
    }
}

#[macro_export]
macro_rules! proc_macro_expr_impl {
    ($(
        $( #[$attr:meta] )*
        pub fn $func:ident($input:ident: &str ) -> Result<String, String> $body:block
    )+) => {
        $(
            $( #[$attr] )*
            #[proc_macro_derive($func)]
            pub fn $func(input: $crate::TokenStream) -> $crate::TokenStream {
                let source = input.to_string();

                let prefix = "#[allow(unused)]\nenum ProcMacroHack { Input = { stringify!(";
                let suffix = "); 0 }, }\n";
                if !(source.starts_with(prefix) && source.ends_with(suffix)) {
                    panic!("`{}` procedural macro failed", stringify!($func));
                }

                let tokens = &source[prefix.len() .. source.len() - suffix.len()];

                fn func($input: &str) -> Result<String, String> $body

                let wrap = match func(tokens) {
                    Ok(expr) => {
                        format!("
                            macro_rules! proc_macro_call {{
                                () => {{
                                    {}
                                }}
                            }}
                        ", expr)
                    }
                    Err(msg) => panic!(msg)
                };

                wrap.parse().unwrap()
            }
        )+
    }
}

#[macro_export]
macro_rules! proc_macro_item_impl {
    ($(
        $( #[$attr:meta] )*
        pub fn $func:ident($input:ident: &str ) -> Result<String, String> $body:block
    )+) => {
        $(
            $( #[$attr] )*
            #[proc_macro_derive($func)]
            pub fn $func(input: $crate::TokenStream) -> $crate::TokenStream {
                let source = input.to_string();

                let prefix = "#[allow(unused)]\nenum ProcMacroHack { Input = { stringify!(";
                let suffix = "); 0 }, }\n";
                if !(source.starts_with(prefix) && source.ends_with(suffix)) {
                    panic!("`{}` procedural macro failed", stringify!($func));
                }

                let tokens = &source[prefix.len() .. source.len() - suffix.len()];

                fn func($input: &str) -> Result<String, String> $body

                func(tokens).unwrap_or_else(|msg| panic!(msg)).parse().unwrap()
            }
        )+
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate serde;
extern crate serde_json;

use serde::{Serialize, Serializer};
use serde_json::to_string;
use std::io::{Write, stderr, stdout};

#[macro_export]
macro_rules! json_object {
    ( $( $key:expr => $value:expr ),* ) => {
        {
            use serde_json::{Value, to_value, Map};
            let mut m: Map<String, Value> = Map::new();
            $(
                m.insert($key.to_owned(), to_value(&$value));
            )*
            m
        }
    }
}

#[derive(Debug)]
pub struct SLogMetadata<'a> {
    pub target: &'a str,
    pub level: log::LogLevel,
}

#[derive(Debug)]
pub struct SLogLocation<'a> {
    pub module_path: &'a str,
    pub file: &'a str,
    pub line: u32,
}

#[derive(Debug)]
pub struct SLogInfo<'a> {
    pub metadata: SLogMetadata<'a>,
    pub location: SLogLocation<'a>,
}

impl<'a> SLogInfo<'a> {
    pub fn metadata(&self) -> &SLogMetadata {
        &self.metadata
    }

    pub fn location(&self) -> &SLogLocation {
        &self.location
    }
}

pub trait StructuredLog {
    fn slog(&self, info: &SLogInfo) -> String;
}

#[inline]
pub fn serialize<T>(value: &T, info: &SLogInfo) -> String
    where T: StructuredLog
{
    value.slog(info)
}

#[macro_export]
macro_rules! serialize {
    (target: $target:expr, level: $level:expr, $value:expr) => {
        {
            $crate::serialize(&$value, &$crate::SLogInfo {
                metadata: $crate::SLogMetadata {
                    target: $target,
                    level: $level
                },
                location: $crate::SLogLocation {
                    module_path: module_path!(),
                    file: file!(),
                    line: line!()
                }
            })
        }
    }
}

#[derive(Debug)]
pub struct SLogJson<'a, T: 'a>(&'a T);

impl<'a, T: Serialize> SLogJson<'a, T> {
    pub fn new<'b>(value: &'b T) -> SLogJson<'b, T> {
        SLogJson(value)
    }
}

impl<'a, T: Serialize> Serialize for SLogJson<'a, T> {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        self.0.serialize(serializer)
    }
}

impl<'a, T: Serialize> StructuredLog for SLogJson<'a, T> {
    fn slog(&self, info: &SLogInfo) -> String {
        let obj = json_object! {
            "target" => info.metadata.target,
            "level" => info.metadata.level.to_string(),
            "location" => json_object! {
                "module_path" => info.location.module_path,
                "file" => info.location.file,
                "line" => info.location.line
            },
            "value" => self
        };
        to_string(&obj).unwrap_or_else(|err| {
            writeln!(stderr(), "{}, {:?}", err, obj).unwrap();

            let msg = "Serializing error occured in s_structured_log in serde::to_string. \
                       Details was written out to STDERR.";
            format!("{{ \"level\": \"{}\", \"value\": \"{}\" }}", log::LogLevel::Error, msg)
        })
    }
}

#[macro_export]
macro_rules! s_error {
    (target: $target:expr, $value:expr) => {
        {
            use log;
            trace!(target: $target, "{}", serialize!(target: $target, level: log::LogLevel::Error, $crate::SLogJson::new(&$value)));
        }
    };
    ($value:expr) => {
        {
            s_error!(target: module_path!(), $value);
        }
    };
}

#[macro_export]
macro_rules! s_warn {
    (target: $target:expr, $value:expr) => {
        {
            use log;
            trace!(target: $target, "{}", serialize!(target: $target, level: log::LogLevel::Warn, $crate::SLogJson::new(&$value)));
        }
    };
    ($value:expr) => {
        {
            s_warn!(target: module_path!(), $value);
        }
    };
}

#[macro_export]
macro_rules! s_info {
    (target: $target:expr, $value:expr) => {
        {
            use log;
            trace!(target: $target, "{}", serialize!(target: $target, level: log::LogLevel::Info, $crate::SLogJson::new(&$value)));
        }
    };
    ($value:expr) => {
        {
            s_info!(target: module_path!(), $value);
        }
    };
}

#[macro_export]
macro_rules! s_debug {
    (target: $target:expr, $value:expr) => {
        {
            use log;
            trace!(target: $target, "{}", serialize!(target: $target, level: log::LogLevel::Debug, $crate::SLogJson::new(&$value)));
        }
    };
    ($value:expr) => {
        {
            s_debug!(target: module_path!(), $value);
        }
    };
}

#[macro_export]
macro_rules! s_trace {
    (target: $target:expr, $value:expr) => {
        {
            use log;
            trace!(target: $target, "{}", serialize!(target: $target, level: log::LogLevel::Trace, $crate::SLogJson::new(&$value)));
        }
    };
    ($value:expr) => {
        {
            s_trace!(target: module_path!(), $value);
        }
    };
}

pub enum LoggerOutput {
    Stdout,
    Stderr,
}

struct SimpleLogger {
    filter: log::LogLevelFilter,
    output: LoggerOutput,
}

impl log::Log for SimpleLogger {
    fn enabled(&self, metadata: &log::LogMetadata) -> bool {
        metadata.level() <= self.filter
    }

    fn log(&self, record: &log::LogRecord) {
        if !self.enabled(record.metadata()) {
            return;
        }

        match self.output {
            LoggerOutput::Stderr => writeln!(stderr(), "{}", record.args()).unwrap(),
            LoggerOutput::Stdout => writeln!(stdout(), "{}", record.args()).unwrap(),
        }
    }
}

pub fn init(output: LoggerOutput, log_level: log::LogLevelFilter) {
    let logger = SimpleLogger {
        filter: log_level,
        output: output,
    };

    log::set_logger(|max_log_level| {
            max_log_level.set(logger.filter);
            Box::new(logger)
        })
        .unwrap();
}

#[cfg(feature = "documentation")]
pub mod doc;

#[cfg(test)]
mod tests {
    #[test]
    fn simple_logger() {}
}
<commit_msg>Apply rustfmt<commit_after>#[macro_use]
extern crate log;
extern crate serde;
extern crate serde_json;

use serde::{Serialize, Serializer};
use serde_json::to_string;
use std::io::{Write, stderr, stdout};

#[macro_export]
macro_rules! json_object {
    ( $( $key:expr => $value:expr ),* ) => {
        {
            use serde_json::{Value, to_value, Map};
            let mut m: Map<String, Value> = Map::new();
            $(
                m.insert($key.to_owned(), to_value(&$value));
            )*
            m
        }
    }
}

#[derive(Debug)]
pub struct SLogMetadata<'a> {
    pub target: &'a str,
    pub level: log::LogLevel,
}

#[derive(Debug)]
pub struct SLogLocation<'a> {
    pub module_path: &'a str,
    pub file: &'a str,
    pub line: u32,
}

#[derive(Debug)]
pub struct SLogInfo<'a> {
    pub metadata: SLogMetadata<'a>,
    pub location: SLogLocation<'a>,
}

impl<'a> SLogInfo<'a> {
    pub fn metadata(&self) -> &SLogMetadata {
        &self.metadata
    }

    pub fn location(&self) -> &SLogLocation {
        &self.location
    }
}

pub trait StructuredLog {
    fn slog(&self, info: &SLogInfo) -> String;
}

#[inline]
pub fn serialize<T>(value: &T, info: &SLogInfo) -> String
    where T: StructuredLog
{
    value.slog(info)
}

#[macro_export]
macro_rules! serialize {
    (target: $target:expr, level: $level:expr, $value:expr) => {
        {
            $crate::serialize(&$value, &$crate::SLogInfo {
                metadata: $crate::SLogMetadata {
                    target: $target,
                    level: $level
                },
                location: $crate::SLogLocation {
                    module_path: module_path!(),
                    file: file!(),
                    line: line!()
                }
            })
        }
    }
}

#[derive(Debug)]
pub struct SLogJson<'a, T: 'a>(&'a T);

impl<'a, T: Serialize> SLogJson<'a, T> {
    pub fn new<'b>(value: &'b T) -> SLogJson<'b, T> {
        SLogJson(value)
    }
}

impl<'a, T: Serialize> Serialize for SLogJson<'a, T> {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        self.0.serialize(serializer)
    }
}

impl<'a, T: Serialize> StructuredLog for SLogJson<'a, T> {
    fn slog(&self, info: &SLogInfo) -> String {
        let obj = json_object! {
            "target" => info.metadata.target,
            "level" => info.metadata.level.to_string(),
            "location" => json_object! {
                "module_path" => info.location.module_path,
                "file" => info.location.file,
                "line" => info.location.line
            },
            "value" => self
        };
        to_string(&obj).unwrap_or_else(|err| {
            writeln!(stderr(), "{}, {:?}", err, obj).unwrap();

            let msg = "Serializing error occured in s_structured_log in serde::to_string. \
                       Details was written out to STDERR.";
            format!("{{ \"level\": \"{}\", \"value\": \"{}\" }}",
                    log::LogLevel::Error,
                    msg)
        })
    }
}

#[macro_export]
macro_rules! s_error {
    (target: $target:expr, $value:expr) => {
        {
            use log;
            trace!(target: $target, "{}", serialize!(target: $target, level: log::LogLevel::Error, $crate::SLogJson::new(&$value)));
        }
    };
    ($value:expr) => {
        {
            s_error!(target: module_path!(), $value);
        }
    };
}

#[macro_export]
macro_rules! s_warn {
    (target: $target:expr, $value:expr) => {
        {
            use log;
            trace!(target: $target, "{}", serialize!(target: $target, level: log::LogLevel::Warn, $crate::SLogJson::new(&$value)));
        }
    };
    ($value:expr) => {
        {
            s_warn!(target: module_path!(), $value);
        }
    };
}

#[macro_export]
macro_rules! s_info {
    (target: $target:expr, $value:expr) => {
        {
            use log;
            trace!(target: $target, "{}", serialize!(target: $target, level: log::LogLevel::Info, $crate::SLogJson::new(&$value)));
        }
    };
    ($value:expr) => {
        {
            s_info!(target: module_path!(), $value);
        }
    };
}

#[macro_export]
macro_rules! s_debug {
    (target: $target:expr, $value:expr) => {
        {
            use log;
            trace!(target: $target, "{}", serialize!(target: $target, level: log::LogLevel::Debug, $crate::SLogJson::new(&$value)));
        }
    };
    ($value:expr) => {
        {
            s_debug!(target: module_path!(), $value);
        }
    };
}

#[macro_export]
macro_rules! s_trace {
    (target: $target:expr, $value:expr) => {
        {
            use log;
            trace!(target: $target, "{}", serialize!(target: $target, level: log::LogLevel::Trace, $crate::SLogJson::new(&$value)));
        }
    };
    ($value:expr) => {
        {
            s_trace!(target: module_path!(), $value);
        }
    };
}

pub enum LoggerOutput {
    Stdout,
    Stderr,
}

struct SimpleLogger {
    filter: log::LogLevelFilter,
    output: LoggerOutput,
}

impl log::Log for SimpleLogger {
    fn enabled(&self, metadata: &log::LogMetadata) -> bool {
        metadata.level() <= self.filter
    }

    fn log(&self, record: &log::LogRecord) {
        if !self.enabled(record.metadata()) {
            return;
        }

        match self.output {
            LoggerOutput::Stderr => writeln!(stderr(), "{}", record.args()).unwrap(),
            LoggerOutput::Stdout => writeln!(stdout(), "{}", record.args()).unwrap(),
        }
    }
}

pub fn init(output: LoggerOutput, log_level: log::LogLevelFilter) {
    let logger = SimpleLogger {
        filter: log_level,
        output: output,
    };

    log::set_logger(|max_log_level| {
            max_log_level.set(logger.filter);
            Box::new(logger)
        })
        .unwrap();
}

#[cfg(feature = "documentation")]
pub mod doc;

#[cfg(test)]
mod tests {
    #[test]
    fn simple_logger() {}
}
<|endoftext|>


<commit_before>//! A library for event threading

#![crate_type = "lib"]
#![crate_name = "event"]
#![deny(missing_docs)]
#![deny(missing_copy_implementations)]
#![feature(core)]

#[cfg(test)]
extern crate test;
extern crate input;
extern crate event_loop;
extern crate window;

use window::Window;

pub use event_loop as events;
pub use events::{
    Events,
    MaxFps,
    Ups,
    UpdateArgs,
    RenderArgs,
    AfterRenderArgs,
    IdleArgs,
};
pub use generic_event::GenericEvent;
pub use update::UpdateEvent;
pub use render::RenderEvent;
pub use after_render::AfterRenderEvent;
pub use idle::IdleEvent;
pub use event::Event;
pub use press::PressEvent;
pub use release::ReleaseEvent;
pub use mouse::{ MouseCursorEvent, MouseRelativeEvent, MouseScrollEvent };
pub use text::TextEvent;
pub use resize::ResizeEvent;
pub use focus::FocusEvent;

pub mod generic_event;
mod update;
mod render;
mod after_render;
mod idle;
mod event;
mod press;
mod release;
mod mouse;
mod text;
mod resize;
mod focus;

/// Creates event iterator from window.
pub fn events<W>(window: W) -> event_loop::Events<W, Event<<W as Window>::Event>>
    where
        W: Window,
{
    event_loop::Events::new(window)
}
<commit_msg>Fix warnings<commit_after>//! A library for event threading

#![crate_type = "lib"]
#![crate_name = "event"]
#![deny(missing_docs)]
#![deny(missing_copy_implementations)]
#![feature(core)]
#![cfg_attr(test, feature(test))]

#[cfg(test)]
extern crate test;
extern crate input;
extern crate event_loop;
extern crate window;

use window::Window;

pub use event_loop as events;
pub use events::{
    Events,
    MaxFps,
    Ups,
    UpdateArgs,
    RenderArgs,
    AfterRenderArgs,
    IdleArgs,
};
pub use generic_event::GenericEvent;
pub use update::UpdateEvent;
pub use render::RenderEvent;
pub use after_render::AfterRenderEvent;
pub use idle::IdleEvent;
pub use event::Event;
pub use press::PressEvent;
pub use release::ReleaseEvent;
pub use mouse::{ MouseCursorEvent, MouseRelativeEvent, MouseScrollEvent };
pub use text::TextEvent;
pub use resize::ResizeEvent;
pub use focus::FocusEvent;

pub mod generic_event;
mod update;
mod render;
mod after_render;
mod idle;
mod event;
mod press;
mod release;
mod mouse;
mod text;
mod resize;
mod focus;

/// Creates event iterator from window.
pub fn events<W>(window: W) -> event_loop::Events<W, Event<<W as Window>::Event>>
    where
        W: Window,
{
    event_loop::Events::new(window)
}
<|endoftext|>


<commit_before>pub fn quicksort<T: PartialEq + PartialOrd>(vec: &mut [T]) -> &mut [T] {
    if vec.len() <= 1 {
        return vec;
    }
    let pivot: usize = 0;
    let mut first_opened = Vec::new();
    let mut last_closed: usize = 0;

    for i in 1..vec.len() {
        first_opened.push(i);
        if vec[i] < vec[pivot] {
            let to = first_opened.remove(0);
            vec.swap(i, to);
            last_closed = to;
        }
    }

    vec.swap(pivot, last_closed);
    quicksort(&mut vec[0..last_closed]);
    quicksort(&mut vec[last_closed+1..]);
    vec
}

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

    #[test]
    fn test_vec_of_u64() {
        let sorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
        let mut unsorted: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
        quicksort(&mut unsorted);

        assert_eq!(unsorted, sorted.as_slice());
    }

    #[test]
    fn test_vec_of_u8() {
        let sorted = "        Tabcdeeefghhijklmnoooopqrrstuuvwxyz".to_string().into_bytes();
        let mut unsorted = "The quick brown fox jumps over the lazy dog".to_string().into_bytes();
        quicksort(&mut unsorted);

        assert_eq!(sorted, unsorted);
    }
}
<commit_msg>Add test_array_of_u8<commit_after>pub fn quicksort<T: PartialEq + PartialOrd>(vec: &mut [T]) -> &mut [T] {
    if vec.len() <= 1 {
        return vec;
    }
    let pivot: usize = 0;
    let mut first_opened = Vec::new();
    let mut last_closed: usize = 0;

    for i in 1..vec.len() {
        first_opened.push(i);
        if vec[i] < vec[pivot] {
            let to = first_opened.remove(0);
            vec.swap(i, to);
            last_closed = to;
        }
    }

    vec.swap(pivot, last_closed);
    quicksort(&mut vec[0..last_closed]);
    quicksort(&mut vec[last_closed+1..]);
    vec
}

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

    #[test]
    fn test_vec_of_u64() {
        let sorted: Vec<u64> = vec![1, 1, 2, 3, 3, 4, 5, 5, 6, 9];
        let mut unsorted: Vec<u64> = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
        quicksort(&mut unsorted);

        assert_eq!(unsorted, sorted.as_slice());
    }

    #[test]
    fn test_vec_of_u8() {
        let sorted = "        Tabcdeeefghhijklmnoooopqrrstuuvwxyz".to_string().into_bytes();
        let mut unsorted = "The quick brown fox jumps over the lazy dog".to_string().into_bytes();
        quicksort(&mut unsorted);

        assert_eq!(sorted, unsorted);
    }

    #[test]
    fn test_array_of_u8() {
        let sorted: [u8; 10] = [1, 2, 3, 4, 5, 5, 5, 7, 9, 10];
        let mut unsorted: [u8; 10] = [7, 5, 3, 2, 5, 1, 4, 5, 9, 10];
        quicksort(&mut unsorted);

        assert_eq!(sorted, unsorted);
    }
}
<|endoftext|>


<commit_before>// Module for parsing ISO Base Media Format aka video/mp4 streams.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

/// Basic ISO box structure.
pub struct BoxHeader {
    /// Four character box type
pub name: u32,
    /// Size of the box in bytes
pub size: u64,
    /// Offset to the start of the contained data (or header size).
pub offset: u64,
}

/// File type box 'ftyp'.
pub struct FileTypeBox {
    name: u32,
    size: u64,
    major_brand: u32,
    minor_version: u32,
    compatible_brands: Vec<u32>,
}

extern crate byteorder;
use byteorder::{BigEndian, ReadBytesExt};
use std::io::{Result, Seek, SeekFrom};

/// Parse a box out of a data buffer.
pub fn read_box_header<T: ReadBytesExt>(src: &mut T) -> Option<BoxHeader> {
    let tmp_size = src.read_u32::<BigEndian>().unwrap();
    let name = src.read_u32::<BigEndian>().unwrap();
    let size = match tmp_size {
        1 => src.read_u64::<BigEndian>().unwrap(),
        _ => tmp_size as u64,
    };
    assert!(size >= 8);
    if tmp_size == 1 {
        assert!(size >= 16);
    }
    let offset = match tmp_size {
        1 => 4 + 4 + 8,
        _ => 4 + 4,
    };
    assert!(offset <= size);
    Some(BoxHeader{
        name: name,
        size: size,
        offset: offset,
    })
}

/// Skip over the contents of a box.
pub fn skip_box_content<T: ReadBytesExt + Seek>
  (src: &mut T, header: &BoxHeader)
  -> std::io::Result<u64>
{
    src.seek(SeekFrom::Current((header.size - header.offset) as i64))
}

/// Parse an ftype box.
pub fn read_ftyp<T: ReadBytesExt>(src: &mut T) -> Option<FileTypeBox> {
    let head = read_box_header(src).unwrap();
    let major = src.read_u32::<BigEndian>().unwrap();
    let minor = src.read_u32::<BigEndian>().unwrap();
    let brand_count = (head.size - 8 - 8) /4;
    let mut brands = Vec::new();
    for _ in 0..brand_count {
        brands.push(src.read_u32::<BigEndian>().unwrap());
    }
    Some(FileTypeBox{
        name: head.name,
        size: head.size,
        major_brand: major,
        minor_version: minor,
        compatible_brands: brands,
    })
}

/// Convert the 4-character iso box type to a string.
fn mp4_box_to_string(name: u32) -> String {
    let u32_to_vec = |u| {
        vec!((u >> 24 & 0xffu32) as u8,
             (u >> 16 & 0xffu32) as u8,
             (u >>  8 & 0xffu32) as u8,
             (u & 0xffu32) as u8)
    };
    let name_bytes = u32_to_vec(name);
    String::from_utf8_lossy(&name_bytes).into_owned()
}

use std::fmt;
impl fmt::Display for BoxHeader {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "'{}' {} bytes", mp4_box_to_string(self.name), self.size)
    }
}

impl fmt::Display for FileTypeBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = mp4_box_to_string(self.name);
        let brand = mp4_box_to_string(self.major_brand);
        write!(f, "'{}' {} bytes '{}' v{}", name, self.size,
            brand, self.minor_version)
    }
}

#[test]
fn test_read_box_header() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 8];  // minimal box length
    write!(&mut test, "test").unwrap(); // box type
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1952805748);
    assert_eq!(parsed.size, 8);
    println!("box {}", parsed);
}

#[test]
fn test_read_box_header_long() {
    use std::io::Cursor;
    let mut test: Vec<u8> = vec![0, 0, 0, 1]; // long box extension code
    test.extend("long".to_string().into_bytes()); // box type
    test.extend(vec![0, 0, 0, 0, 0, 0, 16, 0]); // 64 bit size
    // Skip generating box content.
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1819242087);
    assert_eq!(parsed.size, 4096);
    println!("box {}", parsed);
}

#[test]
fn test_read_ftyp() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 24]; // size
    write!(&mut test, "ftyp").unwrap(); // type
    write!(&mut test, "mp42").unwrap(); // major brand
    test.extend(vec![0, 0, 0, 0]);      // minor version
    write!(&mut test, "isom").unwrap(); // compatible brands...
    write!(&mut test, "mp42").unwrap();
    assert_eq!(test.len(), 24);

    let mut stream = Cursor::new(test);
    let parsed = read_ftyp(&mut stream).unwrap();
    assert_eq!(parsed.name, 1718909296);
    assert_eq!(parsed.size, 24);
    assert_eq!(parsed.major_brand, 1836069938);
    assert_eq!(parsed.minor_version, 0);
    assert_eq!(parsed.compatible_brands.len(), 2);
    println!("box {}", parsed);
}
<commit_msg>Use a more descriptive fourcc_to_string() name.<commit_after>// Module for parsing ISO Base Media Format aka video/mp4 streams.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

/// Basic ISO box structure.
pub struct BoxHeader {
    /// Four character box type
pub name: u32,
    /// Size of the box in bytes
pub size: u64,
    /// Offset to the start of the contained data (or header size).
pub offset: u64,
}

/// File type box 'ftyp'.
pub struct FileTypeBox {
    name: u32,
    size: u64,
    major_brand: u32,
    minor_version: u32,
    compatible_brands: Vec<u32>,
}

extern crate byteorder;
use byteorder::{BigEndian, ReadBytesExt};
use std::io::{Result, Seek, SeekFrom};

/// Parse a box out of a data buffer.
pub fn read_box_header<T: ReadBytesExt>(src: &mut T) -> Option<BoxHeader> {
    let tmp_size = src.read_u32::<BigEndian>().unwrap();
    let name = src.read_u32::<BigEndian>().unwrap();
    let size = match tmp_size {
        1 => src.read_u64::<BigEndian>().unwrap(),
        _ => tmp_size as u64,
    };
    assert!(size >= 8);
    if tmp_size == 1 {
        assert!(size >= 16);
    }
    let offset = match tmp_size {
        1 => 4 + 4 + 8,
        _ => 4 + 4,
    };
    assert!(offset <= size);
    Some(BoxHeader{
        name: name,
        size: size,
        offset: offset,
    })
}

/// Skip over the contents of a box.
pub fn skip_box_content<T: ReadBytesExt + Seek>
  (src: &mut T, header: &BoxHeader)
  -> std::io::Result<u64>
{
    src.seek(SeekFrom::Current((header.size - header.offset) as i64))
}

/// Parse an ftype box.
pub fn read_ftyp<T: ReadBytesExt>(src: &mut T) -> Option<FileTypeBox> {
    let head = read_box_header(src).unwrap();
    let major = src.read_u32::<BigEndian>().unwrap();
    let minor = src.read_u32::<BigEndian>().unwrap();
    let brand_count = (head.size - 8 - 8) /4;
    let mut brands = Vec::new();
    for _ in 0..brand_count {
        brands.push(src.read_u32::<BigEndian>().unwrap());
    }
    Some(FileTypeBox{
        name: head.name,
        size: head.size,
        major_brand: major,
        minor_version: minor,
        compatible_brands: brands,
    })
}

/// Convert the iso box type or other 4-character value to a string.
fn fourcc_to_string(name: u32) -> String {
    let u32_to_vec = |u| {
        vec!((u >> 24 & 0xffu32) as u8,
             (u >> 16 & 0xffu32) as u8,
             (u >>  8 & 0xffu32) as u8,
             (u & 0xffu32) as u8)
    };
    let name_bytes = u32_to_vec(name);
    String::from_utf8_lossy(&name_bytes).into_owned()
}

use std::fmt;
impl fmt::Display for BoxHeader {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "'{}' {} bytes", fourcc_to_string(self.name), self.size)
    }
}

impl fmt::Display for FileTypeBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = fourcc_to_string(self.name);
        let brand = fourcc_to_string(self.major_brand);
        write!(f, "'{}' {} bytes '{}' v{}", name, self.size,
            brand, self.minor_version)
    }
}

#[test]
fn test_read_box_header() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 8];  // minimal box length
    write!(&mut test, "test").unwrap(); // box type
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1952805748);
    assert_eq!(parsed.size, 8);
    println!("box {}", parsed);
}

#[test]
fn test_read_box_header_long() {
    use std::io::Cursor;
    let mut test: Vec<u8> = vec![0, 0, 0, 1]; // long box extension code
    test.extend("long".to_string().into_bytes()); // box type
    test.extend(vec![0, 0, 0, 0, 0, 0, 16, 0]); // 64 bit size
    // Skip generating box content.
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1819242087);
    assert_eq!(parsed.size, 4096);
    println!("box {}", parsed);
}

#[test]
fn test_read_ftyp() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 24]; // size
    write!(&mut test, "ftyp").unwrap(); // type
    write!(&mut test, "mp42").unwrap(); // major brand
    test.extend(vec![0, 0, 0, 0]);      // minor version
    write!(&mut test, "isom").unwrap(); // compatible brands...
    write!(&mut test, "mp42").unwrap();
    assert_eq!(test.len(), 24);

    let mut stream = Cursor::new(test);
    let parsed = read_ftyp(&mut stream).unwrap();
    assert_eq!(parsed.name, 1718909296);
    assert_eq!(parsed.size, 24);
    assert_eq!(parsed.major_brand, 1836069938);
    assert_eq!(parsed.minor_version, 0);
    assert_eq!(parsed.compatible_brands.len(), 2);
    println!("box {}", parsed);
}
<|endoftext|>


<commit_before>// Copyright 2017 array_matrix Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! A macro to create a 2d matrix struct with manipulation methods using an internal array.
#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
                unused_qualifications, unused_results)]

pub use array_matrix::ArrayMatrix;
mod array_matrix;

/// A macro that takes a struct-like definition that takes an array type and (row, column)
/// size arguments and implements the required methods.
///
/// Usage:
/// #impl_matrix!{
/// #    struct MyMatrix([f32; (3, 3)]);
/// #};
///
/// #let mut matrix =  MyMatrix([0.0; 9]);
/// #matrix[(2,1)] = 8.1;
/// #println!("{:?}", matrix);
/// #println!("{}", m.row());
///
/// The matrix methods are based on the [`generic_matrix`] crate which uses an internal Vec<T> to
/// hold data.
///
/// [`generic_matrix`]: http://gifnksm.github.io/generic-matrix-rs/generic_matrix/index.html
#[macro_export]
macro_rules! impl_matrix {
    ($st:ident([$t:ty; ($row:expr, $col:expr)])) => {
        struct $st([$t; $row * $col]);

        impl $st {
            /// Creates an identity matrix.
            #[allow(dead_code)]
            fn identity() -> $st {
                let mut m = $st([0 as $t; $row * $col]);
                for i in 0..$row {
                    m[(i, i)] = 1 as $t;
                }
                m
            }
        }

        impl ArrayMatrix for $st {
            fn row(&self) -> usize {
                $row
            }

            fn column(&self) -> usize {
                $col
            }

            fn size(&self) -> (usize, usize) {
                (self.row(), self.column())
            }

            fn swap(&mut self, (a_i, a_j): (usize, usize), (b_i, b_j): (usize, usize)) {
                self.0.swap(a_i * $col + a_j, b_i * $col + b_j);
            }

            fn transpose(&self) -> Self {
                let mut trans = $st([0 as $t; $row * $col]);
                for i in 0..self.0.len() {
                   let r = i / $col;
                   let c = i % $col;
                   trans[(c, r)] = self[(r, c)].clone();
                }
                trans
            }

            fn transpose_mut(&mut self) {
                let mut positions = (0..self.0.len()).map(|i| {
                   (i / $col, i % $col)
                });
                loop {
                    if let Some((r, c)) = positions.next() {
                        //println!("({}, {}) {}", r, c, self[(r, c)]);
                        if r == c {
                            if r < $row - 1 {
                                // Consume the rest of the row to avoid double swapping
                                let _ = positions.nth($row - r - 2);
                            }
                        } else {
                            let a = r * $col + c;
                            let b = c * $row + r;
                            //assert_eq!(self[(r, c)], self.0[a]);
                            //assert_eq!(self[(c, r)], self.0[b]);
                            self.0.swap(a, b);
                        }
                    } else {
                        break
                    }
                }
            }
        }

        impl Index<(usize, usize)> for $st {
            type Output = $t;

            #[inline]
            fn index(&self, (i, j): (usize, usize)) -> &$t {
                assert!(i < $row && j < $col);
                &self.0[i * $col + j]
            }
        }

        impl IndexMut<(usize, usize)> for $st {

            #[inline]
            fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut $t {
                assert!(i < $row && j < $col);
                &mut self.0[i * $col + j]
            }
        }

        impl fmt::Debug for $st {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                f.debug_list().entries(self.0.iter()).finish()
            }
        }

        impl Eq for $st {}

        impl PartialEq for $st {
            fn eq(&self, other: &$st) -> bool {
                self.0[..] == other.0[..]
            }
        }

        impl Add for $st {
            type Output = $st;

            fn add(self, other: $st) -> $st {
                let mut a = [0 as $t; $row * $col];
                for i in 0..a.len() {
                    a[i] = self.0[i].clone() + other.0[i].clone();
                }
                $st(a)
            }
        }

        impl Sub for $st {
            type Output = $st;

            fn sub(self, other: $st) -> $st {
                let mut a = [0 as $t; $row * $col];
                for i in 0..a.len() {
                    a[i] = self.0[i].clone() - other.0[i].clone();
                }
                $st(a)
            }
        }
    }
}

#[macro_use]
#[cfg(test)]
mod tests {
    use array_matrix::ArrayMatrix;
    use std::ops::{Index, IndexMut, Add, Sub};
    use std::fmt;

    #[test]
    fn ident() {
        impl_matrix!(TestMatrix([i32; (2, 2)]));
        let m = TestMatrix::identity();

        assert_eq!(m, TestMatrix([1, 0, 0, 1]));
    }

    #[test]
    fn row_col() {
        const ROW: usize = 3;
        const COLUMN: usize = 3;
        impl_matrix!(TestMatrix([i32; (ROW, COLUMN)]));
        let m = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);

        assert_eq!(m.row(), ROW);
        assert_eq!(m.column(), COLUMN);
    }

    #[test]
    fn transpose() {
        impl_matrix!(TestMatrix([i32; (2, 2)]));
        let m = TestMatrix([1, 2, 3, 4]);
        let trans = m.transpose();

        assert_eq!(trans, TestMatrix([1, 3, 2, 4]));
    }

    #[test]
    fn transpose_mut() {
        impl_matrix!(TestMatrix([i32; (2, 2)]));
        let mut m = TestMatrix([1, 2, 3, 4]);
        m.transpose_mut();

        assert_eq!(m, TestMatrix([1, 3, 2, 4]));
    }

    #[test]
    fn transpose_large() {
        impl_matrix!(TestMatrix([i32; (6, 6)]));
        let m = TestMatrix([
                           0, 1, 2, 3, 4, 5,
                           6, 7, 8, 9, 10, 11,
                           12, 13, 14, 15, 16, 17,
                           18, 19, 20, 21, 22, 23,
                           24, 25, 26, 27, 28, 29,
                           30, 31, 32, 33, 34, 35
        ]);
        let trans = m.transpose();

        assert_eq!(trans,
                   TestMatrix([
                              0, 6, 12, 18, 24, 30,
                              1, 7, 13, 19, 25, 31,
                              2, 8, 14, 20, 26, 32,
                              3, 9, 15, 21, 27, 33,
                              4, 10, 16, 22, 28, 34,
                              5, 11, 17, 23, 29, 35
                   ]));
    }

    #[test]
    fn index() {
        impl_matrix!(TestMatrix([i32; (3, 3)]));
        let m = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);
        assert_eq!(m[(1, 2)], 6);
    }

    #[test]
    fn index_mut() {
        impl_matrix!(TestMatrix([i32; (3, 3)]));
        let mut m = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);
        assert_eq!(m[(1, 2)], 6);
        m[(1, 2)] = 30;
        assert_eq!(m[(1, 2)], 30);
    }

    #[test]
    fn eq() {
        impl_matrix!(TestMatrix([i32; (3, 3)]));
        let m_a = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);
        let m_b = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);

        assert_eq!(m_a, m_b);
    }

    #[test]
    fn add() {
        impl_matrix!(TestMatrix([i32; (2, 2)]));
        let m_a = TestMatrix([1, 2, 3, 4]);
        let m_b = TestMatrix([1, 2, 3, 4]);
        let m_c = m_a + m_b;

        assert_eq!(m_c, TestMatrix([2, 4, 6, 8]));
    }

    #[test]
    fn subtract() {
        impl_matrix!(TestMatrix([i32; (2, 2)]));
        let m_a = TestMatrix([1, 2, 3, 4]);
        let m_b = TestMatrix([1, 2, 3, 4]);
        let m_c = m_a - m_b;

        assert_eq!(m_c, TestMatrix([0, 0, 0, 0]));
    }

    #[test]
    fn multiply() {
        impl_matrix!(TestMatrix([i32; (2, 2)]));
        let m_a = TestMatrix([1, 2,
                             3, 4]);
        let m_b = TestMatrix([1, 2,
                             3, 4]);
        let m_c = m_a * m_b;

        assert_eq!(m_c[..], [7, 22]);
    }

    #[test]
    fn impl_two_matrix() {
        impl_matrix!(TestMatrixA([i32; (2, 2)]));
        impl_matrix!(TestMatrixB([f32; (2, 2)]));

        let m_a = TestMatrixA([1, 2, 3, 4]);
        let m_b = TestMatrixB([1., 2., 3., 4.]);

        assert_eq!(m_a[(0, 0)] as f32, m_b[(0, 0)]);
    }

    #[test]
    fn large_matrix() {
        impl_matrix!(TestMatrixA([i32; (6, 6)]));
        let m_a = TestMatrixA([1; 36]);
        let m_b = TestMatrixA([1; 36]);

        assert_eq!(m_a, m_b);
    }
}
<commit_msg>Remove test for Mul. Impl is incomplete.<commit_after>// Copyright 2017 array_matrix Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! A macro to create a 2d matrix struct with manipulation methods using an internal array.
#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
                unused_qualifications, unused_results)]

pub use array_matrix::ArrayMatrix;
mod array_matrix;

/// A macro that takes a struct-like definition that takes an array type and (row, column)
/// size arguments and implements the required methods.
///
/// Usage:
/// #impl_matrix!{
/// #    struct MyMatrix([f32; (3, 3)]);
/// #};
///
/// #let mut matrix =  MyMatrix([0.0; 9]);
/// #matrix[(2,1)] = 8.1;
/// #println!("{:?}", matrix);
/// #println!("{}", m.row());
///
/// The matrix methods are based on the [`generic_matrix`] crate which uses an internal Vec<T> to
/// hold data.
///
/// [`generic_matrix`]: http://gifnksm.github.io/generic-matrix-rs/generic_matrix/index.html
#[macro_export]
macro_rules! impl_matrix {
    ($st:ident([$t:ty; ($row:expr, $col:expr)])) => {
        struct $st([$t; $row * $col]);

        impl $st {
            /// Creates an identity matrix.
            #[allow(dead_code)]
            fn identity() -> $st {
                let mut m = $st([0 as $t; $row * $col]);
                for i in 0..$row {
                    m[(i, i)] = 1 as $t;
                }
                m
            }
        }

        impl ArrayMatrix for $st {
            fn row(&self) -> usize {
                $row
            }

            fn column(&self) -> usize {
                $col
            }

            fn size(&self) -> (usize, usize) {
                (self.row(), self.column())
            }

            fn swap(&mut self, (a_i, a_j): (usize, usize), (b_i, b_j): (usize, usize)) {
                self.0.swap(a_i * $col + a_j, b_i * $col + b_j);
            }

            fn transpose(&self) -> Self {
                let mut trans = $st([0 as $t; $row * $col]);
                for i in 0..self.0.len() {
                   let r = i / $col;
                   let c = i % $col;
                   trans[(c, r)] = self[(r, c)].clone();
                }
                trans
            }

            fn transpose_mut(&mut self) {
                let mut positions = (0..self.0.len()).map(|i| {
                   (i / $col, i % $col)
                });
                loop {
                    if let Some((r, c)) = positions.next() {
                        //println!("({}, {}) {}", r, c, self[(r, c)]);
                        if r == c {
                            if r < $row - 1 {
                                // Consume the rest of the row to avoid double swapping
                                let _ = positions.nth($row - r - 2);
                            }
                        } else {
                            let a = r * $col + c;
                            let b = c * $row + r;
                            //assert_eq!(self[(r, c)], self.0[a]);
                            //assert_eq!(self[(c, r)], self.0[b]);
                            self.0.swap(a, b);
                        }
                    } else {
                        break
                    }
                }
            }
        }

        impl Index<(usize, usize)> for $st {
            type Output = $t;

            #[inline]
            fn index(&self, (i, j): (usize, usize)) -> &$t {
                assert!(i < $row && j < $col);
                &self.0[i * $col + j]
            }
        }

        impl IndexMut<(usize, usize)> for $st {

            #[inline]
            fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut $t {
                assert!(i < $row && j < $col);
                &mut self.0[i * $col + j]
            }
        }

        impl fmt::Debug for $st {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                f.debug_list().entries(self.0.iter()).finish()
            }
        }

        impl Eq for $st {}

        impl PartialEq for $st {
            fn eq(&self, other: &$st) -> bool {
                self.0[..] == other.0[..]
            }
        }

        impl Add for $st {
            type Output = $st;

            fn add(self, other: $st) -> $st {
                let mut a = [0 as $t; $row * $col];
                for i in 0..a.len() {
                    a[i] = self.0[i].clone() + other.0[i].clone();
                }
                $st(a)
            }
        }

        impl Sub for $st {
            type Output = $st;

            fn sub(self, other: $st) -> $st {
                let mut a = [0 as $t; $row * $col];
                for i in 0..a.len() {
                    a[i] = self.0[i].clone() - other.0[i].clone();
                }
                $st(a)
            }
        }
    }
}

#[macro_use]
#[cfg(test)]
mod tests {
    use array_matrix::ArrayMatrix;
    use std::ops::{Index, IndexMut, Add, Sub};
    use std::fmt;

    #[test]
    fn ident() {
        impl_matrix!(TestMatrix([i32; (2, 2)]));
        let m = TestMatrix::identity();

        assert_eq!(m, TestMatrix([1, 0, 0, 1]));
    }

    #[test]
    fn row_col() {
        const ROW: usize = 3;
        const COLUMN: usize = 3;
        impl_matrix!(TestMatrix([i32; (ROW, COLUMN)]));
        let m = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);

        assert_eq!(m.row(), ROW);
        assert_eq!(m.column(), COLUMN);
    }

    #[test]
    fn transpose() {
        impl_matrix!(TestMatrix([i32; (2, 2)]));
        let m = TestMatrix([1, 2, 3, 4]);
        let trans = m.transpose();

        assert_eq!(trans, TestMatrix([1, 3, 2, 4]));
    }

    #[test]
    fn transpose_mut() {
        impl_matrix!(TestMatrix([i32; (2, 2)]));
        let mut m = TestMatrix([1, 2, 3, 4]);
        m.transpose_mut();

        assert_eq!(m, TestMatrix([1, 3, 2, 4]));
    }

    #[test]
    fn transpose_large() {
        impl_matrix!(TestMatrix([i32; (6, 6)]));
        let m = TestMatrix([
                           0, 1, 2, 3, 4, 5,
                           6, 7, 8, 9, 10, 11,
                           12, 13, 14, 15, 16, 17,
                           18, 19, 20, 21, 22, 23,
                           24, 25, 26, 27, 28, 29,
                           30, 31, 32, 33, 34, 35
        ]);
        let trans = m.transpose();

        assert_eq!(trans,
                   TestMatrix([
                              0, 6, 12, 18, 24, 30,
                              1, 7, 13, 19, 25, 31,
                              2, 8, 14, 20, 26, 32,
                              3, 9, 15, 21, 27, 33,
                              4, 10, 16, 22, 28, 34,
                              5, 11, 17, 23, 29, 35
                   ]));
    }

    #[test]
    fn index() {
        impl_matrix!(TestMatrix([i32; (3, 3)]));
        let m = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);
        assert_eq!(m[(1, 2)], 6);
    }

    #[test]
    fn index_mut() {
        impl_matrix!(TestMatrix([i32; (3, 3)]));
        let mut m = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);
        assert_eq!(m[(1, 2)], 6);
        m[(1, 2)] = 30;
        assert_eq!(m[(1, 2)], 30);
    }

    #[test]
    fn eq() {
        impl_matrix!(TestMatrix([i32; (3, 3)]));
        let m_a = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);
        let m_b = TestMatrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);

        assert_eq!(m_a, m_b);
    }

    #[test]
    fn add() {
        impl_matrix!(TestMatrix([i32; (2, 2)]));
        let m_a = TestMatrix([1, 2, 3, 4]);
        let m_b = TestMatrix([1, 2, 3, 4]);
        let m_c = m_a + m_b;

        assert_eq!(m_c, TestMatrix([2, 4, 6, 8]));
    }

    #[test]
    fn subtract() {
        impl_matrix!(TestMatrix([i32; (2, 2)]));
        let m_a = TestMatrix([1, 2, 3, 4]);
        let m_b = TestMatrix([1, 2, 3, 4]);
        let m_c = m_a - m_b;

        assert_eq!(m_c, TestMatrix([0, 0, 0, 0]));
    }

    #[test]
    fn impl_two_matrix() {
        impl_matrix!(TestMatrixA([i32; (2, 2)]));
        impl_matrix!(TestMatrixB([f32; (2, 2)]));

        let m_a = TestMatrixA([1, 2, 3, 4]);
        let m_b = TestMatrixB([1., 2., 3., 4.]);

        assert_eq!(m_a[(0, 0)] as f32, m_b[(0, 0)]);
    }

    #[test]
    fn large_matrix() {
        impl_matrix!(TestMatrixA([i32; (6, 6)]));
        let m_a = TestMatrixA([1; 36]);
        let m_b = TestMatrixA([1; 36]);

        assert_eq!(m_a, m_b);
    }
}
<|endoftext|>