<commit_before>#![feature(macro_rules)]
extern crate serialize;
extern crate rest_client;

pub use self::serialize::json::DecoderError as JsonError;

use self::rest_client::RestError;

#[deriving(Show)]
pub enum APIError {
    RestErr(RestError),
    StatusErr(String),
    JsonErr(JsonError),
}

macro_rules! rest(
    ($verb_ext: ident $url:expr: fn $fn_name:ident ($(?$param:ident: $ty: ty),+ $($arg:ident: $ty:ty),+) -> $ret:ty) => (
        fn $fn_name($($arg: $ty),+) -> Result<$ret, APIError> {
            use rest_client::RestClient;
            use serialize::json::decode;

            pair!()

            let url = format!($url, $($param),+);

            let owned = [$((stringify!($arg), $arg.to_string())),+];
            let params: Vec<(&str, &str)> = owned.iter().map(pair).collect();

            let response = try!(RestClient::$verb_ext(url.as_slice(), params.as_slice()).map_err(|e| RestErr(e)));

            if response.body.is_empty() {
                Err(StatusErr(response.status.to_string()))
            } else {
                decode::<$ret>(response.body.as_slice()).map_err(|e| JsonErr(e))
            }
        }
    );
    ($verb:ident $url:expr: fn $fn_name:ident ($(?$param:ident: $ty:ty),+) -> $ret:ty) => (
        fn $fn_name($($param: $ty),+) -> Result<$ret, APIError> {
            use rest_client::RestClient;
            use serialize::json::decode;

            let url = format!($url, $($param),+);

            let response = try!(RestClient::$verb(url.as_slice()).map_err(|e| RestErr(e)));

            if response.body.is_empty() {
                Err(StatusErr(response.status.to_string()))
            } else {
                decode::<$ret>(response.body.as_slice()).map_err(|e| JsonErr(e))
            }
        }
    );
    ($verb:ident $url:expr: fn $fn_name:ident () -> $ret:ty) => (
        fn $fn_name() -> Result<$ret, APIError> {
            use rest_client::RestClient;
            use serialize::json::decode;

            const URL: &'static str = $url;

            let response = try!(RestClient::$verb(URL).map_err(|e| RestErr(e)));

            if response.body.is_empty() {
                Err(StatusErr(response.status.to_string()))
            } else {
                decode::<$ret>(response.body.as_slice()).map_err(|e| JsonErr(e))
            }
        }
    );
    ($verb_ext:ident $url:expr: fn $fn_name:ident ($($arg:ident: $ty:ty),+) -> $ret:ty) => (
        fn $fn_name($($arg: $ty),+) -> Result<$ret, APIError> {
            use rest_client::RestClient;
            use serialize::json::decode;

            pair!()

            const URL: &'static str = $url;

            let owned = [$((stringify!($arg), $arg.to_string())),+];
            let params: Vec<(&str, &str)> =  owned.iter().map(pair).collect();

            let response = try!(RestClient::$verb_ext(URL, params.as_slice()).map_err(|e| RestErr(e)));

            if response.body.is_empty() {
                Err(StatusErr(response.status.to_string()))
            } else {
                decode::<$ret>(response.body.as_slice()).map_err(|e| JsonErr(e))
            }
        }
    );

)

macro_rules! pair(
    () => (
        fn pair<'a>(tup: &'a (&'a str, String)) -> (&'a str, &'a str) {
            let (ref a, ref b) = *tup;
            (*a, b.as_slice())
        }
    )
)

#[macro_export]
macro_rules! get(
    ($url:expr: fn $fn_name:ident () -> $ret:ty) => (
        rest!(get $url: fn $fn_name() -> $ret)
    );
    ($url:expr: fn $fn_name:ident ($(?$param:ident: $ty: ty),+) -> $ret:ty) => (
        rest!(get $url: fn $fn_name($(?$param: $ty),+) -> $ret)
    );
    ($url:expr: fn $fn_name:ident ($(?$param:ident: $ty: ty),+ $($arg:ident: $ty:ty),+) -> $ret:ty) => (
        rest!(get_with_params $url: fn $fn_name($(?$param: $ty),+ $($arg: $ty),+) -> $ret)
    );
    ($url:expr: fn $fn_name:ident ($($arg:ident: $ty:ty),*) -> $ret:ty) => (
        rest!(get_with_params $url: fn $fn_name($($arg: $ty),+) -> $ret)
    );
)

#[cfg(test)]
mod test{
    use super::{APIError, RestErr, StatusErr, JsonErr};

    #[deriving(Decodable)]
    struct Test {
        hello: String,
    }

    // TODO: Host these on GitHub-Pages or a local test server
    get!("https://raw.githubusercontent.com/cybergeek94/ferrite/master/json/hello_world.json": fn hello_world() -> Test)

    get!("https://raw.githubusercontent.com/cybergeek94/ferrite/master/json/hello_vec.json": fn hello_vec() -> Vec<Test>)

    get!("https://raw.githubusercontent.com/cybergeek94/ferrite/master/json/hello_{}.json": fn hello(?val: &str) -> Test)

    #[test]
    fn test_hello_world() {
        let test = hello_world().unwrap();

        assert!(test.hello.as_slice() == "world");
    }

    #[test]
    fn test_hello() {
        let test = hello("world").unwrap();

        assert!(test.hello.as_slice() == "world");
    }

    #[test]
    fn test_hello_vec() {
        let test_vec = hello_vec().unwrap();
        let mut test_iter = test_vec.iter();

        assert!(test_iter.next().unwrap().hello.as_slice() == "world");
        assert!(test_iter.next().unwrap().hello.as_slice() == "nation");
        assert!(test_iter.next().unwrap().hello.as_slice() == "city");
        assert!(test_iter.next().unwrap().hello.as_slice() == "person");
        assert!(test_iter.next().is_none());
    }

}
<commit_msg>Fix scoping issues between tests and external use<commit_after>#![feature(macro_rules)]
#![allow(unused_imports)]
extern crate serialize;
extern crate rest_client;

/// Reexported types
pub use self::ferrite::{
    JsonError,
    RestClient,
    RestError,
    decode,
    APIError,
    RestErr,
    StatusErr,
    JsonErr
};

mod ferrite {
    pub use serialize::json::DecoderError as JsonError;
    pub use rest_client::{RestClient, RestError};
    pub use serialize::json::decode;

    #[deriving(Show)]
    pub enum APIError {
        RestErr(RestError),
        StatusErr(String),
        JsonErr(JsonError),
    }
}

macro_rules! rest(
    ($verb_ext: ident $url:expr: fn $fn_name:ident ($(?$param:ident: $ty: ty),+ $($arg:ident: $ty:ty),+) -> $ret:ty) => (
        fn $fn_name($($arg: $ty),+) -> Result<$ret, APIError> {
            use ferrite::{
                JsonError,
                RestClient,
                RestError,
                decode,
                APIError,
                RestErr,
                StatusErr,
                JsonErr
            };

            pair!()

            let url = format!($url, $($param),+);

            let owned = [$((stringify!($arg), $arg.to_string())),+];
            let params: Vec<(&str, &str)> = owned.iter().map(pair).collect();

            let response = try!(RestClient::$verb_ext(url.as_slice(), params.as_slice()).map_err(|e| RestErr(e)));

            if response.body.is_empty() {
                Err(StatusErr(response.status.to_string()))
            } else {
                decode::<$ret>(response.body.as_slice()).map_err(|e| JsonErr(e))
            }
        }
    );
    ($verb:ident $url:expr: fn $fn_name:ident ($(?$param:ident: $ty:ty),+) -> $ret:ty) => (
        fn $fn_name($($param: $ty),+) -> Result<$ret, APIError> {
            use ferrite::{
                JsonError,
                RestClient,
                RestError,
                decode,
                APIError,
                RestErr,
                StatusErr,
                JsonErr
            };

            let url = format!($url, $($param),+);

            let response = try!(RestClient::$verb(url.as_slice()).map_err(|e| RestErr(e)));

            if response.body.is_empty() {
                Err(StatusErr(response.status.to_string()))
            } else {
                decode::<$ret>(response.body.as_slice()).map_err(|e| JsonErr(e))
            }
        }
    );
    ($verb:ident $url:expr: fn $fn_name:ident () -> $ret:ty) => (
        fn $fn_name() -> Result<$ret, APIError> {
            use ferrite::{
                JsonError,
                RestClient,
                RestError,
                decode,
                APIError,
                RestErr,
                StatusErr,
                JsonErr
            };

            const URL: &'static str = $url;

            let response = try!(RestClient::$verb(URL).map_err(|e| RestErr(e)));

            if response.body.is_empty() {
                Err(StatusErr(response.status.to_string()))
            } else {
                decode::<$ret>(response.body.as_slice()).map_err(|e| JsonErr(e))
            }
        }
    );
    ($verb_ext:ident $url:expr: fn $fn_name:ident ($($arg:ident: $ty:ty),+) -> $ret:ty) => (
        fn $fn_name($($arg: $ty),+) -> Result<$ret, APIError> {
            use ferrite::{
                JsonError,
                RestClient,
                RestError,
                decode,
                APIError,
                RestErr,
                StatusErr,
                JsonErr
            };

            pair!()

            const URL: &'static str = $url;

            let owned = [$((stringify!($arg), $arg.to_string())),+];
            let params: Vec<(&str, &str)> =  owned.iter().map(pair).collect();

            let response = try!(RestClient::$verb_ext(URL, params.as_slice()).map_err(|e| RestErr(e)));

            if response.body.is_empty() {
                Err(StatusErr(response.status.to_string()))
            } else {
                decode::<$ret>(response.body.as_slice()).map_err(|e| JsonErr(e))
            }
        }
    );

)

macro_rules! pair(
    () => (
        fn pair<'a>(tup: &'a (&'a str, String)) -> (&'a str, &'a str) {
            let (ref a, ref b) = *tup;
            (*a, b.as_slice())
        }
    )
)

