<commit_before>// De-duplication macro used in src/app.rs
macro_rules! get_help {
    ($opt:ident) => {
        if let Some(h) = $opt.help {
            format!("{}{}", h,
                if let Some(ref pv) = $opt.possible_vals {
                    let mut pv_s = pv.iter().fold(String::with_capacity(50), |acc, name| {
                        acc + &format!(" {}",name)[..]
                    });
                    pv_s.shrink_to_fit();
                    format!(" [values:{}]", &pv_s[..])
                }else{"".to_owned()})
        } else {
            "    ".to_owned()
        }
    };
}

// De-duplication macro used in src/app.rs
macro_rules! parse_group_reqs {
    ($me:ident, $arg:ident) => {
        for ag in $me.groups.values() {
            let mut found = false;
            for name in ag.args.iter() {
                if name == &$arg.name {
                    $me.required.remove(ag.name);
                    if let Some(ref reqs) = ag.requires {
                        for r in reqs {
                            $me.required.insert(r);
                        }
                    }
                    if let Some(ref bl) = ag.conflicts {
                        for b in bl {
                            $me.blacklist.insert(b);
                        }
                    }
                    found = true;
                    break;
                }
            }
            if found {
                for name in ag.args.iter() {
                    if name == &$arg.name { continue }
                    $me.required.remove(name);
                    $me.blacklist.insert(name);
                }
            }
        }
    };
}

// De-duplication macro used in src/app.rs
macro_rules! validate_reqs {
    ($me:ident, $t:ident, $m:ident, $n:ident) => {
        if let Some(a) = $me.$t.get($n) {
            if let Some(ref bl) = a.blacklist {
                for n in bl.iter() {
                    if $m.args.contains_key(n) {
                        return false
                    } else if $me.groups.contains_key(n) {
                        let grp = $me.groups.get(n).unwrap();
                        for an in grp.args.iter() {
                            if $m.args.contains_key(an) {
                                return false
                            }
                        }
                    }
                }
            }
        }
    };
}

// Thanks to bluss and flan3002 in #rust IRC
//
// Helps with rightward drift when iterating over something and matching each item.
macro_rules! for_match {
    ($it:ident, $($p:pat => $($e:expr);+),*) => {
        for i in $it {
            match i {
            $(
                $p => { $($e)+ }
            )*
            }
        }
    };
}

/// Convenience macro getting a typed value `T` where `T` implements `std::str::FromStr`
/// This macro returns a `Result<T,String>` which allows you as the developer to decide
/// what you'd like to do on a failed parse. There are two types of errors, parse failures
/// and those where the argument wasn't present (such as a non-required argument).
///
/// You can use it to get a single value, or a `Vec<T>` with the `values_of()`
///
/// **NOTE:** Be cautious, as since this a macro invocation it's not exactly like
/// standard syntax.
///
///
/// # Example single value
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///               .arg_from_usage("[length] 'Set the length to use as a pos whole num, i.e. 20'")
///               .get_matches();
/// let len = value_t!(matches.value_of("length"), u32)
///                 .unwrap_or_else(|e|{
///                     println!("{}",e);
///                     std::process::exit(1)
///                 });
///
/// println!("{} + 2: {}", len, len + 2);
/// # }
/// ```
///
///
/// # Example multiple values
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///               .arg_from_usage("[seq]... 'A sequence of pos whole nums, i.e. 20 45'")
///               .get_matches();
/// for v in value_t!(matches.values_of("seq"), u32)
///             .unwrap_or_else(|e|{
///                 println!("{}",e);
///                 std::process::exit(1)
///             }) {
///     println!("{} + 2: {}", v, v + 2);
/// }
/// # }
/// ```
#[macro_export]
macro_rules! value_t {
    ($m:ident.value_of($v:expr), $t:ty) => {
        match $m.value_of($v) {
            Some(v) => {
                match v.parse::<$t>() {
                    Ok(val) => Ok(val),
                    Err(_)  => Err(format!("{} isn't a valid {}",v,stringify!($t))),
                }
            },
            None => Err(format!("Argument \"{}\" not found", $v))
        }
    };
    ($m:ident.values_of($v:expr), $t:ty) => {
        match $m.values_of($v) {
            Some(ref v) => {
                let mut tmp = Vec::with_capacity(v.len());
                let mut err = None;
                for pv in v {
                    match pv.parse::<$t>() {
                        Ok(rv) => tmp.push(rv),
                        Err(e) => {
                            err = Some(format!("{} isn't a valid {}\n{}",pv,stringify!($t),e));
                            break
                        }
                    }
                }
                match err {
                    Some(e) => Err(e),
                    None => Ok(tmp)
                }
            },
            None => Err(format!("Argument \"{}\" not found", $v))
        }
    };
}

/// Convenience macro getting a typed value `T` where `T` implements `std::str::FromStr`
/// This macro returns a `T` or `Vec<T>` or exits with a usage string upon failure. This
/// removes some of the boiler plate to handle failures from value_t! above.
///
/// You can use it to get a single value `T`, or a `Vec<T>` with the `values_of()`
///
/// **NOTE:** This should only be used on required arguments, as it can be confusing to the user
/// why they are getting error messages when it appears they're entering all required argumetns.
///
/// **NOTE:** Be cautious, as since this a macro invocation it's not exactly like
/// standard syntax.
///
///
/// # Example single value
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///               .arg_from_usage("[length] 'Set the length to use as a pos whole num, i.e. 20'")
///               .get_matches();
/// let len = value_t_or_exit!(matches.value_of("length"), u32);
///
/// println!("{} + 2: {}", len, len + 2);
/// # }
/// ```
///
///
/// # Example multiple values
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///                   .arg_from_usage("[seq]... 'A sequence of pos whole nums, i.e. 20 45'")
///                   .get_matches();
/// for v in value_t_or_exit!(matches.values_of("seq"), u32) {
///     println!("{} + 2: {}", v, v + 2);
/// }
/// # }
/// ```
#[macro_export]
macro_rules! value_t_or_exit {
    ($m:ident.value_of($v:expr), $t:ty) => {
        match $m.value_of($v) {
            Some(v) => {
                match v.parse::<$t>() {
                    Ok(val) => val,
                    Err(e)  => {
                        println!("{} isn't a valid {}\n{}\n{}\nPlease re-run with --help for \
                            more information",
                            v,
                            stringify!($t),
                            e,
                            $m.usage());
                        ::std::process::exit(1);
                    }
                }
            },
            None => {
                println!("Argument \"{}\" not found or is not valid\n{}\nPlease re-run with \
                    --help for more information",
                    $v,
                    $m.usage());
                ::std::process::exit(1);
            }
        }
    };
    ($m:ident.values_of($v:expr), $t:ty) => {
        match $m.values_of($v) {
            Some(ref v) => {
                let mut tmp = Vec::with_capacity(v.len());
                for pv in v {
                    match pv.parse::<$t>() {
                        Ok(rv) => tmp.push(rv),
                        Err(_)  => {
                            println!("{} isn't a valid {}\n{}\nPlease re-run with --help for more \
                                information",
                                pv,
                                stringify!($t),
                                $m.usage());
                            ::std::process::exit(1);
                        }
                    }
                }
                tmp
            },
            None => {
                println!("Argument \"{}\" not found or is not valid\n{}\nPlease re-run with \
                    --help for more information",
                    $v,
                    $m.usage());
                ::std::process::exit(1);
            }
        }
    };
}

