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

//! The `bitflags!` macro generates a `struct` that holds a set of C-style
//! bitmask flags. It is useful for creating typesafe wrappers for C APIs.
//!
//! The flags should only be defined for integer types, otherwise unexpected
//! type errors may occur at compile time.
//!
//! # Example
//!
//! ~~~rust
//! #[feature(phase)];
//! #[phase(syntax)] extern crate collections;
//!
//! bitflags!(Flags: u32 {
//!     FlagA       = 0x00000001,
//!     FlagB       = 0x00000010,
//!     FlagC       = 0x00000100,
//!     FlagABC     = FlagA.bits
//!                 | FlagB.bits
//!                 | FlagC.bits
//! })
//!
//! fn main() {
//!     let e1 = FlagA | FlagC;
//!     let e2 = FlagB | FlagC;
//!     assert!((e1 | e2) == FlagABC);   // union
//!     assert!((e1 & e2) == FlagC);     // intersection
//!     assert!((e1 - e2) == FlagA);     // set difference
//! }
//! ~~~
//!
//! # Operators
//!
//! The following operator traits are implemented for the generated `struct`:
//!
//! - `BitOr`: union
//! - `BitAnd`: intersection
//! - `Sub`: set difference
//!
//! # Methods
//!
//! The following methods are defined for the generated `struct`:
//!
//! - `empty`: an empty set of flags
//! - `bits`: the raw value of the flags currently stored
//! - `is_empty`: `true` if no flags are currently stored
//! - `intersects`: `true` if there are flags common to both `self` and `other`
//! - `contains`: `true` all of the flags in `other` are contained within `self`
//! - `insert`: inserts the specified flags in-place
//! - `remove`: removes the specified flags in-place

#[macro_export]
macro_rules! bitflags(
    ($BitFlags:ident: $T:ty {
        $($Flag:ident = $value:expr),+
    }) => (
        #[deriving(Eq, TotalEq, Clone)]
        pub struct $BitFlags {
            priv bits: $T,
        }

        $(pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+

        impl $BitFlags {
            /// Returns an empty set of flags.
            pub fn empty() -> $BitFlags {
                $BitFlags { bits: 0 }
            }

            /// Returns the raw value of the flags currently stored.
            pub fn bits(&self) -> $T {
                self.bits
            }

            /// Returns `true` if no flags are currently stored.
            pub fn is_empty(&self) -> bool {
                *self == $BitFlags::empty()
            }

            /// Returns `true` if there are flags common to both `self` and `other`.
            pub fn intersects(&self, other: $BitFlags) -> bool {
                !(self & other).is_empty()
            }

            /// Returns `true` all of the flags in `other` are contained within `self`.
            pub fn contains(&self, other: $BitFlags) -> bool {
                (self & other) == other
            }

            /// Inserts the specified flags in-place.
            pub fn insert(&mut self, other: $BitFlags) {
                self.bits |= other.bits;
            }

            /// Removes the specified flags in-place.
            pub fn remove(&mut self, other: $BitFlags) {
                self.bits &= !other.bits;
            }
        }

        impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the union of the two sets of flags.
            #[inline]
            fn bitor(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits | other.bits }
            }
        }

        impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the intersection between the two sets of flags.
            #[inline]
            fn bitand(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & other.bits }
            }
        }

        impl Sub<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the set difference of the two sets of flags.
            #[inline]
            fn sub(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & !other.bits }
            }
        }
    )
)

#[cfg(test)]
mod tests {
    bitflags!(Flags: u32 {
        FlagA       = 0x00000001,
        FlagB       = 0x00000010,
        FlagC       = 0x00000100,
        FlagABC     = FlagA.bits
                    | FlagB.bits
                    | FlagC.bits
    })

    #[test]
    fn test_bits(){
        assert_eq!(Flags::empty().bits(), 0x00000000);
        assert_eq!(FlagA.bits(), 0x00000001);
        assert_eq!(FlagABC.bits(), 0x00000111);
    }

    #[test]
    fn test_is_empty(){
        assert!(Flags::empty().is_empty());
        assert!(!FlagA.is_empty());
        assert!(!FlagABC.is_empty());
    }

    #[test]
    fn test_two_empties_do_not_intersect() {
        let e1 = Flags::empty();
        let e2 = Flags::empty();
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_empty_does_not_intersect_with_full() {
        let e1 = Flags::empty();
        let e2 = FlagABC;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_disjoint_intersects() {
        let e1 = FlagA;
        let e2 = FlagB;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_overlapping_intersects() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(e1.intersects(e2));
    }

    #[test]
    fn test_contains() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(!e1.contains(e2));
        assert!(e2.contains(e1));
        assert!(FlagABC.contains(e2));
    }

    #[test]
    fn test_insert(){
        let mut e1 = FlagA;
        let e2 = FlagA | FlagB;
        e1.insert(e2);
        assert!(e1 == e2);
    }

    #[test]
    fn test_remove(){
        let mut e1 = FlagA | FlagB;
        let e2 = FlagA | FlagC;
        e1.remove(e2);
        assert!(e1 == FlagB);
    }

    #[test]
    fn test_operators() {
        let e1 = FlagA | FlagC;
        let e2 = FlagB | FlagC;
        assert!((e1 | e2) == FlagABC);   // union
        assert!((e1 & e2) == FlagC);     // intersection
        assert!((e1 - e2) == FlagA);     // set difference
    }
}
<commit_msg>Document how generated bitflags can be extended with type and trait implementations<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The `bitflags!` macro generates a `struct` that holds a set of C-style
//! bitmask flags. It is useful for creating typesafe wrappers for C APIs.
//!
//! The flags should only be defined for integer types, otherwise unexpected
//! type errors may occur at compile time.
//!
//! # Example
//!
//! ~~~rust
//! #[feature(phase)];
//! #[phase(syntax)] extern crate collections;
//!
//! bitflags!(Flags: u32 {
//!     FlagA       = 0x00000001,
//!     FlagB       = 0x00000010,
//!     FlagC       = 0x00000100,
//!     FlagABC     = FlagA.bits
//!                 | FlagB.bits
//!                 | FlagC.bits
//! })
//!
//! fn main() {
//!     let e1 = FlagA | FlagC;
//!     let e2 = FlagB | FlagC;
//!     assert!((e1 | e2) == FlagABC);   // union
//!     assert!((e1 & e2) == FlagC);     // intersection
//!     assert!((e1 - e2) == FlagA);     // set difference
//! }
//! ~~~
//!
//! The generated `struct`s can also be extended with type and trait implementations:
//!
//! ~~~rust
//! #[feature(phase)];
//! #[phase(syntax)] extern crate collections;
//!
//! use std::fmt;
//!
//! bitflags!(Flags: u32 {
//!     FlagA   = 0x00000001,
//!     FlagB   = 0x00000010
//! })
//!
//! impl Flags {
//!     pub fn clear(&mut self) {
//!         self.bits = 0;  // The `bits` field can be accessed from within the
//!                         // same module where the `bitflags!` macro was invoked.
//!     }
//! }
//!
//! impl fmt::Show for Flags {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f.buf, "hi!")
//!     }
//! }
//!
//! fn main() {
//!     let mut flags = FlagA | FlagB;
//!     flags.clear();
//!     assert!(flags.is_empty());
//!     assert_eq!(format!("{}", flags), ~"hi!");
//! }
//! ~~~
//!
//! # Operators
//!
//! The following operator traits are implemented for the generated `struct`:
//!
//! - `BitOr`: union
//! - `BitAnd`: intersection
//! - `Sub`: set difference
//!
//! # Methods
//!
//! The following methods are defined for the generated `struct`:
//!
//! - `empty`: an empty set of flags
//! - `bits`: the raw value of the flags currently stored
//! - `is_empty`: `true` if no flags are currently stored
//! - `intersects`: `true` if there are flags common to both `self` and `other`
//! - `contains`: `true` all of the flags in `other` are contained within `self`
//! - `insert`: inserts the specified flags in-place
//! - `remove`: removes the specified flags in-place

#[macro_export]
macro_rules! bitflags(
    ($BitFlags:ident: $T:ty {
        $($Flag:ident = $value:expr),+
    }) => (
        #[deriving(Eq, TotalEq, Clone)]
        pub struct $BitFlags {
            priv bits: $T,
        }

        $(pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+

        impl $BitFlags {
            /// Returns an empty set of flags.
            pub fn empty() -> $BitFlags {
                $BitFlags { bits: 0 }
            }

            /// Returns the raw value of the flags currently stored.
            pub fn bits(&self) -> $T {
                self.bits
            }

            /// Returns `true` if no flags are currently stored.
            pub fn is_empty(&self) -> bool {
                *self == $BitFlags::empty()
            }

            /// Returns `true` if there are flags common to both `self` and `other`.
            pub fn intersects(&self, other: $BitFlags) -> bool {
                !(self & other).is_empty()
            }

            /// Returns `true` all of the flags in `other` are contained within `self`.
            pub fn contains(&self, other: $BitFlags) -> bool {
                (self & other) == other
            }

            /// Inserts the specified flags in-place.
            pub fn insert(&mut self, other: $BitFlags) {
                self.bits |= other.bits;
            }

            /// Removes the specified flags in-place.
            pub fn remove(&mut self, other: $BitFlags) {
                self.bits &= !other.bits;
            }
        }

        impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the union of the two sets of flags.
            #[inline]
            fn bitor(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits | other.bits }
            }
        }

        impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the intersection between the two sets of flags.
            #[inline]
            fn bitand(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & other.bits }
            }
        }

        impl Sub<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the set difference of the two sets of flags.
            #[inline]
            fn sub(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & !other.bits }
            }
        }
    )
)

#[cfg(test)]
mod tests {
    bitflags!(Flags: u32 {
        FlagA       = 0x00000001,
        FlagB       = 0x00000010,
        FlagC       = 0x00000100,
        FlagABC     = FlagA.bits
                    | FlagB.bits
                    | FlagC.bits
    })

    #[test]
    fn test_bits(){
        assert_eq!(Flags::empty().bits(), 0x00000000);
        assert_eq!(FlagA.bits(), 0x00000001);
        assert_eq!(FlagABC.bits(), 0x00000111);
    }

    #[test]
    fn test_is_empty(){
        assert!(Flags::empty().is_empty());
        assert!(!FlagA.is_empty());
        assert!(!FlagABC.is_empty());
    }