#[macro_export]
macro_rules! get(
    ($url:expr: fn $fn_name:ident () -> $ret:ty) => (
        rest!(get $url: fn $fn_name() -> $ret)
    );
    ($url:expr: fn $fn_name:ident ($(?$param:ident: $ty: ty),+) -> $ret:ty) => (
        rest!(get $url: fn $fn_name($(?$param: $ty),+) -> $ret)
    );
    ($url:expr: fn $fn_name:ident ($(?$param:ident: $ty: ty),+ $($arg:ident: $ty:ty),+) -> $ret:ty) => (
        rest!(get_with_params $url: fn $fn_name($(?$param: $ty),+ $($arg: $ty),+) -> $ret)
    );
    ($url:expr: fn $fn_name:ident ($($arg:ident: $ty:ty),*) -> $ret:ty) => (
        rest!(get_with_params $url: fn $fn_name($($arg: $ty),+) -> $ret)
    );
)

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

    #[deriving(Decodable)]
    struct Test {
        hello: String,
    }

    // TODO: Host these on GitHub-Pages or a local test server
    get!("https://raw.githubusercontent.com/cybergeek94/ferrite/master/json/hello_world.json": fn hello_world() -> Test)

    get!("https://raw.githubusercontent.com/cybergeek94/ferrite/master/json/hello_vec.json": fn hello_vec() -> Vec<Test>)

    get!("https://raw.githubusercontent.com/cybergeek94/ferrite/master/json/hello_{}.json": fn hello(?val: &str) -> Test)

    #[test]
    fn test_hello_world() {
        let test = hello_world().unwrap();

        assert!(test.hello.as_slice() == "world");
    }

    #[test]
    fn test_hello() {
        let test = hello("world").unwrap();

        assert!(test.hello.as_slice() == "world");
    }

    #[test]
    fn test_hello_vec() {
        let test_vec = hello_vec().unwrap();
        let mut test_iter = test_vec.iter();

        assert!(test_iter.next().unwrap().hello.as_slice() == "world");
        assert!(test_iter.next().unwrap().hello.as_slice() == "nation");
        assert!(test_iter.next().unwrap().hello.as_slice() == "city");
        assert!(test_iter.next().unwrap().hello.as_slice() == "person");
        assert!(test_iter.next().is_none());
    }

}
<|endoftext|>


<commit_before>// use std::io;
// use std::str::FromStr;
use std::num;

pub type Coordinate = (f32, f32, f32);
pub type XYZLine = (String, Coordinate);
pub type Snapshot = (String, Vec<XYZLine>);

#[derive(Debug)]
pub enum XYZError {
    Parse(num::ParseFloatError),
}

pub fn parse_coord(x: &str, y: &str, z: &str) -> Result<Coordinate, XYZError> {
    let vec_x = try!(x.parse::<f32>().map_err(XYZError::Parse));
    let vec_y = try!(y.parse::<f32>().map_err(XYZError::Parse));
    let vec_z = try!(z.parse::<f32>().map_err(XYZError::Parse));

    Ok((vec_x, vec_y, vec_z))
}

// fn read_xyz_line<R: io::BufRead>(reader: &mut R) -> Option<XYZLine> {
//     let mut buffer = String::new();
//     try!(reader.read_line(&mut buffer));
//     let splited: Vec<&str> = buffer.split_whitespace().collect();
//     if splited.len() == 4 {
//         Some(
//             (String::from(splited[0]),
//             parse_coord(splited[1], splited[2], splited[3]))
//             )
//     } else {
//         None
//     }
// }

// fn collect_xyz<R: io::BufRead>(reader: &mut R, num: i32) -> Vec<XYZLine> {
//     let mut vec = Vec::new();
//     for _ in 0..num {
//         match read_xyz_line(reader) {
//             Some(x) => vec.push(x),
//             _ => ()
//         };
//     }
//     vec
// }

// pub fn read_snapshot<R: io::BufRead>(mut reader: &mut R) -> Snapshot {
//     let mut buffer = String::new();
//     try!(reader.read_line(&mut buffer));
//     let num = i32::from_str(&buffer).unwrap(); // TODO try
//     reader.read_line(&mut buffer); // TODO try
//     (buffer.clone(), collect_xyz(reader, num))
// }

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>Use From trait<commit_after>// use std::io;
// use std::str::FromStr;
use std::num;

pub type Coordinate = (f32, f32, f32);
pub type XYZLine = (String, Coordinate);
pub type Snapshot = (String, Vec<XYZLine>);

#[derive(Debug)]
pub enum XYZError {
    ParseError(num::ParseFloatError),
}

impl From<num::ParseFloatError> for XYZError {
    fn from(err: num::ParseFloatError) -> XYZError {
        XYZError::ParseError(err)
    }
}

pub fn parse_coord(x: &str, y: &str, z: &str) -> Result<Coordinate, XYZError> {
    let vec_x = try!(x.parse::<f32>());
    let vec_y = try!(y.parse::<f32>());
    let vec_z = try!(z.parse::<f32>());

    Ok((vec_x, vec_y, vec_z))
}

// fn read_xyz_line<R: io::BufRead>(reader: &mut R) -> Option<XYZLine> {
//     let mut buffer = String::new();
//     try!(reader.read_line(&mut buffer));
//     let splited: Vec<&str> = buffer.split_whitespace().collect();
//     if splited.len() == 4 {
//         Some(
//             (String::from(splited[0]),
//             parse_coord(splited[1], splited[2], splited[3]))
//             )
//     } else {
//         None
//     }
// }

// fn collect_xyz<R: io::BufRead>(reader: &mut R, num: i32) -> Vec<XYZLine> {
//     let mut vec = Vec::new();
//     for _ in 0..num {
//         match read_xyz_line(reader) {
//             Some(x) => vec.push(x),
//             _ => ()
//         };
//     }
//     vec
// }

// pub fn read_snapshot<R: io::BufRead>(mut reader: &mut R) -> Snapshot {
//     let mut buffer = String::new();
//     try!(reader.read_line(&mut buffer));
//     let num = i32::from_str(&buffer).unwrap(); // TODO try
//     reader.read_line(&mut buffer); // TODO try
//     (buffer.clone(), collect_xyz(reader, num))
// }

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


<commit_before>/*
* A basic EBML parser for Rust. Gives methods for both approaches; full parsing
* of an EBML file in-memory or incremental sequential parsing of nodes for
* environments that are more memory-constrained.
*
* The full parser allows you to get all sub-elements of a node in one call,
* because each node has a reference to the data it contains. All of the data is
* loaded into memory when the root node is parsed.
*
* The PartialElement only reads the data it needs to get the header of any
* single element. So if the data source is a file the full parser will load the
* whole file to memory, while the partial parser will only load at most one leaf
* node's value plus its id and size.
*
* The partial parser stores the offset of each node in the input stream, which
* is then used to jump to the node's data in the stream. This may cause the
* partial parser to do more random seeking.
*/

//extern crate time;
//use std::io::Memreader;
//use time::Timespec;

mod rebml {
    use time::Timespec;
    enum Value {
		Uint(u64),
		Int(i64),
		Str(String),
		DateTimespec),
		Bin(&[u8]),
        SubElement,
		Nil, // Empty element
	}

    mod incremental {
        use std::io::{IoResult,IoError};
        pub struct Parser {
            input: &Reader,
            id: u32,
            size: u64
        }

        impl Parser {
            /*
            Create new EBML Parser and read in the first tag, if any. Expects the stream to start with the top-level
            EBML tag [1A][45][DF][A3]. Consumes the input stream.
            */
            pub fn new(input: Reader) -> IoResult<Parser> {
                let mut parser: Parser;
                parser.input = input;
                parser.id = try!(self.read_id());
                parser.size = try!(self.read_size());
                return parser;
            }

            /*
            Get next the next node after this one in the given input stream.
            */
            pub fn next(&self) -> Option<IoError> {
            }

            /*
            Get the subnode below this one, if any exists (returns IoError on failure)
            */
            pub fn down(&self) -> Option<IoError> {
            }

            /*
            Get the current depth in the Element tree
            */
            pub fn level(&self) -> u32 {}

            /*
            Get the value of this node
            */
            pub fn value(input: &Reader) -> IoResult<Value> {
            }

            /*
            Helper function to extract the (remaining) byte count for a UTF-8-like value
            */
            fn byte_count(firstbyte: &u8) -> u8 {
                let mut mask = 0x80;
                let mut bytecount = 0;
                while firstbyte & mask == 0 {
                    firstbyte = firstbyte << 1;
                    bytecount += 1;
                }
                return bytecount;
            }

            /*
            Helper function to read an id from the stream
            */
            fn read_id(&self) -> IoResult<u32> {
                // read first byte
                let firstbyte = try!(self.input.read_byte());
                // Count zeroes to get number of trailing bytes
                let mut count = byte_count(firstbyte);
                let mut offset = 24;
                let mut id: u32 = firstbyte as u32 << offset;
                // TODO: Read trailing bytes and add them to the id
				let bytes = try!(self.input.read_exact(count));
				// functional method?
				id += bytes.iter()
				.zip(range_step(16, -1, -8))
				.fold(|acc, (i, o)| i as u32 << o);
				return id;
            }

            /*
            Helper function to read size from the stream
            */
            fn read_size(&self) -> IoResult<u64> {
            }
        }
    }

    [#test]
    fn test_new() {
		let bytes = vec![0x1Au8, 0x45, 0xDF, 0xA3, 0x80];
		let buf = BufReader::new(bytes)
		assert!(Parser::new(buf).is_ok());
	}
}
<commit_msg>Implemented read_size method to get size of an EBML element.<commit_after>/*
* A basic EBML parser for Rust. Gives methods for both approaches; full parsing
* of an EBML file in-memory or incremental sequential parsing of nodes for
* environments that are more memory-constrained.
*
* The full parser allows you to get all sub-elements of a node in one call,
* because each node has a reference to the data it contains. All of the data is
* loaded into memory when the root node is parsed.
*
* The PartialElement only reads the data it needs to get the header of any
* single element. So if the data source is a file the full parser will load the
* whole file to memory, while the partial parser will only load at most one leaf
* node's value plus its id and size.
*
* The partial parser stores the offset of each node in the input stream, which
* is then used to jump to the node's data in the stream. This may cause the
* partial parser to do more random seeking.
*/

//extern crate time;
//use std::io::Memreader;
//use time::Timespec;

