<commit_before>use super::super::request::Request;
use super::super::response::Response;
use super::super::middleware::{Middleware, Continue, Unwind, Status};
use super::super::alloy::Alloy;

use super::Chain;

/// The default `Chain` used by `Iron`.
/// `StackChain` runs each `Request` through all `Middleware` in its stack.
/// When it hits `Middleware` which returns `Unwind`, it passes
/// the `Request` back up through all `Middleware` it has hit so far.
pub struct StackChain {
    /// The storage used by `StackChain` to hold all `Middleware`
    /// that have been `linked` to it.
    stack: Vec<Box<Middleware + Send>>,
    exit_stack: Vec<Box<Middleware + Send>>
}

impl Clone for StackChain {
    fn clone(&self) -> StackChain {
        StackChain {
            stack: self.stack.clone(),
            exit_stack: self.exit_stack.clone()
        }
    }
}

/// `StackChain` is a `Chain`
impl Chain for StackChain {
    fn chain_enter(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status {
        // The `exit_stack` will hold all `Middleware` that are passed through
        // in the enter loop. This is so we know to take exactly the same
        // path through `Middleware` in reverse order than we did on the way in.
        self.exit_stack = vec![];

        'enter: for middleware in self.stack.mut_iter() {
            match middleware.enter(request, response, alloy) {
                Unwind   => return Unwind,
                // Mark the middleware for traversal on exit.
                Continue => self.exit_stack.push(middleware.clone_box())
            }
        }

        Continue
    }

    fn chain_exit(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status {
        // Reverse the stack so we go through in the reverse order.
        // i.e. LIFO.
        self.exit_stack.reverse();
        // Call each middleware's exit handler.
        'exit: for middleware in self.exit_stack.mut_iter() {
            let _ = middleware.exit(request, response, alloy);
        }

        Continue
    }

    /// Add `Middleware` to the `Chain`.
    fn link<M: Middleware>(&mut self, middleware: M) {
        self.stack.push(box middleware);
    }

    /// Create a new instance of `StackChain`.
    fn new() -> StackChain {
        StackChain {
            stack: vec![],
            exit_stack: vec![]
        }
    }
}

#[cfg(test)]
mod test {
    pub use super::*;
    pub use super::super::super::request::Request;
    pub use super::super::super::response::Response;
    pub use super::super::super::alloy::Alloy;
    pub use super::super::super::middleware::{Middleware, Status, Continue};
    pub use std::sync::{Arc, Mutex};

    #[deriving(Clone)]
    pub struct CallCount {
        enter: Arc<Mutex<u64>>,
        exit: Arc<Mutex<u64>>
    }

    impl Middleware for CallCount {
        fn enter(&mut self, _req: &mut Request,
                 _res: &mut Response, _alloy: &mut Alloy) -> Status {
            let mut enter = self.enter.lock();
            *enter += 1;
            Continue
        }

        fn exit(&mut self, _req: &mut Request,
                _res: &mut Response, _alloy: &mut Alloy) -> Status {
            let mut exit = self.exit.lock();
            *exit += 1;
            Continue
        }
    }

    mod dispatch {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 1);
        }

        #[test]
        fn calls_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 1);
        }

        #[test]
        fn calls_all_middleware_enter_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter_exits: Vec<(Arc<Mutex<u64>>, Arc<Mutex<u64>>)> = vec![];

            for _ in range(0, 10) {
                let (enter, exit) = (Arc::new(Mutex::new(0)), Arc::new(Mutex::new(0)));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            }

            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }

            for (enter, exit) in enter_exits.move_iter() {
                assert_eq!(*enter.lock(), 1);
                assert_eq!(*exit.lock(), 1);
            }
        }
    }

    mod chain_enter {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.chain_enter(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 1);
        }

        #[test]
        fn doesnt_call_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.chain_enter(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 0);
        }
    }

    mod chain_exit {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.exit_stack.push(box CallCount {
                enter: enter.clone(), exit: exit.clone()
            });
            unsafe {
                let _  = testchain.chain_exit(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 1);
        }

        #[test]
        fn doesnt_call_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.exit_stack.push(box CallCount {
                enter: enter.clone(), exit: exit.clone()
            });
            unsafe {
                let _  = testchain.chain_exit(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 0);
        }
    }

    mod bench {
        use super::super::super::super::middleware::Middleware;

        #[deriving(Clone)]
        struct Noop;

        impl Middleware for Noop {}

        macro_rules! bench_noop_x (
            ($name:ident, $num:expr, $method:ident) => {
                #[bench]
                fn $name(b: &mut Bencher) {
                    let mut testchain: StackChain = Chain::new();
                    for _ in range(0, $num) {
                        testchain.link(Noop);
                    }
                    b.iter(|| {
                        black_box(unsafe {
                            let _ = testchain.$method(
                                uninitialized(),
                                uninitialized(),
                                uninitialized()
                            );
                        })
                    });
                }
            }
        )

        macro_rules! bench_method (
            ($method:ident) => {
                mod $method {
                    use std::mem::uninitialized;
                    use test::{Bencher, black_box};
                    use super::Noop;
                    use super::super::super::StackChain;
                    use super::super::super::super::Chain;

                    bench_noop_x!(bench_empty, 0, $method)
                    bench_noop_x!(bench_1, 1, $method)
                    bench_noop_x!(bench_2, 2, $method)
                    bench_noop_x!(bench_3, 3, $method)
                    bench_noop_x!(bench_4, 4, $method)
                    bench_noop_x!(bench_10, 10, $method)
                }
            }
        )

        bench_method!(dispatch)
        bench_method!(chain_enter)
    }
}

<commit_msg>(fix) Specified types for nightly break.<commit_after>use super::super::request::Request;
use super::super::response::Response;
use super::super::middleware::{Middleware, Continue, Unwind, Status};
use super::super::alloy::Alloy;

use super::Chain;

/// The default `Chain` used by `Iron`.
/// `StackChain` runs each `Request` through all `Middleware` in its stack.
/// When it hits `Middleware` which returns `Unwind`, it passes
/// the `Request` back up through all `Middleware` it has hit so far.
pub struct StackChain {
    /// The storage used by `StackChain` to hold all `Middleware`
    /// that have been `linked` to it.
    stack: Vec<Box<Middleware + Send>>,
    exit_stack: Vec<Box<Middleware + Send>>
}

impl Clone for StackChain {
    fn clone(&self) -> StackChain {
        StackChain {
            stack: self.stack.clone(),
            exit_stack: self.exit_stack.clone()
        }
    }
}

/// `StackChain` is a `Chain`
impl Chain for StackChain {
    fn chain_enter(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status {
        // The `exit_stack` will hold all `Middleware` that are passed through
        // in the enter loop. This is so we know to take exactly the same
        // path through `Middleware` in reverse order than we did on the way in.
        self.exit_stack = vec![];

        'enter: for middleware in self.stack.mut_iter() {
            match middleware.enter(request, response, alloy) {
                Unwind   => return Unwind,
                // Mark the middleware for traversal on exit.
                Continue => self.exit_stack.push(middleware.clone_box())
            }
        }

        Continue
    }

    fn chain_exit(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status {
        // Reverse the stack so we go through in the reverse order.
        // i.e. LIFO.
        self.exit_stack.reverse();
        // Call each middleware's exit handler.
        'exit: for middleware in self.exit_stack.mut_iter() {
            let _ = middleware.exit(request, response, alloy);
        }

        Continue
    }

    /// Add `Middleware` to the `Chain`.
    fn link<M: Middleware>(&mut self, middleware: M) {
        self.stack.push(box middleware);
    }

    /// Create a new instance of `StackChain`.
    fn new() -> StackChain {
        StackChain {
            stack: vec![],
            exit_stack: vec![]
        }
    }
}

#[cfg(test)]
mod test {
    pub use super::*;
    pub use super::super::super::request::Request;
    pub use super::super::super::response::Response;
    pub use super::super::super::alloy::Alloy;
    pub use super::super::super::middleware::{Middleware, Status, Continue};
    pub use std::sync::{Arc, Mutex};

    #[deriving(Clone)]
    pub struct CallCount {
        enter: Arc<Mutex<u64>>,
        exit: Arc<Mutex<u64>>
    }

    impl Middleware for CallCount {
        fn enter(&mut self, _req: &mut Request,
                 _res: &mut Response, _alloy: &mut Alloy) -> Status {
            let mut enter = self.enter.lock();
            *enter += 1;
            Continue
        }

        fn exit(&mut self, _req: &mut Request,
                _res: &mut Response, _alloy: &mut Alloy) -> Status {
            let mut exit = self.exit.lock();
            *exit += 1;
            Continue
        }
    }

    mod dispatch {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 1);
        }

        #[test]
        fn calls_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 1);
        }

        #[test]
        fn calls_all_middleware_enter_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter_exits: Vec<(Arc<Mutex<u64>>, Arc<Mutex<u64>>)> = vec![];

            for _ in range(0u8, 10) {
                let (enter, exit) = (Arc::new(Mutex::new(0)), Arc::new(Mutex::new(0)));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            }

            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }

            for (enter, exit) in enter_exits.move_iter() {
                assert_eq!(*enter.lock(), 1);
                assert_eq!(*exit.lock(), 1);
            }
        }
    }

    mod chain_enter {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.chain_enter(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 1);
        }

        #[test]
        fn doesnt_call_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.chain_enter(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 0);
        }
    }

    mod chain_exit {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.exit_stack.push(box CallCount {
                enter: enter.clone(), exit: exit.clone()
            });
            unsafe {
                let _  = testchain.chain_exit(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 1);
        }

        #[test]
        fn doesnt_call_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.exit_stack.push(box CallCount {
                enter: enter.clone(), exit: exit.clone()
            });
            unsafe {
                let _  = testchain.chain_exit(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 0);
        }
    }

    mod bench {
        use super::super::super::super::middleware::Middleware;

        #[deriving(Clone)]
        struct Noop;

        impl Middleware for Noop {}

        macro_rules! bench_noop_x (
            ($name:ident, $num:expr, $method:ident) => {
                #[bench]
                fn $name(b: &mut Bencher) {
                    let mut testchain: StackChain = Chain::new();
                    for _ in range(0, $num) {
                        testchain.link(Noop);
                    }
                    b.iter(|| {
                        black_box(unsafe {
                            let _ = testchain.$method(
                                uninitialized(),
                                uninitialized(),
                                uninitialized()
                            );
                        })
                    });
                }
            }
        )

        macro_rules! bench_method (
            ($method:ident) => {
                mod $method {
                    use std::mem::uninitialized;
                    use test::{Bencher, black_box};
                    use super::Noop;
                    use super::super::super::StackChain;
                    use super::super::super::super::Chain;

                    bench_noop_x!(bench_empty, 0u8, $method)
                    bench_noop_x!(bench_1, 1u8, $method)
                    bench_noop_x!(bench_2, 2u8, $method)
                    bench_noop_x!(bench_3, 3u8, $method)
                    bench_noop_x!(bench_4, 4u8, $method)
                    bench_noop_x!(bench_10, 10u8, $method)
                }
            }
        )

        bench_method!(dispatch)
        bench_method!(chain_enter)
    }
}