/// Convenience macro generated a simple enum with variants to be used as a type when parsing
/// arguments.
///
/// # Example
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::{App, Arg};
/// simple_enum!{Foo => Bar, Baz, Qux}
/// // Foo enum can now be used via Foo::Bar, or Foo::Baz, etc
/// // and implements std::str::FromStr to use with the value_t! macros
/// fn main() {
///     let enum_vals = ["Bar", "Baz", "Qux"];
///     let m = App::new("app")
///                 .arg(Arg::from_usage("<foo> 'the foo'")
///                     .possible_values(&enum_vals))
///                 .get_matches();
///     let f = value_t_or_exit!(m.value_of("foo"), Foo);
///
///     // Use f like any other Foo variant...
/// }
/// ```
#[macro_export]
macro_rules! simple_enum {
    ($e:ident => $($v:ident),+) => {
        enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
}

/// Convenience macro to generate more complete enums with variants to be used as a type when
/// parsing arguments.
///
/// These enums support pub (or not) and use of the #[derive()] traits
///
///
/// # Example
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::{App, Arg};
/// arg_enum!{
///     #[derive(Debug)]
///     pub enum Foo {
///         Bar,
///         Baz,
///         Qux
///     }
/// }
/// // Foo enum can now be used via Foo::Bar, or Foo::Baz, etc
/// // and implements std::str::FromStr to use with the value_t! macros
/// fn main() {
///     let m = App::new("app")
///                 .arg_from_usage("<foo> 'the foo'")
///                 .get_matches();
///     let f = value_t_or_exit!(m.value_of("foo"), Foo);
///
///     // Use f like any other Foo variant...
/// }
/// ```
#[macro_export]
macro_rules! arg_enum {
    (enum $e:ident { $($v:ident),+ } ) => {
        enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
    (pub enum $e:ident { $($v:ident),+ } ) => {
        pub enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
    (#[derive($($d:ident),+)] enum $e:ident { $($v:ident),+ } ) => {
        #[derive($($d,)+)]
        enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
    (#[derive($($d:ident),+)] pub enum $e:ident { $($v:ident),+ } ) => {
        #[derive($($d,)+)]
        pub enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
}

/// Allows you pull the version for an from your Cargo.toml as MAJOR.MINOR.PATCH_PKGVERSION_PRE
///
/// # Example
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
///     let m = App::new("app")
///                 .version(&crate_version!()[..])
///                 .get_matches();
/// # }
/// ```
#[macro_export]
macro_rules! crate_version {
    () => {
        format!("{}.{}.{}{}",
            env!("CARGO_PKG_VERSION_MAJOR"),
            env!("CARGO_PKG_VERSION_MINOR"),
            env!("CARGO_PKG_VERSION_PATCH"),
            option_env!("CARGO_PKG_VERSION_PRE").unwrap_or(""))
    }
}
<commit_msg>im(arg_enum): allows ascii case insensitivity for enum variants<commit_after>// De-duplication macro used in src/app.rs
macro_rules! get_help {
    ($opt:ident) => {
        if let Some(h) = $opt.help {
            format!("{}{}", h,
                if let Some(ref pv) = $opt.possible_vals {
                    let mut pv_s = pv.iter().fold(String::with_capacity(50), |acc, name| {
                        acc + &format!(" {}",name)[..]
                    });
                    pv_s.shrink_to_fit();
                    format!(" [values:{}]", &pv_s[..])
                }else{"".to_owned()})
        } else {
            "    ".to_owned()
        }
    };
}

// De-duplication macro used in src/app.rs
macro_rules! parse_group_reqs {
    ($me:ident, $arg:ident) => {
        for ag in $me.groups.values() {
            let mut found = false;
            for name in ag.args.iter() {
                if name == &$arg.name {
                    $me.required.remove(ag.name);
                    if let Some(ref reqs) = ag.requires {
                        for r in reqs {
                            $me.required.insert(r);
                        }
                    }
                    if let Some(ref bl) = ag.conflicts {
                        for b in bl {
                            $me.blacklist.insert(b);
                        }
                    }
                    found = true;
                    break;
                }
            }
            if found {
                for name in ag.args.iter() {
                    if name == &$arg.name { continue }
                    $me.required.remove(name);
                    $me.blacklist.insert(name);
                }
            }
        }
    };
}

// De-duplication macro used in src/app.rs
macro_rules! validate_reqs {
    ($me:ident, $t:ident, $m:ident, $n:ident) => {
        if let Some(a) = $me.$t.get($n) {
            if let Some(ref bl) = a.blacklist {
                for n in bl.iter() {
                    if $m.args.contains_key(n) {
                        return false
                    } else if $me.groups.contains_key(n) {
                        let grp = $me.groups.get(n).unwrap();
                        for an in grp.args.iter() {
                            if $m.args.contains_key(an) {
                                return false
                            }
                        }
                    }
                }
            }
        }
    };
}

// Thanks to bluss and flan3002 in #rust IRC
//
// Helps with rightward drift when iterating over something and matching each item.
macro_rules! for_match {
    ($it:ident, $($p:pat => $($e:expr);+),*) => {
        for i in $it {
            match i {
            $(
                $p => { $($e)+ }
            )*
            }
        }
    };
}

/// Convenience macro getting a typed value `T` where `T` implements `std::str::FromStr`
/// This macro returns a `Result<T,String>` which allows you as the developer to decide
/// what you'd like to do on a failed parse. There are two types of errors, parse failures
/// and those where the argument wasn't present (such as a non-required argument).
///
/// You can use it to get a single value, or a `Vec<T>` with the `values_of()`
///
/// **NOTE:** Be cautious, as since this a macro invocation it's not exactly like
/// standard syntax.
///
///
/// # Example single value
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///               .arg_from_usage("[length] 'Set the length to use as a pos whole num, i.e. 20'")
///               .get_matches();
/// let len = value_t!(matches.value_of("length"), u32)
///                 .unwrap_or_else(|e|{
///                     println!("{}",e);
///                     std::process::exit(1)
///                 });
///
/// println!("{} + 2: {}", len, len + 2);
/// # }
/// ```
///
///
/// # Example multiple values
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///               .arg_from_usage("[seq]... 'A sequence of pos whole nums, i.e. 20 45'")
///               .get_matches();
/// for v in value_t!(matches.values_of("seq"), u32)
///             .unwrap_or_else(|e|{
///                 println!("{}",e);
///                 std::process::exit(1)
///             }) {
///     println!("{} + 2: {}", v, v + 2);
/// }
/// # }
/// ```
#[macro_export]
macro_rules! value_t {
    ($m:ident.value_of($v:expr), $t:ty) => {
        match $m.value_of($v) {
            Some(v) => {
                match v.parse::<$t>() {
                    Ok(val) => Ok(val),
                    Err(_)  => Err(format!("{} isn't a valid {}",v,stringify!($t))),
                }
            },
            None => Err(format!("Argument \"{}\" not found", $v))
        }
    };
    ($m:ident.values_of($v:expr), $t:ty) => {
        match $m.values_of($v) {
            Some(ref v) => {
                let mut tmp = Vec::with_capacity(v.len());
                let mut err = None;
                for pv in v {
                    match pv.parse::<$t>() {
                        Ok(rv) => tmp.push(rv),
                        Err(e) => {
                            err = Some(format!("{} isn't a valid {}\n{}",pv,stringify!($t),e));
                            break
                        }
                    }
                }
                match err {
                    Some(e) => Err(e),
                    None => Ok(tmp)
                }
            },
            None => Err(format!("Argument \"{}\" not found", $v))
        }
    };
}

/// Convenience macro getting a typed value `T` where `T` implements `std::str::FromStr`
/// This macro returns a `T` or `Vec<T>` or exits with a usage string upon failure. This
/// removes some of the boiler plate to handle failures from value_t! above.
///
/// You can use it to get a single value `T`, or a `Vec<T>` with the `values_of()`
///
/// **NOTE:** This should only be used on required arguments, as it can be confusing to the user
/// why they are getting error messages when it appears they're entering all required argumetns.
///
/// **NOTE:** Be cautious, as since this a macro invocation it's not exactly like
/// standard syntax.
///
///
/// # Example single value
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///               .arg_from_usage("[length] 'Set the length to use as a pos whole num, i.e. 20'")
///               .get_matches();
/// let len = value_t_or_exit!(matches.value_of("length"), u32);
///
/// println!("{} + 2: {}", len, len + 2);
/// # }
/// ```
///
///
/// # Example multiple values
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
/// let matches = App::new("myapp")
///                   .arg_from_usage("[seq]... 'A sequence of pos whole nums, i.e. 20 45'")
///                   .get_matches();
/// for v in value_t_or_exit!(matches.values_of("seq"), u32) {
///     println!("{} + 2: {}", v, v + 2);
/// }
/// # }
/// ```
#[macro_export]
macro_rules! value_t_or_exit {
    ($m:ident.value_of($v:expr), $t:ty) => {
        match $m.value_of($v) {
            Some(v) => {
                match v.parse::<$t>() {
                    Ok(val) => val,
                    Err(e)  => {
                        println!("{} isn't a valid {}\n\t{}\n{}\nPlease re-run with --help for \
                            more information",
                            v,
                            stringify!($t),
                            e,
                            $m.usage());
                        ::std::process::exit(1);
                    }
                }
            },
            None => {
                println!("Argument \"{}\" not found or is not valid\n{}\nPlease re-run with \
                    --help for more information",
                    $v,
                    $m.usage());
                ::std::process::exit(1);
            }
        }
    };
    ($m:ident.values_of($v:expr), $t:ty) => {
        match $m.values_of($v) {
            Some(ref v) => {
                let mut tmp = Vec::with_capacity(v.len());
                for pv in v {
                    match pv.parse::<$t>() {
                        Ok(rv) => tmp.push(rv),
                        Err(_)  => {
                            println!("{} isn't a valid {}\n\t{}\nPlease re-run with --help for more \
                                information",
                                pv,
                                stringify!($t),
                                $m.usage());
                            ::std::process::exit(1);
                        }
                    }
                }
                tmp
            },
            None => {
                println!("Argument \"{}\" not found or is not valid\n{}\nPlease re-run with \
                    --help for more information",
                    $v,
                    $m.usage());
                ::std::process::exit(1);
            }
        }
    };
}

/// Convenience macro generated a simple enum with variants to be used as a type when parsing
/// arguments.
///
/// # Example
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::{App, Arg};
/// simple_enum!{Foo => Bar, Baz, Qux}
/// // Foo enum can now be used via Foo::Bar, or Foo::Baz, etc
/// // and implements std::str::FromStr to use with the value_t! macros
/// fn main() {
///     let enum_vals = ["Bar", "Baz", "Qux"];
///     let m = App::new("app")
///                 .arg(Arg::from_usage("<foo> 'the foo'")
///                     .possible_values(&enum_vals))
///                 .get_matches();
///     let f = value_t_or_exit!(m.value_of("foo"), Foo);
///
///     // Use f like any other Foo variant...
/// }
/// ```
#[macro_export]
macro_rules! simple_enum {
    ($e:ident => $($v:ident),+) => {
        enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
}

/// Convenience macro to generate more complete enums with variants to be used as a type when
/// parsing arguments.
///
/// **NOTE:** Case insensitivity is supported for ASCII characters
///
/// These enums support pub (or not) and use of the #[derive()] traits
///
///
/// # Example
///
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::{App, Arg};
/// arg_enum!{
///     #[derive(Debug)]
///     pub enum Foo {
///         Bar,
///         Baz,
///         Qux
///     }
/// }
/// // Foo enum can now be used via Foo::Bar, or Foo::Baz, etc
/// // and implements std::str::FromStr to use with the value_t! macros
/// fn main() {
///     let m = App::new("app")
///                 .arg_from_usage("<foo> 'the foo'")
///                 .get_matches();
///     let f = value_t_or_exit!(m.value_of("foo"), Foo);
///
///     // Use f like any other Foo variant...
/// }
/// ```
#[macro_export]
macro_rules! arg_enum {
    (enum $e:ident { $($v:ident),+ } ) => {
        enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                use ::std::ascii::AsciiExt;
                match s {
                    $(stringify!($v) |
                    _ if s.eq_ignore_ascii_case(stringify!($v)) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid values:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
    (pub enum $e:ident { $($v:ident),+ } ) => {
        pub enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
    (#[derive($($d:ident),+)] enum $e:ident { $($v:ident),+ } ) => {
        #[derive($($d,)+)]
        enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
    (#[derive($($d:ident),+)] pub enum $e:ident { $($v:ident),+ } ) => {
        #[derive($($d,)+)]
        pub enum $e {
            $($v),+
        }

        impl ::std::str::FromStr for $e {
            type Err = String;

            fn from_str(s: &str) -> Result<Self,Self::Err> {
                match s {
                    $(stringify!($v) => Ok($e::$v),)+
                    _                => Err({
                                            let v = vec![
                                                $(stringify!($v),)+
                                            ];
                                            format!("valid:{}",
                                                v.iter().fold(String::new(), |a, i| {
                                                    a + &format!(" {}", i)[..]
                                                }))
                                        })
                }
            }
        }
    };
}

/// Allows you pull the version for an from your Cargo.toml as MAJOR.MINOR.PATCH_PKGVERSION_PRE
///
/// # Example
/// ```no_run
/// # #[macro_use]
/// # extern crate clap;
/// # use clap::App;
/// # fn main() {
///     let m = App::new("app")
///                 .version(&crate_version!()[..])
///                 .get_matches();
/// # }
/// ```
#[macro_export]
macro_rules! crate_version {
    () => {
        format!("{}.{}.{}{}",
            env!("CARGO_PKG_VERSION_MAJOR"),
            env!("CARGO_PKG_VERSION_MINOR"),
            env!("CARGO_PKG_VERSION_PATCH"),
            option_env!("CARGO_PKG_VERSION_PRE").unwrap_or(""))
    }
}
<|endoftext|>


<commit_before>#[doc(hidden)]
#[macro_export]
macro_rules! var {
    ($idx:expr) => {{
        use $crate::{Client, RepeatedField, Term, Datum, TT, DT};

        // ID
        let mut id = Datum::new();
        id.set_field_type(DT::R_NUM);
        id.set_r_num($idx as f64);
        // DATUM
        let mut datum = Term::new();
        datum.set_field_type(TT::DATUM);
        datum.set_datum(id);
        // VAR
        let mut var = Term::new();
        var.set_field_type(TT::VAR);
        let args = RepeatedField::from_vec(vec![datum]);
        var.set_args(args);
        let mut client = Client::new();
        client.set_term(Ok(var));
        client
    }}
}

#[doc(hidden)]
#[macro_export]
macro_rules! func {
    ($f:tt, $( $v:expr ),* $(,)* ) => {{
        use $crate::{Client, RepeatedField, Term, Datum, TT, DT};

        // IDs
        // when closure has no args ids doesn't need to be mutable
        // this lint is ignored (see https://github.com/rust-lang/rust/issues/40491)
        #[allow(unused_mut)]
        let mut ids = Vec::new();
        let res: Client = $f(
            $({
                let id = $v;
                for t in id.term().unwrap().get_args() {
                    ids.push(t.get_datum().clone());
                }
                id
            },)*
        );
        let mut closure = Client::new();
        match res.term() {
            Ok(res) => {
                // ARRAY
                let mut array = Datum::new();
                array.set_field_type(DT::R_ARRAY);
                let args = RepeatedField::from_vec(ids);
                array.set_r_array(args);
                // DATUM
                let mut datum = Term::new();
                datum.set_field_type(TT::DATUM);
                datum.set_datum(array);
                // FUNC
                let mut func = Term::new();
                func.set_field_type(TT::FUNC);
                let args = RepeatedField::from_vec(vec![datum, res.clone()]);
                func.set_args(args);
                closure.set_term(Ok(func));
            }
            Err(error) => {
                closure.set_term(Err(error));
            }
        }
        closure
    }}
}

macro_rules! with_args {
    ( $cmd:ident, $args:ident ) => {{
        let mut tmp_args = $args;
        if let Ok(ref mut term) = $cmd.term {
            if tmp_args.has_field_type() { // did not come from the args macro
                term.mut_args().push(tmp_args);
            } else { // came from the args macro
                for arg in tmp_args.take_args().into_vec() {
                    term.mut_args().push(arg);
                }
                for pair in tmp_args.take_optargs().into_vec() {
                    term.mut_optargs().push(pair);
                }
            }
        }
    }}
}
<commit_msg>remove obsolete comment<commit_after>#[doc(hidden)]
#[macro_export]
macro_rules! var {
    ($idx:expr) => {{
        use $crate::{Client, RepeatedField, Term, Datum, TT, DT};

        // ID
        let mut id = Datum::new();
        id.set_field_type(DT::R_NUM);
        id.set_r_num($idx as f64);
        // DATUM
        let mut datum = Term::new();
        datum.set_field_type(TT::DATUM);
        datum.set_datum(id);
        // VAR
        let mut var = Term::new();
        var.set_field_type(TT::VAR);
        let args = RepeatedField::from_vec(vec![datum]);
        var.set_args(args);
        let mut client = Client::new();
        client.set_term(Ok(var));
        client
    }}
}

#[doc(hidden)]
#[macro_export]
macro_rules! func {
    ($f:tt, $( $v:expr ),* $(,)* ) => {{
        use $crate::{Client, RepeatedField, Term, Datum, TT, DT};

        // IDs
        #[allow(unused_mut)]
        let mut ids = Vec::new();
        let res: Client = $f(
            $({
                let id = $v;
                for t in id.term().unwrap().get_args() {
                    ids.push(t.get_datum().clone());
                }
                id
            },)*
        );
        let mut closure = Client::new();
        match res.term() {
            Ok(res) => {
                // ARRAY
                let mut array = Datum::new();
                array.set_field_type(DT::R_ARRAY);
                let args = RepeatedField::from_vec(ids);
                array.set_r_array(args);
                // DATUM
                let mut datum = Term::new();
                datum.set_field_type(TT::DATUM);
                datum.set_datum(array);
                // FUNC
                let mut func = Term::new();
                func.set_field_type(TT::FUNC);
                let args = RepeatedField::from_vec(vec![datum, res.clone()]);
                func.set_args(args);
                closure.set_term(Ok(func));
            }
            Err(error) => {
                closure.set_term(Err(error));
            }
        }
        closure
    }}
}

macro_rules! with_args {
    ( $cmd:ident, $args:ident ) => {{
        let mut tmp_args = $args;
        if let Ok(ref mut term) = $cmd.term {
            if tmp_args.has_field_type() { // did not come from the args macro
                term.mut_args().push(tmp_args);
            } else { // came from the args macro
                for arg in tmp_args.take_args().into_vec() {
                    term.mut_args().push(arg);
                }
                for pair in tmp_args.take_optargs().into_vec() {
                    term.mut_optargs().push(pair);
                }
            }
        }
    }}
}
<|endoftext|>


<commit_before>/// Return early with an error.
///
/// This macro is equivalent to `return Err(From::from($err))`.
///
/// # Example
///
/// ```
/// # use anyhow::{bail, Result};
/// #
/// # fn has_permission(user: usize, resource: usize) -> bool {
/// #     true
/// # }
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #     let resource = 0;
/// #
/// if !has_permission(user, resource) {
///     bail!("permission denied for accessing {}", resource);
/// }
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{bail, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// if depth > MAX_DEPTH {
///     bail!(ScienceError::RecursionLimitExceeded);
/// }
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! bail {
    ($msg:literal $(,)?) => {
        return $crate::private::Err($crate::anyhow!($msg));
    };
    ($err:expr $(,)?) => {
        return $crate::private::Err($crate::anyhow!($err));
    };
    ($fmt:expr, $($arg:tt)*) => {
        return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
    };
}

/// Return early with an error if a condition is not satisfied.
///
/// This macro is equivalent to `if !$cond { return Err(From::from($err)); }`.
///
/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`
/// rather than panicking.
///
/// # Example
///
/// ```
/// # use anyhow::{ensure, Result};
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #
/// ensure!(user == 0, "only user 0 is allowed");
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{ensure, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! ensure {
    ($cond:expr, $msg:literal $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($msg));
        }
    };
    ($cond:expr, $err:expr $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($err));
        }
    };
    ($cond:expr, $fmt:expr, $($arg:tt)*) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
        }
    };
}

/// Construct an ad-hoc error from a string or existing non-`anyhow` error
/// value.
///
/// This evaluates to an `Error`. It can take either just a string, or a format
/// string with arguments. It also can take any custom type which implements
/// `Debug` and `Display`.
///
/// If called with a single argument whose type implements `std::error::Error`
/// (in addition to `Debug` and `Display`, which are always required), then that
/// Error impl's `source` is preserved as the `source` of the resulting
/// `anyhow::Error`.
///
/// # Example
///
/// ```
/// # type V = ();
/// #
/// use anyhow::{anyhow, Result};
///
/// fn lookup(key: &str) -> Result<V> {
///     if key.len() != 16 {
///         return Err(anyhow!("key length must be 16 characters, got {:?}", key));
///     }
///
///     // ...
///     # Ok(())
/// }
/// ```
#[macro_export]
macro_rules! anyhow {
    ($msg:literal $(,)?) => {
        // Handle $:literal as a special case to make cargo-expanded code more
        // concise in the common case.
        $crate::private::new_adhoc($msg)
    };
    ($err:expr $(,)?) => ({
        use $crate::private::kind::*;
        let error = $err;
        (&error).anyhow_kind().new(error)
    });
    ($fmt:expr, $($arg:tt)*) => {
        $crate::private::new_adhoc(format!($fmt, $($arg)*))
    };
}
<commit_msg>Link from `anyhow!` to anyhow::Error<commit_after>/// Return early with an error.
///
/// This macro is equivalent to `return Err(From::from($err))`.
///
/// # Example
///
/// ```
/// # use anyhow::{bail, Result};
/// #
/// # fn has_permission(user: usize, resource: usize) -> bool {
/// #     true
/// # }
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #     let resource = 0;
/// #
/// if !has_permission(user, resource) {
///     bail!("permission denied for accessing {}", resource);
/// }
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{bail, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// if depth > MAX_DEPTH {
///     bail!(ScienceError::RecursionLimitExceeded);
/// }
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! bail {
    ($msg:literal $(,)?) => {
        return $crate::private::Err($crate::anyhow!($msg));
    };
    ($err:expr $(,)?) => {
        return $crate::private::Err($crate::anyhow!($err));
    };
    ($fmt:expr, $($arg:tt)*) => {
        return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
    };
}

/// Return early with an error if a condition is not satisfied.
///
/// This macro is equivalent to `if !$cond { return Err(From::from($err)); }`.
///
/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`
/// rather than panicking.
///
/// # Example
///
/// ```
/// # use anyhow::{ensure, Result};
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #
/// ensure!(user == 0, "only user 0 is allowed");
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{ensure, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! ensure {
    ($cond:expr, $msg:literal $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($msg));
        }
    };
    ($cond:expr, $err:expr $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($err));
        }
    };
    ($cond:expr, $fmt:expr, $($arg:tt)*) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
        }
    };
}

/// Construct an ad-hoc error from a string or existing non-`anyhow` error
/// value.
///
/// This evaluates to an [`Error`][crate::Error]. It can take either just a
/// string, or a format string with arguments. It also can take any custom type
/// which implements `Debug` and `Display`.
///
/// If called with a single argument whose type implements `std::error::Error`
/// (in addition to `Debug` and `Display`, which are always required), then that
/// Error impl's `source` is preserved as the `source` of the resulting
/// `anyhow::Error`.
///
/// # Example
///
/// ```
/// # type V = ();
/// #
/// use anyhow::{anyhow, Result};
///
/// fn lookup(key: &str) -> Result<V> {
///     if key.len() != 16 {
///         return Err(anyhow!("key length must be 16 characters, got {:?}", key));
///     }
///
///     // ...
///     # Ok(())
/// }
/// ```
#[macro_export]
macro_rules! anyhow {
    ($msg:literal $(,)?) => {
        // Handle $:literal as a special case to make cargo-expanded code more
        // concise in the common case.
        $crate::private::new_adhoc($msg)
    };
    ($err:expr $(,)?) => ({
        use $crate::private::kind::*;
        let error = $err;
        (&error).anyhow_kind().new(error)
    });
    ($fmt:expr, $($arg:tt)*) => {
        $crate::private::new_adhoc(format!($fmt, $($arg)*))
    };
}
<|endoftext|>


<commit_before>use std::str::FromStr;

#[derive(Debug, PartialEq)]
pub enum Instruction {
    NOP,
    MOV { src: Operand, dst: Operand },
    SWP,
    SAV,
    ADD { addend: Operand },
    SUB { subtrahend: Operand} ,
    NEG,
    J { cond: Condition, dst: Label},
    JRO { dst: Operand },
}

pub static BAD_OPCODE_ERR: &'static str = "Bad opcode for # of arguments";
pub static NUM_ARGS_ERR: &'static str = "Wrong number of arguments";
pub static LIT_DST_ERR: &'static str = "Literal not allowed as dst operand";

impl FromStr for Instruction {
    type Err = &'static str;

    fn from_str(insn: &str) -> Result<Instruction, Self::Err> {
        //Nightly: let words: Vec<&str> = insn.split_whitespace().collect();
        let words: Vec<&str> = insn.split(' ').filter(|s| *s != "").collect();

        match words.len() {
            1 => match words[0] {
                "NOP" => Ok(Instruction::NOP),
                "SWP" => Ok(Instruction::SWP),
                "SAV" => Ok(Instruction::SAV),
                "NEG" => Ok(Instruction::NEG),
                _ => Err(BAD_OPCODE_ERR),
            },

            2 => match words[0] {
                "ADD" => Operand::from_str(words[1]).map(|o| Instruction::ADD { addend: o }),
                "SUB" => Operand::from_str(words[1]).map(|o| Instruction::SUB { subtrahend: o }),
                "JMP" => Ok(Instruction::J { cond: Condition::Unconditional, dst: words[1].to_string() }),
                "JEZ" => Ok(Instruction::J { cond: Condition::Ez,            dst: words[1].to_string() }),
                "JNZ" => Ok(Instruction::J { cond: Condition::Nz,            dst: words[1].to_string() }),
                "JGZ" => Ok(Instruction::J { cond: Condition::Gz,            dst: words[1].to_string() }),
                "JLZ" => Ok(Instruction::J { cond: Condition::Lz,            dst: words[1].to_string() }),
                "JRO" => Operand::from_str(words[1]).map(|o| Instruction::JRO { dst: o }),
                _ => Err(BAD_OPCODE_ERR),
            },

            3 => match words[0] {
                "MOV" => Operand::from_str(words[1]).and_then(|s| Operand::from_str(words[2])
                    .and_then(|d| match d {
                        Operand::Lit(_) => Err(LIT_DST_ERR),
                        _ => Ok(Instruction::MOV { src: s, dst: d })
                        })),
                _ => Err(BAD_OPCODE_ERR),
            },

            _ => Err(NUM_ARGS_ERR)
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Port {
    Up,
    Down,
    Left,
    Right,
    Any,
    Last,
}

impl FromStr for Port {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "UP" =>     Ok(Port::Up),
            "DOWN" =>   Ok(Port::Down),
            "LEFT" =>   Ok(Port::Left),
            "RIGHT" =>  Ok(Port::Right),
            "ANY" =>    Ok(Port::Any),
            "LAST" =>   Ok(Port::Last),
            _ =>        Err("bad port"),
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Operand {
    Lit(i32),
    Port(Port),
    ACC,
}

impl FromStr for Operand {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s == "ACC" {
            Ok(Operand::ACC)
        } else if let Ok(as_int) = i32::from_str(s) {
            Ok(Operand::Lit(as_int))
        } else if let Ok(as_port) = Port::from_str(s) {
            Ok(Operand::Port(as_port))
        } else {
            Err("Invalid operand")
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Condition {
    Unconditional,
    Ez,
    Nz,
    Gz,
    Lz,
}

pub type Label = String;

#[cfg(test)]
mod tests {
    use super::{Condition, Instruction, Operand, Port};
    use super::{BAD_OPCODE_ERR,NUM_ARGS_ERR, LIT_DST_ERR};
    use std::str::FromStr;

    #[test]
    fn port_from_str() {
        assert_eq!(Port::from_str("UP").unwrap(),   Port::Up);
        assert_eq!(Port::from_str("DOWN").unwrap(), Port::Down);
        assert_eq!(Port::from_str("LEFT").unwrap(), Port::Left);
        assert_eq!(Port::from_str("RIGHT").unwrap(), Port::Right);
        assert_eq!(Port::from_str("ANY").unwrap(),  Port::Any);
        assert_eq!(Port::from_str("LAST").unwrap(), Port::Last);
        assert_eq!(Port::from_str("OTHER").unwrap_err(), "bad port");
    }

    #[test]
    fn operand_from_str() {
        assert_eq!(Operand::from_str("ACC").unwrap(), Operand::ACC);
        assert_eq!(Operand::from_str("32").unwrap(), Operand::Lit(32));
        assert_eq!(Operand::from_str("UP").unwrap(), Operand::Port(Port::Up));
        assert_eq!(Operand::from_str("FOO").unwrap_err(), "Invalid operand");
    }

    #[test]
    fn instruction_from_str() {
        fn i(s: &str) -> Instruction {
            Instruction::from_str(s).unwrap()
        }
        assert_eq!(i("NOP"), Instruction::NOP);
        assert_eq!(i("SWP"), Instruction::SWP);
        assert_eq!(i("SAV"), Instruction::SAV);
        assert_eq!(i("NEG"), Instruction::NEG);
        assert_eq!(Instruction::from_str("BOGUS").unwrap_err(), BAD_OPCODE_ERR);

        assert_eq!(i("ADD 10"), Instruction::ADD { addend: Operand::Lit(10) });
        assert_eq!(i("SUB 10"), Instruction::SUB { subtrahend: Operand::Lit(10) });
        assert_eq!(i("JMP LOC"), Instruction::J { cond: Condition::Unconditional,   dst: "LOC".to_string() });
        assert_eq!(i("JEZ LOC"), Instruction::J { cond: Condition::Ez,              dst: "LOC".to_string() });
        assert_eq!(i("JNZ LOC"), Instruction::J { cond: Condition::Nz,              dst: "LOC".to_string() });
        assert_eq!(i("JGZ LOC"), Instruction::J { cond: Condition::Gz,              dst: "LOC".to_string() });
        assert_eq!(i("JLZ LOC"), Instruction::J { cond: Condition::Lz,              dst: "LOC".to_string() });
        assert_eq!(i("JRO 1"), Instruction::JRO { dst: Operand::Lit(1) });
        assert_eq!(Instruction::from_str("JEQ LOC").unwrap_err(), BAD_OPCODE_ERR);

        assert_eq!(i("MOV UP DOWN"),    Instruction::MOV { src: Operand::Port(Port::Up), dst: Operand::Port(Port::Down) });
        assert_eq!(i("MOV  UP  DOWN"),  Instruction::MOV { src: Operand::Port(Port::Up), dst: Operand::Port(Port::Down) });
        assert_eq!(i("MOV UP ACC"),     Instruction::MOV { src: Operand::Port(Port::Up), dst: Operand::ACC });
        assert_eq!(i("MOV ACC ACC"),    Instruction::MOV { src: Operand::ACC, dst: Operand::ACC });
        assert_eq!(Instruction::from_str("MV UP ACC").unwrap_err(), BAD_OPCODE_ERR);
        assert_eq!(Instruction::from_str("MOV UP 10").unwrap_err(), LIT_DST_ERR);

        assert_eq!(Instruction::from_str("1 2 3 4").unwrap_err(), NUM_ARGS_ERR);
    }
}
<commit_msg>instruction: implement Display for Port<commit_after>use std::fmt;
use std::str::FromStr;

#[derive(Debug, PartialEq)]
pub enum Instruction {
    NOP,
    MOV { src: Operand, dst: Operand },
    SWP,
    SAV,
    ADD { addend: Operand },
    SUB { subtrahend: Operand} ,
    NEG,
    J { cond: Condition, dst: Label},
    JRO { dst: Operand },
}

pub static BAD_OPCODE_ERR: &'static str = "Bad opcode for # of arguments";
pub static NUM_ARGS_ERR: &'static str = "Wrong number of arguments";
pub static LIT_DST_ERR: &'static str = "Literal not allowed as dst operand";

impl FromStr for Instruction {
    type Err = &'static str;

    fn from_str(insn: &str) -> Result<Instruction, Self::Err> {
        //Nightly: let words: Vec<&str> = insn.split_whitespace().collect();
        let words: Vec<&str> = insn.split(' ').filter(|s| *s != "").collect();

        match words.len() {
            1 => match words[0] {
                "NOP" => Ok(Instruction::NOP),
                "SWP" => Ok(Instruction::SWP),
                "SAV" => Ok(Instruction::SAV),
                "NEG" => Ok(Instruction::NEG),
                _ => Err(BAD_OPCODE_ERR),
            },

            2 => match words[0] {
                "ADD" => Operand::from_str(words[1]).map(|o| Instruction::ADD { addend: o }),
                "SUB" => Operand::from_str(words[1]).map(|o| Instruction::SUB { subtrahend: o }),
                "JMP" => Ok(Instruction::J { cond: Condition::Unconditional, dst: words[1].to_string() }),
                "JEZ" => Ok(Instruction::J { cond: Condition::Ez,            dst: words[1].to_string() }),
                "JNZ" => Ok(Instruction::J { cond: Condition::Nz,            dst: words[1].to_string() }),
                "JGZ" => Ok(Instruction::J { cond: Condition::Gz,            dst: words[1].to_string() }),
                "JLZ" => Ok(Instruction::J { cond: Condition::Lz,            dst: words[1].to_string() }),
                "JRO" => Operand::from_str(words[1]).map(|o| Instruction::JRO { dst: o }),
                _ => Err(BAD_OPCODE_ERR),
            },

            3 => match words[0] {
                "MOV" => Operand::from_str(words[1]).and_then(|s| Operand::from_str(words[2])
                    .and_then(|d| match d {
                        Operand::Lit(_) => Err(LIT_DST_ERR),
                        _ => Ok(Instruction::MOV { src: s, dst: d })
                        })),
                _ => Err(BAD_OPCODE_ERR),
            },

            _ => Err(NUM_ARGS_ERR)
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Port {
    Up,
    Down,
    Left,
    Right,
    Any,
    Last,
}

impl fmt::Display for Port {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let d = self as &fmt::Debug;
        d.fmt(f)
    }
}

impl FromStr for Port {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "UP" =>     Ok(Port::Up),
            "DOWN" =>   Ok(Port::Down),
            "LEFT" =>   Ok(Port::Left),
            "RIGHT" =>  Ok(Port::Right),
            "ANY" =>    Ok(Port::Any),
            "LAST" =>   Ok(Port::Last),
            _ =>        Err("bad port"),
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Operand {
    Lit(i32),
    Port(Port),
    ACC,
}

impl FromStr for Operand {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s == "ACC" {
            Ok(Operand::ACC)
        } else if let Ok(as_int) = i32::from_str(s) {
            Ok(Operand::Lit(as_int))
        } else if let Ok(as_port) = Port::from_str(s) {
            Ok(Operand::Port(as_port))
        } else {
            Err("Invalid operand")
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Condition {
    Unconditional,
    Ez,
    Nz,
    Gz,
    Lz,
}

pub type Label = String;

#[cfg(test)]
mod tests {
    use super::{Condition, Instruction, Operand, Port};
    use super::{BAD_OPCODE_ERR,NUM_ARGS_ERR, LIT_DST_ERR};
    use std::str::FromStr;

    #[test]
    fn port_from_str() {
        assert_eq!(Port::from_str("UP").unwrap(),   Port::Up);
        assert_eq!(Port::from_str("DOWN").unwrap(), Port::Down);
        assert_eq!(Port::from_str("LEFT").unwrap(), Port::Left);
        assert_eq!(Port::from_str("RIGHT").unwrap(), Port::Right);
        assert_eq!(Port::from_str("ANY").unwrap(),  Port::Any);
        assert_eq!(Port::from_str("LAST").unwrap(), Port::Last);
        assert_eq!(Port::from_str("OTHER").unwrap_err(), "bad port");
    }

    #[test]
    fn operand_from_str() {
        assert_eq!(Operand::from_str("ACC").unwrap(), Operand::ACC);
        assert_eq!(Operand::from_str("32").unwrap(), Operand::Lit(32));
        assert_eq!(Operand::from_str("UP").unwrap(), Operand::Port(Port::Up));
        assert_eq!(Operand::from_str("FOO").unwrap_err(), "Invalid operand");
    }

    #[test]
    fn instruction_from_str() {
        fn i(s: &str) -> Instruction {
            Instruction::from_str(s).unwrap()
        }
        assert_eq!(i("NOP"), Instruction::NOP);
        assert_eq!(i("SWP"), Instruction::SWP);
        assert_eq!(i("SAV"), Instruction::SAV);
        assert_eq!(i("NEG"), Instruction::NEG);
        assert_eq!(Instruction::from_str("BOGUS").unwrap_err(), BAD_OPCODE_ERR);

        assert_eq!(i("ADD 10"), Instruction::ADD { addend: Operand::Lit(10) });
        assert_eq!(i("SUB 10"), Instruction::SUB { subtrahend: Operand::Lit(10) });
        assert_eq!(i("JMP LOC"), Instruction::J { cond: Condition::Unconditional,   dst: "LOC".to_string() });
        assert_eq!(i("JEZ LOC"), Instruction::J { cond: Condition::Ez,              dst: "LOC".to_string() });
        assert_eq!(i("JNZ LOC"), Instruction::J { cond: Condition::Nz,              dst: "LOC".to_string() });
        assert_eq!(i("JGZ LOC"), Instruction::J { cond: Condition::Gz,              dst: "LOC".to_string() });
        assert_eq!(i("JLZ LOC"), Instruction::J { cond: Condition::Lz,              dst: "LOC".to_string() });
        assert_eq!(i("JRO 1"), Instruction::JRO { dst: Operand::Lit(1) });
        assert_eq!(Instruction::from_str("JEQ LOC").unwrap_err(), BAD_OPCODE_ERR);

        assert_eq!(i("MOV UP DOWN"),    Instruction::MOV { src: Operand::Port(Port::Up), dst: Operand::Port(Port::Down) });
        assert_eq!(i("MOV  UP  DOWN"),  Instruction::MOV { src: Operand::Port(Port::Up), dst: Operand::Port(Port::Down) });
        assert_eq!(i("MOV UP ACC"),     Instruction::MOV { src: Operand::Port(Port::Up), dst: Operand::ACC });
        assert_eq!(i("MOV ACC ACC"),    Instruction::MOV { src: Operand::ACC, dst: Operand::ACC });
        assert_eq!(Instruction::from_str("MV UP ACC").unwrap_err(), BAD_OPCODE_ERR);
        assert_eq!(Instruction::from_str("MOV UP 10").unwrap_err(), LIT_DST_ERR);

        assert_eq!(Instruction::from_str("1 2 3 4").unwrap_err(), NUM_ARGS_ERR);
    }
}
<|endoftext|>


<commit_before>
use std;
use std::io::{Write};
use std::sync::{Arc, Barrier};
use std::sync::mpsc::Sender;
use std::collections::VecDeque;
use parse::EOF;
use parse::Code;

pub struct Repl {
  // TODO: Better name
  tx: Sender<Vec<u8>>,
  barrier: Arc<Barrier>,
  running: bool,
}

impl Repl {
  pub fn new() -> Self {
    let barrier = Arc::new(Barrier::new(2));
    let (tx, rx) = std::sync::mpsc::channel();
    let mut code = Code::new_from_channel(rx, barrier.clone());
    std::thread::spawn(move|| {
      code.parse_and_run();
    });
    Repl {
      tx: tx,
      barrier: barrier,
      running: false,
    }
  }

  pub fn start(&mut self) {
    self.running = true;
    Repl::display_carrot(false);
    self.barrier.wait();
    while self.running {
      let mut input = String::new();
      match Repl::read_line(&mut input) {
        Ok(num_read) => {
          if num_read == 0 {
            self.send(vec![EOF]);
            self.running = false;
          }
          else if num_read == 1 {
            continue;
          }
          else {
            let will_output = self.interpret_command(&input);
            if self.running {
              self.send(input.into_bytes());
              Repl::display_carrot(will_output);
            }
          }
        },
        Err(err) => panic!("Error reading from stdin: {}", err),
      }
    }
  }

  fn read_line(buffer: &mut String) -> std::io::Result<usize> {
    let ret = std::io::stdin().read_line(buffer);
    ret
  }

  fn display_carrot(newline: bool) {
    if newline { print!("\n") };
    print!("bf> ");
    match std::io::stdout().flush() {
      Ok(_) => {},
      Err(err) => panic!("Error flushing stdout: {}", err),
    }
  }

  fn send(&mut self, data: Vec<u8>) {
    match self.tx.send(data) {
      Ok(_) => {},
      Err(_) => {
        self.running = false;
        return;
      }
    }
    self.barrier.wait();
  }

  fn interpret_command(&mut self, command: &str) -> bool {
    let lowercase = command.trim().to_lowercase();
    let will_output = lowercase.contains(".");
    match lowercase.as_ref() {
      "quit" => {
        self.send(vec![EOF]);
        self.running = false;
        false
      },
      _ => will_output,
    }
  }
}

pub struct Context {
  tape: Vec<u8>,
  current_index: usize,
  input_buffer: VecDeque<u8>,
}

impl Context {
  pub fn new() -> Self {
    Context {
      tape: vec![0; 1],
      current_index: 0,
      input_buffer: VecDeque::new(),
    }
  }

  pub fn move_right(&mut self) {
    self.current_index += 1;
    while self.current_index >= self.tape.len() {
      self.tape.push(0);
    }
  }

  pub fn move_left(&mut self) {
    if self.current_index > 0 {
      self.current_index -= 1;
    }
  }

  pub fn input(&mut self) {

    loop {
      match self.input_buffer.pop_front() {
        Some(input) => {
          self.write(input);
          break;
        }
        None => self.input_buffer.append(&mut read_input()),
      }
    }
  }

  pub fn output(&self) {
    print!("{}", char::from(self.read()));
    match std::io::stdout().flush() {
      Ok(_) => {},
      Err(err) => println!("Error flushing the output buffer: {}", err),
    }
  }

  fn write(&mut self, value: u8) {
    self.tape[self.current_index] = value;
  }

  fn read(&self) -> u8 {
    self.tape[self.current_index]
  }

  pub fn increment(&mut self) {
    let old = self.tape[self.current_index];
    self.tape[self.current_index] = old.wrapping_add(1);
  }

  pub fn decrement(&mut self) {
    let old = self.tape[self.current_index];
    self.tape[self.current_index] = old.wrapping_sub(1);
  }

  pub fn current_cell_is_zero(&mut self) -> bool {
    self.tape[self.current_index] == 0
  }
}

fn read_input() -> VecDeque<u8> {
  let mut buffer = String::new();
  match std::io::stdin().read_line(&mut buffer) {
    Ok(_) => {},
    Err(err) => panic!("Error reading from stdin: {}", err),
  }
  let bytes = buffer.into_bytes();
  let mut ret = VecDeque::new();
  for byte in bytes.into_iter() {
    ret.push_back(byte);
  }
  ret
}
<commit_msg>add name to parsing thread<commit_after>
use std;
use std::io::{Write};
use std::sync::{Arc, Barrier};
use std::sync::mpsc::Sender;
use std::collections::VecDeque;
use parse::EOF;
use parse::Code;

pub struct Repl {
  // TODO: Better name
  tx: Sender<Vec<u8>>,
  barrier: Arc<Barrier>,
  running: bool,
}

impl Repl {
  pub fn new() -> Self {
    let barrier = Arc::new(Barrier::new(2));
    let (tx, rx) = std::sync::mpsc::channel();
    let mut code = Code::new_from_channel(rx, barrier.clone());
    let _handle = std::thread::Builder::new()
      .name(String::from("parse"))
      .spawn(move|| {
         code.parse_and_run();
       });

    Repl {
      tx: tx,
      barrier: barrier,
      running: false,
    }
  }

  pub fn start(&mut self) {
    self.running = true;
    Repl::display_carrot(false);
    self.barrier.wait();
    while self.running {
      let mut input = String::new();
      match Repl::read_line(&mut input) {
        Ok(num_read) => {
          if num_read == 0 {
            self.send(vec![EOF]);
            self.running = false;
          }
          else if num_read == 1 {
            continue;
          }
          else {
            let will_output = self.interpret_command(&input);
            if self.running {
              self.send(input.into_bytes());
              Repl::display_carrot(will_output);
            }
          }
        },
        Err(err) => panic!("Error reading from stdin: {}", err),
      }
    }
  }

  fn read_line(buffer: &mut String) -> std::io::Result<usize> {
    let ret = std::io::stdin().read_line(buffer);
    ret
  }

  fn display_carrot(newline: bool) {
    if newline { print!("\n") };
    print!("bf> ");
    match std::io::stdout().flush() {
      Ok(_) => {},
      Err(err) => panic!("Error flushing stdout: {}", err),
    }
  }

  fn send(&mut self, data: Vec<u8>) {
    match self.tx.send(data) {
      Ok(_) => {},
      Err(_) => {
        self.running = false;
        return;
      }
    }
    self.barrier.wait();
  }

  fn interpret_command(&mut self, command: &str) -> bool {
    let lowercase = command.trim().to_lowercase();
    let will_output = lowercase.contains(".");
    match lowercase.as_ref() {
      "quit" => {
        self.send(vec![EOF]);
        self.running = false;
        false
      },
      _ => will_output,
    }
  }
}

pub struct Context {
  tape: Vec<u8>,
  current_index: usize,
  input_buffer: VecDeque<u8>,
}

impl Context {
  pub fn new() -> Self {
    Context {
      tape: vec![0; 1],
      current_index: 0,
      input_buffer: VecDeque::new(),
    }
  }

  pub fn move_right(&mut self) {
    self.current_index += 1;
    while self.current_index >= self.tape.len() {
      self.tape.push(0);
    }
  }

  pub fn move_left(&mut self) {
    if self.current_index > 0 {
      self.current_index -= 1;
    }
  }

  pub fn input(&mut self) {

    loop {
      match self.input_buffer.pop_front() {
        Some(input) => {
          self.write(input);
          break;
        }
        None => self.input_buffer.append(&mut read_input()),
      }
    }
  }

  pub fn output(&self) {
    print!("{}", char::from(self.read()));
    match std::io::stdout().flush() {
      Ok(_) => {},
      Err(err) => println!("Error flushing the output buffer: {}", err),
    }
  }

  fn write(&mut self, value: u8) {
    self.tape[self.current_index] = value;
  }

  fn read(&self) -> u8 {
    self.tape[self.current_index]
  }

  pub fn increment(&mut self) {
    let old = self.tape[self.current_index];
    self.tape[self.current_index] = old.wrapping_add(1);
  }

  pub fn decrement(&mut self) {
    let old = self.tape[self.current_index];
    self.tape[self.current_index] = old.wrapping_sub(1);
  }

  pub fn current_cell_is_zero(&mut self) -> bool {
    self.tape[self.current_index] == 0
  }
}

fn read_input() -> VecDeque<u8> {
  let mut buffer = String::new();
  match std::io::stdin().read_line(&mut buffer) {
    Ok(_) => {},
    Err(err) => panic!("Error reading from stdin: {}", err),
  }
  let bytes = buffer.into_bytes();
  let mut ret = VecDeque::new();
  for byte in bytes.into_iter() {
    ret.push_back(byte);
  }
  ret
}
<|endoftext|>


<commit_before>use mio::tcp::{TcpListener,TcpStream};
use mio::Token;
use std::net::SocketAddr;
use std::io::Write;

use irc::util::LineReader;
use irc::protocol::*;
use irc::security::AuthSession;

#[derive(Debug)]
pub struct Client {
    stream: TcpStream,
    line_reader: LineReader,
    nickname: Option<String>,
    username: Option<String>,
    pub auth: AuthSession,
}

impl Client {
    pub fn new(stream: TcpStream) -> Self {
        Client {
            stream: stream,
            line_reader: LineReader::new(),
            nickname: None,
            username: None,
            auth: AuthSession::new(),
        }
    }

    pub fn stream(&self) -> &TcpStream {
        &self.stream
    }

    pub fn read_message(&mut self) -> Option<Message> {
        match self.line_reader.read(&mut self.stream) {
            Some(line) =>
                Some(Message::from_str(line.trim())),
            None => None
        }
    }

    pub fn set_nickname(&mut self, nickname: String) {
        self.nickname = Some(nickname);
    }

    pub fn nickname(&self) -> Option<&String> {
        match self.nickname {
            None => None,
            Some(ref s) => Some(s)
        }
    }

    pub fn join(&mut self, channel: &str) {
        let pfx = self.nickname.clone().unwrap();
        self.send(&Message {
            prefix: Some(pfx),
            command: Command::Join,
            args: vec![channel.to_string()],
            suffix: None
        });
    }

    pub fn pong(&mut self) {
        self.send(&Message::from(Command::Pong));
    }

    pub fn welcome(&mut self, message: &str) {
        self.send(&Message {
            prefix: Some("pto".to_string()),
            command: Command::Numeric(1),
            args: vec![message.to_string()],
            suffix: None
        });
    }

    pub fn send(&mut self, message: &Message) {
        self.stream.write(&message.to_string().trim().as_bytes());
        self.stream.write("\r\n".as_bytes());
        println!("Wrote {:?}", message.to_string());
    }
}

pub struct Server {
    listener: TcpListener,
}

impl Server {
    pub fn new(addr: &SocketAddr) -> Self {
        Server {
            listener: TcpListener::bind(addr).unwrap(),
        }
    }

    pub fn accept(&mut self) -> Option<Client> {
         match self.listener.accept() {
             Ok(None) => None,
             Ok(Some((socket, _))) =>
                 Some(Client::new(socket)),
             Err(e) => panic!(e),
         }
    }

    pub fn listener(&self) -> &TcpListener {
        &self.listener
    }
}

<commit_msg>irc: streams: client: make username public<commit_after>use mio::tcp::{TcpListener,TcpStream};
use mio::Token;
use std::net::SocketAddr;
use std::io::Write;

use irc::util::LineReader;
use irc::protocol::*;
use irc::security::AuthSession;

#[derive(Debug)]
pub struct Client {
    stream: TcpStream,
    line_reader: LineReader,
    nickname: Option<String>,
    pub username: Option<String>,
    pub auth: AuthSession,
}

impl Client {
    pub fn new(stream: TcpStream) -> Self {
        Client {
            stream: stream,
            line_reader: LineReader::new(),
            nickname: None,
            username: None,
            auth: AuthSession::new(),
        }
    }

    pub fn stream(&self) -> &TcpStream {
        &self.stream
    }

    pub fn read_message(&mut self) -> Option<Message> {
        match self.line_reader.read(&mut self.stream) {
            Some(line) =>
                Some(Message::from_str(line.trim())),
            None => None
        }
    }

    pub fn set_nickname(&mut self, nickname: String) {
        self.nickname = Some(nickname);
    }

    pub fn nickname(&self) -> Option<&String> {
        match self.nickname {
            None => None,
            Some(ref s) => Some(s)
        }
    }

    pub fn join(&mut self, channel: &str) {
        let pfx = self.nickname.clone().unwrap();
        self.send(&Message {
            prefix: Some(pfx),
            command: Command::Join,
            args: vec![channel.to_string()],
            suffix: None
        });
    }

    pub fn pong(&mut self) {
        self.send(&Message::from(Command::Pong));
    }

    pub fn welcome(&mut self, message: &str) {
        self.send(&Message {
            prefix: Some("pto".to_string()),
            command: Command::Numeric(1),
            args: vec![message.to_string()],
            suffix: None
        });
    }

    pub fn send(&mut self, message: &Message) {
        self.stream.write(&message.to_string().trim().as_bytes());
        self.stream.write("\r\n".as_bytes());
        println!("Wrote {:?}", message.to_string());
    }
}

pub struct Server {
    listener: TcpListener,
}

impl Server {
    pub fn new(addr: &SocketAddr) -> Self {
        Server {
            listener: TcpListener::bind(addr).unwrap(),
        }
    }

    pub fn accept(&mut self) -> Option<Client> {
         match self.listener.accept() {
             Ok(None) => None,
             Ok(Some((socket, _))) =>
                 Some(Client::new(socket)),
             Err(e) => panic!(e),
         }
    }

    pub fn listener(&self) -> &TcpListener {
        &self.listener
    }
}

<|endoftext|>


<commit_before>use core::cmp::*;

use redox::*;

pub struct Sprite {
    point: Point,
    image: BMP,
    cols: usize,
    rows: usize,
    col: usize,
    row: usize
}

impl Sprite {
    pub fn draw(&self, content: &Display){
        self.image.draw(content, self.point);
    }
}

pub fn main(){
    let mut window = Window::new(Point::new((rand() % 400 + 50) as isize, (rand() % 300 + 50) as isize), Size::new(640, 480), "Example Game (Loading)".to_string());
    window.redraw();

    let mut audio = File::open(&"audio://".to_string());

    let mut player;
    {
        let mut resource = File::open(&"file:///game/ninjaroo.bmp".to_string());
        let mut bytes: Vec<u8> = Vec::new();
        resource.read_to_end(&mut bytes);
        player = Sprite {
            point: Point::new(200, 200),
            image: BMP::from_data(&bytes),
            cols: 2,
            rows: 8,
            col: 0,
            row: 0
        };
    }

    let sound;
    {
        let mut resource = File::open(&"file:///game/wilhelm.wav".to_string());
        let mut bytes: Vec<u8> = Vec::new();
        resource.read_to_end(&mut bytes);

        sound = WAV::from_data(&bytes);
    }

    window.title = "Example Game".to_string();
    window.redraw();

    let mut keys: Vec<u8> = Vec::new();
    let mut running = true;
    while running {
        loop {
            match window.poll() {
                EventOption::Key(key_event) => {
                    if key_event.pressed {
                        match key_event.scancode {
                            K_ESC => {
                                running = false;
                                break;
                            },
                            K_DEL => {
                                window.title = "Example Game (Screaming)".to_string();
                                window.redraw();

                                audio.write(sound.data.as_slice());

                                window.title = "Example Game".to_string();
                                window.redraw();
                            },
                            _ => ()
                        }

                        let mut found = false;
                        for key in keys.iter() {
                            if *key == key_event.scancode {
                                found = true;
                                break;
                            }
                        }
                        if ! found {
                            keys.push(key_event.scancode);
                        }
                    }else{
                        let mut i = 0;
                        while i < keys.len() {
                            let mut remove = false;
                            if let Option::Some(key) = keys.get(i) {
                                if *key == key_event.scancode {
                                    remove = true;
                                }
                            }
                            if remove {
                                keys.remove(i);
                            }else{
                                i += 1;
                            }
                        }
                    }
                },
                EventOption::None => break,
                _ => ()
            }
        }

        for key in keys.iter() {
            match *key {
                K_LEFT => player.point.x = max(0, player.point.x - 1),
                K_RIGHT => player.point.x = min(window.content.width as isize - 1, player.point.x + 1),
                K_UP => player.point.y = max(0, player.point.y - 1),
                K_DOWN => player.point.y = min(window.content.height as isize - 1, player.point.y + 1),
                _ => ()
            }
        }

        {
            let content = &mut window.content;
            content.set(Color::new(128, 128, 255));

            player.draw(content);
        }

        window.redraw();

        Duration::new(0, 10*NANOS_PER_MILLI).sleep();
    }

    window.title = "Example Game (Closing)".to_string();
    RedrawEvent { redraw: REDRAW_ALL }.trigger();

    {
        let mut resource = File::open(&"file:///game/game_over.wav".to_string());
        let mut bytes: Vec<u8> = Vec::new();
        resource.read_to_end(&mut bytes);

        let game_over = WAV::from_data(&bytes);
        audio.write(game_over.data.as_slice());
    }
}
<commit_msg>Fix game paths<commit_after>use core::cmp::*;

use redox::*;

pub struct Sprite {
    point: Point,
    image: BMP,
    cols: usize,
    rows: usize,
    col: usize,
    row: usize
}

impl Sprite {
    pub fn draw(&self, content: &Display){
        self.image.draw(content, self.point);
    }
}

pub fn main(){
    let mut window = Window::new(Point::new((rand() % 400 + 50) as isize, (rand() % 300 + 50) as isize), Size::new(640, 480), "Example Game (Loading)".to_string());
    window.redraw();

    let mut audio = File::open(&"audio://".to_string());

    let mut player;
    {
        let mut resource = File::open(&"file:///apps/game/ninjaroo.bmp".to_string());
        let mut bytes: Vec<u8> = Vec::new();
        resource.read_to_end(&mut bytes);
        player = Sprite {
            point: Point::new(200, 200),
            image: BMP::from_data(&bytes),
            cols: 2,
            rows: 8,
            col: 0,
            row: 0
        };
    }

    let sound;
    {
        let mut resource = File::open(&"file:///apps/game/wilhelm.wav".to_string());
        let mut bytes: Vec<u8> = Vec::new();
        resource.read_to_end(&mut bytes);

        sound = WAV::from_data(&bytes);
    }

    window.title = "Example Game".to_string();
    window.redraw();

    let mut keys: Vec<u8> = Vec::new();
    let mut running = true;
    while running {
        loop {
            match window.poll() {
                EventOption::Key(key_event) => {
                    if key_event.pressed {
                        match key_event.scancode {
                            K_ESC => {
                                running = false;
                                break;
                            },
                            K_DEL => {
                                window.title = "Example Game (Screaming)".to_string();
                                window.redraw();

                                audio.write(sound.data.as_slice());

                                window.title = "Example Game".to_string();
                                window.redraw();
                            },
                            _ => ()
                        }

                        let mut found = false;
                        for key in keys.iter() {
                            if *key == key_event.scancode {
                                found = true;
                                break;
                            }
                        }
                        if ! found {
                            keys.push(key_event.scancode);
                        }
                    }else{
                        let mut i = 0;
                        while i < keys.len() {
                            let mut remove = false;
                            if let Option::Some(key) = keys.get(i) {
                                if *key == key_event.scancode {
                                    remove = true;
                                }
                            }
                            if remove {
                                keys.remove(i);
                            }else{
                                i += 1;
                            }
                        }
                    }
                },
                EventOption::None => break,
                _ => ()
            }
        }

        for key in keys.iter() {
            match *key {
                K_LEFT => player.point.x = max(0, player.point.x - 1),
                K_RIGHT => player.point.x = min(window.content.width as isize - 1, player.point.x + 1),
                K_UP => player.point.y = max(0, player.point.y - 1),
                K_DOWN => player.point.y = min(window.content.height as isize - 1, player.point.y + 1),
                _ => ()
            }
        }

        {
            let content = &mut window.content;
            content.set(Color::new(128, 128, 255));

            player.draw(content);
        }

        window.redraw();

        Duration::new(0, 10*NANOS_PER_MILLI).sleep();
    }

    window.title = "Example Game (Closing)".to_string();
    RedrawEvent { redraw: REDRAW_ALL }.trigger();

    {
        let mut resource = File::open(&"file:///apps/game/game_over.wav".to_string());
        let mut bytes: Vec<u8> = Vec::new();
        resource.read_to_end(&mut bytes);

        let game_over = WAV::from_data(&bytes);
        audio.write(game_over.data.as_slice());
    }
}
<|endoftext|>