mod rebml {
    use time::Timespec;
    enum Value {
		Uint(u64),
		Int(i64),
		Str(String),
		DateTimespec),
		Bin(&[u8]),
        SubElement,
		Nil, // Empty element
	}

    mod incremental {
        use std::io::{IoResult,IoError};
        pub struct Parser {
            input: &Reader,
            id: u32,
            size: u64
        }

        impl Parser {
            /*
            Create new EBML Parser and read in the first tag, if any. Expects the stream to start with the top-level
            EBML tag [1A][45][DF][A3]. Consumes the input stream.
            */
            pub fn new(input: Reader) -> IoResult<Parser> {
                let mut parser: Parser;
                parser.input = input;
                parser.id = try!(self.read_id());
                parser.size = try!(self.read_size());
                if (parser.id != 0x1A45DFA3) {
                    // Return error, first tag isn't EBML tag.
                    // TODO: I have a feeling this can be done better using a match statement or something for the parser.id assignment.
                }
                return parser;
            }

            /*
            Get next the next node after this one in the given input stream.
            */
            pub fn next(&self) -> Option<IoError> {
            }

            /*
            Get the subnode below this one, if any exists (returns IoError on failure)
            */
            pub fn down(&self) -> Option<IoError> {
            }

            /*
            Get the current depth in the Element tree
            */
            pub fn level(&self) -> u32 {}

            /*
            Get the value of this node
            */
            pub fn value(input: &Reader) -> IoResult<Value> {
            }

            /*
            Helper function to extract the (remaining) byte count for a UTF-8-like value from the first byte
            */
            fn byte_count(firstbyte: &u8) -> u8 {
                let mut mask = 0x80;
                let mut bytecount = 0;
                while firstbyte & mask == 0 {
                    firstbyte = firstbyte << 1;
                    bytecount += 1;
                }
                return bytecount;
            }

            /*
            Helper function to read an id from the stream
            */
            fn read_id(&self) -> IoResult<u32> {
                // read first byte
                let firstbyte = try!(self.input.read_byte());
                // Count zeroes to get number of trailing bytes
                let mut count = byte_count(firstbyte);
                let mut id: u32 = firstbyte as u32 << (32 - 8);
                // Read trailing bytes and add them to the id
                let bytes = try!(self.input.read_exact(count));
                // integrate the rest of the bytes into the size
                id += bytes.iter()
                .zip(range_step(32 - 16, -1, -8))
                .fold(|acc, (i, o)| i as u32 << o);
              	return id;
            }

            /*
            Helper function to read size from the stream
            */
            fn read_size(&self) -> IoResult<u64> {
                // read first byte
                let firstbyte = try!(self.input.read_byte());
                // Count zeroes to get number of trailing bytes
                let mut count = byte_count(firstbyte);
                // Compose the first byte into the size, but cancel out the first one, which isn't part of the actual size
                let mut size: u64 = (firstbyte & !(0x80 >> count)) as u64 << (64 - 8);
                // Read trailing bytes and add them to the size
                let bytes = try!(self.input.read_exact(count));
                // integrate bytes into size
                id += bytes.iter()
                .zip(range_step(64 - 16, -1, -8))
                .fold(|acc, (i, o)| i as u64 << o);
                return id;
            }
        }
    }

    [#test]
    fn test_new() {
		let bytes = vec![0x1Au8, 0x45, 0xDF, 0xA3, 0x80];
		let buf = BufReader::new(bytes)
		assert!(Parser::new(buf).is_ok());
	}
}
<|endoftext|>


<commit_before>#![feature(collections)]
extern crate shared_slice;

use std::collections::{BTreeMap, HashSet};
use std::hash::{Hash, Hasher};
use std::str::from_utf8_unchecked;
use shared_slice::rc::RcStr;

/// A Document contains an id and content, both of which are reference-counted strings.
/// Hashing and equality are based only on the id field.
#[derive(Clone, Eq)]
pub struct Document {
    id: RcStr,
    content: RcStr,
}

impl Document {
    /// Construct a new Document from an id and content.
    /// Both two arguments can be anything that can be turned into a String.
    pub fn new<S, T>(id: S, content: T) -> Document
        where S: Into<String>,
              T: Into<String>
    {
        Document {
            id: into_rc_str(id),
            content: into_rc_str(content),
        }
    }

    pub fn id(&self) -> &str {
        unsafe { from_utf8_unchecked(&*self.id) }
    }

    pub fn content(&self) -> &str {
        unsafe { from_utf8_unchecked(&*self.content) }
    }
}

fn into_rc_str<S: Into<String>>(id: S) -> RcStr {
    let id = id.into();
    let id: Vec<u8> = id.into();
    RcStr::new(id.into_boxed_slice())
}

impl Hash for Document {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        state.write(&*self.id);
    }
}

impl PartialEq<Document> for Document {
    fn eq(&self, other: &Document) -> bool {
        self.id == other.id
    }
}

impl std::fmt::Debug for Document {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(fmt, "Document {{ id: {:?}, content: {:?} }}", self.id(), self.content())
    }
}

/// An Index is anything that can store Documents and return matching Documents for a query.
trait Index {
    /// Given a Document, stores it in the index.
    fn index(&mut self, doc: Document);
    /// Given a query, return the set of Documents that match the query.
    /// What constitutes a "match" is implementation-specific; loosely, a Document should
    /// match a query if they are somehow related. A naive implementation might simply
    /// return the set of Documents for which `query` is a substring of their content.
    fn search(&self, query: &str) -> HashSet<Document>;
}

/// A basic implementation of an `Index`, the inverted index is a data structure that maps
/// from words to sets of Documents.
type InvertedIndex = BTreeMap<RcStr, HashSet<Document>>;

impl Index for InvertedIndex {
    /// A basic implementation of index, splits the document's content into whitespace-separated
    /// words, and inserts each word-document pair into the map.
    fn index(&mut self, doc: Document) {
        let lowercased = doc.content().to_lowercase();
        let ngrams = into_rc_str(lowercased)
            .split_whitespace()
            .flat_map(|word: RcStr| (1..word.len() + 1).map(move |to| word.clone().slice_to(to)));

        for ngram in ngrams {
            self.entry(ngram).or_insert_with(|| HashSet::new()).insert(doc.clone());
        }
    }

    /// A basic search implementation that splits the query's content into whitespace-separated
    /// words, looks up the set of Documents for each word, and then concatenates the sets.
    fn search(&self, query: &str) -> HashSet<Document> {
        query.split_whitespace()
            .flat_map(|word| self.get(&into_rc_str(word)))
            .flat_map(|docs| docs)
            .cloned()
            .collect()
    }
}

#[test]
fn test_search1() {
    let mut index = InvertedIndex::new();
    let doc1 = Document::new("1", "learn to program in rust today");
    let doc2 = Document::new("2", "what did you do today");
    index.index(doc1.clone());
    index.index(doc2.clone());
    let search_results = index.search("today");
    assert!(search_results.contains(&doc1));
    assert!(search_results.contains(&doc2));
}

#[test]
fn test_ngrams() {
    let mut index = InvertedIndex::new();
    let doc1 = Document::new("1", "learn to program in rust today");
    let doc2 = Document::new("2", "what did you do today");
    index.index(doc1.clone());
    index.index(doc2.clone());
    let search_results = index.search("to");
    assert!(search_results.contains(&doc1));
    assert!(search_results.contains(&doc2));
}

#[test]
fn test_search2() {
    let mut index = InvertedIndex::new();
    index.index(Document::new("2", "what did you do today"));
    index.index(Document::new("3", "hey today"));
    let search_results = index.search("today");
    assert_eq!(search_results.len(), 2);
}
<commit_msg>Use Rc<Document> instead of RcStr fields.<commit_after>#![feature(collections)]
extern crate shared_slice;

use std::collections::{BTreeMap, HashSet};
use std::hash::{Hash, Hasher};
use std::rc::Rc;
use shared_slice::rc::RcStr;

/// A Document contains an id and content.
/// Hashing and equality are based only on the id field.
#[derive(Clone, Eq)]
pub struct Document {
    id: String,
    content: String,
}

impl Document {
    /// Construct a new Document from an id and content.
    /// Both two arguments can be anything that can be turned into a String.
    pub fn new<S, T>(id: S, content: T) -> Document
        where S: Into<String>,
              T: Into<String>
    {
        Document { id: id.into(), content: content.into(), }
    }

    pub fn id(&self) -> &str {
        &self.id
    }

    pub fn content(&self) -> &str {
        &self.content
    }
}

fn into_rc_str<S: Into<String>>(id: S) -> RcStr {
    let id = id.into();
    let id: Vec<u8> = id.into();
    RcStr::new(id.into_boxed_slice())
}

impl Hash for Document {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        state.write(self.id.as_bytes());
    }
}

impl PartialEq<Document> for Document {
    fn eq(&self, other: &Document) -> bool {
        self.id == other.id
    }
}

impl std::fmt::Debug for Document {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(fmt, "Document {{ id: {:?}, content: {:?} }}", self.id(), self.content())
    }
}

/// An Index is anything that can store Documents and return matching Documents for a query.
trait Index {
    /// Given a Document, stores it in the index.
    fn index(&mut self, doc: Document);
    /// Given a query, return the set of Documents that match the query.
    /// What constitutes a "match" is implementation-specific; loosely, a Document should
    /// match a query if they are somehow related. A naive implementation might simply
    /// return the set of Documents for which `query` is a substring of their content.
    fn search(&self, query: &str) -> HashSet<Rc<Document>>;
}

/// A basic implementation of an `Index`, the inverted index is a data structure that maps
/// from words to sets of Documents.
type InvertedIndex = BTreeMap<RcStr, HashSet<Rc<Document>>>;

impl Index for InvertedIndex {
    /// A basic implementation of index, splits the document's content into whitespace-separated
    /// words, and inserts each word-document pair into the map.
    fn index(&mut self, doc: Document) {
        let doc = Rc::new(doc);
        let lowercased = doc.content().to_lowercase();
        let ngrams = into_rc_str(lowercased)
            .split_whitespace()
            .flat_map(|word: RcStr| (1..word.len() + 1).map(move |to| word.clone().slice_to(to)));

        for ngram in ngrams {
            self.entry(ngram).or_insert_with(|| HashSet::new()).insert(doc.clone());
        }
    }

    /// A basic search implementation that splits the query's content into whitespace-separated
    /// words, looks up the set of Documents for each word, and then concatenates the sets.
    fn search(&self, query: &str) -> HashSet<Rc<Document>> {
        query.split_whitespace()
            .flat_map(|word| self.get(&into_rc_str(word)))
            .flat_map(|docs| docs)
            .cloned()
            .collect()
    }
}