    #[test]
    fn test_two_empties_do_not_intersect() {
        let e1 = Flags::empty();
        let e2 = Flags::empty();
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_empty_does_not_intersect_with_full() {
        let e1 = Flags::empty();
        let e2 = FlagABC;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_disjoint_intersects() {
        let e1 = FlagA;
        let e2 = FlagB;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_overlapping_intersects() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(e1.intersects(e2));
    }

    #[test]
    fn test_contains() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(!e1.contains(e2));
        assert!(e2.contains(e1));
        assert!(FlagABC.contains(e2));
    }

    #[test]
    fn test_insert(){
        let mut e1 = FlagA;
        let e2 = FlagA | FlagB;
        e1.insert(e2);
        assert!(e1 == e2);
    }

    #[test]
    fn test_remove(){
        let mut e1 = FlagA | FlagB;
        let e2 = FlagA | FlagC;
        e1.remove(e2);
        assert!(e1 == FlagB);
    }

    #[test]
    fn test_operators() {
        let e1 = FlagA | FlagC;
        let e2 = FlagB | FlagC;
        assert!((e1 | e2) == FlagABC);   // union
        assert!((e1 & e2) == FlagC);     // intersection
        assert!((e1 - e2) == FlagA);     // set difference
    }
}
<|endoftext|>


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

#![allow(dead_code)] // runtime init functions not used during testing

use os::windows::prelude::*;
use sys::windows::os::current_exe;
use sys::c;
use ffi::OsString;
use fmt;
use vec;
use core::iter;
use slice;
use path::PathBuf;

pub unsafe fn init(_argc: isize, _argv: *const *const u8) { }

pub unsafe fn cleanup() { }

pub fn args() -> Args {
    unsafe {
        let lp_cmd_line = c::GetCommandLineW();
        let parsed_args_list = parse_lp_cmd_line(
            lp_cmd_line as *const u16,
            || current_exe().map(PathBuf::into_os_string).unwrap_or_else(|_| OsString::new()));

        Args { parsed_args_list: parsed_args_list }
    }
}

/// Implements the Windows command-line argument parsing algorithm, described at
/// <https://docs.microsoft.com/en-us/previous-versions//17w5ykft(v=vs.85)>.
///
/// Windows includes a function to do this in shell32.dll,
/// but linking with that DLL causes the process to be registered as a GUI application.
/// GUI applications add a bunch of overhead, even if no windows are drawn. See
/// <https://randomascii.wordpress.com/2018/12/03/a-not-called-function-can-cause-a-5x-slowdown/>.
unsafe fn parse_lp_cmd_line<F: Fn() -> OsString>(lp_cmd_line: *const u16, exe_name: F)
                                                 -> vec::IntoIter<OsString> {
    const BACKSLASH: u16 = '\\' as u16;
    const QUOTE: u16 = '"' as u16;
    const TAB: u16 = '\t' as u16;
    const SPACE: u16 = ' ' as u16;
    let mut in_quotes = false;
    let mut was_in_quotes = false;
    let mut backslash_count: usize = 0;
    let mut ret_val = Vec::new();
    let mut cur = Vec::new();
    if lp_cmd_line.is_null() || *lp_cmd_line == 0 {
        ret_val.push(exe_name());
        return ret_val.into_iter();
    }
    let mut i = 0;
    // The executable name at the beginning is special.
    match *lp_cmd_line {
        // The executable name ends at the next quote mark,
        // no matter what.
        QUOTE => {
            loop {
                i += 1;
                if *lp_cmd_line.offset(i) == 0 {
                    ret_val.push(OsString::from_wide(
                        slice::from_raw_parts(lp_cmd_line.offset(1), i as usize - 1)
                    ));
                    return ret_val.into_iter();
                }
                if *lp_cmd_line.offset(i) == QUOTE {
                    break;
                }
            }
            ret_val.push(OsString::from_wide(
                slice::from_raw_parts(lp_cmd_line.offset(1), i as usize - 1)
            ));
            i += 1;
        }
        // Implement quirk: when they say whitespace here,
        // they include the entire ASCII control plane:
        // "However, if lpCmdLine starts with any amount of whitespace, CommandLineToArgvW
        // will consider the first argument to be an empty string. Excess whitespace at the
        // end of lpCmdLine is ignored."
        0...SPACE => {
            ret_val.push(OsString::new());
            i += 1;
        },
        // The executable name ends at the next whitespace,
        // no matter what.
        _ => {
            loop {
                i += 1;
                if *lp_cmd_line.offset(i) == 0 {
                    ret_val.push(OsString::from_wide(
                        slice::from_raw_parts(lp_cmd_line, i as usize)
                    ));
                    return ret_val.into_iter();
                }
                if let 0...SPACE = *lp_cmd_line.offset(i) {
                    break;
                }
            }
            ret_val.push(OsString::from_wide(
                slice::from_raw_parts(lp_cmd_line, i as usize)
            ));
            i += 1;
        }
    }
    loop {
        let c = *lp_cmd_line.offset(i);
        match c {
            // backslash
            BACKSLASH => {
                backslash_count += 1;
                was_in_quotes = false;
            },
            QUOTE if backslash_count % 2 == 0 => {
                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count / 2));
                backslash_count = 0;
                if was_in_quotes {
                    cur.push('"' as u16);
                    was_in_quotes = false;
                } else {
                    was_in_quotes = in_quotes;
                    in_quotes = !in_quotes;
                }
            }
            QUOTE if backslash_count % 2 != 0 => {
                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count / 2));
                backslash_count = 0;
                was_in_quotes = false;
                cur.push(b'"' as u16);
            }
            SPACE | TAB if !in_quotes => {
                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count));
                if !cur.is_empty() || was_in_quotes {
                    ret_val.push(OsString::from_wide(&cur[..]));
                    cur.truncate(0);
                }
                backslash_count = 0;
                was_in_quotes = false;
            }
            0x00 => {
                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count));
                // include empty quoted strings at the end of the arguments list
                if !cur.is_empty() || was_in_quotes || in_quotes {
                    ret_val.push(OsString::from_wide(&cur[..]));
                }
                break;
            }
            _ => {
                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count));
                backslash_count = 0;
                was_in_quotes = false;
                cur.push(c);
            }
        }
        i += 1;
    }
    ret_val.into_iter()
}

pub struct Args {
    parsed_args_list: vec::IntoIter<OsString>,
}

pub struct ArgsInnerDebug<'a> {
    args: &'a Args,
}

impl<'a> fmt::Debug for ArgsInnerDebug<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("[")?;
        let mut first = true;
        for i in self.args.parsed_args_list.clone() {
            if !first {
                f.write_str(", ")?;
            }
            first = false;

            fmt::Debug::fmt(i, f)?;
        }
        f.write_str("]")?;
        Ok(())
    }
}

impl Args {
    pub fn inner_debug(&self) -> ArgsInnerDebug {
        ArgsInnerDebug {
            args: self
        }
    }
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> { self.parsed_args_list.next() }
    fn size_hint(&self) -> (usize, Option<usize>) { self.parsed_args_list.size_hint() }
}

impl DoubleEndedIterator for Args {
    fn next_back(&mut self) -> Option<OsString> { self.parsed_args_list.next_back() }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize { self.parsed_args_list.len() }
}

#[cfg(test)]
mod tests {
    use sys::windows::args::*;
    use ffi::OsString;

    fn chk(string: &str, parts: &[&str]) {
        let mut wide: Vec<u16> = OsString::from(string).encode_wide().collect();
        wide.push(0);
        let parsed = unsafe {
            parse_lp_cmd_line(wide.as_ptr() as *const u16, || OsString::from("TEST.EXE"))
        };
        let expected: Vec<OsString> = parts.iter().map(|k| OsString::from(k)).collect();
        assert_eq!(parsed, expected);
    }

    #[test]
    fn empty() {
        chk("", &["TEST.EXE"]);
        chk("\0", &["TEST.EXE"]);
    }

    #[test]
    fn single_words() {
        chk("EXE one_word", &["EXE", "one_word"]);
        chk("EXE a", &["EXE", "a"]);
        chk("EXE 😅", &["EXE", "😅"]);
        chk("EXE 😅🤦", &["EXE", "😅🤦"]);
    }