<|endoftext|>


<commit_before>// TODO
// impl ToGeojson for ....
// generic number instead of f64 for position?
// rename Position to Pos

extern crate serialize;

use std::collections::TreeMap;
use serialize::json::ToJson;
use serialize::json;

/*
 * Position
 * GeoJSON Format Specification § 2.1.1
 * http://geojson.org/geojson-spec.html#positions
 */
pub struct Position(Vec<f64>);

impl ToJson for Position {
    fn to_json(&self) -> json::Json {
        let &Position(ref nums) = self;
        nums.to_json()
    }
}

/*
 * Point
 * GeoJSON Format Specification § 2.1.2
 * http://geojson.org/geojson-spec.html#point
 */
pub struct Point {
    coordinates: Position,
}

impl ToJson for Point {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Point".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates.to_json());
        d.to_json()
    }
}

/*
 * MultiPoint
 * GeoJSON Format Specification § 2.1.3
 * http://geojson.org/geojson-spec.html#multipoint
 */
pub struct MultiPoint {
    coordinates: Vec<Position>,
}

impl ToJson for MultiPoint {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiPoint".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates.to_json());
        d.to_json()
    }
}

fn main() {
    let point = Point {
        coordinates: Position(vec![1., 2., 3.]),
    };

    let j: json::Json = point.to_json();
    let s: String = j.to_pretty_str();

    println!("{}", s);
}
<commit_msg>Rename struct property to better reflect contents<commit_after>// TODO
// impl ToGeojson for ....
// generic number instead of f64 for position?
// rename Position to Pos

extern crate serialize;

use std::collections::TreeMap;
use serialize::json::ToJson;
use serialize::json;

/*
 * Position
 * GeoJSON Format Specification § 2.1.1
 * http://geojson.org/geojson-spec.html#positions
 */
pub struct Position(Vec<f64>);

impl ToJson for Position {
    fn to_json(&self) -> json::Json {
        let &Position(ref nums) = self;
        nums.to_json()
    }
}

/*
 * Point
 * GeoJSON Format Specification § 2.1.2
 * http://geojson.org/geojson-spec.html#point
 */
pub struct Point {
    coordinates: Position,
}

impl ToJson for Point {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Point".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates.to_json());
        d.to_json()
    }
}

/*
 * MultiPoint
 * GeoJSON Format Specification § 2.1.3
 * http://geojson.org/geojson-spec.html#multipoint
 */
pub struct MultiPoint {
    points: Vec<Point>,
}

impl ToJson for MultiPoint {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiPoint".to_string().to_json());
        d.insert("coordinates".to_string(), self.points.to_json());
        d.to_json()
    }
}

fn main() {
    let point = Point {
        coordinates: Position(vec![1., 2., 3.]),
    };

    let j: json::Json = point.to_json();
    let s: String = j.to_pretty_str();

    println!("{}", s);
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fs;
use std::path::*;
use std::io::{Result, Write};
use case::CaseExt;

use env::Env;
use file_saver::*;
use library;
use nameutil::*;
use super::ffi_type::ffi_type;
use super::functions;
use super::statics;
use super::super::general::{self, tabs};
use traits::*;

pub fn generate(env: &Env) {
    println!("generating sys for {}", env.config.library_name);

    let path =  PathBuf::from(&env.config.target_path)
        .join(file_name_sys("lib"));

    let parent = path.parent().unwrap();
    //TODO: do only if not exists
    let _ = fs::create_dir(parent);

    println!("Generating file {:?}", path);
    save_to_file(&path, &mut |w| generate_lib(w, env));
}

fn generate_lib<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    try!(general::start_comments(w, &env.config));
    try!(statics::begin(w));

    try!(generate_extern_crates(w, env));
    try!(statics::after_extern_crates(w));

    if env.config.library_name != "GLib" {
        try!(statics::use_glib_ffi(w));
    } else {
        try!(statics::only_for_glib(w));
    }
    if env.config.library_name == "Gtk" {
        try!(statics::only_for_gtk(w));
    }

    let ns = env.library.namespace(library::MAIN_NAMESPACE);
    let classes = prepare(ns);
    let interfaces = prepare(ns);

    try!(generate_aliases(w, env, &prepare(ns)));
    try!(generate_enums(w, &ns.name, &prepare(ns)));
    try!(generate_bitfields(w, &ns.name, &prepare(ns)));
    try!(generate_unions(w, &prepare(ns)));
    try!(functions::generate_callbacks(w, env, &prepare(ns)));
    try!(generate_records(w, env, &prepare(ns)));
    try!(generate_classes_structs(w, &classes));
    try!(generate_interfaces_structs(w, &interfaces));

    try!(writeln!(w, ""));
    try!(writeln!(w, "extern \"C\" {{"));
    try!(functions::generate_classes_funcs(w, env, &classes));
    try!(functions::generate_interfaces_funcs(w, env, &interfaces));

    //TODO: other functions
    try!(writeln!(w, "\n}}"));

    Ok(())
}

fn generate_extern_crates<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    for library_name in &env.config.external_libraries {
        try!(writeln!(w, "extern crate {0}_sys as {0}_ffi;", crate_name(library_name)));
    }

    Ok(())
}

fn prepare<T: Ord>(ns: &library::Namespace) -> Vec<&T>
where library::Type: MaybeRef<T> {
    let mut vec: Vec<&T> = Vec::with_capacity(ns.types.len());
    for typ in ns.types.iter().filter_map(|t| t.as_ref()) {
        if let Some(ref x) = typ.maybe_ref() {
            vec.push(x);
        }
    }
    vec.sort();
    vec
}

fn generate_aliases<W: Write>(w: &mut W, env: &Env, items: &[&library::Alias])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        let (comment, c_type) = match ffi_type(env, item.typ, &item.target_c_type) {
            Ok(x) => ("", x),
            Err(x) => ("//", x),
        };
        try!(writeln!(w, "{}pub type {} = {};", comment, item.c_identifier, c_type));
    }

    Ok(())
}

fn generate_bitfields<W: Write>(w: &mut W, ns_name: &str, items: &[&library::Bitfield])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        try!(writeln!(w, "bitflags! {{\n{}#[repr(C)]\n{0}flags {}: c_uint {{", tabs(1), item.name));
        for member in &item.members {
            let val: i64 = member.value.parse().unwrap();
            try!(writeln!(w, "{}const {} = {},",
                          tabs(2), strip_prefix(ns_name, &member.c_identifier), val as u32));
        }
        try!(writeln!(w, "{}}}\n}}", tabs(1)));
        try!(writeln!(w, "pub type {} = {};", item.c_type, item.name));
        try!(writeln!(w, ""));
    }

    Ok(())
}

fn generate_enums<W: Write>(w: &mut W, ns_name: &str, items: &[&library::Enumeration])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        if item.members.len() == 1 {
            try!(writeln!(w, "pub type {} = c_int;", item.name));
            try!(writeln!(w, "pub const {}: {} = {};",
                          item.members[0].c_identifier, item.name, item.members[0].value));
            try!(writeln!(w, "pub type {} = {};", item.c_type, item.name));
            try!(writeln!(w, ""));
            continue;
        }

        let mut vals = HashMap::new();
        try!(writeln!(w, "#[derive(Clone, Copy, Debug, Eq, PartialEq)]\n#[repr(C)]"));
        try!(writeln!(w, "pub enum {} {{", item.name));
        for member in &item.members {
            if vals.get(&member.value).is_some() {
                continue;
            }
            try!(writeln!(w, "{}{} = {},",
                          tabs(1), &prepare_enum_member_name(&member.name), member.value));
            vals.insert(member.value.clone(), member.name.clone());
        }
        try!(writeln!(w, "}}"));
        for member in &item.members {
            try!(writeln!(w, "pub const {}: {} = {1}::{};",
                          prepare_enum_member_name(strip_prefix(ns_name, &member.c_identifier)),
                          item.name, &prepare_enum_member_name(vals.get(&member.value).unwrap())));
        }
        try!(writeln!(w, "pub type {} = {};", item.c_type, item.name));
        try!(writeln!(w, ""));
    }

    Ok(())
}

fn generate_unions<W: Write>(w: &mut W, items: &[&library::Union])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        try!(writeln!(w, "pub type {} = c_void;", item.name));
        if let Some(ref c_type) = item.c_type {
            try!(writeln!(w, "pub type {} = {};", c_type, item.name));
        }
        try!(writeln!(w, ""));
    }

    Ok(())
}

fn prepare_enum_member_name(name: &str) -> String {
    let cameled = name.to_camel();
    if name.chars().next().unwrap().is_digit(10) {
        format!("_{}", cameled)
    } else {
        cameled
    }
}

fn generate_classes_structs<W: Write>(w: &mut W, classes: &[&library::Class]) -> Result<()> {
    try!(writeln!(w, ""));
    for klass in classes {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", klass.c_type));
    }

    Ok(())
}

fn generate_interfaces_structs<W: Write>(w: &mut W, interfaces: &[&library::Interface]) -> Result<()> {
    try!(writeln!(w, ""));
    for interface in interfaces {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", interface.c_type));
    }

    Ok(())
}