#[test]
fn test_search1() {
    let mut index = InvertedIndex::new();
    let doc1 = Document::new("1", "learn to program in rust today");
    let doc2 = Document::new("2", "what did you do today");
    index.index(doc1.clone());
    index.index(doc2.clone());
    let search_results = index.search("today");
    assert!(search_results.contains(&doc1));
    assert!(search_results.contains(&doc2));
}

#[test]
fn test_ngrams() {
    let mut index = InvertedIndex::new();
    let doc1 = Document::new("1", "learn to program in rust today");
    let doc2 = Document::new("2", "what did you do today");
    index.index(doc1.clone());
    index.index(doc2.clone());
    let search_results = index.search("to");
    assert!(search_results.contains(&doc1));
    assert!(search_results.contains(&doc2));
}

#[test]
fn test_search2() {
    let mut index = InvertedIndex::new();
    index.index(Document::new("2", "what did you do today"));
    index.index(Document::new("3", "hey today"));
    let search_results = index.search("today");
    assert_eq!(search_results.len(), 2);
}
<|endoftext|>


<commit_before>#![feature(core)]
extern crate core;
use core::fmt::Debug;
use std::marker::PhantomData;

pub struct Expectation<Lhs: Debug>(Lhs);

pub struct To<Lhs: Debug>(Lhs);

pub trait Matcher<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool;
    fn fail_msg(&self, rhs: &Lhs) -> String;
}

pub trait WithLen {
    fn len(&self) -> usize;
    fn is_empty(&self) -> bool;
}

impl<T> WithLen for Vec<T> {
    fn len(&self) -> usize { self.len() }
    fn is_empty(&self) -> bool { self.is_empty() }
}

impl WithLen for String {
    fn len(&self) -> usize { self.chars().count() }
    fn is_empty(&self) -> bool { self.chars().count() == 0 }
}

impl<'a> WithLen for &'a str {
    fn len(&self) -> usize { self.chars().count() }
    fn is_empty(&self) -> bool { self.chars().count() == 0 }
}

pub struct Empty;
impl<Lhs: Debug + WithLen> Matcher<Lhs> for Empty {
    fn matches(&self, rhs: &Lhs) -> bool {
        rhs.is_empty()
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to be empty", rhs)
    }
}

pub struct Equal<Lhs: Debug>(Lhs);

impl<Lhs: Debug + PartialEq> Matcher<Lhs> for Equal<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool {
        &self.0 == rhs
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to equal {:?}", rhs, self.0)
    }
}

pub struct Not<A, M>(M, PhantomData<A>) where A: Debug, M: Matcher<A>;

impl<Lhs: Debug, M: Matcher<Lhs>> Matcher<Lhs> for Not<Lhs, M> {
    fn matches(&self, rhs: &Lhs) -> bool {
        !self.0.matches(rhs)
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("not {}", self.0.fail_msg(rhs))
    }
}

impl<Lhs: Debug> Expectation<Lhs> {
    pub fn is<T>(&self, matcher: T) where T: Matcher<Lhs> {
        self.to(matcher)
    }

    pub fn to<T>(&self, matcher: T) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }
}

pub fn expect<T: Debug>(lhs: T) -> Expectation<T> {
    Expectation(lhs)
}

pub fn equal<T: Debug>(rhs: T) -> Equal<T> {
    Equal(rhs)
}

pub fn not<T: Debug, M: Matcher<T>>(rhs: M) -> Not<T, M> {
    Not(rhs, PhantomData)
}

pub fn empty() -> Empty {
    Empty
}

#[cfg(test)]
mod test {
    use super::{expect, equal, not, empty};

    #[test]
    fn test_expect_equality() {
        expect(1).to(equal(1));
    }

    #[test]
    #[should_panic(expected="expected 1 to equal 2")]
    fn test_expect_not_equality_to_fail() {
        expect(1).to(equal(2));
    }

    #[test]
    fn test_partial_eq_equality() {
        #[derive(PartialEq, Debug)]
        struct Foo { a: u16, b: String }

        expect(Foo{ a: 10u16, b: "Hello".to_string()})
            .to(equal(Foo{ a: 10u16, b: "Hello".to_string()}));
    }

    #[test]
    fn test_invert_equality() {
        expect(1).to(not(equal(2)));
    }

    #[test]
    fn test_invert_invert_equality() {
        expect(1).to(not(not(equal(1))));
    }

    #[test]
    #[should_panic(expected="not expected 1 to equal 1")]
    fn test_invert_equality_equal_to_fail() {
        expect(1).to(not(equal(1)));
    }

    #[test]
    fn test_empty() {
        let v: Vec<usize> = Vec::new();
        expect(v).is(empty());
    }

    #[test]
    fn test_not_empty() {
        let v = vec![1, 2, 3];
        expect(v).is(not(empty()));
    }

    #[test]
    fn test_empty_string() {
        expect("".to_string()).is(empty());
    }

    #[test]
    fn test_not_empty_string() {
        expect("not-empty".to_string()).is(not(empty()));
    }

    #[test]
    fn test_empty_str() {
        expect("").is(empty());
    }

    #[test]
    fn test_not_empty_str() {
        expect("not-empty").is(not(empty()));
    }
}
<commit_msg>Add `contain` matcher<commit_after>#![feature(core)]
extern crate core;
use core::fmt::Debug;
use std::slice::Iter;
use std::marker::PhantomData;

pub struct Expectation<Lhs: Debug>(Lhs);

pub struct To<Lhs: Debug>(Lhs);

pub trait Matcher<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool;
    fn fail_msg(&self, rhs: &Lhs) -> String;
}

pub trait WithLen {
    fn match_len(&self) -> usize;
    fn match_is_empty(&self) -> bool;
}

impl<T> WithLen for Vec<T> {
    fn match_len(&self) -> usize { self.len() }
    fn match_is_empty(&self) -> bool { self.is_empty() }
}

impl WithLen for String {
    fn match_len(&self) -> usize { self.chars().count() }
    fn match_is_empty(&self) -> bool { self.chars().count() == 0 }
}

impl<'a> WithLen for &'a str {
    fn match_len(&self) -> usize { self.chars().count() }
    fn match_is_empty(&self) -> bool { self.chars().count() == 0 }
}

pub trait WithIter<T> {
    fn match_iter(&self) -> Iter<T>;
}

impl<T> WithIter<T> for Vec<T> {
    fn match_iter(&self) -> Iter<T> { self.iter() }
}

pub struct Contains<T>(T);

impl<T: Debug + PartialEq, Lhs: Debug + WithIter<T>> Matcher<Lhs> for Contains<T> {
    fn matches(&self, lhs: &Lhs) -> bool {
        lhs.match_iter().any(|i| *i == self.0)
    }

    fn fail_msg(&self, lhs: &Lhs) -> String {
        format!("expected {:?} to contain {:?}", lhs, self.0)
    }
}

pub struct Empty;

impl<Lhs: Debug + WithLen> Matcher<Lhs> for Empty {
    fn matches(&self, rhs: &Lhs) -> bool {
        rhs.match_is_empty()
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to be empty", rhs)
    }
}

pub struct Equal<Lhs: Debug>(Lhs);

impl<Lhs: Debug + PartialEq> Matcher<Lhs> for Equal<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool {
        &self.0 == rhs
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to equal {:?}", rhs, self.0)
    }
}

pub struct Not<A, M>(M, PhantomData<A>) where A: Debug, M: Matcher<A>;

impl<Lhs: Debug, M: Matcher<Lhs>> Matcher<Lhs> for Not<Lhs, M> {
    fn matches(&self, rhs: &Lhs) -> bool {
        !self.0.matches(rhs)
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("not {}", self.0.fail_msg(rhs))
    }
}

impl<Lhs: Debug> Expectation<Lhs> {
    pub fn is<T>(&self, matcher: T) where T: Matcher<Lhs> {
        self.to(matcher)
    }

    pub fn to<T>(&self, matcher: T) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }
}

pub fn expect<T: Debug>(lhs: T) -> Expectation<T> {
    Expectation(lhs)
}

pub fn equal<T: Debug>(rhs: T) -> Equal<T> {
    Equal(rhs)
}

pub fn not<T: Debug, M: Matcher<T>>(rhs: M) -> Not<T, M> {
    Not(rhs, PhantomData)
}

pub fn empty() -> Empty {
    Empty
}

pub fn contain<T: Debug>(rhs: T) -> Contains<T> {
    Contains(rhs)
}

#[cfg(test)]
mod test {
    use super::{expect, equal, not, empty, contain};

    #[test]
    fn test_expect_equality() {
        expect(1).to(equal(1));
    }

    #[test]
    #[should_panic(expected="expected 1 to equal 2")]
    fn test_expect_not_equality_to_fail() {
        expect(1).to(equal(2));
    }

    #[test]
    fn test_partial_eq_equality() {
        #[derive(PartialEq, Debug)]
        struct Foo { a: u16, b: String }

        expect(Foo{ a: 10u16, b: "Hello".to_string()})
            .to(equal(Foo{ a: 10u16, b: "Hello".to_string()}));
    }

    #[test]
    fn test_invert_equality() {
        expect(1).to(not(equal(2)));
    }

    #[test]
    fn test_invert_invert_equality() {
        expect(1).to(not(not(equal(1))));
    }

    #[test]
    #[should_panic(expected="not expected 1 to equal 1")]
    fn test_invert_equality_equal_to_fail() {
        expect(1).to(not(equal(1)));
    }

    #[test]
    fn test_empty() {
        let v: Vec<usize> = Vec::new();
        expect(v).is(empty());
    }

    #[test]
    fn test_not_empty() {
        let v = vec![1, 2, 3];
        expect(v).is(not(empty()));
    }

    #[test]
    fn test_empty_string() {
        expect("".to_string()).is(empty());
    }

    #[test]
    fn test_not_empty_string() {
        expect("not-empty".to_string()).is(not(empty()));
    }

    #[test]
    fn test_empty_str() {
        expect("").is(empty());
    }

    #[test]
    fn test_not_empty_str() {
        expect("not-empty").is(not(empty()));
    }

    #[test]
    fn test_contains() {
        expect(vec![1, 2, 3]).to(contain(1));
    }