    #[test]
    fn official_examples() {
        chk(r#"EXE "abc" d e"#, &["EXE", "abc", "d", "e"]);
        chk(r#"EXE a\\\b d"e f"g h"#, &["EXE", r#"a\\\b"#, "de fg", "h"]);
        chk(r#"EXE a\\\"b c d"#, &["EXE", r#"a\"b"#, "c", "d"]);
        chk(r#"EXE a\\\\"b c" d e"#, &["EXE", r#"a\\b c"#, "d", "e"]);
    }

    #[test]
    fn whitespace_behavior() {
        chk(r#" test"#, &["", "test"]);
        chk(r#"  test"#, &["", "test"]);
        chk(r#" test test2"#, &["", "test", "test2"]);
        chk(r#" test  test2"#, &["", "test", "test2"]);
        chk(r#"test test2 "#, &["test", "test2"]);
        chk(r#"test  test2 "#, &["test", "test2"]);
        chk(r#"test "#, &["test"]);
    }

    #[test]
    fn genius_quotes() {
        chk(r#"EXE "" """#, &["EXE", "", ""]);
        chk(r#"EXE "" """"#, &["EXE", "", "\""]);
        chk(
            r#"EXE "this is """all""" in the same argument""#,
            &["EXE", "this is \"all\" in the same argument"]
        );
        chk(r#"EXE "\u{1}"""#, &["EXE", "\u{1}\""]);
        chk(r#"EXE "a"" a"#, &["EXE", "a\"", "a"]);
    }
}
<commit_msg>Fix poorly-transcribed test case<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(dead_code)] // runtime init functions not used during testing

use os::windows::prelude::*;
use sys::windows::os::current_exe;
use sys::c;
use ffi::OsString;
use fmt;
use vec;
use core::iter;
use slice;
use path::PathBuf;

pub unsafe fn init(_argc: isize, _argv: *const *const u8) { }

pub unsafe fn cleanup() { }

pub fn args() -> Args {
    unsafe {
        let lp_cmd_line = c::GetCommandLineW();
        let parsed_args_list = parse_lp_cmd_line(
            lp_cmd_line as *const u16,
            || current_exe().map(PathBuf::into_os_string).unwrap_or_else(|_| OsString::new()));

        Args { parsed_args_list: parsed_args_list }
    }
}

/// Implements the Windows command-line argument parsing algorithm, described at
/// <https://docs.microsoft.com/en-us/previous-versions//17w5ykft(v=vs.85)>.
///
/// Windows includes a function to do this in shell32.dll,
/// but linking with that DLL causes the process to be registered as a GUI application.
/// GUI applications add a bunch of overhead, even if no windows are drawn. See
/// <https://randomascii.wordpress.com/2018/12/03/a-not-called-function-can-cause-a-5x-slowdown/>.
unsafe fn parse_lp_cmd_line<F: Fn() -> OsString>(lp_cmd_line: *const u16, exe_name: F)
                                                 -> vec::IntoIter<OsString> {
    const BACKSLASH: u16 = '\\' as u16;
    const QUOTE: u16 = '"' as u16;
    const TAB: u16 = '\t' as u16;
    const SPACE: u16 = ' ' as u16;
    let mut in_quotes = false;
    let mut was_in_quotes = false;
    let mut backslash_count: usize = 0;
    let mut ret_val = Vec::new();
    let mut cur = Vec::new();
    if lp_cmd_line.is_null() || *lp_cmd_line == 0 {
        ret_val.push(exe_name());
        return ret_val.into_iter();
    }
    let mut i = 0;
    // The executable name at the beginning is special.
    match *lp_cmd_line {
        // The executable name ends at the next quote mark,
        // no matter what.
        QUOTE => {
            loop {
                i += 1;
                if *lp_cmd_line.offset(i) == 0 {
                    ret_val.push(OsString::from_wide(
                        slice::from_raw_parts(lp_cmd_line.offset(1), i as usize - 1)
                    ));
                    return ret_val.into_iter();
                }
                if *lp_cmd_line.offset(i) == QUOTE {
                    break;
                }
            }
            ret_val.push(OsString::from_wide(
                slice::from_raw_parts(lp_cmd_line.offset(1), i as usize - 1)
            ));
            i += 1;
        }
        // Implement quirk: when they say whitespace here,
        // they include the entire ASCII control plane:
        // "However, if lpCmdLine starts with any amount of whitespace, CommandLineToArgvW
        // will consider the first argument to be an empty string. Excess whitespace at the
        // end of lpCmdLine is ignored."
        0...SPACE => {
            ret_val.push(OsString::new());
            i += 1;
        },
        // The executable name ends at the next whitespace,
        // no matter what.
        _ => {
            loop {
                i += 1;
                if *lp_cmd_line.offset(i) == 0 {
                    ret_val.push(OsString::from_wide(
                        slice::from_raw_parts(lp_cmd_line, i as usize)
                    ));
                    return ret_val.into_iter();
                }
                if let 0...SPACE = *lp_cmd_line.offset(i) {
                    break;
                }
            }
            ret_val.push(OsString::from_wide(
                slice::from_raw_parts(lp_cmd_line, i as usize)
            ));
            i += 1;
        }
    }
    loop {
        let c = *lp_cmd_line.offset(i);
        match c {
            // backslash
            BACKSLASH => {
                backslash_count += 1;
                was_in_quotes = false;
            },
            QUOTE if backslash_count % 2 == 0 => {
                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count / 2));
                backslash_count = 0;
                if was_in_quotes {
                    cur.push('"' as u16);
                    was_in_quotes = false;
                } else {
                    was_in_quotes = in_quotes;
                    in_quotes = !in_quotes;
                }
            }
            QUOTE if backslash_count % 2 != 0 => {
                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count / 2));
                backslash_count = 0;
                was_in_quotes = false;
                cur.push(b'"' as u16);
            }
            SPACE | TAB if !in_quotes => {
                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count));
                if !cur.is_empty() || was_in_quotes {
                    ret_val.push(OsString::from_wide(&cur[..]));
                    cur.truncate(0);
                }
                backslash_count = 0;
                was_in_quotes = false;
            }
            0x00 => {
                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count));
                // include empty quoted strings at the end of the arguments list
                if !cur.is_empty() || was_in_quotes || in_quotes {
                    ret_val.push(OsString::from_wide(&cur[..]));
                }
                break;
            }
            _ => {
                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count));
                backslash_count = 0;
                was_in_quotes = false;
                cur.push(c);
            }
        }
        i += 1;
    }
    ret_val.into_iter()
}

pub struct Args {
    parsed_args_list: vec::IntoIter<OsString>,
}

pub struct ArgsInnerDebug<'a> {
    args: &'a Args,
}

impl<'a> fmt::Debug for ArgsInnerDebug<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("[")?;
        let mut first = true;
        for i in self.args.parsed_args_list.clone() {
            if !first {
                f.write_str(", ")?;
            }
            first = false;

            fmt::Debug::fmt(&i, f)?;
        }
        f.write_str("]")?;
        Ok(())
    }
}

impl Args {
    pub fn inner_debug(&self) -> ArgsInnerDebug {
        ArgsInnerDebug {
            args: self
        }
    }
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> { self.parsed_args_list.next() }
    fn size_hint(&self) -> (usize, Option<usize>) { self.parsed_args_list.size_hint() }
}

impl DoubleEndedIterator for Args {
    fn next_back(&mut self) -> Option<OsString> { self.parsed_args_list.next_back() }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize { self.parsed_args_list.len() }
}

#[cfg(test)]
mod tests {
    use sys::windows::args::*;
    use ffi::OsString;

    fn chk(string: &str, parts: &[&str]) {
        let mut wide: Vec<u16> = OsString::from(string).encode_wide().collect();
        wide.push(0);
        let parsed = unsafe {
            parse_lp_cmd_line(wide.as_ptr() as *const u16, || OsString::from("TEST.EXE"))
        };
        let expected: Vec<OsString> = parts.iter().map(|k| OsString::from(k)).collect();
        assert_eq!(parsed.as_slice(), expected.as_slice());
    }

    #[test]
    fn empty() {
        chk("", &["TEST.EXE"]);
        chk("\0", &["TEST.EXE"]);
    }

    #[test]
    fn single_words() {
        chk("EXE one_word", &["EXE", "one_word"]);
        chk("EXE a", &["EXE", "a"]);
        chk("EXE 😅", &["EXE", "😅"]);
        chk("EXE 😅🤦", &["EXE", "😅🤦"]);
    }