fn generate_records<W: Write>(w: &mut W, env: &Env, records: &[&library::Record]) -> Result<()> {
    try!(writeln!(w, ""));
    for record in records {
        let mut lines = Vec::new();
        let mut commented = false;
        let mut truncated = false;
        for field in &record.fields {
            let is_union = env.library.type_(field.typ).maybe_ref_as::<library::Union>().is_some();
            let is_bits = field.bits.is_some();
            if !truncated && (is_union || is_bits) {
                warn!("Record `{}` field `{}` not expressible in Rust, truncated",
                      record.name, field.name);
                lines.push(format!("{}_truncated_record_marker: (),", tabs(1)));
                truncated = true;
            }
            if truncated {
                if is_union {
                    lines.push(format!("{}//union,", tabs(1)));
                }
                else {
                    let bits = field.bits.map(|n| format!(": {}", n)).unwrap_or("".into());
                    lines.push(
                        format!("{}//{}: {}{},", tabs(1), field.name,
                                field.c_type.as_ref().map(|s| &s[..]).unwrap_or("fn"), bits));
                };
                continue;
            }

            let vis = if field.private { "" } else { "pub " };

            if let Some(ref c_type) = field.c_type {
                let name = mangle_keywords(&*field.name);
                let c_type = ffi_type(env, field.typ, c_type);
                lines.push(format!("{}{}{}: {},", tabs(1), vis, name, c_type.as_str()));
                if c_type.is_err() {
                    commented = true;
                }
            }
            else {
                let name = mangle_keywords(&*field.name);
                if let Some(ref func) =
                        env.library.type_(field.typ).maybe_ref_as::<library::Function>() {
                    let (com, sig) = functions::function_signature(env, func, true);
                    lines.push(format!("{}{}{}: fn{},", tabs(1), vis, name, sig));
                    commented |= com;
                }
                else if let Some(c_type) = env.library.type_(field.typ).get_glib_name() {
                    warn!("Record `{}`, field `{}` missing c:type assumed `{}`",
                          record.name, field.name, c_type);
                    let c_type = ffi_type(env, field.typ, c_type);
                    lines.push(format!("{}{}{}: {},", tabs(1), vis, name, c_type.as_str()));
                    if c_type.is_err() {
                        commented = true;
                    }
                }
                else {
                    lines.push(format!("{}{}{}: [{:?} {}],", tabs(1),
                        vis, name, field.typ, field.typ.full_name(&env.library)));
                    commented = true;
                }
            }
        }
        let comment = if commented { "//" } else { "" };
        if lines.is_empty() {
            try!(writeln!(w, "{}#[repr(C)]\n{0}pub struct {};\n", comment, record.c_type));
        }
        else {
            try!(writeln!(w, "{}#[repr(C)]\n{0}pub struct {} {{", comment, record.c_type));
            for line in lines {
                try!(writeln!(w, "{}{}", comment, line));
            }
            try!(writeln!(w, "{}}}\n", comment));
        }
    }
    Ok(())
}
<commit_msg>Stop stripping prefixes from enums and bitfields<commit_after>use std::collections::HashMap;
use std::fs;
use std::path::*;
use std::io::{Result, Write};
use case::CaseExt;

use env::Env;
use file_saver::*;
use library;
use nameutil::*;
use super::ffi_type::ffi_type;
use super::functions;
use super::statics;
use super::super::general::{self, tabs};
use traits::*;

pub fn generate(env: &Env) {
    println!("generating sys for {}", env.config.library_name);

    let path =  PathBuf::from(&env.config.target_path)
        .join(file_name_sys("lib"));

    let parent = path.parent().unwrap();
    //TODO: do only if not exists
    let _ = fs::create_dir(parent);

    println!("Generating file {:?}", path);
    save_to_file(&path, &mut |w| generate_lib(w, env));
}

fn generate_lib<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    try!(general::start_comments(w, &env.config));
    try!(statics::begin(w));

    try!(generate_extern_crates(w, env));
    try!(statics::after_extern_crates(w));

    if env.config.library_name != "GLib" {
        try!(statics::use_glib_ffi(w));
    } else {
        try!(statics::only_for_glib(w));
    }
    if env.config.library_name == "Gtk" {
        try!(statics::only_for_gtk(w));
    }

    let ns = env.library.namespace(library::MAIN_NAMESPACE);
    let classes = prepare(ns);
    let interfaces = prepare(ns);

    try!(generate_aliases(w, env, &prepare(ns)));
    try!(generate_enums(w, &prepare(ns)));
    try!(generate_bitfields(w, &prepare(ns)));
    try!(generate_unions(w, &prepare(ns)));
    try!(functions::generate_callbacks(w, env, &prepare(ns)));
    try!(generate_records(w, env, &prepare(ns)));
    try!(generate_classes_structs(w, &classes));
    try!(generate_interfaces_structs(w, &interfaces));

    try!(writeln!(w, ""));
    try!(writeln!(w, "extern \"C\" {{"));
    try!(functions::generate_classes_funcs(w, env, &classes));
    try!(functions::generate_interfaces_funcs(w, env, &interfaces));

    //TODO: other functions
    try!(writeln!(w, "\n}}"));

    Ok(())
}

fn generate_extern_crates<W: Write>(w: &mut W, env: &Env) -> Result<()>{
    for library_name in &env.config.external_libraries {
        try!(writeln!(w, "extern crate {0}_sys as {0}_ffi;", crate_name(library_name)));
    }

    Ok(())
}

fn prepare<T: Ord>(ns: &library::Namespace) -> Vec<&T>
where library::Type: MaybeRef<T> {
    let mut vec: Vec<&T> = Vec::with_capacity(ns.types.len());
    for typ in ns.types.iter().filter_map(|t| t.as_ref()) {
        if let Some(ref x) = typ.maybe_ref() {
            vec.push(x);
        }
    }
    vec.sort();
    vec
}

fn generate_aliases<W: Write>(w: &mut W, env: &Env, items: &[&library::Alias])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        let (comment, c_type) = match ffi_type(env, item.typ, &item.target_c_type) {
            Ok(x) => ("", x),
            Err(x) => ("//", x),
        };
        try!(writeln!(w, "{}pub type {} = {};", comment, item.c_identifier, c_type));
    }

    Ok(())
}

fn generate_bitfields<W: Write>(w: &mut W, items: &[&library::Bitfield])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        try!(writeln!(w, "bitflags! {{\n{}#[repr(C)]\n{0}flags {}: c_uint {{",
                      tabs(1), item.c_type));
        for member in &item.members {
            let val: i64 = member.value.parse().unwrap();
            try!(writeln!(w, "{}const {} = {},", tabs(2), member.c_identifier, val as u32));
        }
        try!(writeln!(w, "{}}}\n}}", tabs(1)));
        try!(writeln!(w, ""));
    }

    Ok(())
}

fn generate_enums<W: Write>(w: &mut W, items: &[&library::Enumeration])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        if item.members.len() == 1 {
            try!(writeln!(w, "pub type {} = c_int;", item.name));
            try!(writeln!(w, "pub const {}: {} = {};",
                          item.members[0].c_identifier, item.name, item.members[0].value));
            try!(writeln!(w, "pub type {} = {};", item.c_type, item.name));
            try!(writeln!(w, ""));
            continue;
        }

        let mut vals = HashMap::new();
        try!(writeln!(w, "#[derive(Clone, Copy, Debug, Eq, PartialEq)]\n#[repr(C)]"));
        try!(writeln!(w, "pub enum {} {{", item.c_type));
        for member in &item.members {
            if vals.get(&member.value).is_some() {
                continue;
            }
            try!(writeln!(w, "{}{} = {},",
                          tabs(1), &prepare_enum_member_name(&member.name), member.value));
            vals.insert(member.value.clone(), member.name.clone());
        }
        try!(writeln!(w, "}}"));
        for member in &item.members {
            try!(writeln!(w, "pub const {}: {} = {1}::{};", member.c_identifier, item.c_type,
                          &prepare_enum_member_name(vals.get(&member.value).unwrap())));
        }
        try!(writeln!(w, ""));
    }

    Ok(())
}

fn generate_unions<W: Write>(w: &mut W, items: &[&library::Union])
        -> Result<()> {
    try!(writeln!(w, ""));
    for item in items {
        if let Some(ref c_type) = item.c_type {
            try!(writeln!(w, "pub type {} = c_void; // union", c_type));
        }
    }
    try!(writeln!(w, ""));

    Ok(())
}

fn prepare_enum_member_name(name: &str) -> String {
    let cameled = name.to_camel();
    if name.chars().next().unwrap().is_digit(10) {
        format!("_{}", cameled)
    } else {
        cameled
    }
}

fn generate_classes_structs<W: Write>(w: &mut W, classes: &[&library::Class]) -> Result<()> {
    try!(writeln!(w, ""));
    for klass in classes {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", klass.c_type));
    }

    Ok(())
}

fn generate_interfaces_structs<W: Write>(w: &mut W, interfaces: &[&library::Interface]) -> Result<()> {
    try!(writeln!(w, ""));
    for interface in interfaces {
        try!(writeln!(w, "#[repr(C)]\npub struct {};", interface.c_type));
    }

    Ok(())
}

fn generate_records<W: Write>(w: &mut W, env: &Env, records: &[&library::Record]) -> Result<()> {
    try!(writeln!(w, ""));
    for record in records {
        let mut lines = Vec::new();
        let mut commented = false;
        let mut truncated = false;
        for field in &record.fields {
            let is_union = env.library.type_(field.typ).maybe_ref_as::<library::Union>().is_some();
            let is_bits = field.bits.is_some();
            if !truncated && (is_union || is_bits) {
                warn!("Record `{}` field `{}` not expressible in Rust, truncated",
                      record.name, field.name);
                lines.push(format!("{}_truncated_record_marker: (),", tabs(1)));
                truncated = true;
            }
            if truncated {
                if is_union {
                    lines.push(format!("{}//union,", tabs(1)));
                }
                else {
                    let bits = field.bits.map(|n| format!(": {}", n)).unwrap_or("".into());
                    lines.push(
                        format!("{}//{}: {}{},", tabs(1), field.name,
                                field.c_type.as_ref().map(|s| &s[..]).unwrap_or("fn"), bits));
                };
                continue;
            }

            let vis = if field.private { "" } else { "pub " };

            if let Some(ref c_type) = field.c_type {
                let name = mangle_keywords(&*field.name);
                let c_type = ffi_type(env, field.typ, c_type);
                lines.push(format!("{}{}{}: {},", tabs(1), vis, name, c_type.as_str()));
                if c_type.is_err() {
                    commented = true;
                }
            }
            else {
                let name = mangle_keywords(&*field.name);
                if let Some(ref func) =
                        env.library.type_(field.typ).maybe_ref_as::<library::Function>() {
                    let (com, sig) = functions::function_signature(env, func, true);
                    lines.push(format!("{}{}{}: fn{},", tabs(1), vis, name, sig));
                    commented |= com;
                }
                else if let Some(c_type) = env.library.type_(field.typ).get_glib_name() {
                    warn!("Record `{}`, field `{}` missing c:type assumed `{}`",
                          record.name, field.name, c_type);
                    let c_type = ffi_type(env, field.typ, c_type);
                    lines.push(format!("{}{}{}: {},", tabs(1), vis, name, c_type.as_str()));
                    if c_type.is_err() {
                        commented = true;
                    }
                }
                else {
                    lines.push(format!("{}{}{}: [{:?} {}],", tabs(1),
                        vis, name, field.typ, field.typ.full_name(&env.library)));
                    commented = true;
                }
            }
        }
        let comment = if commented { "//" } else { "" };
        if lines.is_empty() {
            try!(writeln!(w, "{}#[repr(C)]\n{0}pub struct {};\n", comment, record.c_type));
        }
        else {
            try!(writeln!(w, "{}#[repr(C)]\n{0}pub struct {} {{", comment, record.c_type));
            for line in lines {
                try!(writeln!(w, "{}{}", comment, line));
            }
            try!(writeln!(w, "{}}}\n", comment));
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>//! Runtime services
//!
//! The `rt` module provides a narrow set of runtime services,
//! including the global heap (exported in `heap`) and unwinding and
//! backtrace support. The APIs in this module are highly unstable,
//! and should be considered as private implementation details for the
//! time being.

#![unstable(feature = "rt",
            reason = "this public module should not exist and is highly likely \
                      to disappear",
            issue = "0")]
#![doc(hidden)]

// Re-export some of our utilities which are expected by other crates.
pub use crate::panicking::{begin_panic, begin_panic_fmt, update_panic_count};

// To reduce the generated code of the new `lang_start`, this function is doing
// the real work.
#[cfg(not(test))]
fn lang_start_internal(main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe),
                       argc: isize, argv: *const *const u8) -> isize {
    use crate::panic;
    use crate::sys;
    use crate::sys_common;
    use crate::sys_common::thread_info;
    use crate::thread::Thread;

    sys::init();

    unsafe {
        let main_guard = sys::thread::guard::init();
        sys::stack_overflow::init();

        // Next, set up the current Thread with the guard information we just
        // created. Note that this isn't necessary in general for new threads,
        // but we just do this to name the main thread and to give it correct
        // info about the stack bounds.
        let thread = Thread::new(Some("main".to_owned()));
        thread_info::set(main_guard, thread);

        // Store our args if necessary in a squirreled away location
        sys::args::init(argc, argv);

        // Let's run some code!
        #[cfg(feature = "backtrace")]
        let exit_code = panic::catch_unwind(|| {
            sys_common::backtrace::__rust_begin_short_backtrace(move || main())
        });
        #[cfg(not(feature = "backtrace"))]
        let exit_code = panic::catch_unwind(move || main());

        sys_common::cleanup();
        exit_code.unwrap_or(101) as isize
    }
}