    #[test]
    fn test_not_contains() {
        expect(vec![1, 2, 3]).to(not(contain(10)));
    }
}
<|endoftext|>


<commit_before>extern crate toml;

// Import traits
use std::io::prelude::Read;

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}

pub fn test() {
    println!("Hello from lib.rs");
}

#[derive(Debug)]
enum OnSuccess {
    Continue,
    Warn {message: String},
    Abort {message: String},
}

#[derive(Debug)]
enum OnFailure {
    Continue,
    Warn {message: String},
    Abort {message: String},
}

#[derive(Debug)]
enum Step {
    Echo {name: String, message: String},
    Run {name: String, command: String, arguments: String, on_success: OnSuccess, on_failure: OnFailure},
    Shell,
    SetEnv,
}

fn parse_toml(filename: &str) -> Vec<Step> {

    println!("Reading toml file {}", filename);

    // Read toml file content
    let mut input = String::new();
    std::fs::File::open(&filename).and_then(|mut f| {
        f.read_to_string(&mut input)
    }).unwrap();

    // Pase toml file
    let mut parser = toml::Parser::new(&input);

    let toml = parser.parse().unwrap_or_else(|| {
        for err in &parser.errors {
            let (loline, locol) = parser.to_linecol(err.lo);
            let (hiline, hicol) = parser.to_linecol(err.hi);
            println!("{}:{}:{}-{}:{} error: {}",
                     filename, loline, locol, hiline, hicol, err.desc);
        }
        panic!("Error parsing toml file.");
    });

    // println!("toml: {:#?}", toml);

    // Parse "variables" table
    // unimplemented!();

    // Parse "steps" table
    let mut steps = Vec::<Step>::with_capacity(10);

    for step in toml.get("step").unwrap().as_slice().unwrap() {
        let action = step.as_table().unwrap().get("action").unwrap().as_str().unwrap();
        let name = step.as_table().unwrap().get("name").unwrap().as_str().unwrap().to_string();
        let details = step.as_table().unwrap().get("details").unwrap().as_table().unwrap();
        let step = match action {
            "echo" => {
                let message = details.get("message").unwrap().as_str().unwrap().to_string();
                Step::Echo {name: name, message: message}
            },
            "run" => {
                let command = details.get("command").unwrap().as_str().unwrap().to_string();
                let arguments = details.get("arguments").unwrap().as_str().unwrap().to_string();

                let on_success = match details.get("on_success") {
                    None => {
                        println!("WARNING: No 'on_success' set for {:?}, default of 'OnSuccess::Continue'", name);
                        OnSuccess::Continue
                    },
                    Some(toml_value) => {
                        let table = toml_value.as_table().unwrap();
                        let (message_type, message) = table.iter().nth(0).unwrap();
                        match message_type.as_ref() {
                            "warn" => OnSuccess::Warn {message: message.as_str().unwrap().to_string()},
                            "abort" => OnSuccess::Abort {message: message.as_str().unwrap().to_string()},
                            _ => unimplemented!()
                        }
                    }
                };

                let on_failure = match details.get("on_failure") {
                    None => {
                        println!("WARNING: No 'on_failure' set for {:?}, default of 'OnFailure::Continue'", name);
                        OnFailure::Continue
                    },
                    Some(toml_value) => {
                        let table = toml_value.as_table().unwrap();
                        let (message_type, message) = table.iter().nth(0).unwrap();
                        match message_type.as_ref() {
                            "warn" => OnFailure::Warn {message: message.as_str().unwrap().to_string()},
                            "abort" => OnFailure::Abort {message: message.as_str().unwrap().to_string()},
                            _ => unimplemented!()
                        }
                    }
                };

                Step::Run {name: name, command: command, arguments: arguments, on_success: on_success, on_failure: on_failure}
            },
            // "shell" => {
            // },
            // "setenv" => {
            // },
            _ => {
                println!("Unknown action '{}' in toml file", action);
                unimplemented!();
            },
        };
        // println!("Step: {:?}", step);

        steps.push(step);
    }

    steps
}

pub fn execute_steps(filename: &str) {

    let steps = parse_toml(filename);

    println!("Steps: {:#?}", steps);
}
<commit_msg>Iterate over steps: Echo<commit_after>extern crate toml;

// Import traits
use std::io::prelude::Read;

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}

pub fn test() {
    println!("Hello from lib.rs");
}

#[derive(Debug)]
enum OnSuccess {
    Continue,
    Warn {message: String},
    Abort {message: String},
}

#[derive(Debug)]
enum OnFailure {
    Continue,
    Warn {message: String},
    Abort {message: String},
}

#[derive(Debug)]
enum Step {
    Echo {name: String, message: String},
    Run {name: String, command: String, arguments: String, on_success: OnSuccess, on_failure: OnFailure},
    Shell,
    SetEnv,
}

fn parse_toml(filename: &str) -> Vec<Step> {

    println!("Reading toml file {}", filename);

    // Read toml file content
    let mut input = String::new();
    std::fs::File::open(&filename).and_then(|mut f| {
        f.read_to_string(&mut input)
    }).unwrap();

    // Pase toml file
    let mut parser = toml::Parser::new(&input);

    let toml = parser.parse().unwrap_or_else(|| {
        for err in &parser.errors {
            let (loline, locol) = parser.to_linecol(err.lo);
            let (hiline, hicol) = parser.to_linecol(err.hi);
            println!("{}:{}:{}-{}:{} error: {}",
                     filename, loline, locol, hiline, hicol, err.desc);
        }
        panic!("Error parsing toml file.");
    });

    // println!("toml: {:#?}", toml);

    // Parse "variables" table
    // unimplemented!();

    // Parse "steps" table
    let mut steps = Vec::<Step>::with_capacity(10);

    for step in toml.get("step").unwrap().as_slice().unwrap() {
        let action = step.as_table().unwrap().get("action").unwrap().as_str().unwrap();
        let name = step.as_table().unwrap().get("name").unwrap().as_str().unwrap().to_string();
        let details = step.as_table().unwrap().get("details").unwrap().as_table().unwrap();
        let step = match action {
            "echo" => {
                let message = details.get("message").unwrap().as_str().unwrap().to_string();
                Step::Echo {name: name, message: message}
            },
            "run" => {
                let command = details.get("command").unwrap().as_str().unwrap().to_string();
                let arguments = details.get("arguments").unwrap().as_str().unwrap().to_string();

                let on_success = match details.get("on_success") {
                    None => {
                        println!("WARNING: No 'on_success' set for {:?}, default of 'OnSuccess::Continue'", name);
                        OnSuccess::Continue
                    },
                    Some(toml_value) => {
                        let table = toml_value.as_table().unwrap();
                        let (message_type, message) = table.iter().nth(0).unwrap();
                        match message_type.as_ref() {
                            "warn" => OnSuccess::Warn {message: message.as_str().unwrap().to_string()},
                            "abort" => OnSuccess::Abort {message: message.as_str().unwrap().to_string()},
                            _ => unimplemented!()
                        }
                    }
                };

                let on_failure = match details.get("on_failure") {
                    None => {
                        println!("WARNING: No 'on_failure' set for {:?}, default of 'OnFailure::Continue'", name);
                        OnFailure::Continue
                    },
                    Some(toml_value) => {
                        let table = toml_value.as_table().unwrap();
                        let (message_type, message) = table.iter().nth(0).unwrap();
                        match message_type.as_ref() {
                            "warn" => OnFailure::Warn {message: message.as_str().unwrap().to_string()},
                            "abort" => OnFailure::Abort {message: message.as_str().unwrap().to_string()},
                            _ => unimplemented!()
                        }
                    }
                };

                Step::Run {name: name, command: command, arguments: arguments, on_success: on_success, on_failure: on_failure}
            },
            // "shell" => {
            // },
            // "setenv" => {
            // },
            _ => {
                println!("Unknown action '{}' in toml file", action);
                unimplemented!();
            },
        };
        // println!("Step: {:?}", step);

        steps.push(step);
    }

    steps
}

pub fn execute_steps(filename: &str) {

    let steps = parse_toml(filename);

    println!("Steps: {:#?}", steps);

    // Loop over steps
    let nb_steps = steps.len();
    for (idx, step) in steps.into_iter().enumerate() {
        // println!("Step {}/{} -- ", idx+1, nb_steps);
        match step {
            Step::Echo {name, message} => {
                // FIXME: Replace environment variables in 'message'
                println!("{}", message);
            },
            Step::Run {name, command, arguments, on_success, on_failure} => {},
            _ => unimplemented!(),
        }
    }

}
<|endoftext|>


<commit_before>// (c) 2014, Ethan Pailes
// All Rights Reserved
//
// Licensed under the "Revised" BSD 3-clause licence. See LICENCE file at the
// root directory of this repository.

//! File Diff
//!
//! This module provides an atomic file diffing function for use in unit tests.
//!
//! The diff_files() function takes two file handles and determines returns true
//! if they point to identical files.
//!
//! ```
//! use file_diff::{diff_files};
//! use std::fs::{File};
//!
//! let mut file1 = match File::open("./src/lib.rs") {
//!     Ok(f) => f,
//!     Err(e) => panic!("{}", e),
//! };
//! let mut file2 = match File::open("./src/lib.rs") {
//!     Ok(f) => f,
//!     Err(e) => panic!("{}", e),
//! };
//!
//! diff_files(&mut file1, &mut file2);
//! ```
//!
//! The diff() function takes string representations of the files and returns true
//! if the strings represent real files and those files are identical.
//!
//! ```
//! use file_diff::{diff};
//!
//! diff("./src/lib.rs", "./src/lib.rs");
//! ```

use std::io::Read;

use std::fs::{File};

/// Takes two file arguments and returns true if the two files are identical.
pub fn diff_files(f1: &mut File, f2: &mut File) -> bool {
    let mut v1 = Vec::new();
    let mut v2 = Vec::new();

    match f1.read_to_end(&mut v1) {
        Err(_) => false
      , Ok(b1) => match f2.read_to_end(&mut v2) {
            Err(_) => false
          , Ok(b2) => b1 == b2
        }
    }
}

/// Takes two string filepaths and returns true if the two files are identical and exist.
pub fn diff(f1: &str, f2: &str) -> bool {
    let mut file1: File = match File::open(f1) {
        Ok(f) => f,
        Err(_) => return false,
    };
    let mut file2: File = match File::open(&f2) {
        Ok(f) => f,
        Err(_) => return false,
    };
    diff_files(&mut file1, &mut file2)
}