    #[test]
    fn official_examples() {
        chk(r#"EXE "abc" d e"#, &["EXE", "abc", "d", "e"]);
        chk(r#"EXE a\\\b d"e f"g h"#, &["EXE", r#"a\\\b"#, "de fg", "h"]);
        chk(r#"EXE a\\\"b c d"#, &["EXE", r#"a\"b"#, "c", "d"]);
        chk(r#"EXE a\\\\"b c" d e"#, &["EXE", r#"a\\b c"#, "d", "e"]);
    }

    #[test]
    fn whitespace_behavior() {
        chk(r#" test"#, &["", "test"]);
        chk(r#"  test"#, &["", "test"]);
        chk(r#" test test2"#, &["", "test", "test2"]);
        chk(r#" test  test2"#, &["", "test", "test2"]);
        chk(r#"test test2 "#, &["test", "test2"]);
        chk(r#"test  test2 "#, &["test", "test2"]);
        chk(r#"test "#, &["test"]);
    }

    #[test]
    fn genius_quotes() {
        chk(r#"EXE "" """#, &["EXE", "", ""]);
        chk(r#"EXE "" """"#, &["EXE", "", "\""]);
        chk(
            r#"EXE "this is """all""" in the same argument""#,
            &["EXE", "this is \"all\" in the same argument"]
        );
        chk(r#"EXE "a"""#, &["EXE", "a\""]);
        chk(r#"EXE "a"" a"#, &["EXE", "a\"", "a"]);
    }
}
<|endoftext|>


<commit_before>pub fn setup_logger() {
    use std::io::Write;

    fn tn() -> String {
        std::thread::current()
            .name()
            .unwrap_or("unknown")
            .to_owned()
    }

    #[cfg(feature = "pretty_backtrace")]
    color_backtrace::install();

    let mut builder = env_logger::Builder::new();
    builder
        .format(|buf, record| {
            writeln!(
                buf,
                "{:05} {:20} {:10} {}",
                record.level(),
                tn(),
                record.module_path().unwrap().split("::").last().unwrap(),
                record.args()
            )
        })
        .filter(None, log::LevelFilter::Info);

    if std::env::var("RUST_LOG").is_ok() {
        builder.parse_filters(&std::env::var("RUST_LOG").unwrap());
    }

    let _r = builder.try_init();
}
<commit_msg>Emit a compile error when tests are build without the testing feature enabled<commit_after>#[cfg(not(feature = "testing"))]
compile_error!(
    "please run tests using the \"testing\" feature, \
    which enables additional checks at runtime and \
    causes more race conditions to jump out by \
    inserting delays in concurrent code."
);

pub fn setup_logger() {
    use std::io::Write;

    fn tn() -> String {
        std::thread::current()
            .name()
            .unwrap_or("unknown")
            .to_owned()
    }

    #[cfg(feature = "pretty_backtrace")]
    color_backtrace::install();

    let mut builder = env_logger::Builder::new();
    builder
        .format(|buf, record| {
            writeln!(
                buf,
                "{:05} {:20} {:10} {}",
                record.level(),
                tn(),
                record.module_path().unwrap().split("::").last().unwrap(),
                record.args()
            )
        })
        .filter(None, log::LevelFilter::Info);

    if std::env::var("RUST_LOG").is_ok() {
        builder.parse_filters(&std::env::var("RUST_LOG").unwrap());
    }

    let _r = builder.try_init();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2018 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#![feature(proc_macro)]

extern crate gdk;
extern crate gtk;
#[macro_use]
extern crate relm;
extern crate relm_attributes;
#[macro_use]
extern crate relm_derive;
#[macro_use]
extern crate relm_test;

use gtk::{
    EditableSignals,
    EntryExt,
    Inhibit,
    LabelExt,
    OrientableExt,
    WidgetExt,
};
use gtk::Orientation::Vertical;
use relm::Widget;
use relm_attributes::widget;

use self::Msg::*;

pub struct Model {
    content: String,
}

#[derive(Msg)]
pub enum Msg {
    Change(String),
    Quit,
}

#[widget]
impl Widget for Win {
    fn model() -> Model {
        Model {
            content: String::new(),
        }
    }

    fn update(&mut self, event: Msg) {
        match event {
            Change(text) => {
                self.model.content = text.chars().rev().collect();
            },
            Quit => gtk::main_quit(),
        }
    }

    view! {
        gtk::Window {
            gtk::Box {
                orientation: Vertical,
                #[name = "entry"]
                gtk::Entry {
                    changed(entry) => Change(entry.get_text().unwrap()),
                    placeholder_text: "Text to reverse",
                },
                #[name = "entry2"]
                gtk::Entry { },
                #[name = "label"]
                gtk::Label {
                    text: &self.model.content,
                },
            },
            delete_event(_, _) => (Quit, Inhibit(false)),
        }
    }
}

#[cfg(test)]
mod tests {
    use gdk::enums::key;
    use gtk::{EntryExt, LabelExt};

    use relm;
    use relm_test::{
        enter_key,
        enter_keys,
        key_press,
        key_release,
    };

    use Win;

    #[test]
    fn label_change() {
        let (_component, widgets) = relm::init_test::<Win>(()).unwrap();
        let entry = &widgets.entry;
        let entry2 = &widgets.entry2;
        let label = &widgets.label;

        key_press(entry, key::A);
        assert_text!(label, "A");
        key_release(entry, key::A);
        assert_text!(label, "A");
        enter_key(entry, key::B);
        enter_key(entry2, key::C);
        assert_text!(label, "BA");
        assert_text!(entry2, "C");
        enter_keys(entry, "CD");
        assert_text!(label, "DCBA");
    }
}
<commit_msg>Travis<commit_after>/*
 * Copyright (c) 2018 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#![feature(proc_macro)]

extern crate gdk;
extern crate gtk;
#[macro_use]
extern crate relm;
extern crate relm_attributes;
#[macro_use]
extern crate relm_derive;
#[macro_use]
extern crate relm_test;

use gtk::{
    EditableSignals,
    EntryExt,
    Inhibit,
    LabelExt,
    OrientableExt,
    WidgetExt,
};
use gtk::Orientation::Vertical;
use relm::Widget;
use relm_attributes::widget;

use self::Msg::*;

pub struct Model {
    content: String,
}

#[derive(Msg)]
pub enum Msg {
    Change(String),
    Quit,
}

#[widget]
impl Widget for Win {
    fn model() -> Model {
        Model {
            content: String::new(),
        }
    }

    fn update(&mut self, event: Msg) {
        match event {
            Change(text) => {
                self.model.content = text.chars().rev().collect();
            },
            Quit => gtk::main_quit(),
        }
    }

    view! {
        gtk::Window {
            gtk::Box {
                orientation: Vertical,
                #[name = "entry"]
                gtk::Entry {
                    changed(entry) => Change(entry.get_text().unwrap()),
                    placeholder_text: "Text to reverse",
                },
                #[name = "entry2"]
                gtk::Entry { },
                #[name = "label"]
                gtk::Label {
                    text: &self.model.content,
                },
            },
            delete_event(_, _) => (Quit, Inhibit(false)),
        }
    }
}

#[cfg(test)]
mod tests {
    use gdk::enums::key;
    use gtk::{EntryExt, LabelExt};

    use relm;
    use relm_test::{
        enter_key,
        enter_keys,
        key_press,
        key_release,
    };

    use Win;

    #[test]
    fn label_change() {
        let (_component, widgets) = relm::init_test::<Win>(()).unwrap();
        let entry = &widgets.entry;
        let entry2 = &widgets.entry2;
        let label = &widgets.label;

        /*
        key_press(entry, key::Shift_L);
        ::relm_test::wait(10);
        key_press(entry, key::A);
        assert_text!(label, "A");
        ::relm_test::wait(10);
        key_release(entry, key::A);
        //enter_key(entry, key::A);
        ::gtk::main();
        assert_text!(label, "A");
        enter_key(entry, key::B);
        enter_key(entry2, key::C);
        assert_text!(label, "BA");
        assert_text!(entry2, "C");
        enter_keys(entry, "CD");
        key_release(entry, key::Shift_L);
        assert_text!(label, "DCBA");
        */
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

use std::{collections::HashMap, env};

use actix_cors::Cors;
use actix_web::{
    http::header,
    middleware,
    web::{self, Data},
    App, Error, HttpResponse, HttpServer,
};
use juniper::{graphql_object, EmptyMutation, EmptySubscription, GraphQLObject, RootNode};
use juniper_actix::{graphiql_handler, graphql_handler, playground_handler};

#[derive(Clone, GraphQLObject)]
///a user
pub struct User {
    ///the id
    id: i32,
    ///the name
    name: String,
}

#[derive(Default, Clone)]
pub struct Database {
    ///this could be a database connection
    users: HashMap<i32, User>,
}
impl Database {
    pub fn new() -> Database {
        let mut users = HashMap::new();
        users.insert(
            1,
            User {
                id: 1,
                name: "Aron".to_string(),
            },
        );
        users.insert(
            2,
            User {
                id: 2,
                name: "Bea".to_string(),
            },
        );
        users.insert(
            3,
            User {
                id: 3,
                name: "Carl".to_string(),
            },
        );
        users.insert(
            4,
            User {
                id: 4,
                name: "Dora".to_string(),
            },
        );
        Database { users }
    }
    pub fn get_user(&self, id: &i32) -> Option<&User> {
        self.users.get(id)
    }
}

// To make our Database usable by Juniper, we have to implement a marker trait.
impl juniper::Context for Database {}

// Queries represent the callable funcitons
struct Query;
#[graphql_object(context = Database)]
impl Query {
    fn api_version() -> &'static str {
        "1.0"
    }

    fn user(
        context: &Database,
        #[graphql(description = "id of the user")] id: i32,
    ) -> Option<&User> {
        context.get_user(&id)
    }
}

type Schema = RootNode<'static, Query, EmptyMutation<Database>, EmptySubscription<Database>>;

fn schema() -> Schema {
    Schema::new(
        Query,
        EmptyMutation::<Database>::new(),
        EmptySubscription::<Database>::new(),
    )
}

async fn graphiql_route() -> Result<HttpResponse, Error> {
    graphiql_handler("/graphgl", None).await
}
async fn playground_route() -> Result<HttpResponse, Error> {
    playground_handler("/graphgl", None).await
}
async fn graphql_route(
    req: actix_web::HttpRequest,
    payload: actix_web::web::Payload,
    schema: web::Data<Schema>,
) -> Result<HttpResponse, Error> {
    let context = Database::new();
    graphql_handler(&schema, &context, req, payload).await
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    env::set_var("RUST_LOG", "info");
    env_logger::init();

    let server = HttpServer::new(move || {
        App::new()
            .app_data(Data::new(schema()))
            .wrap(
                Cors::default()
                    .allow_any_origin()
                    .allowed_methods(vec!["POST", "GET"])
                    .allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
                    .allowed_header(header::CONTENT_TYPE)
                    .supports_credentials()
                    .max_age(3600),
            )
            .wrap(middleware::Compress::default())
            .wrap(middleware::Logger::default())
            .service(
                web::resource("/graphgl")
                    .route(web::post().to(graphql_route))
                    .route(web::get().to(graphql_route)),
            )
            .service(web::resource("/playground").route(web::get().to(playground_route)))
            .service(web::resource("/graphiql").route(web::get().to(graphiql_route)))
    });
    server.bind("127.0.0.1:8080").unwrap().run().await
}
// now go to http://127.0.0.1:8080/playground or graphiql and execute
//{  apiVersion,  user(id: 2){id, name}}
<commit_msg>Fix endpoint name typo in `juniper_actix` example (#976)<commit_after>#![deny(warnings)]

use std::{collections::HashMap, env};

use actix_cors::Cors;
use actix_web::{
    http::header,
    middleware,
    web::{self, Data},
    App, Error, HttpResponse, HttpServer,
};
use juniper::{graphql_object, EmptyMutation, EmptySubscription, GraphQLObject, RootNode};
use juniper_actix::{graphiql_handler, graphql_handler, playground_handler};

#[derive(Clone, GraphQLObject)]
///a user
pub struct User {
    ///the id
    id: i32,
    ///the name
    name: String,
}

#[derive(Default, Clone)]
pub struct Database {
    ///this could be a database connection
    users: HashMap<i32, User>,
}
impl Database {
    pub fn new() -> Database {
        let mut users = HashMap::new();
        users.insert(
            1,
            User {
                id: 1,
                name: "Aron".to_string(),
            },
        );
        users.insert(
            2,
            User {
                id: 2,
                name: "Bea".to_string(),
            },
        );
        users.insert(
            3,
            User {
                id: 3,
                name: "Carl".to_string(),
            },
        );
        users.insert(
            4,
            User {
                id: 4,
                name: "Dora".to_string(),
            },
        );
        Database { users }
    }
    pub fn get_user(&self, id: &i32) -> Option<&User> {
        self.users.get(id)
    }
}

// To make our Database usable by Juniper, we have to implement a marker trait.
impl juniper::Context for Database {}

// Queries represent the callable funcitons
struct Query;
#[graphql_object(context = Database)]
impl Query {
    fn api_version() -> &'static str {
        "1.0"
    }

    fn user(
        context: &Database,
        #[graphql(description = "id of the user")] id: i32,
    ) -> Option<&User> {
        context.get_user(&id)
    }
}

type Schema = RootNode<'static, Query, EmptyMutation<Database>, EmptySubscription<Database>>;

fn schema() -> Schema {
    Schema::new(
        Query,
        EmptyMutation::<Database>::new(),
        EmptySubscription::<Database>::new(),
    )
}

async fn graphiql_route() -> Result<HttpResponse, Error> {
    graphiql_handler("/graphgl", None).await
}
async fn playground_route() -> Result<HttpResponse, Error> {
    playground_handler("/graphgl", None).await
}
async fn graphql_route(
    req: actix_web::HttpRequest,
    payload: actix_web::web::Payload,
    schema: web::Data<Schema>,
) -> Result<HttpResponse, Error> {
    let context = Database::new();
    graphql_handler(&schema, &context, req, payload).await
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    env::set_var("RUST_LOG", "info");
    env_logger::init();

    let server = HttpServer::new(move || {
        App::new()
            .app_data(Data::new(schema()))
            .wrap(
                Cors::default()
                    .allow_any_origin()
                    .allowed_methods(vec!["POST", "GET"])
                    .allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
                    .allowed_header(header::CONTENT_TYPE)
                    .supports_credentials()
                    .max_age(3600),
            )
            .wrap(middleware::Compress::default())
            .wrap(middleware::Logger::default())
            .service(
                web::resource("/graphql")
                    .route(web::post().to(graphql_route))
                    .route(web::get().to(graphql_route)),
            )
            .service(web::resource("/playground").route(web::get().to(playground_route)))
            .service(web::resource("/graphiql").route(web::get().to(graphiql_route)))
    });
    server.bind("127.0.0.1:8080").unwrap().run().await
}
// now go to http://127.0.0.1:8080/playground or graphiql and execute
//{  apiVersion,  user(id: 2){id, name}}
<|endoftext|>


<commit_before>use rgen3_save::{Pokemon, SaveSections};
use rgen3_string::decode_string;
use std::collections::HashMap;

macro_rules! make_poke_map {
    ($($id:literal,$name:literal,$($kind:literal,)+;)+) => {{
        let mut map = HashMap::new();
        $(
            let mut kinds = Vec::new();
            $(
                kinds.push($kind);
            )+
            map.insert($id, ($name, kinds));
        );+
        map
    }}
}

#[allow(clippy::zero_prefixed_literal)]
fn main() {
    let mut args = std::env::args().skip(1);
    let path = args.next().expect("Need path to save as first arg");
    let save = rgen3_save::Save::load_from_file(&path).unwrap();
    let SaveSections { team, pc_boxes, .. } = save.sections();
    let pokemap = include!("../../poke.incl");
    println!("== Team ==");
    for pokemon in team {
        print_pokemon(pokemon, &pokemap);
    }
    println!("== PC ==");
    for pbox in pc_boxes {
        for slot in &pbox.slots {
            if let Some(pokemon) = slot {
                print_pokemon(pokemon, &pokemap);
            }
        }
    }
}

fn print_pokemon(pokemon: &Pokemon, pokemap: &HashMap<u16, (&'static str, Vec<&'static str>)>) {
    let unk_string: String;
    let unk_vec = vec![""];
    let (name, kinds) = match pokemap.get(&pokemon.data.growth.species) {
        Some((name, kinds)) => (*name, kinds),
        None => {
            unk_string = format!("<Unknown> ({})", pokemon.data.growth.species);
            (&unk_string[..], &unk_vec)
        }
    };
    let data = &pokemon.data;
    let evc = &data.evs_and_condition;
    println!(
        "{} <{}> {:?}",
        decode_string(&pokemon.nickname.0),
        name,
        kinds
    );
    println!("friendship: {}", data.growth.friendship);
    println!("EVs:");
    println!("hp: {}", evc.hp);
    println!("atk: {}", evc.attack);
    println!("def: {}", evc.defense);
    println!("spd: {}", evc.speed);
    println!("sp atk: {}", evc.sp_attack);
    println!("sp def: {}", evc.sp_defense);
    println!(
        "total: {}/510",
        u16::from(evc.hp)
            + u16::from(evc.attack)
            + u16::from(evc.defense)
            + u16::from(evc.speed)
            + u16::from(evc.sp_attack)
            + u16::from(evc.sp_defense)
    );
    println!("Contest:");
    println!("cool: {}", evc.coolness);
    println!("beauty: {}", evc.beauty);
    println!("cute: {}", evc.cuteness);
    println!("smart: {}", evc.smartness);
    println!("tough: {}", evc.toughness);
    println!("-")
}
<commit_msg>list-pokemon: Don't print contest stats<commit_after>use rgen3_save::{Pokemon, SaveSections};
use rgen3_string::decode_string;
use std::collections::HashMap;

macro_rules! make_poke_map {
    ($($id:literal,$name:literal,$($kind:literal,)+;)+) => {{
        let mut map = HashMap::new();
        $(
            let mut kinds = Vec::new();
            $(
                kinds.push($kind);
            )+
            map.insert($id, ($name, kinds));
        );+
        map
    }}
}

#[allow(clippy::zero_prefixed_literal)]
fn main() {
    let mut args = std::env::args().skip(1);
    let path = args.next().expect("Need path to save as first arg");
    let save = rgen3_save::Save::load_from_file(&path).unwrap();
    let SaveSections { team, pc_boxes, .. } = save.sections();
    let pokemap = include!("../../poke.incl");
    println!("== Team ==");
    for pokemon in team {
        print_pokemon(pokemon, &pokemap);
    }
    println!("== PC ==");
    for pbox in pc_boxes {
        for slot in &pbox.slots {
            if let Some(pokemon) = slot {
                print_pokemon(pokemon, &pokemap);
            }
        }
    }
}

fn print_pokemon(pokemon: &Pokemon, pokemap: &HashMap<u16, (&'static str, Vec<&'static str>)>) {
    let unk_string: String;
    let unk_vec = vec![""];
    let (name, kinds) = match pokemap.get(&pokemon.data.growth.species) {
        Some((name, kinds)) => (*name, kinds),
        None => {
            unk_string = format!("<Unknown> ({})", pokemon.data.growth.species);
            (&unk_string[..], &unk_vec)
        }
    };
    let data = &pokemon.data;
    let evc = &data.evs_and_condition;
    println!(
        "{} <{}> {:?}",
        decode_string(&pokemon.nickname.0),
        name,
        kinds
    );
    println!("friendship: {}", data.growth.friendship);
    println!("EVs:");
    println!("hp: {}", evc.hp);
    println!("atk: {}", evc.attack);
    println!("def: {}", evc.defense);
    println!("spd: {}", evc.speed);
    println!("sp atk: {}", evc.sp_attack);
    println!("sp def: {}", evc.sp_defense);
    println!(
        "total: {}/510",
        u16::from(evc.hp)
            + u16::from(evc.attack)
            + u16::from(evc.defense)
            + u16::from(evc.speed)
            + u16::from(evc.sp_attack)
            + u16::from(evc.sp_defense)
    );
    println!("-")
}
<|endoftext|>


<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use super::register::{Register, RegisterInterface, RegisterOffset, RegisterRange, RegisterValue};
use std::collections::btree_map::BTreeMap;

/// Register space repesents a set of registers. It can handle read/write operations.
pub struct RegisterSpace {
    regs: BTreeMap<RegisterRange, Box<dyn RegisterInterface>>,
}

impl RegisterSpace {
    /// Creates a new empty RegisterSpace.
    pub fn new() -> RegisterSpace {
        RegisterSpace {
            regs: BTreeMap::new(),
        }
    }

    /// Add a register to register space.
    pub fn add_register<T: RegisterInterface + 'static>(&mut self, reg: T) {
        let range = reg.range();
        debug_assert!(self.get_register(range.from).is_none());
        if cfg!(debug_assertions) {
            if let Some(r) = self.first_before(range.to) {
                debug_assert!(r.range().to < range.to);
            }
        }

        let insert_result = self.regs.insert(range, Box::new(reg)).is_none();
        debug_assert!(insert_result);
    }

    /// Add an array of registers.
    pub fn add_register_array<T: RegisterValue>(&mut self, regs: &[Register<T>]) {
        for r in regs {
            self.add_register(r.clone());
        }
    }

    /// Read range.
    pub fn read(&self, addr: RegisterOffset, data: &mut [u8]) {
        let mut current_addr: RegisterOffset = addr;
        while current_addr < addr + data.len() as RegisterOffset {
            if let Some(r) = self.get_register(current_addr) {
                // Next addr to read is.
                current_addr = r.range().to + 1;
                r.read(addr, data);
            } else {
                // TODO(jkwang) Add logging for debug here.
                current_addr = current_addr + 1;
            }
        }
    }

    /// Write range. If the targeted register has a callback, it will be invoked with the new
    /// value.
    pub fn write(&self, addr: RegisterOffset, data: &[u8]) {
        let mut current_addr: RegisterOffset = addr;
        while current_addr < addr + data.len() as RegisterOffset {
            if let Some(r) = self.get_register(current_addr) {
                // Next addr to read is, range is inclusive.
                current_addr = r.range().to + 1;
                r.write(addr, data);
            } else {
                current_addr = current_addr + 1;
            }
        }
    }

    /// Get first register before this addr.
    fn first_before(&self, addr: RegisterOffset) -> Option<&dyn RegisterInterface> {
        for (range, r) in self.regs.iter().rev() {
            if range.from <= addr {
                return Some(r.as_ref());
            }
        }
        None
    }

    /// Get register at this addr.
    fn get_register(&self, addr: RegisterOffset) -> Option<&dyn RegisterInterface> {
        let r = self.first_before(addr)?;
        let range = r.range();
        if addr <= range.to {
            Some(r)
        } else {
            None
        }
    }
}

#[cfg(test)]
mod tests {
    use super::super::{RegisterSpec, StaticRegister, StaticRegisterSpec};
    use super::*;
    use std::sync::Arc;
    use sync::Mutex;

    #[test]
    fn regs_no_reg() {
        let regs = RegisterSpace::new();
        let mut data: [u8; 4] = [4, 3, 2, 1];
        // Read should be no op cause no register.
        regs.read(0, &mut data);
        assert_eq!([4, 3, 2, 1], data);
        // Write should be no op.
        regs.write(0, &[0, 0, 0, 0]);
        regs.read(0, &mut data);
        assert_eq!([4, 3, 2, 1], data);
    }

    #[test]
    #[should_panic]
    #[cfg(debug_assertions)]
    fn regs_reg_overlap() {
        let mut regs = RegisterSpace::new();
        regs.add_register(static_register!(
        ty: u32,
        offset: 4,
        value: 11,
        ));

        regs.add_register(static_register!(
        ty: u16,
        offset: 7,
        value: 11,
        ));
    }

    #[test]
    fn regs_static_reg() {
        let mut regs = RegisterSpace::new();
        regs.add_register(static_register!(
            ty: u8,
            offset: 0,
            value: 11,
        ));
        let mut data: [u8; 4] = [4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([11, 3, 2, 1], data);
        // Write should be no op.
        regs.write(0, &[0, 0, 0, 0]);
        let mut data: [u8; 4] = [4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([11, 3, 2, 1], data);
    }

    #[test]
    fn regs_static_reg_offset() {
        let mut regs = RegisterSpace::new();
        regs.add_register(static_register!(
            ty: u32,
            offset: 2,
            value: 0xaabbccdd,
        ));
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
        // Write should be no op.
        regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
    }

    #[test]
    fn regs_reg_write() {
        let mut regs = RegisterSpace::new();
        regs.add_register(register!(
            name: "",
            ty: u32,
            offset: 2,
            reset_value: 0xaabbccdd,
        ));
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
        regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0, 0, 0, 0, 2, 1], data);
    }

    #[test]
    fn regs_reg_writeable() {
        let mut regs = RegisterSpace::new();
        regs.add_register(register!(
            name: "",
            ty: u32,
            offset: 2,
            reset_value: 0xaabbccdd,
            guest_writeable_mask: 0x00f0000f,
            guest_write_1_to_clear_mask: 0,
        ));
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
        regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xd0, 0xcc, 0x0b, 0xaa, 2, 1], data);
    }

    #[test]
    fn regs_reg_writeable_callback() {
        let state = Arc::new(Mutex::new(0u32));
        let mut regs = RegisterSpace::new();
        let reg = register!(
            name: "",
            ty: u32,
            offset: 2,
            reset_value: 0xaabbccdd,
            guest_writeable_mask: 0x00f0000f,
            guest_write_1_to_clear_mask: 0,
        );
        regs.add_register(reg.clone());
        let state_clone = state.clone();
        reg.set_write_cb(move |val: u32| {
            *state_clone.lock() = val;
            val
        });

        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
        regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
        assert_eq!(0xaa0bccd0, *state.lock());
    }

    #[test]
    fn regs_reg_write_to_clear() {
        let mut regs = RegisterSpace::new();
        regs.add_register(register!(
        name: "",
        ty: u32,
        offset: 2,
        reset_value: 0xaabbccdd,
        guest_writeable_mask: 0xfff0000f,
        guest_write_1_to_clear_mask: 0xf0000000,
        ));
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
        regs.write(0, &[0, 0, 0, 0, 0, 0xad, 0, 0]);
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xd0, 0xcc, 0x0b, 0x0d, 2, 1], data);
    }

    #[test]
    fn regs_reg_array() {
        let mut regs = RegisterSpace::new();
        regs.add_register_array(&register_array!(
            name: "",
            ty: u8,
            cnt: 8,
            base_offset: 10,
            stride: 2,
            reset_value: 0xff,
            guest_writeable_mask: !0,
            guest_write_1_to_clear_mask: 0,
        ));
        let mut data: [u8; 8] = [0; 8];
        regs.read(8, &mut data);
        assert_eq!([0, 0, 0xff, 0, 0xff, 0, 0xff, 0], data);
    }

    #[test]
    fn regs_reg_multi_array() {
        let mut regs = RegisterSpace::new();
        regs.add_register_array(&register_array!(
        name: "",
        ty: u8,
        cnt: 8,
        base_offset: 10,
        stride: 2,
        reset_value: 0xff,
        guest_writeable_mask: !0,
        guest_write_1_to_clear_mask: 0,
        ));
        regs.add_register_array(&register_array!(
        name: "",
        ty: u8,
        cnt: 8,
        base_offset: 11,
        stride: 2,
        reset_value: 0xee,
        guest_writeable_mask: !0,
        guest_write_1_to_clear_mask: 0,
        ));
        let mut data: [u8; 8] = [0; 8];
        regs.read(8, &mut data);
        assert_eq!([0, 0, 0xff, 0xee, 0xff, 0xee, 0xff, 0xee], data);
    }

}
<commit_msg>devices: usb: remove unused imports in tests<commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use super::register::{Register, RegisterInterface, RegisterOffset, RegisterRange, RegisterValue};
use std::collections::btree_map::BTreeMap;

/// Register space repesents a set of registers. It can handle read/write operations.
pub struct RegisterSpace {
    regs: BTreeMap<RegisterRange, Box<dyn RegisterInterface>>,
}

impl RegisterSpace {
    /// Creates a new empty RegisterSpace.
    pub fn new() -> RegisterSpace {
        RegisterSpace {
            regs: BTreeMap::new(),
        }
    }

    /// Add a register to register space.
    pub fn add_register<T: RegisterInterface + 'static>(&mut self, reg: T) {
        let range = reg.range();
        debug_assert!(self.get_register(range.from).is_none());
        if cfg!(debug_assertions) {
            if let Some(r) = self.first_before(range.to) {
                debug_assert!(r.range().to < range.to);
            }
        }

        let insert_result = self.regs.insert(range, Box::new(reg)).is_none();
        debug_assert!(insert_result);
    }

    /// Add an array of registers.
    pub fn add_register_array<T: RegisterValue>(&mut self, regs: &[Register<T>]) {
        for r in regs {
            self.add_register(r.clone());
        }
    }

    /// Read range.
    pub fn read(&self, addr: RegisterOffset, data: &mut [u8]) {
        let mut current_addr: RegisterOffset = addr;
        while current_addr < addr + data.len() as RegisterOffset {
            if let Some(r) = self.get_register(current_addr) {
                // Next addr to read is.
                current_addr = r.range().to + 1;
                r.read(addr, data);
            } else {
                // TODO(jkwang) Add logging for debug here.
                current_addr = current_addr + 1;
            }
        }
    }

    /// Write range. If the targeted register has a callback, it will be invoked with the new
    /// value.
    pub fn write(&self, addr: RegisterOffset, data: &[u8]) {
        let mut current_addr: RegisterOffset = addr;
        while current_addr < addr + data.len() as RegisterOffset {
            if let Some(r) = self.get_register(current_addr) {
                // Next addr to read is, range is inclusive.
                current_addr = r.range().to + 1;
                r.write(addr, data);
            } else {
                current_addr = current_addr + 1;
            }
        }
    }

    /// Get first register before this addr.
    fn first_before(&self, addr: RegisterOffset) -> Option<&dyn RegisterInterface> {
        for (range, r) in self.regs.iter().rev() {
            if range.from <= addr {
                return Some(r.as_ref());
            }
        }
        None
    }

    /// Get register at this addr.
    fn get_register(&self, addr: RegisterOffset) -> Option<&dyn RegisterInterface> {
        let r = self.first_before(addr)?;
        let range = r.range();
        if addr <= range.to {
            Some(r)
        } else {
            None
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::Arc;
    use sync::Mutex;

    #[test]
    fn regs_no_reg() {
        let regs = RegisterSpace::new();
        let mut data: [u8; 4] = [4, 3, 2, 1];
        // Read should be no op cause no register.
        regs.read(0, &mut data);
        assert_eq!([4, 3, 2, 1], data);
        // Write should be no op.
        regs.write(0, &[0, 0, 0, 0]);
        regs.read(0, &mut data);
        assert_eq!([4, 3, 2, 1], data);
    }

    #[test]
    #[should_panic]
    #[cfg(debug_assertions)]
    fn regs_reg_overlap() {
        let mut regs = RegisterSpace::new();
        regs.add_register(static_register!(
        ty: u32,
        offset: 4,
        value: 11,
        ));

        regs.add_register(static_register!(
        ty: u16,
        offset: 7,
        value: 11,
        ));
    }

    #[test]
    fn regs_static_reg() {
        let mut regs = RegisterSpace::new();
        regs.add_register(static_register!(
            ty: u8,
            offset: 0,
            value: 11,
        ));
        let mut data: [u8; 4] = [4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([11, 3, 2, 1], data);
        // Write should be no op.
        regs.write(0, &[0, 0, 0, 0]);
        let mut data: [u8; 4] = [4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([11, 3, 2, 1], data);
    }

    #[test]
    fn regs_static_reg_offset() {
        let mut regs = RegisterSpace::new();
        regs.add_register(static_register!(
            ty: u32,
            offset: 2,
            value: 0xaabbccdd,
        ));
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
        // Write should be no op.
        regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
    }

    #[test]
    fn regs_reg_write() {
        let mut regs = RegisterSpace::new();
        regs.add_register(register!(
            name: "",
            ty: u32,
            offset: 2,
            reset_value: 0xaabbccdd,
        ));
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
        regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0, 0, 0, 0, 2, 1], data);
    }

    #[test]
    fn regs_reg_writeable() {
        let mut regs = RegisterSpace::new();
        regs.add_register(register!(
            name: "",
            ty: u32,
            offset: 2,
            reset_value: 0xaabbccdd,
            guest_writeable_mask: 0x00f0000f,
            guest_write_1_to_clear_mask: 0,
        ));
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
        regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xd0, 0xcc, 0x0b, 0xaa, 2, 1], data);
    }

    #[test]
    fn regs_reg_writeable_callback() {
        let state = Arc::new(Mutex::new(0u32));
        let mut regs = RegisterSpace::new();
        let reg = register!(
            name: "",
            ty: u32,
            offset: 2,
            reset_value: 0xaabbccdd,
            guest_writeable_mask: 0x00f0000f,
            guest_write_1_to_clear_mask: 0,
        );
        regs.add_register(reg.clone());
        let state_clone = state.clone();
        reg.set_write_cb(move |val: u32| {
            *state_clone.lock() = val;
            val
        });

        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
        regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
        assert_eq!(0xaa0bccd0, *state.lock());
    }

    #[test]
    fn regs_reg_write_to_clear() {
        let mut regs = RegisterSpace::new();
        regs.add_register(register!(
        name: "",
        ty: u32,
        offset: 2,
        reset_value: 0xaabbccdd,
        guest_writeable_mask: 0xfff0000f,
        guest_write_1_to_clear_mask: 0xf0000000,
        ));
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
        regs.write(0, &[0, 0, 0, 0, 0, 0xad, 0, 0]);
        let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
        regs.read(0, &mut data);
        assert_eq!([8, 7, 0xd0, 0xcc, 0x0b, 0x0d, 2, 1], data);
    }

    #[test]
    fn regs_reg_array() {
        let mut regs = RegisterSpace::new();
        regs.add_register_array(&register_array!(
            name: "",
            ty: u8,
            cnt: 8,
            base_offset: 10,
            stride: 2,
            reset_value: 0xff,
            guest_writeable_mask: !0,
            guest_write_1_to_clear_mask: 0,
        ));
        let mut data: [u8; 8] = [0; 8];
        regs.read(8, &mut data);
        assert_eq!([0, 0, 0xff, 0, 0xff, 0, 0xff, 0], data);
    }

    #[test]
    fn regs_reg_multi_array() {
        let mut regs = RegisterSpace::new();
        regs.add_register_array(&register_array!(
        name: "",
        ty: u8,
        cnt: 8,
        base_offset: 10,
        stride: 2,
        reset_value: 0xff,
        guest_writeable_mask: !0,
        guest_write_1_to_clear_mask: 0,
        ));
        regs.add_register_array(&register_array!(
        name: "",
        ty: u8,
        cnt: 8,
        base_offset: 11,
        stride: 2,
        reset_value: 0xee,
        guest_writeable_mask: !0,
        guest_write_1_to_clear_mask: 0,
        ));
        let mut data: [u8; 8] = [0; 8];
        regs.read(8, &mut data);
        assert_eq!([0, 0, 0xff, 0xee, 0xff, 0xee, 0xff, 0xee], data);
    }

}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;
use std::collections::{HashMap, VecDeque};
use std::vec::Vec;
use autograd::variable::*;
use tensor::*;
use RcMut;

thread_local! {
    pub static FUNC_TABLE: RefCell<VecDeque<FuncImpl>> = RefCell::new(VecDeque::new());
}

pub type FuncId = i32;

#[derive(Default)]
pub struct FuncImpl {
    previous_functions: Vec<Function>,
    saved_variables: Vec<VarId>,
    needs_input_grad: Vec<VarId>,
    non_differentiable: Vec<TensorId>,
    requires_grad: bool,
}

#[derive(Clone)]
pub struct Function {
    id: FuncId,
}

impl Default for Function {
    fn default() -> Self {
        Function { id: -1 }
    }
}

impl Function {
    pub fn new() -> Self {
        use std::usize;
        let mut id = usize::MAX;
        FUNC_TABLE.with(|f| {
                            let mut table = f.borrow_mut();
                            id = table.len();
                            table.push_back(FuncImpl::default());
                        });
        Function { id: id as i32 }
    }
    fn access(&self) -> &mut FuncImpl {
        let vecp = FUNC_TABLE.with(|f| f.as_ptr());
        let vec = unsafe { &mut *vecp };
        &mut vec[self.id as usize]
    }

    pub fn from(id: FuncId) -> Self {
        Function { id: id }
    }
}

pub trait FuncDelegate {
    fn delegate(&mut self) -> &mut Function;
}

pub trait FuncIntf: FuncDelegate {
    fn forward<'a, T>(&mut self, input: &RefTensorList<'a, T>) -> TensorList<T>;
    fn backward<'a, T>(&mut self, input: &RefTensorList<'a, T>) -> TensorList<T>;
    fn f<T>(&mut self, mut input: &mut VarList<T>) -> VarList<T> {
        let is_volatile = input.iter().any(|v| v.is_volatile());
        {
            // do start graph stuff with f
            let mut f = self.delegate().access();
            if !is_volatile {
                f.needs_input_grad = input
                    .iter()
                    .filter_map(|v| if v.requires_grad() { Some(v.id) } else { None })
                    .collect();
                f.requires_grad = f.needs_input_grad.len() != 0;
                // XXX - set prev
                //f.previous_functions = input.iter().filter_map(|v| { let grad_fn if Some(v.value.borrow()))
            }
        }
        let inputTs = input.iter_mut().map(|v| v.data()).collect();
        let v = self.forward(&inputTs);
        let f = self.delegate();
        let mut fi = f.access();
        let output = if is_volatile {
            let args = VariableArgs::build().volatile(true).done();
            v.into_iter()
                .map(|t| Variable::new_args(t, &args))
                .collect()
        } else {
            let args = VariableArgs::build()
                .creator(Some(f.clone()))
                .requires_grad(fi.requires_grad)
                .done();
            let mut output: VarList<T> = v.into_iter()
                .map(|t| Variable::new_args(t, &args))
                .collect();
            if !fi.saved_variables.is_empty() {
                /* if a tensor was modified in place replace the old variable with the new one */
                for ref mut var in &mut output {
                    let tid = var.data().id;
                    for varid in fi.saved_variables.iter_mut() {
                        if Variable::<T>::from(*varid).data().id == tid {
                            *varid = var.id;
                        }
                    }
                }
            };
            if !fi.non_differentiable.is_empty() {
                for ref mut var in &mut output {
                    if fi.non_differentiable.contains(&var.data().id) {
                        var.requires_nograd()
                    }
                }
                fi.non_differentiable.clear();
            };
            output
        };
        output
    }
    fn _do_backward<'a, T>(&mut self, grad_output: &RefTensorList<'a, T>, retain_variables: bool) {
        if self.delegate().access().saved_variables.is_empty() {
            panic!("Trying to backward through the graph second \
                    time, but the buffers have already been freed. Please \
                    specify retain_variables=True when calling backward for \
                    the first time.");
        }
    }
}

pub trait FuncIntfX: FuncDelegate {
    fn forwardx<'a, T>(&mut self,
                       input: &RefTensorList<'a, T>,
                       target: &RefTensorList<i64>)
                       -> TensorList<T>;
    fn backwardx<'a, T>(&mut self,
                        input: &RefTensorList<'a, T>,
                        target: &RefTensorList<i64>)
                        -> TensorList<T>;
    fn fx<T>(&mut self, input: &mut VarList<T>, target: &mut VarList<i64>) -> VarList<T> {
        {
            // do start graph stuff with f
            let f = self.delegate();
        }
        let inputTs = input.iter_mut().map(|v| v.data()).collect();
        let targetTs = target.iter_mut().map(|v| v.data()).collect();

        let v = self.forwardx(&inputTs, &targetTs);
        let f = self.delegate();
        let fi = f.access();
        let args = VariableArgs::build()
            .creator(Some(f.clone()))
            .requires_grad(fi.requires_grad)
            .done();
        let output = v.into_iter()
            .map(|t| Variable::new_args(t, &args))
            .collect();
        output

    }
}
<commit_msg>implement Function _do_backward<commit_after>use std::rc::Rc;
use std::cell::RefCell;
use std::collections::{HashMap, VecDeque};
use std::vec::Vec;
use autograd::variable::*;
use tensor::*;
use RcMut;

thread_local! {
    pub static FUNC_TABLE: RefCell<VecDeque<FuncImpl>> = RefCell::new(VecDeque::new());
}

pub type FuncId = i32;

#[derive(Default)]
pub struct FuncImpl {
    previous_functions: Vec<Function>,
    saved_variables: Vec<VarId>,
    needs_input_grad: Vec<VarId>,
    non_differentiable: Vec<TensorId>,
    requires_grad: bool,
}

impl FuncImpl {
    fn _call_hooks<T>(&self, input: &TensorList<T>, output: &RefTensorList<T>) {
        unimplemented!();
    }
}

#[derive(Clone)]
pub struct Function {
    id: FuncId,
}

impl Default for Function {
    fn default() -> Self {
        Function { id: -1 }
    }
}

impl Function {
    pub fn new() -> Self {
        use std::usize;
        let mut id = usize::MAX;
        FUNC_TABLE.with(|f| {
                            let mut table = f.borrow_mut();
                            id = table.len();
                            table.push_back(FuncImpl::default());
                        });
        Function { id: id as i32 }
    }
    fn access(&self) -> &mut FuncImpl {
        let vecp = FUNC_TABLE.with(|f| f.as_ptr());
        let vec = unsafe { &mut *vecp };
        &mut vec[self.id as usize]
    }

    pub fn from(id: FuncId) -> Self {
        Function { id: id }
    }
}

pub trait FuncDelegate {
    fn delegate(&mut self) -> &mut Function;
}

pub trait FuncIntf: FuncDelegate {
    fn forward<'a, T>(&mut self, input: &RefTensorList<'a, T>) -> TensorList<T>;
    fn backward<'a, T>(&mut self, input: &RefTensorList<'a, T>) -> TensorList<T>;
    fn f<T>(&mut self, mut input: &mut VarList<T>) -> VarList<T> {
        let is_volatile = input.iter().any(|v| v.is_volatile());
        {
            // do start graph stuff with f
            let mut f = self.delegate().access();
            if !is_volatile {
                f.needs_input_grad = input
                    .iter()
                    .filter_map(|v| if v.requires_grad() { Some(v.id) } else { None })
                    .collect();
                f.requires_grad = f.needs_input_grad.len() != 0;
                // XXX - set prev
                //f.previous_functions = input.iter().filter_map(|v| { let grad_fn if Some(v.value.borrow()))
            }
        }
        let inputTs = input.iter_mut().map(|v| v.data()).collect();
        let v = self.forward(&inputTs);
        let f = self.delegate();
        let mut fi = f.access();
        let output = if is_volatile {
            let args = VariableArgs::build().volatile(true).done();
            v.into_iter()
                .map(|t| Variable::new_args(t, &args))
                .collect()
        } else {
            let args = VariableArgs::build()
                .creator(Some(f.clone()))
                .requires_grad(fi.requires_grad)
                .done();
            let mut output: VarList<T> = v.into_iter()
                .map(|t| Variable::new_args(t, &args))
                .collect();
            if !fi.saved_variables.is_empty() {
                /* if a tensor was modified in place replace the old variable with the new one */
                for ref mut var in &mut output {
                    let tid = var.data().id;
                    for varid in fi.saved_variables.iter_mut() {
                        if Variable::<T>::from(*varid).data().id == tid {
                            *varid = var.id;
                        }
                    }
                }
            };
            if !fi.non_differentiable.is_empty() {
                for ref mut var in &mut output {
                    if fi.non_differentiable.contains(&var.data().id) {
                        var.requires_nograd()
                    }
                }
                fi.non_differentiable.clear();
            };
            output
        };
        output
    }
    fn _do_backward<'a, T>(&mut self, grad_output: &RefTensorList<'a, T>, retain_variables: bool) {
        if self.delegate().access().saved_variables.is_empty() {
            panic!("Trying to backward through the graph second \
                    time, but the buffers have already been freed. Please \
                    specify retain_variables=True when calling backward for \
                    the first time.");
        }
        let grad_input = self.backward(grad_output);
        let fi = self.delegate().access();
        fi._call_hooks(&grad_input, grad_output);
        if !retain_variables {
            fi.saved_variables.clear();
        }

    }
}

pub trait FuncIntfX: FuncDelegate {
    fn forwardx<'a, T>(&mut self,
                       input: &RefTensorList<'a, T>,
                       target: &RefTensorList<i64>)
                       -> TensorList<T>;
    fn backwardx<'a, T>(&mut self,
                        input: &RefTensorList<'a, T>,
                        target: &RefTensorList<i64>)
                        -> TensorList<T>;
    fn fx<T>(&mut self, input: &mut VarList<T>, target: &mut VarList<i64>) -> VarList<T> {
        {
            // do start graph stuff with f
            let f = self.delegate();
        }
        let inputTs = input.iter_mut().map(|v| v.data()).collect();
        let targetTs = target.iter_mut().map(|v| v.data()).collect();

        let v = self.forwardx(&inputTs, &targetTs);
        let f = self.delegate();
        let fi = f.access();
        let args = VariableArgs::build()
            .creator(Some(f.clone()))
            .requires_grad(fi.requires_grad)
            .done();
        let output = v.into_iter()
            .map(|t| Variable::new_args(t, &args))
            .collect();
        output

    }
}
<|endoftext|>