#[cfg(not(test))]
#[lang = "start"]
fn lang_start<T: crate::process::Termination + 'static>
    (main: fn() -> T, argc: isize, argv: *const *const u8) -> isize {
    lang_start_internal(&move || main().report(), argc, argv)
}
<commit_msg>remove stray change<commit_after>//! Runtime services
//!
//! The `rt` module provides a narrow set of runtime services,
//! including the global heap (exported in `heap`) and unwinding and
//! backtrace support. The APIs in this module are highly unstable,
//! and should be considered as private implementation details for the
//! time being.

#![unstable(feature = "rt",
            reason = "this public module should not exist and is highly likely \
                      to disappear",
            issue = "0")]
#![doc(hidden)]

// Re-export some of our utilities which are expected by other crates.
pub use crate::panicking::{begin_panic, begin_panic_fmt, update_panic_count};

// To reduce the generated code of the new `lang_start`, this function is doing
// the real work.
#[cfg(not(test))]
fn lang_start_internal(main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe),
                       argc: isize, argv: *const *const u8) -> isize {
    use crate::panic;
    use crate::sys;
    use crate::sys_common;
    use crate::sys_common::thread_info;
    use crate::thread::Thread;

    sys::init();

    unsafe {
        let main_guard = sys::thread::guard::init();
        sys::stack_overflow::init();

        // Next, set up the current Thread with the guard information we just
        // created. Note that this isn't necessary in general for new threads,
        // but we just do this to name the main thread and to give it correct
        // info about the stack bounds.
        let thread = Thread::new(Some("main".to_owned()));
        thread_info::set(main_guard, thread);

        // Store our args if necessary in a squirreled away location
        sys::args::init(argc, argv);

        // Let's run some code!
        #[cfg(feature = "backtrace")]
        let exit_code = panic::catch_unwind(|| {
            sys_common::backtrace::__rust_begin_short_backtrace(move || main())
        });
        #[cfg(not(feature = "backtrace"))]
        let exit_code = panic::catch_unwind(move || main());

        sys_common::cleanup();
        exit_code.unwrap_or(101) as isize
    }
}

#[cfg(not(test))]
#[lang = "start"]
fn lang_start<T: crate::process::Termination + 'static>
    (main: fn() -> T, argc: isize, argv: *const *const u8) -> isize
{
    lang_start_internal(&move || main().report(), argc, argv)
}
<|endoftext|>


<commit_before>
use image::{
    GenericImage,
    GrayImage,
    ImageBuffer,
    Luma
};

/// Returns the cumulative histogram of grayscale values in an 8bpp
/// grayscale image
fn cumulative_histogram<I: GenericImage<Pixel=Luma<u8>> + 'static>
    (image: &I) -> [i32;256] {

    let mut hist = [0i32;256];

    for pix in image.pixels() {
        hist[pix.2[0] as usize] += 1;
    }

    for i in 1..hist.len() {
        hist[i] += hist[i - 1];
    }

    hist
}

/// Equalises the histogram of an 8bpp grayscale image in place
/// https://en.wikipedia.org/wiki/Histogram_equalization
pub fn equalize_histogram_mut<I: GenericImage<Pixel=Luma<u8>> + 'static>
    (image: &mut I) {

    let hist = cumulative_histogram(image);
    let total = hist[255] as f32;

    for y in 0..image.height() {
        for x in 0..image.width() {
            let original = image.get_pixel(x, y)[0] as usize;
            if original != 0 {
            println!("Original: {}", original);
            }

            let fraction = hist[original] as f32 / total;
            let out = f32::min(255f32, 255f32 * (hist[original] as f32 / total));
            image.put_pixel(x, y, Luma([out as u8]));
        }
    }
}

/// Equalises the histogram of an 8bpp grayscale image
/// https://en.wikipedia.org/wiki/Histogram_equalization
pub fn equalize_histogram<I: GenericImage<Pixel=Luma<u8>> + 'static>
    (image: &I) -> GrayImage {
    let mut out: GrayImage = ImageBuffer::new(image.width(), image.height());
    out.copy_from(image, 0, 0);
    equalize_histogram_mut(&mut out);
    out
}

#[cfg(test)]
mod test {

    use super::{cumulative_histogram};
    use image::{GrayImage,ImageBuffer};

    #[test]
    fn test_cumulative_histogram() {
        let image: GrayImage = ImageBuffer::from_raw(5, 1, vec![
            1u8, 2u8, 3u8, 2u8, 1u8]).unwrap();

        let hist = cumulative_histogram(&image);

        assert_eq!(hist[0], 0);
        assert_eq!(hist[1], 2);
        assert_eq!(hist[2], 4);
        assert_eq!(hist[3], 5);
        assert!(hist.iter().skip(4).all(|x| *x == 5));
    }
}
<commit_msg>Oops (remove spurious logging)<commit_after>
use image::{
    GenericImage,
    GrayImage,
    ImageBuffer,
    Luma
};

/// Returns the cumulative histogram of grayscale values in an 8bpp
/// grayscale image
fn cumulative_histogram<I: GenericImage<Pixel=Luma<u8>> + 'static>
    (image: &I) -> [i32;256] {

    let mut hist = [0i32;256];

    for pix in image.pixels() {
        hist[pix.2[0] as usize] += 1;
    }

    for i in 1..hist.len() {
        hist[i] += hist[i - 1];
    }

    hist
}

/// Equalises the histogram of an 8bpp grayscale image in place
/// https://en.wikipedia.org/wiki/Histogram_equalization
pub fn equalize_histogram_mut<I: GenericImage<Pixel=Luma<u8>> + 'static>
    (image: &mut I) {

    let hist = cumulative_histogram(image);
    let total = hist[255] as f32;

    for y in 0..image.height() {
        for x in 0..image.width() {
            let original = image.get_pixel(x, y)[0] as usize;
            let fraction = hist[original] as f32 / total;
            let out = f32::min(255f32, 255f32 * (hist[original] as f32 / total));
            image.put_pixel(x, y, Luma([out as u8]));
        }
    }
}

/// Equalises the histogram of an 8bpp grayscale image
/// https://en.wikipedia.org/wiki/Histogram_equalization
pub fn equalize_histogram<I: GenericImage<Pixel=Luma<u8>> + 'static>
    (image: &I) -> GrayImage {
    let mut out: GrayImage = ImageBuffer::new(image.width(), image.height());
    out.copy_from(image, 0, 0);
    equalize_histogram_mut(&mut out);
    out
}

#[cfg(test)]
mod test {

    use super::{cumulative_histogram};
    use image::{GrayImage,ImageBuffer};

    #[test]
    fn test_cumulative_histogram() {
        let image: GrayImage = ImageBuffer::from_raw(5, 1, vec![
            1u8, 2u8, 3u8, 2u8, 1u8]).unwrap();

        let hist = cumulative_histogram(&image);

        assert_eq!(hist[0], 0);
        assert_eq!(hist[1], 2);
        assert_eq!(hist[2], 4);
        assert_eq!(hist[3], 5);
        assert!(hist.iter().skip(4).all(|x| *x == 5));
    }
}
<|endoftext|>


<commit_before>#![crate_id="cargo"]
#![crate_type="rlib"]

#![feature(macro_rules, phase)]

extern crate debug;
extern crate term;
extern crate url;
extern crate serialize;
extern crate semver;
extern crate toml;

#[phase(plugin, link)]
extern crate hammer;

#[phase(plugin, link)]
extern crate log;

#[cfg(test)]
extern crate hamcrest;

use serialize::{Decoder, Encoder, Decodable, Encodable, json};
use std::io;
use std::io::{stdout, stderr};
use std::io::stdio::{stdout_raw, stderr_raw};
use hammer::{Flags, decode_args, usage};

use core::{Shell, MultiShell, ShellConfig};
use term::color::{BLACK};

pub use util::{CargoError, CliError, CliResult, human};

macro_rules! some(
    ($e:expr) => (
        match $e {
            Some(e) => e,
            None => return None
        }
    )
)

// Added so that the try! macro below can refer to cargo::util, while
// other external importers of this macro can use it as well.
//
// "Hygiene strikes again" - @acrichton
mod cargo {
    pub use super::util;
}

#[macro_export]
macro_rules! try (
    ($expr:expr) => ({
        use cargo::util::FromError;
        match $expr.map_err(FromError::from_error) {
            Ok(val) => val,
            Err(err) => return Err(err)
        }
    })
)

macro_rules! raw_try (
    ($expr:expr) => ({
        match $expr {
            Ok(val) => val,
            Err(err) => return Err(err)
        }
    })
)

pub mod core;
pub mod ops;
pub mod sources;
pub mod util;

trait RepresentsJSON : Decodable<json::Decoder, json::DecoderError> {}
impl<T: Decodable<json::Decoder, json::DecoderError>> RepresentsJSON for T {}