#[cfg(test)]
mod tests {
    const LIB_RS: &'static str = "./src/lib.rs";
    const CARGO_FILE: &'static str = "./Cargo.toml";
    const RUST_BIN_FILE: &'static str = "./testdata/rust_hello";
    const C_BIN_FILE: &'static str = "./testdata/c_hello";
    const C_BIN_FILE_COPY: &'static str = "./testdata/c_hello_copy";

    #[test]
    fn diff_the_same_text_file() { assert!(super::diff(LIB_RS, LIB_RS)); }

    #[test]
    fn diff_the_same_binary_file() { assert!(super::diff(RUST_BIN_FILE, RUST_BIN_FILE)); }

    #[test]
    fn diff_identical_binary_files() { assert!(super::diff(C_BIN_FILE, C_BIN_FILE_COPY)); }

    #[test]
    fn diff_different_text_files() { assert!( !super::diff(LIB_RS, CARGO_FILE)); }

    #[test]
    fn diff_different_binary_files() { assert!( !super::diff(RUST_BIN_FILE, C_BIN_FILE)); }
}

<commit_msg>chanced diff to be more monadish, and file_diff to use fixed length buffers.<commit_after>// (c) 2014, Ethan Pailes
// All Rights Reserved
//
// Licensed under the "Revised" BSD 3-clause licence. See LICENCE file at the
// root directory of this repository.

//! File Diff
//!
//! This module provides an atomic file diffing function for use in unit tests.
//!
//! The diff_files() function takes two file handles and determines returns true
//! if they point to identical files.
//!
//! ```
//! use file_diff::{diff_files};
//! use std::fs::{File};
//!
//! let mut file1 = match File::open("./src/lib.rs") {
//!     Ok(f) => f,
//!     Err(e) => panic!("{}", e),
//! };
//! let mut file2 = match File::open("./src/lib.rs") {
//!     Ok(f) => f,
//!     Err(e) => panic!("{}", e),
//! };
//!
//! diff_files(&mut file1, &mut file2);
//! ```
//!
//! The diff() function takes string representations of the files and returns true
//! if the strings represent real files and those files are identical.
//!
//! ```
//! use file_diff::{diff};
//!
//! diff("./src/lib.rs", "./src/lib.rs");
//! ```

use std::io::Read;

use std::fs::{File};

/// Takes two file arguments and returns true if the two files are identical.
pub fn diff_files(f1: &mut File, f2: &mut File) -> bool {

    let mut buff1 : &mut [u8] = &mut [0; 1024];
    let mut buff2 : &mut [u8] = &mut [0; 1024];

    loop {

        match f1.read(buff1) {
            Err(_) => return false,
            Ok(f1_read_len) => match f2.read(buff2) {
                Err(_) => return false,
                Ok(f2_read_len) => {
                    if f1_read_len != f2_read_len {
                        return false;
                    }
                    if f1_read_len == 0 {
                        return true;
                    }
                    if &buff1[0..f1_read_len] != &buff2[0..f2_read_len] {
                        return false;
                    }
                }
            }
        }
    }
}

/// Takes two string filepaths and returns true if the two files are identical and exist.
pub fn diff(f1: &str, f2: &str) -> bool {
    let mut fh1 = File::open(f1);
    let mut fh2 = File::open(f2);

    fh1.as_mut().and_then(|file1|
        fh2.as_mut().and_then(|file2|
            Ok(diff_files(file1, file2)))).unwrap_or(false)
}

#[cfg(test)]
mod tests {
    const LIB_RS: &'static str = "./src/lib.rs";
    const CARGO_FILE: &'static str = "./Cargo.toml";
    const RUST_BIN_FILE: &'static str = "./testdata/rust_hello";
    const C_BIN_FILE: &'static str = "./testdata/c_hello";
    const C_BIN_FILE_COPY: &'static str = "./testdata/c_hello_copy";

    #[test]
    fn diff_the_same_text_file() { assert!(super::diff(LIB_RS, LIB_RS)); }

    #[test]
    fn diff_the_same_binary_file() { assert!(super::diff(RUST_BIN_FILE, RUST_BIN_FILE)); }

    #[test]
    fn diff_identical_binary_files() { assert!(super::diff(C_BIN_FILE, C_BIN_FILE_COPY)); }

    #[test]
    fn diff_different_text_files() { assert!( !super::diff(LIB_RS, CARGO_FILE)); }

    #[test]
    fn diff_different_binary_files() { assert!( !super::diff(RUST_BIN_FILE, C_BIN_FILE)); }
}

<|endoftext|>


<commit_before>#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![feature(associated_consts)]
#![feature(specialization)]

extern crate rand;

pub mod helper;
pub mod locales;
pub use locales::en::Faker;
mod fake;
pub use fake::Fake;
pub mod faker;

#[macro_export]
macro_rules! fake {
    ($locale:ident; $cat:ident . $m:ident ($($args:expr),+)) => (<$crate::locales::$locale::Faker as $crate::faker::$cat>::$m($($args),+));
    ($locale:ident; $cat:ident . $m:ident) => (<$crate::locales::$locale::Faker as $crate::faker::$cat>::$m());
    ($cat:ident . $m:ident ($($args:expr),+)) => (<$crate::locales::en::Faker as $crate::faker::$cat>::$m($($args),+));
    ($cat:ident . $m:ident) => (<$crate::locales::en::Faker as $crate::faker::$cat>::$m());
}

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

    #[test]
    fn lorem_usage() {
        println!("{:?}", <Faker as Lorem>::word());
        println!("{:?}", <Faker as Lorem>::words(10));
        println!("{:?}", <Faker as Lorem>::sentence(4, 6));
        println!("{:?}", <Faker as Lorem>::sentences(10));
        println!("{:?}", <Faker as Lorem>::paragraph(7, 3));
        println!("{:?}", <Faker as Lorem>::paragraphs(3));
    }

    #[test]
    fn name_usage() {
        println!("{:?}", <Faker as Name>::first_name());
        println!("{:?}", <Faker as Name>::last_name());
        println!("{:?}", <Faker as Name>::name());
        println!("{:?}", <Faker as Name>::name_with_middle());
        println!("{:?}", <Faker as Name>::title_descriptor());
        println!("{:?}", <Faker as Name>::title_level());
        println!("{:?}", <Faker as Name>::title_job());
        println!("{:?}", <Faker as Name>::title());

        use super::locales::zh_tw;
        println!("{}", <zh_tw::Faker as Name>::first_name());
        println!("{}", <zh_tw::Faker as Name>::last_name());
        println!("{}", <zh_tw::Faker as Name>::name());
        println!("{:?}", <zh_tw::Faker as Name>::name_with_middle());
        println!("{:?}", <zh_tw::Faker as Name>::title_descriptor());
        println!("{:?}", <zh_tw::Faker as Name>::title_level());
        println!("{:?}", <zh_tw::Faker as Name>::title_job());
        println!("{:?}", <zh_tw::Faker as Name>::title());
    }

    #[test]
    fn number_usage() {
        println!("{:?}", <Faker as Number>::digit());
        println!("{:?}", <Faker as Number>::number(10));
        println!("{:?}", <Faker as Number>::between(5, 10));
        println!("{:?}", <Faker as Number>::between(5.0_f32, 10.0_f32));
    }

    #[test]
    fn boolean_usage() {
        println!("{:?}", <Faker as Boolean>::boolean());
    }

    #[test]
    fn internet_usage() {
        println!("{:?}", <Faker as Internet>::free_email_provider());
        println!("{:?}", <Faker as Internet>::domain_suffix());
        println!("{:?}", <Faker as Internet>::user_name());
        println!("{:?}", <Faker as Internet>::free_email());
        println!("{:?}", <Faker as Internet>::safe_email());
        println!("{:?}", <Faker as Internet>::password(8, 20));
    }

    #[test]
    fn company_usage() {
        println!("{:?}", <Faker as Company>::suffix());
        println!("{:?}", <Faker as Company>::name());
        println!("{:?}", <Faker as Company>::buzzword());
        println!("{:?}", <Faker as Company>::catch_phase());
        println!("{:?}", <Faker as Company>::bs());
        println!("{:?}", <Faker as Company>::profession());
        println!("{:?}", <Faker as Company>::industry());
    }

    #[test]
    fn address_usage() {
        println!("{:?}", <Faker as Address>::time_zone());
        println!("{:?}", <Faker as Address>::city_prefix());
        println!("{:?}", <Faker as Address>::city_suffix());
        println!("{:?}", <Faker as Address>::street_suffix());
        println!("{:?}", <Faker as Address>::state());
        println!("{:?}", <Faker as Address>::state_abbr());
        println!("{:?}", <Faker as Address>::city());
        println!("{:?}", <Faker as Address>::street_name());
        println!("{:?}", <Faker as Address>::building_number());
        println!("{:?}", <Faker as Address>::street_address());
        println!("{:?}", <Faker as Address>::secondary_address());
        println!("{:?}", <Faker as Address>::zip());
        println!("{:?}", <Faker as Address>::postcode());
        println!("{:?}", <Faker as Address>::latitude());
        println!("{:?}", <Faker as Address>::longitude());
    }

    #[test]
    fn phone_number_usage() {
        println!("{:?}", <Faker as PhoneNumber>::phone_number());
        println!("{:?}", <Faker as PhoneNumber>::phone_number_with_format("N#######"));
        println!("{:?}", <Faker as PhoneNumber>::cell_number());
    }

    #[test]
    fn macro_test() {
        println!("{:?}", fake!(Lorem.word));
        println!("{:?}", fake!(Number.number(10)));
        println!("{:?}", fake!(Lorem.sentence(4, 6)));
        println!("{:?}", fake!(zh_tw; Name.name));
    }
}
<commit_msg>Add Macro Variant with "in <lang>"<commit_after>#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![feature(associated_consts)]
#![feature(specialization)]

extern crate rand;

pub mod helper;
pub mod locales;
pub use locales::en::Faker;
mod fake;
pub use fake::Fake;
pub mod faker;