<commit_before>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.3

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::SocketAddr;
use std::io::println;
use std::cell::Cell;
use std::{os, str, io, run, uint};
use extra::arc;
use std::comm::*;
use extra::priority_queue::PriorityQueue;
use std::rt::io::net::ip::*;

static PORT:    int = 4414;
static IP: &'static str = "127.0.0.1";

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath,
    ip: IpAddr,
    filesize: Option<uint>, //filesize added to store file size
}

fn main() {
    let mut req_vec : PriorityQueue<sched_msg> = PriorityQueue::new();
    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    // dequeue file requests, and send responses.
    // FIFO
    do spawn {
        let (sm_port, sm_chan) = stream();

        // a task for sending responses.
        do spawn {
            loop {
                let mut tf: sched_msg = sm_port.recv(); // wait for the dequeued request to handle
                match io::read_whole_file(tf.filepath) { // killed if file size is larger than memory size.
                    Ok(file_data) => {
                        println(fmt!("begin serving file [%?]", tf.filepath));
                        // A web server should always reply a HTTP header for any legal HTTP request.
                        tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream; charset=UTF-8\r\n\r\n".as_bytes());
                        tf.stream.write(file_data);
                        println(fmt!("finish file [%?]", tf.filepath));
                    }
                    Err(err) => {
                        println(err);
                    }
                }
            }
        }

        loop {
            port.recv(); // wait for arrving notification
            do take_vec.write |vec| {
                if ((*vec).len() > 0) {
                    // LIFO didn't make sense in service scheduling, so we modify it as FIFO by using shift_opt() rather than pop().
                    let tf : sched_msg = (*vec).pop();
                    println(fmt!("shift from queue, size: %ud", (*vec).len()));
                    sm_chan.send(tf); // send the request to send-response-task to serve.
                }
            }
        }
    }

    let ip = match FromStr::from_str(IP) { Some(ip) => ip,
                                           None => { println(fmt!("Error: Invalid IP address <%s>", IP));
                                                     return;},
                                         };

    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16});

    println(fmt!("Listening on %s:%d ...", ip.to_str(), PORT));
    let mut acceptor = socket.listen().unwrap();

    let mycount: uint = 0;
    let shared_mycount = arc::RWArc::new(mycount);

    for stream in acceptor.incoming() {
        let stream = Cell::new(stream);

        // Start a new task to handle the each connection
        let child_chan = chan.clone();
        let child_add_vec = add_vec.clone();
        let update_count = shared_mycount.clone();
        do spawn {
            let mut visitor_count = 0;
            do update_count.write |c| {
                *c += 1;
                visitor_count = *c;
             }

            let mut stream = stream.take();

            let mut visitor_ip: IpAddr = std::rt::io::net::ip::Ipv4Addr(-1, -1, -1, -1);

            stream.and_then_mut_ref(|x| {
                    match x.peer_name() {
                        Some(sock_addr) => {visitor_ip = sock_addr.ip;},
                        None => ()
                    }
                    Some(x)
                });

            println(fmt!("Visitor IP is %s", visitor_ip.to_str()));

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
            if req_group.len() > 2 {
                let path = req_group[1];
                println(fmt!("Request for path: \n%?", path));

                let file_path = ~os::getcwd().push(path.replace("/../", ""));
                if !os::path_exists(file_path) || os::path_is_dir(file_path) {
                    println(fmt!("Request received:\n%s", request_str));
                    let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                         <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

                         \r\n", visitor_count);

                    stream.write(response.as_bytes());
                }
                else {
                    // Requests scheduling

		    // Started Problem 3 code here
		    // Creates process that runs and parses file size command for problem 3
		    let mut args : ~[~str] = ~[~"-c", ~"<", file_path.to_str()];
		    let mut pr = run::Process::new("wc", args, run::ProcessOptions::new());
		    let poutput = pr.finish_with_output();
		    let mut poutputc = poutput.output;
		    let mut realstr = str::from_utf8(poutputc);
		    let mut strarray: ~[&str] = realstr.split_iter(' ').collect();
		    let mut formatfsize : Option<uint> = from_str(strarray[0]);
                    let msg: sched_msg = sched_msg{stream: stream, filepath: file_path.clone(), ip: visitor_ip, filesize : formatfsize };

		    println(fmt!("%?", realstr));//print file size served
		    println(fmt!("%?", strarray[0]));//print file size served
		    println(fmt!("%?", formatfsize));//print file size served

		    //Problem 3 Code finishes here

                    let (sm_port, sm_chan) = std::comm::stream();
                    sm_chan.send(msg);

                    do child_add_vec.write |vec| {
                        let msg = sm_port.recv();
                        (*vec).push(msg); // enqueue new request.
                        println("add to queue");
                    }
                    child_chan.send(""); //notify the new arriving request.
                    println(fmt!("get file request: %?", file_path));
                }
            }
            println!("connection terminates")
        }
    }
}