#[deriving(Decodable)]
pub struct NoFlags;

hammer_config!(NoFlags)

#[deriving(Decodable)]
pub struct GlobalFlags {
    verbose: bool,
    help: bool,
    rest: Vec<String>
}

hammer_config!(GlobalFlags |c| {
    c.short("verbose", 'v').short("help", 'h')
})

pub fn execute_main<'a,
                    T: Flags,
                    U: RepresentsJSON,
                    V: Encodable<json::Encoder<'a>, io::IoError>>(
                        exec: fn(T, U, &mut MultiShell) -> CliResult<Option<V>>)
{
    fn call<'a,
            T: Flags,
            U: RepresentsJSON,
            V: Encodable<json::Encoder<'a>, io::IoError>>(
                exec: fn(T, U, &mut MultiShell) -> CliResult<Option<V>>,
                shell: &mut MultiShell,
                args: &[String])
        -> CliResult<Option<V>>
    {
        let flags = try!(flags_from_args::<T>(args));
        let json = try!(json_from_stdin::<U>());

        exec(flags, json, shell)
    }

    process::<T, V>(|rest, shell| call(exec, shell, rest));
}

pub fn execute_main_without_stdin<'a,
                                  T: Flags,
                                  V: Encodable<json::Encoder<'a>, io::IoError>>(
                                      exec: fn(T, &mut MultiShell) -> CliResult<Option<V>>)
{
    fn call<'a,
            T: Flags,
            V: Encodable<json::Encoder<'a>, io::IoError>>(
                exec: fn(T, &mut MultiShell) -> CliResult<Option<V>>,
                shell: &mut MultiShell,
                args: &[String])
        -> CliResult<Option<V>>
    {
        let flags = try!(flags_from_args::<T>(args));
        exec(flags, shell)
    }

    process::<T, V>(|rest, shell| call(exec, shell, rest));
}

fn process<'a,
           T: Flags,
           V: Encodable<json::Encoder<'a>, io::IoError>>(
               callback: |&[String], &mut MultiShell| -> CliResult<Option<V>>) {

    match global_flags() {
        Err(e) => handle_error(e, &mut shell(false)),
        Ok(val) => {
            let mut shell = shell(val.verbose);

            if val.help {
                let (desc, options) = usage::<T>(true);

                desc.map(|d| println!("{}\n", d));

                println!("Options:\n");

                print!("{}", options);

                let (_, options) = usage::<GlobalFlags>(false);
                print!("{}", options);
            } else {
                process_executed(callback(val.rest.as_slice(), &mut shell), &mut shell)
            }
        }
    }
}

pub fn process_executed<'a,
                        T: Encodable<json::Encoder<'a>, io::IoError>>(
                            result: CliResult<Option<T>>,
                            shell: &mut MultiShell)
{
    match result {
        Err(e) => handle_error(e, shell),
        Ok(encodable) => {
            encodable.map(|encodable| {
                let encoded = json::Encoder::str_encode(&encodable);
                println!("{}", encoded);
            });
        }
    }
}

pub fn shell(verbose: bool) -> MultiShell {
    let tty = stderr_raw().isatty();
    let stderr = box stderr() as Box<Writer>;

    let config = ShellConfig { color: true, verbose: verbose, tty: tty };
    let err = Shell::create(stderr, config);

    let tty = stdout_raw().isatty();
    let stdout = box stdout() as Box<Writer>;

    let config = ShellConfig { color: true, verbose: verbose, tty: tty };
    let out = Shell::create(stdout, config);

    MultiShell::new(out, err, verbose)
}

pub fn handle_error(err: CliError, shell: &mut MultiShell) {
    log!(4, "handle_error; err={}", err);

    let CliError { error, exit_code, unknown, .. } = err;

    if unknown {
        let _ = shell.error("An unknown error occurred");
    } else {
        let _ = shell.error(error.to_str());
    }

    if error.cause().is_some() {
        let _ = shell.concise(|shell| {
            shell.err().say("\nTo learn more, run the command again with --verbose.", BLACK)
        });
    }

    let _ = shell.verbose(|shell| {
        let _ = handle_cause(error, shell);
        Ok(())
      });

    std::os::set_exit_status(exit_code as int);
}

fn handle_cause(err: &CargoError, shell: &mut MultiShell) {
    let _ = shell.err().say("\nCaused by:", BLACK);
    let _ = shell.err().say(format!("  {}", err.description()), BLACK);

    err.cause().map(|e| handle_cause(e, shell));
}

fn args() -> Vec<String> {
    std::os::args()
}

fn flags_from_args<T: Flags>(args: &[String]) -> CliResult<T> {
    decode_args(args).map_err(|e| {
        CliError::new(e.message, 1)
    })
}

fn global_flags() -> CliResult<GlobalFlags> {
    decode_args(args().tail()).map_err(|e| {
        CliError::new(e.message, 1)
    })
}

fn json_from_stdin<T: RepresentsJSON>() -> CliResult<T> {
    let mut reader = io::stdin();
    let input = try!(reader.read_to_str().map_err(|_| {
        CliError::new("Standard in did not exist or was not UTF-8", 1)
    }));

    let json = try!(json::from_str(input.as_slice()).map_err(|_| {
        CliError::new("Could not parse standard in as JSON", 1)
    }));
    let mut decoder = json::Decoder::new(json);

    Decodable::decode(&mut decoder).map_err(|_| {
        CliError::new("Could not process standard in as input", 1)
    })
}
<commit_msg>auto merge of #109 : steveklabnik/cargo/json, r=alexcrichton<commit_after>#![crate_id="cargo"]
#![crate_type="rlib"]

#![feature(macro_rules, phase)]

extern crate debug;
extern crate term;
extern crate url;
extern crate serialize;
extern crate semver;
extern crate toml;

#[phase(plugin, link)]
extern crate hammer;

#[phase(plugin, link)]
extern crate log;

#[cfg(test)]
extern crate hamcrest;

use serialize::{Decoder, Encoder, Decodable, Encodable, json};
use std::io;
use std::io::{stdout, stderr};
use std::io::stdio::{stdout_raw, stderr_raw};
use hammer::{Flags, decode_args, usage};

use core::{Shell, MultiShell, ShellConfig};
use term::color::{BLACK};

pub use util::{CargoError, CliError, CliResult, human};

macro_rules! some(
    ($e:expr) => (
        match $e {
            Some(e) => e,
            None => return None
        }
    )
)

// Added so that the try! macro below can refer to cargo::util, while
// other external importers of this macro can use it as well.
//
// "Hygiene strikes again" - @acrichton
mod cargo {
    pub use super::util;
}

#[macro_export]
macro_rules! try (
    ($expr:expr) => ({
        use cargo::util::FromError;
        match $expr.map_err(FromError::from_error) {
            Ok(val) => val,
            Err(err) => return Err(err)
        }
    })
)

macro_rules! raw_try (
    ($expr:expr) => ({
        match $expr {
            Ok(val) => val,
            Err(err) => return Err(err)
        }
    })
)

pub mod core;
pub mod ops;
pub mod sources;
pub mod util;

trait RepresentsJSON : Decodable<json::Decoder, json::DecoderError> {}
impl<T: Decodable<json::Decoder, json::DecoderError>> RepresentsJSON for T {}

#[deriving(Decodable)]
pub struct NoFlags;

hammer_config!(NoFlags)

#[deriving(Decodable)]
pub struct GlobalFlags {
    verbose: bool,
    help: bool,
    rest: Vec<String>
}

hammer_config!(GlobalFlags |c| {
    c.short("verbose", 'v').short("help", 'h')
})

pub fn execute_main<'a,
                    T: Flags,
                    U: RepresentsJSON,
                    V: Encodable<json::Encoder<'a>, io::IoError>>(
                        exec: fn(T, U, &mut MultiShell) -> CliResult<Option<V>>)
{
    fn call<'a,
            T: Flags,
            U: RepresentsJSON,
            V: Encodable<json::Encoder<'a>, io::IoError>>(
                exec: fn(T, U, &mut MultiShell) -> CliResult<Option<V>>,
                shell: &mut MultiShell,
                args: &[String])
        -> CliResult<Option<V>>
    {
        let flags = try!(flags_from_args::<T>(args));
        let json = try!(json_from_stdin::<U>());

        exec(flags, json, shell)
    }

    process::<T, V>(|rest, shell| call(exec, shell, rest));
}

pub fn execute_main_without_stdin<'a,
                                  T: Flags,
                                  V: Encodable<json::Encoder<'a>, io::IoError>>(
                                      exec: fn(T, &mut MultiShell) -> CliResult<Option<V>>)
{
    fn call<'a,
            T: Flags,
            V: Encodable<json::Encoder<'a>, io::IoError>>(
                exec: fn(T, &mut MultiShell) -> CliResult<Option<V>>,
                shell: &mut MultiShell,
                args: &[String])
        -> CliResult<Option<V>>
    {
        let flags = try!(flags_from_args::<T>(args));
        exec(flags, shell)
    }

    process::<T, V>(|rest, shell| call(exec, shell, rest));
}

fn process<'a,
           T: Flags,
           V: Encodable<json::Encoder<'a>, io::IoError>>(
               callback: |&[String], &mut MultiShell| -> CliResult<Option<V>>) {

    match global_flags() {
        Err(e) => handle_error(e, &mut shell(false)),
        Ok(val) => {
            let mut shell = shell(val.verbose);

            if val.help {
                let (desc, options) = usage::<T>(true);

                desc.map(|d| println!("{}\n", d));

                println!("Options:\n");

                print!("{}", options);

                let (_, options) = usage::<GlobalFlags>(false);
                print!("{}", options);
            } else {
                process_executed(callback(val.rest.as_slice(), &mut shell), &mut shell)
            }
        }
    }
}

pub fn process_executed<'a,
                        T: Encodable<json::Encoder<'a>, io::IoError>>(
                            result: CliResult<Option<T>>,
                            shell: &mut MultiShell)
{
    match result {
        Err(e) => handle_error(e, shell),
        Ok(encodable) => {
            encodable.map(|encodable| {
                let encoded = json::encode(&encodable);
                println!("{}", encoded);
            });
        }
    }
}

pub fn shell(verbose: bool) -> MultiShell {
    let tty = stderr_raw().isatty();
    let stderr = box stderr() as Box<Writer>;

    let config = ShellConfig { color: true, verbose: verbose, tty: tty };
    let err = Shell::create(stderr, config);

    let tty = stdout_raw().isatty();
    let stdout = box stdout() as Box<Writer>;

    let config = ShellConfig { color: true, verbose: verbose, tty: tty };
    let out = Shell::create(stdout, config);

    MultiShell::new(out, err, verbose)
}