#[macro_export]
macro_rules! fake {
    ($locale:ident; $cat:ident . $m:ident ($($args:expr),+)) => (<$crate::locales::$locale::Faker as $crate::faker::$cat>::$m($($args),+));
    ($locale:ident; $cat:ident . $m:ident) => (<$crate::locales::$locale::Faker as $crate::faker::$cat>::$m());
    ($cat:ident . $m:ident ($($args:expr),+) in $locale:ident) => (<$crate::locales::$locale::Faker as $crate::faker::$cat>::$m($($args),+));
    ($cat:ident . $m:ident in $locale:ident) => (<$crate::locales::$locale::Faker as $crate::faker::$cat>::$m());
    ($cat:ident . $m:ident ($($args:expr),+)) => (<$crate::locales::en::Faker as $crate::faker::$cat>::$m($($args),+));
    ($cat:ident . $m:ident) => (<$crate::locales::en::Faker as $crate::faker::$cat>::$m());
}

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

    #[test]
    fn lorem_usage() {
        println!("{:?}", <Faker as Lorem>::word());
        println!("{:?}", <Faker as Lorem>::words(10));
        println!("{:?}", <Faker as Lorem>::sentence(4, 6));
        println!("{:?}", <Faker as Lorem>::sentences(10));
        println!("{:?}", <Faker as Lorem>::paragraph(7, 3));
        println!("{:?}", <Faker as Lorem>::paragraphs(3));
    }

    #[test]
    fn name_usage() {
        println!("{:?}", <Faker as Name>::first_name());
        println!("{:?}", <Faker as Name>::last_name());
        println!("{:?}", <Faker as Name>::name());
        println!("{:?}", <Faker as Name>::name_with_middle());
        println!("{:?}", <Faker as Name>::title_descriptor());
        println!("{:?}", <Faker as Name>::title_level());
        println!("{:?}", <Faker as Name>::title_job());
        println!("{:?}", <Faker as Name>::title());

        use super::locales::zh_tw;
        println!("{}", <zh_tw::Faker as Name>::first_name());
        println!("{}", <zh_tw::Faker as Name>::last_name());
        println!("{}", <zh_tw::Faker as Name>::name());
        println!("{:?}", <zh_tw::Faker as Name>::name_with_middle());
        println!("{:?}", <zh_tw::Faker as Name>::title_descriptor());
        println!("{:?}", <zh_tw::Faker as Name>::title_level());
        println!("{:?}", <zh_tw::Faker as Name>::title_job());
        println!("{:?}", <zh_tw::Faker as Name>::title());
    }

    #[test]
    fn number_usage() {
        println!("{:?}", <Faker as Number>::digit());
        println!("{:?}", <Faker as Number>::number(10));
        println!("{:?}", <Faker as Number>::between(5, 10));
        println!("{:?}", <Faker as Number>::between(5.0_f32, 10.0_f32));
    }

    #[test]
    fn boolean_usage() {
        println!("{:?}", <Faker as Boolean>::boolean());
    }

    #[test]
    fn internet_usage() {
        println!("{:?}", <Faker as Internet>::free_email_provider());
        println!("{:?}", <Faker as Internet>::domain_suffix());
        println!("{:?}", <Faker as Internet>::user_name());
        println!("{:?}", <Faker as Internet>::free_email());
        println!("{:?}", <Faker as Internet>::safe_email());
        println!("{:?}", <Faker as Internet>::password(8, 20));
    }

    #[test]
    fn company_usage() {
        println!("{:?}", <Faker as Company>::suffix());
        println!("{:?}", <Faker as Company>::name());
        println!("{:?}", <Faker as Company>::buzzword());
        println!("{:?}", <Faker as Company>::catch_phase());
        println!("{:?}", <Faker as Company>::bs());
        println!("{:?}", <Faker as Company>::profession());
        println!("{:?}", <Faker as Company>::industry());
    }

    #[test]
    fn address_usage() {
        println!("{:?}", <Faker as Address>::time_zone());
        println!("{:?}", <Faker as Address>::city_prefix());
        println!("{:?}", <Faker as Address>::city_suffix());
        println!("{:?}", <Faker as Address>::street_suffix());
        println!("{:?}", <Faker as Address>::state());
        println!("{:?}", <Faker as Address>::state_abbr());
        println!("{:?}", <Faker as Address>::city());
        println!("{:?}", <Faker as Address>::street_name());
        println!("{:?}", <Faker as Address>::building_number());
        println!("{:?}", <Faker as Address>::street_address());
        println!("{:?}", <Faker as Address>::secondary_address());
        println!("{:?}", <Faker as Address>::zip());
        println!("{:?}", <Faker as Address>::postcode());
        println!("{:?}", <Faker as Address>::latitude());
        println!("{:?}", <Faker as Address>::longitude());
    }

    #[test]
    fn phone_number_usage() {
        println!("{:?}", <Faker as PhoneNumber>::phone_number());
        println!("{:?}", <Faker as PhoneNumber>::phone_number_with_format("N#######"));
        println!("{:?}", <Faker as PhoneNumber>::cell_number());
    }

    #[test]
    fn macro_test() {
        println!("{:?}", fake!(Lorem.word));
        println!("{:?}", fake!(Number.number(10)));
        println!("{:?}", fake!(Lorem.sentence(4, 6)));
        println!("{:?}", fake!(zh_tw; Name.name));

        println!("{:?}", fake!(Name.name in zh_tw));
        println!("{:?}", fake!(Lorem.sentence(4, 6) in zh_tw));
    }
}
<|endoftext|>


<commit_before>extern crate rand;
use std::str;
use std::fmt;
use rand::Rng;

#[derive(Debug, Eq, PartialEq, PartialOrd, Clone)]
pub struct Card {
    pub suit:  String,
    pub value: String,
}

#[derive(Debug, Eq, PartialEq, PartialOrd, Clone)]
pub struct Deck {
    pub cards: Vec<Card>
}

impl Card {
    pub fn new(suit: String, value: String) -> Card {
        Card { suit: suit, value: value.to_string() }
    }

    pub fn new_from_str(suit: &str, value: &str) -> Card {
        Card::new(suit.to_string(), value.to_string())
    }
}

impl Ord for Card {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.value.cmp(&other.value)
    }
}

impl fmt::Display for Card {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Suit: {}, Value: {}", self.suit, self.value)
    }
}

impl Deck {
    pub fn new_from_vec(input: Vec<Card>) -> Deck {
        Deck { cards: input }
    }

    pub fn make_standard() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠"];
        let values = &["2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Queen", "King", "Ace"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    pub fn make_fifth_dimension() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠", "★"];
        let values = &["1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Princess", "Queen", "King", "Joker"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    // destructively shuffles the internal vector
    pub fn shuffle(&mut self) {
        rand::thread_rng().shuffle(&mut self.cards);
    }

    // returns a new shuffled deck
    pub fn shuffled(&self) -> Self {
        let mut res = self.clone();
        res.shuffle();
        res
    }

    pub fn len(&self) {
        self.cards.len();
    }
}

impl Ord for Deck {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.cards.cmp(&other.cards)
    }
}
<commit_msg>have len actually return the length<commit_after>extern crate rand;
use std::str;
use std::fmt;
use rand::Rng;

#[derive(Debug, Eq, PartialEq, PartialOrd, Clone)]
pub struct Card {
    pub suit:  String,
    pub value: String,
}

#[derive(Debug, Eq, PartialEq, PartialOrd, Clone)]
pub struct Deck {
    pub cards: Vec<Card>
}

impl Card {
    pub fn new(suit: String, value: String) -> Card {
        Card { suit: suit, value: value.to_string() }
    }

    pub fn new_from_str(suit: &str, value: &str) -> Card {
        Card::new(suit.to_string(), value.to_string())
    }
}

impl Ord for Card {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.value.cmp(&other.value)
    }
}

impl fmt::Display for Card {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Suit: {}, Value: {}", self.suit, self.value)
    }
}

impl Deck {
    pub fn new_from_vec(input: Vec<Card>) -> Deck {
        Deck { cards: input }
    }

    pub fn make_standard() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠"];
        let values = &["2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Queen", "King", "Ace"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    pub fn make_fifth_dimension() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠", "★"];
        let values = &["1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Princess", "Queen", "King", "Joker"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    // destructively shuffles the internal vector
    pub fn shuffle(&mut self) {
        rand::thread_rng().shuffle(&mut self.cards);
    }

    // returns a new shuffled deck
    pub fn shuffled(&self) -> Self {
        let mut res = self.clone();
        res.shuffle();
        res
    }

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

impl Ord for Deck {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.cards.cmp(&other.cards)
    }
}
<|endoftext|>


<commit_before>#![no_std]
#![crate_name = "klogger"]
#![crate_type = "lib"]

use core::fmt;
pub mod macros;

#[cfg(target_arch = "x86_64")]
extern crate x86;

#[cfg(target_arch = "x86_64")]
#[path = "arch/x86.rs"]
mod arch;

pub struct Writer;

impl Writer {
    /// Obtain a logger for the specified module.
    pub fn get_module(module: &str) -> Writer {
        use core::fmt::Write;
        let mut ret = Writer;
        write!(&mut ret, "[{}] ", module).expect("Writer");
        ret
    }

    pub fn get() -> Writer {
        Writer
    }
}

impl ::core::ops::Drop for Writer {
    /// Release the logger.
    fn drop(&mut self) {
        use core::fmt::Write;
        write!(self, "\n").expect("Newline");
    }
}

impl fmt::Write for Writer {
    /// Write stuff to serial out.
    fn write_str(&mut self, s: &str) -> fmt::Result {
        unsafe {
            arch::puts(s);
        }
        Ok(())
    }
}
<commit_msg>Deny warnings by default.<commit_after>#![no_std]
#![crate_name = "klogger"]
#![crate_type = "lib"]
#![deny(warnings)]

use core::fmt;
pub mod macros;

#[cfg(target_arch = "x86_64")]
extern crate x86;

#[cfg(target_arch = "x86_64")]
#[path = "arch/x86.rs"]
mod arch;

pub struct Writer;

impl Writer {
    /// Obtain a logger for the specified module.
    pub fn get_module(module: &str) -> Writer {
        use core::fmt::Write;
        let mut ret = Writer;
        write!(&mut ret, "[{}] ", module).expect("Writer");
        ret
    }

    pub fn get() -> Writer {
        Writer
    }
}

impl ::core::ops::Drop for Writer {
    /// Release the logger.
    fn drop(&mut self) {
        use core::fmt::Write;
        write!(self, "\n").expect("Newline");
    }
}

impl fmt::Write for Writer {
    /// Write stuff to serial out.
    fn write_str(&mut self, s: &str) -> fmt::Result {
        unsafe {
            arch::puts(s);
        }
        Ok(())
    }
}
<|endoftext|>


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

//! Macro to create a "view box", a box containing data plus
//! a "view" struct that can have interior references into the data.
//! The view box can be moved around as an atomic unit.
#![feature(macro_rules, globs, unboxed_closures)]

#[macro_export]
macro_rules! viewbox(
    (struct $name:ident<$d:ty, $v:ident>;) => (
        pub struct $name {
            view: $v<'static>,
            #[allow(dead_code)]
            data: Box<$d>
        }

        #[allow(dead_code)]
        impl $name {
            pub fn new<F>(data: $d, f: F) -> $name
                          where F: for<'a> FnOnce(&'a mut $d) -> $v<'a> {
                let mut d = box data;
                let v = unsafe { ::std::mem::transmute(f(&mut *d)) };

                $name { data: d, view: v }
            }

            pub fn new_result<E,F>(data: $d,
                                   f: F)
                                   -> ::std::result::Result<$name,($d,E)>
                                   where F: for<'a> FnOnce(&'a mut $d) -> ::std::result::Result<$v<'a>,E> {
                let mut d = box data;
                match f(&mut *d).map(|v| unsafe { ::std::mem::transmute(v) }) {
                    Ok(v) => Ok($name { data: d, view: v }),
                    Err(e) => Err((*d,e))
                }
            }