impl Ord for sched_msg {

	fn lt(&self, other: &sched_msg) -> bool {

		let selfIP: IpAddr = self.ip;
		let otherIP: IpAddr = other.ip;

		match selfIP {
			Ipv4Addr(a , b, c, d) => {
				if ((a == 128 && b == 143) || (a == 137 && b == 54)){
					return false;
				}else{
					return true;;
				}
			},
			Ipv6Addr(a, b, c, d, e, f, g, h) => {
				if ((a == 128 && b == 143) || (a == 137 && b == 54)){
					return false;
				}else{
					return true;
				}

			}
		}

	}

}
<commit_msg>change comparator<commit_after>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.3

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::SocketAddr;
use std::io::println;
use std::cell::Cell;
use std::{os, str, io, run, uint};
use extra::arc;
use std::comm::*;
use extra::priority_queue::PriorityQueue;
use std::rt::io::net::ip::*;

static PORT:    int = 4414;
static IP: &'static str = "127.0.0.1";

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath,
    ip: IpAddr,
    filesize: Option<uint>, //filesize added to store file size
}

fn main() {
    let mut req_vec : PriorityQueue<sched_msg> = PriorityQueue::new();
    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    // dequeue file requests, and send responses.
    // FIFO
    do spawn {
        let (sm_port, sm_chan) = stream();

        // a task for sending responses.
        do spawn {
            loop {
                let mut tf: sched_msg = sm_port.recv(); // wait for the dequeued request to handle
                match io::read_whole_file(tf.filepath) { // killed if file size is larger than memory size.
                    Ok(file_data) => {
                        println(fmt!("begin serving file [%?]", tf.filepath));
                        // A web server should always reply a HTTP header for any legal HTTP request.
                        tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream; charset=UTF-8\r\n\r\n".as_bytes());
                        tf.stream.write(file_data);
                        println(fmt!("finish file [%?]", tf.filepath));
                    }
                    Err(err) => {
                        println(err);
                    }
                }
            }
        }

        loop {
            port.recv(); // wait for arrving notification
            do take_vec.write |vec| {
                if ((*vec).len() > 0) {
                    // LIFO didn't make sense in service scheduling, so we modify it as FIFO by using shift_opt() rather than pop().
                    let tf : sched_msg = (*vec).pop();
                    println(fmt!("shift from queue, size: %ud", (*vec).len()));
                    sm_chan.send(tf); // send the request to send-response-task to serve.
                }
            }
        }
    }

    let ip = match FromStr::from_str(IP) { Some(ip) => ip,
                                           None => { println(fmt!("Error: Invalid IP address <%s>", IP));
                                                     return;},
                                         };

    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16});

    println(fmt!("Listening on %s:%d ...", ip.to_str(), PORT));
    let mut acceptor = socket.listen().unwrap();

    let mycount: uint = 0;
    let shared_mycount = arc::RWArc::new(mycount);

    for stream in acceptor.incoming() {
        let stream = Cell::new(stream);

        // Start a new task to handle the each connection
        let child_chan = chan.clone();
        let child_add_vec = add_vec.clone();
        let update_count = shared_mycount.clone();
        do spawn {
            let mut visitor_count = 0;
            do update_count.write |c| {
                *c += 1;
                visitor_count = *c;
             }

            let mut stream = stream.take();

            let mut visitor_ip: IpAddr = std::rt::io::net::ip::Ipv4Addr(-1, -1, -1, -1);

            stream.and_then_mut_ref(|x| {
                    match x.peer_name() {
                        Some(sock_addr) => {visitor_ip = sock_addr.ip;},
                        None => ()
                    }
                    Some(x)
                });

            println(fmt!("Visitor IP is %s", visitor_ip.to_str()));

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
            if req_group.len() > 2 {
                let path = req_group[1];
                println(fmt!("Request for path: \n%?", path));

                let file_path = ~os::getcwd().push(path.replace("/../", ""));
                if !os::path_exists(file_path) || os::path_is_dir(file_path) {
                    println(fmt!("Request received:\n%s", request_str));
                    let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
                         <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

                         \r\n", visitor_count);

                    stream.write(response.as_bytes());
                }
                else {
                    // Requests scheduling

		    // Started Problem 3 code here
		    // Creates process that runs and parses file size command for problem 3
		    let mut args : ~[~str] = ~[~"-c", ~"<", file_path.to_str()];
		    let mut pr = run::Process::new("wc", args, run::ProcessOptions::new());
		    let poutput = pr.finish_with_output();
		    let mut poutputc = poutput.output;
		    let mut realstr = str::from_utf8(poutputc);
		    let mut strarray: ~[&str] = realstr.split_iter(' ').collect();
		    let mut formatfsize : Option<uint> = from_str(strarray[0]);

                    let msg: sched_msg = sched_msg{stream: stream, filepath: file_path.clone(), ip: visitor_ip, filesize : formatfsize };

		    println(fmt!("%?", realstr));//print file size served
		    println(fmt!("%?", strarray[0]));//print file size served
		    println(fmt!("%?", formatfsize));//print file size served

		    //Problem 3 Code finishes here

                    let (sm_port, sm_chan) = std::comm::stream();
                    sm_chan.send(msg);

                    do child_add_vec.write |vec| {
                        let msg = sm_port.recv();
                        (*vec).push(msg); // enqueue new request.
                        println("add to queue");
                    }
                    child_chan.send(""); //notify the new arriving request.
                    println(fmt!("get file request: %?", file_path));
                }
            }
            println!("connection terminates")
        }
    }
}

impl Ord for sched_msg {

	fn lt(&self, other: &sched_msg) -> bool {

		let selfIP: IpAddr = self.ip;
		let otherIP: IpAddr = other.ip;

		let selfSize : Option<uint> = self.filesize;
		let otherSize : Option<uint> = other.filesize;

		match selfIP {
			Ipv4Addr(a , b, c, d) => {
				if ((a == 128 && b == 143) || (a == 137 && b == 54)){
					return false;
				}else{
					if (selfSize < otherSize){
						return false;
					}else{
						return true;
					}
				}
			},
			Ipv6Addr(a, b, c, d, e, f, g, h) => {
				if ((a == 128 && b == 143) || (a == 137 && b == 54)){
					return false;
				}else{
					if (selfSize < otherSize){
						return false;
					}else{
						return true;
					}
				}

			}
		}

	}

}
<|endoftext|>