pub fn handle_error(err: CliError, shell: &mut MultiShell) {
    log!(4, "handle_error; err={}", err);

    let CliError { error, exit_code, unknown, .. } = err;

    if unknown {
        let _ = shell.error("An unknown error occurred");
    } else {
        let _ = shell.error(error.to_str());
    }

    if error.cause().is_some() {
        let _ = shell.concise(|shell| {
            shell.err().say("\nTo learn more, run the command again with --verbose.", BLACK)
        });
    }

    let _ = shell.verbose(|shell| {
        let _ = handle_cause(error, shell);
        Ok(())
      });

    std::os::set_exit_status(exit_code as int);
}

fn handle_cause(err: &CargoError, shell: &mut MultiShell) {
    let _ = shell.err().say("\nCaused by:", BLACK);
    let _ = shell.err().say(format!("  {}", err.description()), BLACK);

    err.cause().map(|e| handle_cause(e, shell));
}

fn args() -> Vec<String> {
    std::os::args()
}

fn flags_from_args<T: Flags>(args: &[String]) -> CliResult<T> {
    decode_args(args).map_err(|e| {
        CliError::new(e.message, 1)
    })
}

fn global_flags() -> CliResult<GlobalFlags> {
    decode_args(args().tail()).map_err(|e| {
        CliError::new(e.message, 1)
    })
}

fn json_from_stdin<T: RepresentsJSON>() -> CliResult<T> {
    let mut reader = io::stdin();
    let input = try!(reader.read_to_str().map_err(|_| {
        CliError::new("Standard in did not exist or was not UTF-8", 1)
    }));

    let json = try!(json::from_str(input.as_slice()).map_err(|_| {
        CliError::new("Could not parse standard in as JSON", 1)
    }));
    let mut decoder = json::Decoder::new(json);

    Decodable::decode(&mut decoder).map_err(|_| {
        CliError::new("Could not process standard in as input", 1)
    })
}
<|endoftext|>


<commit_before>#[cfg(feature = "with-constraint")]
use constraints;

use serde::{Deserialize, Serialize};
use std::collections::{BTreeSet, HashMap};
use std::fmt::{Debug, Display, Formatter, Result};
use std::iter::{Extend, FromIterator};

/// A type must implement BindingsValue in order to be used as the value for some variable.
pub trait BindingsValue
    : Clone + Debug + Default + Deserialize + Display + Eq + PartialEq + PartialOrd + Serialize
    {
    /// Construct a BindingsValue variable using the specified string as it's name
    fn variable(_s: &String) -> Option<Self> {
        None
    }
    /// Extract the name of this BindingsValue variable (if it is a variable)
    fn to_variable(&self) -> Option<String> {
        None
    }
}

/// Bindings is used for storing variables and operating on variables and their bindings.
#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct Bindings<T: BindingsValue> {
    #[serde(default)]
    data: HashMap<String, T>,
    #[serde(default)]
    equivalences: HashMap<String, BTreeSet<String>>,
}

impl<T: BindingsValue> PartialEq for Bindings<T> {
    fn eq(&self, other: &Bindings<T>) -> bool {
        self.data.eq(&other.data) && self.equivalences.eq(&other.equivalences)
    }
}
impl<T: BindingsValue> Eq for Bindings<T> {}

impl<T: BindingsValue> Default for Bindings<T> {
    fn default() -> Self {
        Bindings {
            data: HashMap::new(),
            equivalences: HashMap::new(),
        }
    }
}

impl<T: BindingsValue> Bindings<T> {
    pub fn new() -> Bindings<T> {
        Bindings::default()
    }

    pub fn len(&self) -> usize {
        self.data.len()
    }

    pub fn new_from_vec(data: Vec<(String, T)>) -> Bindings<T> {
        data.into_iter().collect()
    }

    pub fn has_binding(&self, variable: &String) -> bool {
        self.data.contains_key(variable)
    }

    pub fn set_binding(&self, variable: &String, val: T) -> Bindings<T> {
        let mut bindings_copy = self.clone();

        bindings_copy.set_binding_mut(variable, val);

        bindings_copy
    }

    pub fn set_binding_mut(&mut self, variable: &String, val: T) {
        self.ensure_equivalence_exists_mut(variable);

        if let Some(variable2) = val.to_variable() {
            self.add_equivalence(variable, &variable2);
        } else {
            for equivalent_variable in self.equivalences.get(variable).unwrap().iter() {
                self.data.insert(equivalent_variable.clone(), val.clone());
            }
        }
    }

    fn add_equivalence(&mut self, variable: &String, variable2: &String) {
        self.ensure_equivalence_exists_mut(&variable2);
        self.merge_equivalences_mut(variable, &variable2);
    }

    fn ensure_equivalence_exists_mut(&mut self, variable: &String) {
        if !self.equivalences.contains_key(variable) {
            self.equivalences.insert(variable.clone(),
                                     vec![variable.clone()].into_iter().collect());
        }
    }

    fn merge_equivalences_mut(&mut self, variable: &String, variable2: &String) {
        let mut merge = self.equivalences.get(variable).cloned().unwrap();
        merge.extend(self.equivalences.get(variable2).cloned().unwrap());

        self.equivalences.insert(variable.clone(), merge.clone());
        self.equivalences.insert(variable2.clone(), merge);
    }

    pub fn get_binding(&self, variable: &String) -> Option<T> {
        match self.data.get(variable) {
            Some(val) => Some(val.clone()),
            None => None,
        }
    }

    pub fn update_bindings(&self, variable: &String, value: &T) -> Option<Self> {
        // If we are setting a variable to itself, then do nothing
        if Some(variable.clone()) == value.to_variable() {
            return Some(self.clone());
        }
        match self.get_binding(&variable) {
            Some(ref val) if val == value => Some(self.clone()),
            Some(_) => None,
            None => Some(self.set_binding(variable, value.clone())),
        }
    }

    pub fn merge(&self, other: &Self) -> Self {
        let mut bindings = self.clone();

        // Merge in equivalences
        for (ref key, ref equivalences) in other.equivalences.iter() {
            for equivalent_key in equivalences.iter() {
                bindings.ensure_equivalence_exists_mut(key);
                bindings.add_equivalence(key, equivalent_key);
            }
        }

        // Merge in values
        for (key, value) in other.data.iter() {
            bindings.set_binding_mut(&key, value.clone())
        }

        bindings
    }

    pub fn equivalences_string(&self) -> String {
        let equivalent_v: Vec<String> = self.equivalences.iter().map(|(key, value)| format!("{} => {:?}", key, value)).collect();
        equivalent_v.join(",")
    }
}

impl<T: BindingsValue> FromIterator<(String, T)> for Bindings<T> {
    fn from_iter<I: IntoIterator<Item = (String, T)>>(iter: I) -> Bindings<T> {
        let mut bindings: Bindings<T> = Bindings::new();
        for (key, value) in iter {
            bindings.set_binding_mut(&key, value);
        }
        bindings
    }
}

impl<T: BindingsValue> Extend<(String, T)> for Bindings<T> {
    fn extend<It>(&mut self, iter: It)
        where It: IntoIterator<Item = (String, T)>
    {
        for (key, value) in iter {
            self.set_binding_mut(&key, value);
        }
    }
}

impl<T: BindingsValue> Display for Bindings<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        try!(write!(f, "("));
        let mut sorted_keys: Vec<String> = self.data.keys().cloned().collect();
        sorted_keys.sort();
        for key in sorted_keys.into_iter() {
            let ref val = self.data[&key];
            try!(write!(f, "{} => {}, ", key, val));
        }
        try!(write!(f, "Equivalences: {}", self.equivalences_string()));
        write!(f, ")")
    }
}

/// A type must implement the Unify trait for it to be unifiable -  this only requirement for a data structure
/// that the algorithms in this library operate on.
pub trait Unify<T: BindingsValue>
    : Clone + Debug + Display + Eq + Serialize + Deserialize + PartialEq {
    /// Check if this structure can be unified with another of the same type.
    fn unify(&self, &Self, &Bindings<T>) -> Option<Bindings<T>>;
    /// Given some bindings, construct a new instance with any variables replaced by their values
    fn apply_bindings(&self, &Bindings<T>) -> Option<Self>;
    /// Return all variables in this tructure
    fn variables(&self) -> Vec<String>;
    /// Rename any variables in this structure with another variable name
    fn rename_variables(&self, &HashMap<String, String>) -> Self;
    /// Return a 'nil' sentinel value unique to this type of structure
    fn nil() -> Self;
}

/// A type that implements Operation constructs new Unifys from existing Unifys that match it's input patterns.
pub trait Operation<T: BindingsValue, U: Unify<T>>
    : Clone + Debug + Display + Eq + PartialEq + Deserialize + Serialize {
    // NOTE: replace constraints with validate_bindings?
    #[cfg(feature = "with-constraint")]
    fn constraints<'a>(&'a self) -> Vec<&'a constraints::Constraint>;

    /// Creates a new instance of this Operation where all variables are unique
    fn snowflake(&self, String) -> Self;

    /// Return a vector of input patterns that must be unified with in order to apply this Operation.
    fn input_patterns(&self) -> Vec<U> {
        Vec::new()
    }

    /// Given some bindings, construct a set of output patterns
    fn apply_match(&self, _bindings: &Bindings<T>) -> Option<Vec<U>>;

    /// Given some bindings, construct a set of input patterns that would match
    fn r_apply_match(&self, _fact: &U) -> Option<(Vec<U>, Bindings<T>)>;
}

#[cfg(test)]
mod tests;
<commit_msg>More docs updates<commit_after>#[cfg(feature = "with-constraint")]
use constraints;

use serde::{Deserialize, Serialize};
use std::collections::{BTreeSet, HashMap};
use std::fmt::{Debug, Display, Formatter, Result};
use std::iter::{Extend, FromIterator};

/// A type must implement BindingsValue in order to be used as the value for some variable.
pub trait BindingsValue
    : Clone + Debug + Default + Deserialize + Display + Eq + PartialEq + PartialOrd + Serialize
    {
    /// Construct a BindingsValue variable using the specified string as it's name
    fn variable(_s: &String) -> Option<Self> {
        None
    }
    /// Extract the name of this BindingsValue variable (if it is a variable)
    fn to_variable(&self) -> Option<String> {
        None
    }
}

/// Bindings is used for storing variables and operating on variables and their bindings.
#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct Bindings<T: BindingsValue> {
    #[serde(default)]
    data: HashMap<String, T>,
    #[serde(default)]
    equivalences: HashMap<String, BTreeSet<String>>,
}

impl<T: BindingsValue> PartialEq for Bindings<T> {
    fn eq(&self, other: &Bindings<T>) -> bool {
        self.data.eq(&other.data) && self.equivalences.eq(&other.equivalences)
    }
}
impl<T: BindingsValue> Eq for Bindings<T> {}