            pub fn into_inner(self)-> $d {
                let $name { data: box data, .. } = self;
                data
            }

            pub fn view<'a>(&'a self) -> &'a $v<'a> {
                unsafe { ::std::mem::transmute(&self.view) }
            }

            pub fn view_mut<'a>(&'a mut self) -> &'a mut $v<'a> {
                unsafe { ::std::mem::transmute(&mut self.view) }
            }
        }
    );
    (#[deriving(PartialEq $(,$derive:ident)*)] struct $name:ident<$d:ty, $v:ident>;) => (
        impl ::std::cmp::PartialEq for $name {
            fn eq(&self, other: &$name) -> bool { self.view() == other.view(); }
        }
        viewbox!(struct $name<$d,$v>;)
    );
    (#[deriving(Show $(,$derive:ident)*)] struct $name:ident<$d:ty, $v:ident>;) => (
        impl ::std::fmt::Show for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                   -> ::std::result::Result<(), ::std::fmt::FormatError> {
                self.view().fmt(fmt)
            }
        }
        viewbox!(struct $name<$d,$v>;)
    );
    (#[deriving()] struct $name:ident<$d:ty, $v:ident>;) => (
        viewbox!(struct $name<$d,$v>;)
    );
)

#[cfg(test)]
mod test {
    extern crate arena;
    use self::arena::TypedArena;

    // Test data structure
    #[deriving(PartialEq,Show)]
    struct TestData {
        foo: i32,
        bar: String
    }

    // View structure that has references into the boxed data
    struct TestView<'a> {
        x: &'a i32,
        y: &'a str
    }

    // Create TestBox which combines TestData and TestView
    viewbox! {
        struct TestBox<TestData,TestView>;
    }

    // Mutable view into TestData
    struct MutView<'a> {
        x: &'a mut i32,
        y: &'a mut String
    }

    // MutBox combines TestData and MutView
    viewbox! {
        struct MutBox<TestData, MutView>;
    }

    #[test]
    fn basic() {
        // Create some data
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        // Move it into box, creating a view with interior references
        let v = TestBox::new(t, |d| TestView { x: &d.foo, y: d.bar.as_slice() });

        // We can access the boxed data via the view
        assert_eq!(v.view().x, &42i32);
        assert_eq!(v.view().y, "Hello");
        // We can unwrap the view to get the data back
        let t = v.into_inner();
        assert_eq!(t.foo, 42i32);
        assert_eq!(t.bar, "Hello".to_string());
    }

    #[test]
    fn mutation() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let mut v = MutBox::new(t, |d| MutView { x: &mut d.foo, y: &mut d.bar });

        *v.view_mut().x = 5;
        *v.view_mut().y = "Goodbye".to_string();
        let t = v.into_inner();
        assert_eq!(t, TestData { foo: 5, bar: "Goodbye".to_string() });
    }

    #[test]
    fn error() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let v = MutBox::new_result(t, |_| Err("Nope")).err().unwrap();
        assert_eq!(v, (TestData { foo: 42, bar: "Hello".to_string() }, "Nope"))
    }

    struct ArenaView<'a> {
        arena: &'a TypedArena<int>,
        vec: Vec<&'a int>
    }

    viewbox! {
        struct ArenaBox<TypedArena<int>, ArenaView>;
    }

    #[test]
    fn arenaview() {
        let mut vb = ArenaBox::new(
            TypedArena::new(),
            |a| ArenaView { arena: a, vec: Vec::new()});

        spawn(move || {
            let v = vb.view_mut();
            let a = v.arena.alloc(1);
            let b = v.arena.alloc(2);
            let c = v.arena.alloc(3);
            v.vec.push(a);
            v.vec.push(b);
            v.vec.push(c);
        });
    }
}
<commit_msg>Fix errors and warnings<commit_after>#![crate_type = "rlib"]

//! Macro to create a "view box", a box containing data plus
//! a "view" struct that can have interior references into the data.
//! The view box can be moved around as an atomic unit.
#![feature(macro_rules, globs, unboxed_closures)]

#[macro_export]
macro_rules! viewbox {
    (struct $name:ident<$d:ty, $v:ident>;) => (
        pub struct $name {
            view: $v<'static>,
            #[allow(dead_code)]
            data: Box<$d>
        }

        #[allow(dead_code)]
        impl $name {
            pub fn new<F>(data: $d, f: F) -> $name
                          where F: for<'a> FnOnce(&'a mut $d) -> $v<'a> {
                let mut d = box data;
                let v = unsafe { ::std::mem::transmute(f(&mut *d)) };

                $name { data: d, view: v }
            }

            pub fn new_result<E,F>(data: $d,
                                   f: F)
                                   -> ::std::result::Result<$name,($d,E)>
                                   where F: for<'a> FnOnce(&'a mut $d) -> ::std::result::Result<$v<'a>,E> {
                let mut d = box data;
                match f(&mut *d).map(|v| unsafe { ::std::mem::transmute(v) }) {
                    Ok(v) => Ok($name { data: d, view: v }),
                    Err(e) => Err((*d,e))
                }
            }

            pub fn into_inner(self)-> $d {
                let $name { data: box data, .. } = self;
                data
            }

            pub fn view<'a>(&'a self) -> &'a $v<'a> {
                unsafe { ::std::mem::transmute(&self.view) }
            }

            pub fn view_mut<'a>(&'a mut self) -> &'a mut $v<'a> {
                unsafe { ::std::mem::transmute(&mut self.view) }
            }
        }
    );
    (#[deriving(PartialEq $(,$derive:ident)*)] struct $name:ident<$d:ty, $v:ident>;) => (
        impl ::std::cmp::PartialEq for $name {
            fn eq(&self, other: &$name) -> bool { self.view() == other.view(); }
        }
        viewbox!(struct $name<$d,$v>;)
    );
    (#[deriving(Show $(,$derive:ident)*)] struct $name:ident<$d:ty, $v:ident>;) => (
        impl ::std::fmt::Show for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                   -> ::std::result::Result<(), ::std::fmt::FormatError> {
                self.view().fmt(fmt)
            }
        }
        viewbox!(struct $name<$d,$v>;)
    );
    (#[deriving()] struct $name:ident<$d:ty, $v:ident>;) => (
        viewbox!(struct $name<$d,$v>;)
    );
}

#[cfg(test)]
mod test {
    extern crate arena;
    use self::arena::TypedArena;
    use std::thread::Thread;

    // Test data structure
    #[deriving(PartialEq,Show)]
    struct TestData {
        foo: i32,
        bar: String
    }

    // View structure that has references into the boxed data
    struct TestView<'a> {
        x: &'a i32,
        y: &'a str
    }

    // Create TestBox which combines TestData and TestView
    viewbox! {
        struct TestBox<TestData,TestView>;
    }

    // Mutable view into TestData
    struct MutView<'a> {
        x: &'a mut i32,
        y: &'a mut String
    }

    // MutBox combines TestData and MutView
    viewbox! {
        struct MutBox<TestData, MutView>;
    }

    #[test]
    fn basic() {
        // Create some data
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        // Move it into box, creating a view with interior references
        let v = TestBox::new(t, |d| TestView { x: &d.foo, y: d.bar.as_slice() });

        // We can access the boxed data via the view
        assert_eq!(v.view().x, &42i32);
        assert_eq!(v.view().y, "Hello");
        // We can unwrap the view to get the data back
        let t = v.into_inner();
        assert_eq!(t.foo, 42i32);
        assert_eq!(t.bar, "Hello".to_string());
    }

    #[test]
    fn mutation() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let mut v = MutBox::new(t, |d| MutView { x: &mut d.foo, y: &mut d.bar });

        *v.view_mut().x = 5;
        *v.view_mut().y = "Goodbye".to_string();
        let t = v.into_inner();
        assert_eq!(t, TestData { foo: 5, bar: "Goodbye".to_string() });
    }

    #[test]
    fn error() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let v = MutBox::new_result(t, |_| Err("Nope")).err().unwrap();
        assert_eq!(v, (TestData { foo: 42, bar: "Hello".to_string() }, "Nope"))
    }

    struct ArenaView<'a> {
        arena: &'a TypedArena<int>,
        vec: Vec<&'a int>
    }

    viewbox! {
        struct ArenaBox<TypedArena<int>, ArenaView>;
    }

    #[test]
    fn arenaview() {
        let mut vb = ArenaBox::new(
            TypedArena::new(),
            |a| ArenaView { arena: a, vec: Vec::new()});

        Thread::spawn(move || {
            let v = vb.view_mut();
            let a = v.arena.alloc(1);
            let b = v.arena.alloc(2);
            let c = v.arena.alloc(3);
            v.vec.push(a);
            v.vec.push(b);
            v.vec.push(c);
        }).join().ok().unwrap();
    }
}
<|endoftext|>