impl<T: BindingsValue> Default for Bindings<T> {
    fn default() -> Self {
        Bindings {
            data: HashMap::new(),
            equivalences: HashMap::new(),
        }
    }
}

impl<T: BindingsValue> Bindings<T> {
    pub fn new() -> Bindings<T> {
        Bindings::default()
    }

    pub fn len(&self) -> usize {
        self.data.len()
    }

    pub fn new_from_vec(data: Vec<(String, T)>) -> Bindings<T> {
        data.into_iter().collect()
    }

    pub fn has_binding(&self, variable: &String) -> bool {
        self.data.contains_key(variable)
    }

    pub fn set_binding(&self, variable: &String, val: T) -> Bindings<T> {
        let mut bindings_copy = self.clone();

        bindings_copy.set_binding_mut(variable, val);

        bindings_copy
    }

    pub fn set_binding_mut(&mut self, variable: &String, val: T) {
        self.ensure_equivalence_exists_mut(variable);

        if let Some(variable2) = val.to_variable() {
            self.add_equivalence(variable, &variable2);
        } else {
            for equivalent_variable in self.equivalences.get(variable).unwrap().iter() {
                self.data.insert(equivalent_variable.clone(), val.clone());
            }
        }
    }

    fn add_equivalence(&mut self, variable: &String, variable2: &String) {
        self.ensure_equivalence_exists_mut(&variable2);
        self.merge_equivalences_mut(variable, &variable2);
    }

    fn ensure_equivalence_exists_mut(&mut self, variable: &String) {
        if !self.equivalences.contains_key(variable) {
            self.equivalences.insert(variable.clone(),
                                     vec![variable.clone()].into_iter().collect());
        }
    }

    fn merge_equivalences_mut(&mut self, variable: &String, variable2: &String) {
        let mut merge = self.equivalences.get(variable).cloned().unwrap();
        merge.extend(self.equivalences.get(variable2).cloned().unwrap());

        self.equivalences.insert(variable.clone(), merge.clone());
        self.equivalences.insert(variable2.clone(), merge);
    }

    pub fn get_binding(&self, variable: &String) -> Option<T> {
        match self.data.get(variable) {
            Some(val) => Some(val.clone()),
            None => None,
        }
    }

    pub fn update_bindings(&self, variable: &String, value: &T) -> Option<Self> {
        // If we are setting a variable to itself, then do nothing
        if Some(variable.clone()) == value.to_variable() {
            return Some(self.clone());
        }
        match self.get_binding(&variable) {
            Some(ref val) if val == value => Some(self.clone()),
            Some(_) => None,
            None => Some(self.set_binding(variable, value.clone())),
        }
    }

    pub fn merge(&self, other: &Self) -> Self {
        let mut bindings = self.clone();

        // Merge in equivalences
        for (ref key, ref equivalences) in other.equivalences.iter() {
            for equivalent_key in equivalences.iter() {
                bindings.ensure_equivalence_exists_mut(key);
                bindings.add_equivalence(key, equivalent_key);
            }
        }

        // Merge in values
        for (key, value) in other.data.iter() {
            bindings.set_binding_mut(&key, value.clone())
        }

        bindings
    }

    pub fn equivalences_string(&self) -> String {
        let equivalent_v: Vec<String> = self.equivalences.iter().map(|(key, value)| format!("{} => {:?}", key, value)).collect();
        equivalent_v.join(",")
    }
}

impl<T: BindingsValue> FromIterator<(String, T)> for Bindings<T> {
    fn from_iter<I: IntoIterator<Item = (String, T)>>(iter: I) -> Bindings<T> {
        let mut bindings: Bindings<T> = Bindings::new();
        for (key, value) in iter {
            bindings.set_binding_mut(&key, value);
        }
        bindings
    }
}

impl<T: BindingsValue> Extend<(String, T)> for Bindings<T> {
    fn extend<It>(&mut self, iter: It)
        where It: IntoIterator<Item = (String, T)>
    {
        for (key, value) in iter {
            self.set_binding_mut(&key, value);
        }
    }
}

impl<T: BindingsValue> Display for Bindings<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        try!(write!(f, "("));
        let mut sorted_keys: Vec<String> = self.data.keys().cloned().collect();
        sorted_keys.sort();
        for key in sorted_keys.into_iter() {
            let ref val = self.data[&key];
            try!(write!(f, "{} => {}, ", key, val));
        }
        try!(write!(f, "Equivalences: {}", self.equivalences_string()));
        write!(f, ")")
    }
}

/// A type must implement the Unify trait for it to be unifiable -  this only requirement for a data structure
/// that the algorithms in this library operate on.
pub trait Unify<T: BindingsValue>
    : Clone + Debug + Display + Eq + Serialize + Deserialize + PartialEq {
    /// Check if this structure can be unified with another of the same type.
    fn unify(&self, &Self, &Bindings<T>) -> Option<Bindings<T>>;

    /// Given some bindings, construct a new instance with any variables replaced by their values
    fn apply_bindings(&self, &Bindings<T>) -> Option<Self>;

    /// Return all variables in this tructure
    fn variables(&self) -> Vec<String>;

    /// Rename any variables in this structure with another variable name
    fn rename_variables(&self, &HashMap<String, String>) -> Self;

    /// Return a 'nil' sentinel value unique to this type of structure
    fn nil() -> Self;
}

/// A type that implements Operation constructs new Unifys from existing Unifys that match it's input patterns.
pub trait Operation<T: BindingsValue, U: Unify<T>>
    : Clone + Debug + Display + Eq + PartialEq + Deserialize + Serialize {
    // NOTE: replace constraints with validate_bindings?
    #[cfg(feature = "with-constraint")]
    fn constraints<'a>(&'a self) -> Vec<&'a constraints::Constraint>;

    /// Creates a new instance of this Operation where all variables are unique
    fn snowflake(&self, String) -> Self;

    /// Return a vector of input patterns that must be unified with in order to apply this Operation.
    fn input_patterns(&self) -> Vec<U> {
        Vec::new()
    }

    /// Given some bindings, construct a set of output patterns
    fn apply_match(&self, _bindings: &Bindings<T>) -> Option<Vec<U>>;

    /// Given some bindings, construct a set of input patterns that would match
    fn r_apply_match(&self, _fact: &U) -> Option<(Vec<U>, Bindings<T>)>;
}

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>use crossbeam_deque::{Deque, Stealer, Steal};

use std::thread::yield_now;
use std::sync::{Mutex, TryLockError};
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering};

use iter::ParallelIterator;
use iter::plumbing::{UnindexedConsumer, UnindexedProducer, bridge_unindexed, Folder};
use current_num_threads;

/// Conversion trait to convert an `Iterator` to a `ParallelIterator`.
///
/// This needs to be distinct from `IntoParallelIterator` because that trait is already implemented
/// on a few `Iterator`s, like `std::ops::Range`.
pub trait ParallelBridge {
    /// What is the type of the output `ParallelIterator`?
    type Iter: ParallelIterator<Item = Self::Item>;

    /// What is the `Item` of the output `ParallelIterator`?
    type Item: Send;

    /// Convert this type to a `ParallelIterator`.
    fn par_bridge(self) -> Self::Iter;
}

impl<T: Iterator + Send> ParallelBridge for T
    where T::Item: Send
{
    type Iter = IterParallel<T>;
    type Item = T::Item;

    fn par_bridge(self) -> Self::Iter {
        IterParallel {
            iter: self,
        }
    }
}

/// `IterParallel` is a parallel iterator that wraps a sequential iterator.
#[derive(Debug)]
pub struct IterParallel<Iter> {
    iter: Iter,
}

impl<Iter: Iterator + Send> ParallelIterator for IterParallel<Iter>
    where Iter::Item: Send
{
    type Item = Iter::Item;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let split_count = AtomicUsize::new(current_num_threads());
        let deque = Deque::new();
        let stealer = deque.stealer();
        let done = AtomicBool::new(false);
        let iter = Mutex::new((self.iter, deque));

        bridge_unindexed(IterParallelProducer {
            split_count: &split_count,
            done: &done,
            iter: &iter,
            items: stealer,
        }, consumer)
    }
}

struct IterParallelProducer<'a, Iter: Iterator + 'a> {
    split_count: &'a AtomicUsize,
    done: &'a AtomicBool,
    iter: &'a Mutex<(Iter, Deque<Iter::Item>)>,
    items: Stealer<Iter::Item>,
}

// manual clone because T doesn't need to be Clone, but the derive assumes it should be
impl<'a, Iter: Iterator + 'a> Clone for IterParallelProducer<'a, Iter> {
    fn clone(&self) -> Self {
        IterParallelProducer {
            split_count: self.split_count,
            done: self.done,
            iter: self.iter,
            items: self.items.clone(),
        }
    }
}

impl<'a, Iter: Iterator + Send + 'a> UnindexedProducer for IterParallelProducer<'a, Iter>
    where Iter::Item: Send
{
    type Item = Iter::Item;

    fn split(self) -> (Self, Option<Self>) {
        let mut count = self.split_count.load(Ordering::SeqCst);

        loop {
            let done = self.done.load(Ordering::SeqCst);
            match count.checked_sub(1) {
                Some(new_count) if !done => {
                    let last_count = self.split_count.compare_and_swap(count, new_count, Ordering::SeqCst);
                    if last_count == count {
                        return (self.clone(), Some(self));
                    } else {
                        count = last_count;
                    }
                }
                _ => {
                    return (self, None);
                }
            }
        }
    }

    fn fold_with<F>(self, mut folder: F) -> F
        where F: Folder<Self::Item>
    {
        loop {
            match self.items.steal() {
                Steal::Data(it) => {
                    folder = folder.consume(it);
                    if folder.full() {
                        return folder;
                    }
                }
                Steal::Empty => {
                    if self.done.load(Ordering::SeqCst) {
                        // the iterator is out of items, no use in continuing
                        return folder;
                    } else {
                        // our cache is out of items, time to load more from the iterator
                        match self.iter.try_lock() {
                            Ok(mut guard) => {
                                let count = current_num_threads();
                                let count = (count * count) * 2;

                                let (ref mut iter, ref deque) = *guard;

                                while deque.len() < count {
                                    if let Some(it) = iter.next() {
                                        deque.push(it);
                                    } else {
                                        self.done.store(true, Ordering::SeqCst);
                                        break;
                                    }
                                }
                            }
                            Err(TryLockError::WouldBlock) => {
                                // someone else has the mutex, just sit tight until it's ready
                                yield_now(); //TODO: use a thread=pool-aware yield? (#548)
                            }
                            Err(TryLockError::Poisoned(_)) => {
                                // any panics from other threads will have been caught by the pool,
                                // and will be re-thrown when joined - just exit
                                return folder;
                            }
                        }
                    }
                }
                Steal::Retry => (),
            }
        }
    }
}
<commit_msg>update docs for ParallelBridge and IterParallel<commit_after>use crossbeam_deque::{Deque, Stealer, Steal};

use std::thread::yield_now;
use std::sync::{Mutex, TryLockError};
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering};

use iter::ParallelIterator;
use iter::plumbing::{UnindexedConsumer, UnindexedProducer, bridge_unindexed, Folder};
use current_num_threads;

/// Conversion trait to convert an `Iterator` to a `ParallelIterator`.
///
/// This creates a "bridge" from a sequential iterator to a parallel one, by distributing its items
/// across the Rayon thread pool. This has the advantage of being able to parallelize just about
/// anything, but the resulting `ParallelIterator` can be less efficient than if you started with
/// `par_iter` instead. However, it can still be useful for iterators that are difficult to
/// parallelize by other means, like channels or file or network I/O.
///
/// The resulting iterator is not guaranteed to keep the order of the original iterator.
///
/// # Examples
///
/// To use this trait, take an existing `Iterator` and call `par_bridge` on it. After that, you can
/// use any of the `ParallelIterator` methods:
///
/// ```
/// use rayon::iter::ParallelBridge;
/// use rayon::prelude::ParallelIterator;
/// use std::sync::mpsc::channel;
///
/// let rx = {
///     let (tx, rx) = channel();
///
///     tx.send("one!");
///     tx.send("two!");
///     tx.send("three!");
///
///     rx
/// };
///
/// let mut output: Vec<&'static str> = rx.into_iter().par_bridge().collect();
/// output.sort_unstable();
///
/// assert_eq!(&*output, &["one!", "three!", "two!"]);
/// ```
pub trait ParallelBridge {
    /// What is the type of the output `ParallelIterator`?
    type Iter: ParallelIterator<Item = Self::Item>;

    /// What is the `Item` of the output `ParallelIterator`?
    type Item: Send;

    /// Convert this type to a `ParallelIterator`.
    fn par_bridge(self) -> Self::Iter;
}

impl<T: Iterator + Send> ParallelBridge for T
    where T::Item: Send
{
    type Iter = IterParallel<T>;
    type Item = T::Item;

    fn par_bridge(self) -> Self::Iter {
        IterParallel {
            iter: self,
        }
    }
}

/// `IterParallel` is a parallel iterator that wraps a sequential iterator.
///
/// This type is created when using the `par_bridge` method on `ParallelBridge`. See the
/// [`ParallelBridge`] documentation for details.
///
/// [`ParallelBridge`]: trait.ParallelBridge.html
#[derive(Debug)]
pub struct IterParallel<Iter> {
    iter: Iter,
}

impl<Iter: Iterator + Send> ParallelIterator for IterParallel<Iter>
    where Iter::Item: Send
{
    type Item = Iter::Item;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let split_count = AtomicUsize::new(current_num_threads());
        let deque = Deque::new();
        let stealer = deque.stealer();
        let done = AtomicBool::new(false);
        let iter = Mutex::new((self.iter, deque));

        bridge_unindexed(IterParallelProducer {
            split_count: &split_count,
            done: &done,
            iter: &iter,
            items: stealer,
        }, consumer)
    }
}

struct IterParallelProducer<'a, Iter: Iterator + 'a> {
    split_count: &'a AtomicUsize,
    done: &'a AtomicBool,
    iter: &'a Mutex<(Iter, Deque<Iter::Item>)>,
    items: Stealer<Iter::Item>,
}

// manual clone because T doesn't need to be Clone, but the derive assumes it should be
impl<'a, Iter: Iterator + 'a> Clone for IterParallelProducer<'a, Iter> {
    fn clone(&self) -> Self {
        IterParallelProducer {
            split_count: self.split_count,
            done: self.done,
            iter: self.iter,
            items: self.items.clone(),
        }
    }
}

impl<'a, Iter: Iterator + Send + 'a> UnindexedProducer for IterParallelProducer<'a, Iter>
    where Iter::Item: Send
{
    type Item = Iter::Item;

    fn split(self) -> (Self, Option<Self>) {
        let mut count = self.split_count.load(Ordering::SeqCst);

        loop {
            let done = self.done.load(Ordering::SeqCst);
            match count.checked_sub(1) {
                Some(new_count) if !done => {
                    let last_count = self.split_count.compare_and_swap(count, new_count, Ordering::SeqCst);
                    if last_count == count {
                        return (self.clone(), Some(self));
                    } else {
                        count = last_count;
                    }
                }
                _ => {
                    return (self, None);
                }
            }
        }
    }

    fn fold_with<F>(self, mut folder: F) -> F
        where F: Folder<Self::Item>
    {
        loop {
            match self.items.steal() {
                Steal::Data(it) => {
                    folder = folder.consume(it);
                    if folder.full() {
                        return folder;
                    }
                }
                Steal::Empty => {
                    if self.done.load(Ordering::SeqCst) {
                        // the iterator is out of items, no use in continuing
                        return folder;
                    } else {
                        // our cache is out of items, time to load more from the iterator
                        match self.iter.try_lock() {
                            Ok(mut guard) => {
                                let count = current_num_threads();
                                let count = (count * count) * 2;

                                let (ref mut iter, ref deque) = *guard;

                                while deque.len() < count {
                                    if let Some(it) = iter.next() {
                                        deque.push(it);
                                    } else {
                                        self.done.store(true, Ordering::SeqCst);
                                        break;
                                    }
                                }
                            }
                            Err(TryLockError::WouldBlock) => {
                                // someone else has the mutex, just sit tight until it's ready
                                yield_now(); //TODO: use a thread=pool-aware yield? (#548)
                            }
                            Err(TryLockError::Poisoned(_)) => {
                                // any panics from other threads will have been caught by the pool,
                                // and will be re-thrown when joined - just exit
                                return folder;
                            }
                        }
                    }
                }
                Steal::Retry => (),
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate session_types;

use std::thread::spawn;
use session_types::*;

// recv and assert a value, then close the channel
macro_rules! recv_assert_eq_close(
    ($e:expr, $rx:ident.recv())
        =>
    ({
        let (c, v) = $rx.recv();
        assert_eq!($e, v);
        c.close();
    })
);

#[test]
fn chan_select_hselect() {
    let (tcs, rcs) = session_channel();
    let (tcu, rcu) = session_channel();

    let receivers = vec!(rcs, rcu);

    tcs.send(1u64).close();

    let (ready, mut rest) = hselect(receivers);

    let (to_close, received) = ready.recv();
    assert_eq!(received, 1u64);
    to_close.close();

    tcu.send(2u64).close();

    rest
        .drain(..)
        .for_each(|r| {
            let (to_close, received) = r.recv();
            assert_eq!(received, 2u64);
            to_close.close()
        });
}

#[test]
fn chan_select_simple() {
    let (tcs, rcs) = session_channel();
    let (tcu, rcu) = session_channel();

    // Spawn threads
    send_str(tcs);

    // The lifetime of `sel` is reduced to the point where we call
    // `wait()`. This ensures we don't hold on to Chan references, but still
    // prevents using the channels the ChanSelect holds references to.
    let index = {
        let mut sel = ChanSelect::new();
        sel.add_recv(&rcs); // Assigned 0
        sel.add_recv(&rcu); // Assigned 1
        sel.wait() // Destroys the ChanSelect, releases references to
        // rcs and rcu
    };

    assert_eq!(0, index);
    recv_assert_eq_close!("Hello, World!".to_owned(), rcs.recv());

    let (tcs, rcs) = session_channel();

    send_usize(tcu);

    let index = {
        let mut sel = ChanSelect::new();
        sel.add_recv(&rcs);
        sel.add_recv(&rcu);
        sel.wait()
    };

    assert_eq!(1, index);
    recv_assert_eq_close!(42, rcu.recv());

    // Not really necessary for the test, just used to coerce the types of
    // tcs and rcs
    send_str(tcs);
    recv_assert_eq_close!("Hello, World!".to_owned(), rcs.recv());
}

// Utility functions

fn send_str(c: Chan<(), Send<String, Eps>>) {
    c.send("Hello, World!".to_string()).close();
}

fn send_usize(c: Chan<(), Send<usize, Eps>>) {
    c.send(42).close();
}
<commit_msg>Remove unused import<commit_after>extern crate session_types;

use session_types::*;

// recv and assert a value, then close the channel
macro_rules! recv_assert_eq_close(
    ($e:expr, $rx:ident.recv())
        =>
    ({
        let (c, v) = $rx.recv();
        assert_eq!($e, v);
        c.close();
    })
);

#[test]
fn chan_select_hselect() {
    let (tcs, rcs) = session_channel();
    let (tcu, rcu) = session_channel();

    let receivers = vec!(rcs, rcu);

    tcs.send(1u64).close();

    let (ready, mut rest) = hselect(receivers);

    let (to_close, received) = ready.recv();
    assert_eq!(received, 1u64);
    to_close.close();

    tcu.send(2u64).close();

    rest
        .drain(..)
        .for_each(|r| {
            let (to_close, received) = r.recv();
            assert_eq!(received, 2u64);
            to_close.close()
        });
}

#[test]
fn chan_select_simple() {
    let (tcs, rcs) = session_channel();
    let (tcu, rcu) = session_channel();

    // Spawn threads
    send_str(tcs);

    // The lifetime of `sel` is reduced to the point where we call
    // `wait()`. This ensures we don't hold on to Chan references, but still
    // prevents using the channels the ChanSelect holds references to.
    let index = {
        let mut sel = ChanSelect::new();
        sel.add_recv(&rcs); // Assigned 0
        sel.add_recv(&rcu); // Assigned 1
        sel.wait() // Destroys the ChanSelect, releases references to
        // rcs and rcu
    };

    assert_eq!(0, index);
    recv_assert_eq_close!("Hello, World!".to_owned(), rcs.recv());

    let (tcs, rcs) = session_channel();

    send_usize(tcu);

    let index = {
        let mut sel = ChanSelect::new();
        sel.add_recv(&rcs);
        sel.add_recv(&rcu);
        sel.wait()
    };

    assert_eq!(1, index);
    recv_assert_eq_close!(42, rcu.recv());

    // Not really necessary for the test, just used to coerce the types of
    // tcs and rcs
    send_str(tcs);
    recv_assert_eq_close!("Hello, World!".to_owned(), rcs.recv());
}

// Utility functions

fn send_str(c: Chan<(), Send<String, Eps>>) {
    c.send("Hello, World!".to_string()).close();
}

fn send_usize(c: Chan<(), Send<usize, Eps>>) {
    c.send(42).close();
}
<|endoftext|>