<commit_before>#![feature(vec_push_all)]

pub struct JsonEncoder {
    buffer: Vec<u8>
}

impl JsonEncoder {
    #[inline(always)]
    pub fn new() -> JsonEncoder {
        JsonEncoder{buffer: Vec::new()}
    }

    #[inline(always)]
    pub fn with_capacity(capa: usize) -> JsonEncoder {
        JsonEncoder{buffer: Vec::with_capacity(capa)}
    }

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

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

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

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

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

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

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

            self.encode_raw(escaped);

            start = i + 1;
        }

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

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

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

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

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

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

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

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

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

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

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

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

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

    pub fn encode_array_nobrackets<F>(&mut self, f: F) where F: Fn(&mut JsonArrayEncoder) {
        f(&mut JsonArrayEncoder {js: self, needs_sep: false});
    }

}

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

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

        f(self.js);
    }

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

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

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

}

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

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

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

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

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

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

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

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

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

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

pub struct JsonEncoder {
    buffer: Vec<u8>
}

impl JsonEncoder {
    #[inline(always)]
    pub fn new() -> JsonEncoder {
        JsonEncoder{buffer: Vec::new()}
    }

    #[inline(always)]
    pub fn with_capacity(capa: usize) -> JsonEncoder {
        JsonEncoder{buffer: Vec::with_capacity(capa)}
    }

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

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

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

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

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

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

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

            self.encode_raw(escaped);

            start = i + 1;
        }

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

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

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

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

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

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

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

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

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

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

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

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

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

    pub fn encode_array_nobrackets<F, T>(&mut self, f: F) -> T where F: Fn(&mut JsonArrayEncoder) -> T{
        f(&mut JsonArrayEncoder {js: self, needs_sep: false})
    }

}

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

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

        f(self.js)
    }

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

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

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

}

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

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

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

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

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

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

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

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

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

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


<commit_before>use std::{fmt, error, string};

const STANDARD: [u8; 64] = [
    0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
    0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
    0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
    0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
    0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
    0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
    0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
];

const URL_SAFE: [u8; 64] = [
    0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
    0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
    0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
    0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
    0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
    0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
    0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2D, 0x5F
];

pub enum Base64Mode {
    Standard,
    UrlSafe,
    //TODO MIME
}

#[derive(Debug)]
pub enum Base64Error {
    Utf8(string::FromUtf8Error),
    InvalidByte(usize, u8),
    InvalidLength
}

impl fmt::Display for Base64Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Base64Error::Utf8(ref err) => err.fmt(f),
            Base64Error::InvalidByte(index, byte) =>
                write!(f, "Invalid byte {}, offset {}.", byte, index),
            Base64Error::InvalidLength =>
                write!(f, "Encoded text cannot have a 6-bit remainder.")
        }
    }
}

impl error::Error for Base64Error {
    fn description(&self) -> &str {
        match *self {
            Base64Error::Utf8(ref err) => err.description(),
            Base64Error::InvalidByte(_,_) => "invalid byte",
            Base64Error::InvalidLength => "invalid length"
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Base64Error::Utf8(ref err) => Some(err as &error::Error),
            _ => None
        }
    }
}

impl From<string::FromUtf8Error> for Base64Error {
    fn from(err: string::FromUtf8Error) -> Base64Error {
        Base64Error::Utf8(err)
    }
}

///Encode arbitrary octets as base64.
///Returns a String.
///Convenience for `encode_mode(input, Base64Mode::Standard);`.
///
///# Example
///
///```rust
///extern crate base64;
///
///fn main() {
///    let b64 = base64::encode(b"hello world");
///    println!("{}", b64);
///}
///```
pub fn encode(input: &[u8]) -> String {
    encode_mode(input, Base64Mode::Standard)
}

///Decode from string reference as octets.
///Returns a Result containing a Vec<u8>.
///Convenience `decode_mode(input, Base64Mode::Standard);`.
///
///# Example
///
///```rust
///extern crate base64;
///
///fn main() {
///    let bytes = base64::decode("aGVsbG8gd29ybGQ=").unwrap();
///    println!("{:?}", bytes);
///}
///```
pub fn decode(input: &str) -> Result<Vec<u8>, Base64Error> {
    decode_mode(input, Base64Mode::Standard)
}

///DEPRECATED -- will be replaced by `decode_mode(input, Base64Mode::MIME);`
///
///Decode from string reference as octets.
///Returns a Result containing a Vec<u8>.
///Ignores extraneous whitespace.
///
///# Example
///
///```rust
///extern crate base64;
///
///fn main() {
///    let bytes = base64::decode_ws("aG VsbG8gd2\r\n9ybGQ=").unwrap();
///    println!("{:?}", bytes);
///}
///```
pub fn decode_ws(input: &str) -> Result<Vec<u8>, Base64Error> {
    let mut raw = Vec::<u8>::with_capacity(input.len());
    raw.extend(input.bytes().filter(|b| !b" \n\t\r\x0c".contains(b)));

    let sans_ws = String::from_utf8(raw).unwrap();
    decode_mode(&sans_ws, Base64Mode::Standard)
}

///Encode arbitrary octets as base64.
///Returns a String.
///
///# Example
///
///```rust
///extern crate base64;
///use base64::Base64Mode;
///
///fn main() {
///    let b64 = base64::encode_mode(b"hello world~", Base64Mode::Standard);
///    println!("{}", b64);
///
///    let b64_url = base64::encode_mode(b"hello internet~", Base64Mode::UrlSafe);
///    println!("{}", b64_url);
///}
///```
pub fn encode_mode(bytes: &[u8], mode: Base64Mode) -> String {
    let (ref charset, _) = match mode {
        Base64Mode::Standard => (STANDARD, false),
        Base64Mode::UrlSafe => (URL_SAFE, false),
        //TODO Base64Mode::MIME => (STANDARD, true)
    };

    let rem = bytes.len() % 3;
    let div = bytes.len() - rem;

    let mut raw = Vec::<u8>::with_capacity(4*div/3 + if rem == 0 {4} else {0});
    let mut i = 0;

    while i < div {
        raw.push(charset[(bytes[i] >> 2) as usize]);
        raw.push(charset[((bytes[i] << 4 | bytes[i+1] >> 4) & 0x3f) as usize]);
        raw.push(charset[((bytes[i+1] << 2 | bytes[i+2] >> 6) & 0x3f) as usize]);
        raw.push(charset[(bytes[i+2] & 0x3f) as usize]);

        i+=3;
    }

    if rem == 2 {
        raw.push(charset[(bytes[div] >> 2) as usize]);
        raw.push(charset[((bytes[div] << 4 | bytes[div+1] >> 4) & 0x3f) as usize]);
        raw.push(charset[(bytes[div+1] << 2 & 0x3f) as usize]);
    } else if rem == 1 {
        raw.push(charset[(bytes[div] >> 2) as usize]);
        raw.push(charset[(bytes[div] << 4 & 0x3f) as usize]);
    }

    for _ in 0..(3-rem)%3 {
        raw.push(0x3d);
    }

    //this should never panic, all bytes from charset so always valid ascii
    String::from_utf8(raw).unwrap()
}

///Decode from string reference as octets.
///Returns a Result containing a Vec<u8>.
///
///# Example
///
///```rust
///extern crate base64;
///use base64::Base64Mode;
///
///fn main() {
///    let bytes = base64::decode_mode("aGVsbG8gd29ybGR+Cg==", Base64Mode::Standard).unwrap();
///    println!("{:?}", bytes);
///
///    let bytes_url = base64::decode_mode("aGVsbG8gaW50ZXJuZXR-Cg==", Base64Mode::UrlSafe).unwrap();
///    println!("{:?}", bytes_url);
///}
///```
pub fn decode_mode(input: &str, mode: Base64Mode) -> Result<Vec<u8>, Base64Error> {
    let (ref charset, _) = match mode {
        Base64Mode::Standard => (STANDARD, false),
        Base64Mode::UrlSafe => (URL_SAFE, false),
        //TODO Base64Mode::MIME => (STANDARD, true)
    };

    let (penult_byte, ult_byte) = (charset[62], charset[63]);

    let mut buffer = Vec::<u8>::with_capacity(input.len());

    for (i, b) in input.bytes().enumerate() {
        if b > 0x40 && b < 0x5b {
            buffer.push(b - 0x41);
        } else if b > 0x60 && b < 0x7b {
            buffer.push(b - 0x61 + 0x1a);
        } else if b > 0x2f && b < 0x3a {
            buffer.push(b - 0x30 + 0x34);
        } else if b == penult_byte {
            buffer.push(0x3e);
        } else if b == ult_byte {
            buffer.push(0x3f);
        } else if b == 0x3d {
            ;
        } else {
            return Err(Base64Error::InvalidByte(i, b));
        }
    }

    let rem = buffer.len() % 4;

    if rem == 1 {
        return Err(Base64Error::InvalidLength);
    }

    let div = buffer.len() - rem;

    let mut raw = Vec::<u8>::with_capacity(3*div/4 + rem);
    let mut i = 0;

    while i < div {
        raw.push(buffer[i] << 2 | buffer[i+1] >> 4);
        raw.push(buffer[i+1] << 4 | buffer[i+2] >> 2);
        raw.push(buffer[i+2] << 6 | buffer[i+3]);

        i+=4;
    }

    if rem > 1 {
        raw.push(buffer[div] << 2 | buffer[div+1] >> 4);
    }
    if rem > 2 {
        raw.push(buffer[div+1] << 4 | buffer[div+2] >> 2);
    }

    Ok(raw)
}
<commit_msg>Update lib.rs<commit_after>use std::{fmt, error, string};

const STANDARD: [u8; 64] = [
    0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
    0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
    0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
    0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
    0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
    0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
    0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
];

const URL_SAFE: [u8; 64] = [
    0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
    0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
    0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
    0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
    0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
    0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
    0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2D, 0x5F
];

pub enum Base64Mode {
    Standard,
    UrlSafe,
    //TODO MIME
}

#[derive(Debug, PartialEq, Eq)]
pub enum Base64Error {
    Utf8(str::Utf8Error),
    InvalidByte(usize, u8),
    InvalidLength,
}

impl fmt::Display for Base64Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Base64Error::Utf8(ref err) => err.fmt(f),
            Base64Error::InvalidByte(index, byte) =>
                write!(f, "Invalid byte {}, offset {}.", byte, index),
            Base64Error::InvalidLength =>
                write!(f, "Encoded text cannot have a 6-bit remainder.")
        }
    }
}

impl error::Error for Base64Error {
    fn description(&self) -> &str {
        match *self {
            Base64Error::Utf8(ref err) => err.description(),
            Base64Error::InvalidByte(_,_) => "invalid byte",
            Base64Error::InvalidLength => "invalid length"
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Base64Error::Utf8(ref err) => Some(err as &error::Error),
            _ => None
        }
    }
}

impl From<str::Utf8Error> for Base64Error {
    fn from(err: str::Utf8Error) -> Base64Error {
        Base64Error::Utf8(err)
    }
}

///Encode arbitrary octets as base64.
///Returns a String.
///Convenience for `encode_mode(input, Base64Mode::Standard);`.
///
///# Example
///
///```rust
///extern crate base64;
///
///fn main() {
///    let b64 = base64::encode(b"hello world");
///    println!("{}", b64);
///}
///```
pub fn encode(input: &[u8]) -> String {
    encode_mode(input, Base64Mode::Standard)
}

///Decode from string reference as octets.
///Returns a Result containing a Vec<u8>.
///Convenience `decode_mode(input, Base64Mode::Standard);`.
///
///# Example
///
///```rust
///extern crate base64;
///
///fn main() {
///    let bytes = base64::decode("aGVsbG8gd29ybGQ=").unwrap();
///    println!("{:?}", bytes);
///}
///```
pub fn decode(input: &str) -> Result<Vec<u8>, Base64Error> {
    decode_mode(input, Base64Mode::Standard)
}

///DEPRECATED -- will be replaced by `decode_mode(input, Base64Mode::MIME);`
///
///Decode from string reference as octets.
///Returns a Result containing a Vec<u8>.
///Ignores extraneous whitespace.
///
///# Example
///
///```rust
///extern crate base64;
///
///fn main() {
///    let bytes = base64::decode_ws("aG VsbG8gd2\r\n9ybGQ=").unwrap();
///    println!("{:?}", bytes);
///}
///```
pub fn decode_ws(input: &str) -> Result<Vec<u8>, Base64Error> {
    let mut raw = Vec::<u8>::with_capacity(input.len());
    raw.extend(input.bytes().filter(|b| !b" \n\t\r\x0c".contains(b)));

    let sans_ws = String::from_utf8(raw).unwrap();
    decode_mode(&sans_ws, Base64Mode::Standard)
}

///Encode arbitrary octets as base64.
///Returns a String.
///
///# Example
///
///```rust
///extern crate base64;
///use base64::Base64Mode;
///
///fn main() {
///    let b64 = base64::encode_mode(b"hello world~", Base64Mode::Standard);
///    println!("{}", b64);
///
///    let b64_url = base64::encode_mode(b"hello internet~", Base64Mode::UrlSafe);
///    println!("{}", b64_url);
///}
///```
pub fn encode_mode(bytes: &[u8], mode: Base64Mode) -> String {
    let (ref charset, _) = match mode {
        Base64Mode::Standard => (STANDARD, false),
        Base64Mode::UrlSafe => (URL_SAFE, false),
        //TODO Base64Mode::MIME => (STANDARD, true)
    };

    let rem = bytes.len() % 3;
    let div = bytes.len() - rem;

    let mut raw = Vec::<u8>::with_capacity(4*div/3 + if rem == 0 {4} else {0});
    let mut i = 0;

    while i < div {
        raw.push(charset[(bytes[i] >> 2) as usize]);
        raw.push(charset[((bytes[i] << 4 | bytes[i+1] >> 4) & 0x3f) as usize]);
        raw.push(charset[((bytes[i+1] << 2 | bytes[i+2] >> 6) & 0x3f) as usize]);
        raw.push(charset[(bytes[i+2] & 0x3f) as usize]);

        i+=3;
    }

    if rem == 2 {
        raw.push(charset[(bytes[div] >> 2) as usize]);
        raw.push(charset[((bytes[div] << 4 | bytes[div+1] >> 4) & 0x3f) as usize]);
        raw.push(charset[(bytes[div+1] << 2 & 0x3f) as usize]);
    } else if rem == 1 {
        raw.push(charset[(bytes[div] >> 2) as usize]);
        raw.push(charset[(bytes[div] << 4 & 0x3f) as usize]);
    }

    for _ in 0..(3-rem)%3 {
        raw.push(0x3d);
    }

    //this should never panic, all bytes from charset so always valid ascii
    String::from_utf8(raw).unwrap()
}

///Decode from string reference as octets.
///Returns a Result containing a Vec<u8>.
///
///# Example
///
///```rust
///extern crate base64;
///use base64::Base64Mode;
///
///fn main() {
///    let bytes = base64::decode_mode("aGVsbG8gd29ybGR+Cg==", Base64Mode::Standard).unwrap();
///    println!("{:?}", bytes);
///
///    let bytes_url = base64::decode_mode("aGVsbG8gaW50ZXJuZXR-Cg==", Base64Mode::UrlSafe).unwrap();
///    println!("{:?}", bytes_url);
///}
///```
pub fn decode_mode(input: &str, mode: Base64Mode) -> Result<Vec<u8>, Base64Error> {
    let (ref charset, _) = match mode {
        Base64Mode::Standard => (STANDARD, false),
        Base64Mode::UrlSafe => (URL_SAFE, false),
        //TODO Base64Mode::MIME => (STANDARD, true)
    };

    let (penult_byte, ult_byte) = (charset[62], charset[63]);

    let mut buffer = Vec::<u8>::with_capacity(input.len());

    for (i, b) in input.bytes().enumerate() {
        if b > 0x40 && b < 0x5b {
            buffer.push(b - 0x41);
        } else if b > 0x60 && b < 0x7b {
            buffer.push(b - 0x61 + 0x1a);
        } else if b > 0x2f && b < 0x3a {
            buffer.push(b - 0x30 + 0x34);
        } else if b == penult_byte {
            buffer.push(0x3e);
        } else if b == ult_byte {
            buffer.push(0x3f);
        } else if b == 0x3d {
            ;
        } else {
            return Err(Base64Error::InvalidByte(i, b));
        }
    }

    let rem = buffer.len() % 4;

    if rem == 1 {
        return Err(Base64Error::InvalidLength);
    }

    let div = buffer.len() - rem;

    let mut raw = Vec::<u8>::with_capacity(3*div/4 + rem);
    let mut i = 0;

    while i < div {
        raw.push(buffer[i] << 2 | buffer[i+1] >> 4);
        raw.push(buffer[i+1] << 4 | buffer[i+2] >> 2);
        raw.push(buffer[i+2] << 6 | buffer[i+3]);

        i+=4;
    }

    if rem > 1 {
        raw.push(buffer[div] << 2 | buffer[div+1] >> 4);
    }
    if rem > 2 {
        raw.push(buffer[div+1] << 4 | buffer[div+2] >> 2);
    }

    Ok(raw)
}
<|endoftext|>


<commit_before>//! The couchdb crate is a thin wrapper around the CouchDB API, providing
//! low-level access to individual CouchDB commands—e.g., PUT database, GET
//! document, etc. The goal for the crate is to deal with the menial task of
//! sending HTTP requests and receiving HTTP responses and to allow application
//! programmers to focus on their business logic.
//!
//! This documentation has been written assuming the application programmer is
//! familiar with the CouchDB API. Descriptions of types, methods, etc. in the
//! couchdb crate should provide just enough information for the programmer to
//! map the crate's concepts onto the CouchDB API and then use the CouchDB
//! documentation as needed to fill in remaining details. Most names in the
//! crate API are identical to the names used in the CouchDB API so as to make
//! this mapping straightforward. There's also a table, below, that [shows the
//! mapping a high level](#couchdb-api-coverage).
//!
//! One key difference between the couchdb crate's API and the CouchDB API is
//! the crate provides stronger type-safety beyond working with raw strings. For
//! example, applications get and put documents using structured types, and
//! other types, such as revisions and views, are strongly typed as well.
//!
//! To deal with JSON, the couchdb crate relies on Serde and its traits
//! `serde::Serialize` and `serde::Deserialize`. These traits are fundamental to
//! the crate's API—they are not mere implementation details. As such,
//! applications must use these traits when working with documents, views, or
//! any type that is JSON-encoded in the CouchDB API.
//!
//! ## Example: create and read a document
//!
//! This example (1) creates a database, (2) creates a document within that
//! database, and (3) reads the new document.
//!
//! ```no_run
//! extern crate couchdb;
//! extern crate serde_json;
//!
//! let client = couchdb::Client::new("http://couchdb-server:5984/").unwrap();
//!
//! client.put_database("/baseball").run().unwrap();
//!
//! let value = serde_json::builder::ObjectBuilder::new()
//!                 .insert("name", "Babe Ruth")
//!                 .insert("career_hr", 714)
//!                 .unwrap();
//! let (rev, doc_id) = client.post_to_database("/baseball", &value)
//!                           .run()
//!                           .unwrap();
//!
//! let doc = client.get_document::<_, serde_json::Value>(("/baseball", doc_id.clone()))
//!                 .run()
//!                 .unwrap()
//!                 .unwrap();
//! assert_eq!(doc.id, doc_id);
//! assert_eq!(doc.revision, rev);
//! assert_eq!(doc.content, value);
//! ```
//!
//! ## CouchDB API coverage
//!
//! In the couchdb crate, the `Client` type is the principal type for
//! communicating with a CouchDB server. All HTTP requests to the CouchDB server
//! go through a `Client` instance.
//!
//! This table maps each CouchDB API resource to the `Client` method that accesses
//! that resource.
//!
//!

//!

//!

//!    CouchDB URI
//!    HTTP method
//!    Client method
//!    Description
//!

//!

//!

//!

//!
//!

/_all_dbs

//!
//!    GET
//!    get_all_databases
//!    Get list of all databases.
//!

//!

//!
//!

/db

//!
//!    HEAD
//!    head_database
//!    Test whether a database exists.
//!

//!

//!    GET
//!    get_database
//!    Get meta-information about a database.
//!

//!

//!    PUT
//!    put_database
//!    Create a database.
//!

//!

//!    DELETE
//!    delete_database
//!    Delete a database.
//!

//!

//!    POST
//!    post_to_database
//!    Create a document.
//!

//!

//!
//!

//!
/db/doc

//!
/db/_design/design-doc

//!
/db/_local/id

//!

//!
//!    HEAD
//!    head_document
//!    Test whether a document exists.
//!

//!

//!    GET
//!    get_document
//!    Get meta-information and application-defined content for a
//!    document.
//!

//!

//!    PUT
//!    put_document
//!    Create or update a document.
//!

//!

//!    DELETE
//!    delete_document
//!    Delete a document.
//!

//!

//!
//!

/db/_design/design-doc/_view/view

//!
//!    GET
//!    get_view
//!    Execute a view.
//!

//!

//!

extern crate hyper;
extern crate regex;
extern crate serde;
extern crate serde_json;
extern crate tempdir;
extern crate url;

pub mod command;

mod client;
mod dbtype;
mod error;
mod json;
mod path;
mod server;

pub use client::{Client, IntoUrl};
pub use dbtype::{Database, DatabaseName, Design, DesignBuilder, DesignDocumentName, Document,
                 DocumentId, DocumentName, ErrorResponse, ViewName, Revision, ViewFunction,
                 ViewFunctionMap, ViewResult, ViewRow};
pub use path::{IntoDatabasePath, IntoDesignDocumentPath, IntoDocumentPath, IntoViewPath,
               DatabasePath, DesignDocumentPath, DocumentPath, ViewPath};
pub use error::Error;
pub use server::Server;
<commit_msg>Clarify crate-level doc comment example<commit_after>//! The couchdb crate is a thin wrapper around the CouchDB API, providing
//! low-level access to individual CouchDB commands—e.g., PUT database, GET
//! document, etc. The goal for the crate is to deal with the menial task of
//! sending HTTP requests and receiving HTTP responses and to allow application
//! programmers to focus on their business logic.
//!
//! This documentation has been written assuming the application programmer is
//! familiar with the CouchDB API. Descriptions of types, methods, etc. in the
//! couchdb crate should provide just enough information for the programmer to
//! map the crate's concepts onto the CouchDB API and then use the CouchDB
//! documentation as needed to fill in remaining details. Most names in the
//! crate API are identical to the names used in the CouchDB API so as to make
//! this mapping straightforward. There's also a table, below, that [shows the
//! mapping a high level](#couchdb-api-coverage).
//!
//! One key difference between the couchdb crate's API and the CouchDB API is
//! the crate provides stronger type-safety beyond working with raw strings. For
//! example, applications get and put documents using structured types, and
//! other types, such as revisions and views, are strongly typed as well.
//!
//! To deal with JSON, the couchdb crate relies on Serde and its traits
//! `serde::Serialize` and `serde::Deserialize`. These traits are fundamental to
//! the crate's API—they are not mere implementation details. As such,
//! applications must use these traits when working with documents, views, or
//! any type that is JSON-encoded in the CouchDB API.
//!
//! ## Example: Create a document, read a document
//!
//! This example shows how the couchdb crates thinly wraps the CouchDB API.
//!
//! The following program (1) constructs a `Client` with which to connect to the
//! CouchDB server, (2) creates a database (via the `put_database` method), (3)
//! creates a document within that database (via the `post_to_database` method),
//! and (4) reads the new document (via the `get_document` method).
//!
//! ```no_run
//! extern crate couchdb;
//! extern crate serde_json;
//!
//! // The `Client` type is the entry point for sending all HTTP requests to the
//! // CouchDB server.
//! let client = couchdb::Client::new("http://couchdb-server:5984/").unwrap();
//!
//! // PUT http://couchdb-server:5984/baseball
//! client.put_database("/baseball").run().unwrap();
//!
//! // POST http://couchdb-server:5984/baseball
//! let value = serde_json::builder::ObjectBuilder::new()
//!                 .insert("name", "Babe Ruth")
//!                 .insert("career_hr", 714)
//!                 .unwrap();
//! let (rev, doc_id) = client.post_to_database("/baseball", &value)
//!                           .run()
//!                           .unwrap();
//!
//! // GET http://couchdb-server:5984/baseball/<doc_id>
//! let doc = client.get_document::<_, serde_json::Value>(("/baseball", doc_id.clone()))
//!                 .run()
//!                 .unwrap()
//!                 .unwrap();
//! assert_eq!(doc.id, doc_id);
//! assert_eq!(doc.revision, rev);
//! assert_eq!(doc.content, value);
//! ```
//!
//! ## CouchDB API coverage
//!
//! In the couchdb crate, the `Client` type is the principal type for
//! communicating with a CouchDB server. All HTTP requests to the CouchDB server
//! go through a `Client` instance.
//!
//! This table maps each CouchDB API resource to the `Client` method that accesses
//! that resource.
//!
//!

//!

//!

//!    CouchDB URI
//!    HTTP method
//!    Client method
//!    Description
//!

//!

//!

//!

//!
//!

/_all_dbs

//!
//!    GET
//!    get_all_databases
//!    Get list of all databases.
//!

//!

//!
//!

/db

//!
//!    HEAD
//!    head_database
//!    Test whether a database exists.
//!

//!

//!    GET
//!    get_database
//!    Get meta-information about a database.
//!

//!

//!    PUT
//!    put_database
//!    Create a database.
//!

//!

//!    DELETE
//!    delete_database
//!    Delete a database.
//!

//!

//!    POST
//!    post_to_database
//!    Create a document.
//!

//!

//!
//!

//!
/db/doc

//!
/db/_design/design-doc

//!
/db/_local/id

//!

//!
//!    HEAD
//!    head_document
//!    Test whether a document exists.
//!

//!

//!    GET
//!    get_document
//!    Get meta-information and application-defined content for a
//!    document.
//!

//!

//!    PUT
//!    put_document
//!    Create or update a document.
//!

//!

//!    DELETE
//!    delete_document
//!    Delete a document.
//!

//!

//!
//!

/db/_design/design-doc/_view/view

//!
//!    GET
//!    get_view
//!    Execute a view.
//!

//!

//!

extern crate hyper;
extern crate regex;
extern crate serde;
extern crate serde_json;
extern crate tempdir;
extern crate url;

pub mod command;

mod client;
mod dbtype;
mod error;
mod json;
mod path;
mod server;

pub use client::{Client, IntoUrl};
pub use dbtype::{Database, DatabaseName, Design, DesignBuilder, DesignDocumentName, Document,
                 DocumentId, DocumentName, ErrorResponse, ViewName, Revision, ViewFunction,
                 ViewFunctionMap, ViewResult, ViewRow};
pub use path::{IntoDatabasePath, IntoDesignDocumentPath, IntoDocumentPath, IntoViewPath,
               DatabasePath, DesignDocumentPath, DocumentPath, ViewPath};
pub use error::Error;
pub use server::Server;
<|endoftext|>


<commit_before>extern crate libc;

use std::ffi::{CString, CStr, OsStr};
use std::os::unix::ffi::OsStrExt;
use std::path::Path;

use libc::statfs;

#[derive(Debug)]
pub enum Error {
    Ffi(std::ffi::NulError),
    Io(std::io::Error),
    S(String),
}

impl From<std::ffi::NulError> for Error {
    fn from(err: std::ffi::NulError) -> Error {
        Error::Ffi(err)
    }
}

impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<String> for Error {
    fn from(err: String) -> Error {
        Error::S(err)
    }
}

/// Given a path, find the prefix for the current path that is the mount point prefix.  This uses
/// `statfs` from `libc`, and presumse that you will be passing in fully-qualified canonical paths
/// (to minimize allocation overhead, because the mountpoint that gets returned is a slice of the
/// path that was passed in).
pub fn get_mount_prefix(path: &Path) -> Result<&Path, Error> {
    let cstr = CString::new(path.to_str().unwrap())?;

    let raw_mountpoint = unsafe {
        let mut fs_stat: statfs = std::mem::uninitialized();
        if statfs(cstr.as_ptr(), &mut fs_stat) != 0 {
            return Err(Error::from(std::io::Error::last_os_error()));
        } else {
            // CStr::from_ptr seeks NUL to delimit the slice
            CStr::from_ptr(fs_stat.f_mntonname.as_ptr())
        }
    };

    // from_bytes comes from OsStrExt -- it would be nice to figure out a more direct way to go
    // from CStr to OsStr
    let mountpoint = OsStr::from_bytes(raw_mountpoint.to_bytes());
    let len = mountpoint.len();
    assert!(path.starts_with(mountpoint));
    assert!(len > 0);

    let view = path.as_os_str().as_bytes();
    Ok(&Path::new(OsStr::from_bytes(&view[..len])))
}

#[cfg(test)]
mod tests {
    use super::get_mount_prefix;
    use std::path::Path;

    #[test]
    fn integration_basic() {
        let sample = Path::new("./Cargo.toml").canonicalize().unwrap();
        let result = get_mount_prefix(sample.as_path());
        assert_eq!(result.unwrap().to_str().unwrap(), "/");
    }

    #[test]
    fn integration_another_fs() {
        let sample = Path::new("/Volumes/energeia/CONFIG.SYS");
        let result = get_mount_prefix(sample);
        assert_eq!(result.unwrap().to_str().unwrap(), "/Volumes/energeia");
    }

    #[test]
    #[should_panic(expected = "No such file or directory")]
    fn nonexistent_path() {
        let sample = Path::new("/Volumes/NOxSUCHxMOUNT/prj/Cargo.toml");
        let result = get_mount_prefix(sample).unwrap();
        assert_eq!(result.to_str().unwrap(), "/");
    }
}
<commit_msg>add a variant that first finds canonical path<commit_after>extern crate libc;

use std::ffi::{CString, CStr, OsStr};
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};

#[derive(Debug)]
pub enum Error {
    Ffi(std::ffi::NulError),
    Io(std::io::Error),
    S(String),
}

impl From<std::ffi::NulError> for Error {
    fn from(err: std::ffi::NulError) -> Error {
        Error::Ffi(err)
    }
}

impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<String> for Error {
    fn from(err: String) -> Error {
        Error::S(err)
    }
}

/// Find the portion of a canonicalized path that is the mount point for the provided path.
///
/// This uses `libc::statfs`, and as a result is (partially) unsafe.
///
/// It presumes that you will be passing in fully-qualified canonical paths (to minimize allocation
/// overhead, because the mountpoint that gets returned is a slice of the path that was passed in).
pub fn find_mountpoint_pre_canonicalized(path: &Path) -> Result<&Path, Error> {
    let cstr = CString::new(path.as_os_str().as_bytes())?;

    let raw_mountpoint = unsafe {
        let mut fs_stat: libc::statfs = std::mem::uninitialized();
        if libc::statfs(cstr.as_ptr(), &mut fs_stat) != 0 {
            return Err(Error::from(std::io::Error::last_os_error()));
        } else {
            // CStr::from_ptr uses `libc::strlen` to delimit the slice and `transmute` to cast.
            CStr::from_ptr(fs_stat.f_mntonname.as_ptr())
        }
    };

    // from_bytes comes from OsStrExt -- it would be nice to figure out a more direct way to go
    // from CStr to OsStr
    let mountpoint = OsStr::from_bytes(raw_mountpoint.to_bytes());

    // I may remove these later, but for now I want to verify that these invariants hold in the
    // wild.
    assert!(path.starts_with(mountpoint));
    assert!(mountpoint.len() > 0);

    Ok(&Path::new(mountpoint))
}

/// Find the mountpoint for the volume containing the provided path. Canonicalizes the path before
/// calling `find_mountpoint_pre_canonicalized`. Because canonicalization produces a PathBuf,
/// lifetime management requires returning an owned path, hence returns a PathBuf instead of a
/// reference to a Path.
pub fn find_mountpoint(path: &Path) -> Result<PathBuf, Error> {
    let canonicalized = path.canonicalize()?;
    let found = find_mountpoint_pre_canonicalized(canonicalized.as_path())?;
    Ok(found.to_path_buf())
}

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

    #[test]
    fn integration_basic() {
        let sample = Path::new("./Cargo.toml").canonicalize().unwrap();
        let result = find_mountpoint_pre_canonicalized(sample.as_path());
        assert_eq!(result.unwrap().to_str().unwrap(), "/");
    }

    #[test]
    fn integration_basic_without_canonicalization() {
        let sample = Path::new("./Cargo.toml");
        let result = find_mountpoint(sample);
        assert_eq!(result.unwrap().to_str().unwrap(), "/");
    }

    #[test]
    fn integration_another_fs() {
        let sample = Path::new("/Volumes/energeia/CONFIG.SYS");
        let result = find_mountpoint_pre_canonicalized(sample);
        assert_eq!(result.unwrap().to_str().unwrap(), "/Volumes/energeia");
    }

    #[test]
    #[should_panic(expected = "No such file or directory")]
    fn nonexistent_path() {
        let sample = Path::new("/Volumes/NOxSUCHxMOUNT/prj/Cargo.toml");
        find_mountpoint_pre_canonicalized(sample).unwrap();
    }

    #[test]
    #[should_panic(expected = "No such file or directory")]
    fn nonexistent_path_without_canonicalization() {
        let sample = Path::new("../vegan/porkchop/sandwiches");
        find_mountpoint(sample).unwrap();
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Brendan Zabarauskas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A crate that provides traits and macros for testing the approximate equality of
//! floating-point types, using either relative difference, or units in the last place (ULPs)
//! comparisons.
//!
//! ```rust
//! #[macro_use]
//! extern crate approx;
//! use std::f64;
//!
//! # fn main() {
//! relative_eq!(1.0, 1.0);
//! relative_eq!(1.0, 1.0, epsilon = f64::EPSILON);
//! relative_eq!(1.0, 1.0, max_relative = 1.0);
//! relative_eq!(1.0, 1.0, epsilon = f64::EPSILON, max_relative = 1.0);
//! relative_eq!(1.0, 1.0, max_relative = 1.0, epsilon = f64::EPSILON);
//! # }
//! ```
//!
//! ```rust
//! #[macro_use]
//! extern crate approx;
//! use std::f64;
//!
//! # fn main() {
//! ulps_eq!(1.0, 1.0);
//! ulps_eq!(1.0, 1.0, epsilon = f64::EPSILON);
//! ulps_eq!(1.0, 1.0, max_ulps = 4);
//! ulps_eq!(1.0, 1.0, epsilon = f64::EPSILON, max_ulps = 4);
//! ulps_eq!(1.0, 1.0, max_ulps = 4, epsilon = f64::EPSILON);
//! # }
//! ```
//!
//! ## Implementing approximate equality for custom types
//!
//! The `ApproxEq` trait allows approximate equalities to be implemented on types, based on the
//! fundamental floating point implementations.
//!
//! For example, we might want to be able to do approximate assertions on a complex number type:
//!
//! ```rust
//! # #[macro_use]
//! # extern crate approx;
//! # use approx::ApproxEq;
//! #[derive(Debug)]
//! struct Complex<T> {
//!     x: T,
//!     i: T,
//! }
//! # impl<T: ApproxEq> ApproxEq for Complex<T> {
//! #     type Epsilon = T::Epsilon;
//! #     fn default_epsilon() -> T::Epsilon { T::default_epsilon() }
//! #     fn default_max_relative() -> T::Epsilon { T::default_max_relative() }
//! #     fn default_max_ulps() -> u32 { T::default_max_ulps() }
//! #     fn relative_eq(&self, other: &Self, epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool { T::relative_eq(&self.x, &other.x, epsilon, max_relative) && T::relative_eq(&self.i, &other.i, epsilon, max_relative) }
//! #     fn ulps_eq(&self, other: &Self, epsilon: T::Epsilon, max_ulps: u32) -> bool { T::ulps_eq(&self.x, &other.x, epsilon, max_ulps) && T::ulps_eq(&self.i, &other.i, epsilon, max_ulps) }
//! # }
//!
//! # fn main() {
//! let x = Complex { x: 1.2, i: 2.3 };
//!
//! assert_relative_eq!(x, x);
//! assert_ulps_eq!(x, x, max_ulps = 4);
//! # }
//! ```
//!
//! To do this we can implement `ApproxEq` generically in terms of a type parameter that also
//! implements `ApproxEq`. This means that we can make comparisons for either `Complex<f32>` or
//! `Complex<f64>`:
//!
//! ```rust
//! # use approx::ApproxEq;
//! # #[derive(Debug)]
//! # struct Complex<T> { x: T, i: T, }
//! #
//! impl<T: ApproxEq> ApproxEq for Complex<T> {
//!     type Epsilon = T::Epsilon;
//!
//!     fn default_epsilon() -> T::Epsilon {
//!         T::default_epsilon()
//!     }
//!
//!     fn default_max_relative() -> T::Epsilon {
//!         T::default_max_relative()
//!     }
//!
//!     fn default_max_ulps() -> u32 {
//!         T::default_max_ulps()
//!     }
//!
//!     fn relative_eq(&self, other: &Self, epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool {
//!         T::relative_eq(&self.x, &other.x, epsilon, max_relative) &&
//!         T::relative_eq(&self.i, &other.i, epsilon, max_relative)
//!     }
//!
//!     fn ulps_eq(&self, other: &Self, epsilon: T::Epsilon, max_ulps: u32) -> bool {
//!         T::ulps_eq(&self.x, &other.x, epsilon, max_ulps) &&
//!         T::ulps_eq(&self.i, &other.i, epsilon, max_ulps)
//!     }
//! }
//! ```
//!
//!
//! # References
//!
//! Floating point is HARD! Thanks goes to these links for helping to make things a _little_ easier
//! to understand:
//!
//! - [Comparing Floating Point Numbers, 2012 Edition]
//!   (https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/)
//! - [The Floating Point Guide - Comparison](http://floating-point-gui.de/errors/comparison/)
//! - [What Every Computer Scientist Should Know About Floating-Point Arithmetic]
//!   (https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)

pub mod macro_support;
mod macros;

/// Equality comparisons based on floating point tolerances.
pub trait ApproxEq: Sized {
    /// Used for specifying relative comparisons. This is usually a floating point value.
    type Epsilon: Copy;

    /// The default tolerance to use when testing values that are close together.
    ///
    /// This is used when no `epsilon` value is supplied to the `relative_eq` or `ulps_eq` macros.
    fn default_epsilon() -> Self::Epsilon;

    /// The default relative tolerance for testing values that are far-apart.
    ///
    /// This is used when no `max_relative` value is supplied to the `relative_eq` macro.
    fn default_max_relative() -> Self::Epsilon;

    /// The default ULPs to tolerate when testing values that are far-apart.
    ///
    /// This is used when no `max_relative` value is supplied to the `relative_eq` macro.
    fn default_max_ulps() -> u32;

    /// A test for equality that uses a relative comparison if the values are far apart.
    fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool;

    /// The inverse of `ApproxEq::relative_eq`.
    fn relative_ne(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
        !Self::relative_eq(self, other, epsilon, max_relative)
    }

    /// A test for equality that uses units in the last place (ULP) if the values are far apart.
    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool;

    /// The inverse of `ApproxEq::ulps_eq`.
    fn ulps_ne(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
        !Self::ulps_eq(self, other, epsilon, max_ulps)
    }
}

macro_rules! impl_float_relative_eq {
    ($T:ident, $U:ident) => {
        impl ApproxEq for $T {
            type Epsilon = $T;

            #[inline]
            fn default_epsilon() -> $T { std::$T::EPSILON }

            #[inline]
            fn default_max_relative() -> $T { std::$T::EPSILON }

            #[inline]
            fn default_max_ulps() -> u32 { 4 }

            fn relative_eq(&self, other: &$T, epsilon: $T, max_relative: $T) -> bool {
                // Implementation based on: [Comparing Floating Point Numbers, 2012 Edition]
                // (https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/)

                // Handle infinities
                if self == other { return true; }

                let abs_diff = $T::abs(self - other);

                // For when the numbers are really close together
                if abs_diff <= epsilon { return true };

                // Use a relative difference comparison
                let abs_self = $T::abs(*self);
                let abs_other = $T::abs(*other);
                let largest = if abs_other > abs_self { abs_other } else { abs_self };

                abs_diff <= largest * max_relative
            }

            fn ulps_eq(&self, other: &$T, epsilon: $T, max_ulps: u32) -> bool {
                // Implementation based on: [Comparing Floating Point Numbers, 2012 Edition]
                // (https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/)

                // For when the numbers are really close together
                if $T::abs(self - other) <= epsilon { return true }

                // Trivial negative sign check
                if self.signum() != other.signum() {
                    // Handle -0 == +0
                    return self == other;
                }

                let int_self: $U = unsafe { std::mem::transmute(*self) };
                let int_other: $U = unsafe { std::mem::transmute(*other) };

                // ULPS difference comparison
                $U::abs(int_self - int_other) < max_ulps as $U
            }
        }
    }
}

impl_float_relative_eq!(f32, i32);
impl_float_relative_eq!(f64, i64);

impl<'a, T: ApproxEq> ApproxEq for &'a T {
    type Epsilon = T::Epsilon;

    #[inline]
    fn default_epsilon() -> Self::Epsilon {
        T::default_epsilon()
    }

    #[inline]
    fn default_max_relative() -> Self::Epsilon {
        T::default_max_relative()
    }

    #[inline]
    fn default_max_ulps() -> u32 {
        T::default_max_ulps()
    }

    #[inline]
    fn relative_eq(&self, other: &&'a T, epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool {
        T::relative_eq(*self, *other, epsilon, max_relative)
    }

    #[inline]
    fn ulps_eq(&self, other: &&'a T, epsilon: T::Epsilon, max_ulps: u32) -> bool {
        T::ulps_eq(*self, *other, epsilon, max_ulps)
    }
}

impl<'a, T: ApproxEq> ApproxEq for &'a mut T {
    type Epsilon = T::Epsilon;

    #[inline]
    fn default_epsilon() -> Self::Epsilon {
        T::default_epsilon()
    }

    #[inline]
    fn default_max_relative() -> Self::Epsilon {
        T::default_max_relative()
    }

    #[inline]
    fn default_max_ulps() -> u32 {
        T::default_max_ulps()
    }

    #[inline]
    fn relative_eq(&self, other: &&'a mut T, epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool {
        T::relative_eq(*self, *other, epsilon, max_relative)
    }

    #[inline]
    fn ulps_eq(&self, other: &&'a mut T, epsilon: T::Epsilon, max_ulps: u32) -> bool {
        T::ulps_eq(*self, *other, epsilon, max_ulps)
    }
}
<commit_msg>Remove Copy bound from associated type<commit_after>// Copyright 2015 Brendan Zabarauskas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A crate that provides traits and macros for testing the approximate equality of
//! floating-point types, using either relative difference, or units in the last place (ULPs)
//! comparisons.
//!
//! ```rust
//! #[macro_use]
//! extern crate approx;
//! use std::f64;
//!
//! # fn main() {
//! relative_eq!(1.0, 1.0);
//! relative_eq!(1.0, 1.0, epsilon = f64::EPSILON);
//! relative_eq!(1.0, 1.0, max_relative = 1.0);
//! relative_eq!(1.0, 1.0, epsilon = f64::EPSILON, max_relative = 1.0);
//! relative_eq!(1.0, 1.0, max_relative = 1.0, epsilon = f64::EPSILON);
//! # }
//! ```
//!
//! ```rust
//! #[macro_use]
//! extern crate approx;
//! use std::f64;
//!
//! # fn main() {
//! ulps_eq!(1.0, 1.0);
//! ulps_eq!(1.0, 1.0, epsilon = f64::EPSILON);
//! ulps_eq!(1.0, 1.0, max_ulps = 4);
//! ulps_eq!(1.0, 1.0, epsilon = f64::EPSILON, max_ulps = 4);
//! ulps_eq!(1.0, 1.0, max_ulps = 4, epsilon = f64::EPSILON);
//! # }
//! ```
//!
//! ## Implementing approximate equality for custom types
//!
//! The `ApproxEq` trait allows approximate equalities to be implemented on types, based on the
//! fundamental floating point implementations.
//!
//! For example, we might want to be able to do approximate assertions on a complex number type:
//!
//! ```rust
//! # #[macro_use]
//! # extern crate approx;
//! # use approx::ApproxEq;
//! #[derive(Debug)]
//! struct Complex<T> {
//!     x: T,
//!     i: T,
//! }
//! # impl<T: ApproxEq> ApproxEq for Complex<T> where T::Epsilon: Copy {
//! #     type Epsilon = T::Epsilon;
//! #     fn default_epsilon() -> T::Epsilon { T::default_epsilon() }
//! #     fn default_max_relative() -> T::Epsilon { T::default_max_relative() }
//! #     fn default_max_ulps() -> u32 { T::default_max_ulps() }
//! #     fn relative_eq(&self, other: &Self, epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool { T::relative_eq(&self.x, &other.x, epsilon, max_relative) && T::relative_eq(&self.i, &other.i, epsilon, max_relative) }
//! #     fn ulps_eq(&self, other: &Self, epsilon: T::Epsilon, max_ulps: u32) -> bool { T::ulps_eq(&self.x, &other.x, epsilon, max_ulps) && T::ulps_eq(&self.i, &other.i, epsilon, max_ulps) }
//! # }
//!
//! # fn main() {
//! let x = Complex { x: 1.2, i: 2.3 };
//!
//! assert_relative_eq!(x, x);
//! assert_ulps_eq!(x, x, max_ulps = 4);
//! # }
//! ```
//!
//! To do this we can implement `ApproxEq` generically in terms of a type parameter that also
//! implements `ApproxEq`. This means that we can make comparisons for either `Complex<f32>` or
//! `Complex<f64>`:
//!
//! ```rust
//! # use approx::ApproxEq;
//! # #[derive(Debug)]
//! # struct Complex<T> { x: T, i: T, }
//! #
//! impl<T: ApproxEq> ApproxEq for Complex<T> where
//!     T::Epsilon: Copy,
//! {
//!     type Epsilon = T::Epsilon;
//!
//!     fn default_epsilon() -> T::Epsilon {
//!         T::default_epsilon()
//!     }
//!
//!     fn default_max_relative() -> T::Epsilon {
//!         T::default_max_relative()
//!     }
//!
//!     fn default_max_ulps() -> u32 {
//!         T::default_max_ulps()
//!     }
//!
//!     fn relative_eq(&self, other: &Self, epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool {
//!         T::relative_eq(&self.x, &other.x, epsilon, max_relative) &&
//!         T::relative_eq(&self.i, &other.i, epsilon, max_relative)
//!     }
//!
//!     fn ulps_eq(&self, other: &Self, epsilon: T::Epsilon, max_ulps: u32) -> bool {
//!         T::ulps_eq(&self.x, &other.x, epsilon, max_ulps) &&
//!         T::ulps_eq(&self.i, &other.i, epsilon, max_ulps)
//!     }
//! }
//! ```
//!
//!
//! # References
//!
//! Floating point is HARD! Thanks goes to these links for helping to make things a _little_ easier
//! to understand:
//!
//! - [Comparing Floating Point Numbers, 2012 Edition]
//!   (https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/)
//! - [The Floating Point Guide - Comparison](http://floating-point-gui.de/errors/comparison/)
//! - [What Every Computer Scientist Should Know About Floating-Point Arithmetic]
//!   (https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)

pub mod macro_support;
mod macros;

/// Equality comparisons based on floating point tolerances.
pub trait ApproxEq: Sized {
    /// Used for specifying relative comparisons.
    type Epsilon;

    /// The default tolerance to use when testing values that are close together.
    ///
    /// This is used when no `epsilon` value is supplied to the `relative_eq` or `ulps_eq` macros.
    fn default_epsilon() -> Self::Epsilon;

    /// The default relative tolerance for testing values that are far-apart.
    ///
    /// This is used when no `max_relative` value is supplied to the `relative_eq` macro.
    fn default_max_relative() -> Self::Epsilon;

    /// The default ULPs to tolerate when testing values that are far-apart.
    ///
    /// This is used when no `max_relative` value is supplied to the `relative_eq` macro.
    fn default_max_ulps() -> u32;

    /// A test for equality that uses a relative comparison if the values are far apart.
    fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool;

    /// The inverse of `ApproxEq::relative_eq`.
    fn relative_ne(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
        !Self::relative_eq(self, other, epsilon, max_relative)
    }

    /// A test for equality that uses units in the last place (ULP) if the values are far apart.
    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool;

    /// The inverse of `ApproxEq::ulps_eq`.
    fn ulps_ne(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
        !Self::ulps_eq(self, other, epsilon, max_ulps)
    }
}

macro_rules! impl_float_relative_eq {
    ($T:ident, $U:ident) => {
        impl ApproxEq for $T {
            type Epsilon = $T;

            #[inline]
            fn default_epsilon() -> $T { std::$T::EPSILON }

            #[inline]
            fn default_max_relative() -> $T { std::$T::EPSILON }

            #[inline]
            fn default_max_ulps() -> u32 { 4 }

            fn relative_eq(&self, other: &$T, epsilon: $T, max_relative: $T) -> bool {
                // Implementation based on: [Comparing Floating Point Numbers, 2012 Edition]
                // (https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/)

                // Handle infinities
                if self == other { return true; }

                let abs_diff = $T::abs(self - other);

                // For when the numbers are really close together
                if abs_diff <= epsilon { return true };

                // Use a relative difference comparison
                let abs_self = $T::abs(*self);
                let abs_other = $T::abs(*other);
                let largest = if abs_other > abs_self { abs_other } else { abs_self };

                abs_diff <= largest * max_relative
            }

            fn ulps_eq(&self, other: &$T, epsilon: $T, max_ulps: u32) -> bool {
                // Implementation based on: [Comparing Floating Point Numbers, 2012 Edition]
                // (https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/)

                // For when the numbers are really close together
                if $T::abs(self - other) <= epsilon { return true }

                // Trivial negative sign check
                if self.signum() != other.signum() {
                    // Handle -0 == +0
                    return self == other;
                }

                let int_self: $U = unsafe { std::mem::transmute(*self) };
                let int_other: $U = unsafe { std::mem::transmute(*other) };

                // ULPS difference comparison
                $U::abs(int_self - int_other) < max_ulps as $U
            }
        }
    }
}

impl_float_relative_eq!(f32, i32);
impl_float_relative_eq!(f64, i64);

impl<'a, T: ApproxEq> ApproxEq for &'a T {
    type Epsilon = T::Epsilon;

    #[inline]
    fn default_epsilon() -> Self::Epsilon {
        T::default_epsilon()
    }

    #[inline]
    fn default_max_relative() -> Self::Epsilon {
        T::default_max_relative()
    }

    #[inline]
    fn default_max_ulps() -> u32 {
        T::default_max_ulps()
    }

    #[inline]
    fn relative_eq(&self, other: &&'a T, epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool {
        T::relative_eq(*self, *other, epsilon, max_relative)
    }

    #[inline]
    fn ulps_eq(&self, other: &&'a T, epsilon: T::Epsilon, max_ulps: u32) -> bool {
        T::ulps_eq(*self, *other, epsilon, max_ulps)
    }
}

impl<'a, T: ApproxEq> ApproxEq for &'a mut T {
    type Epsilon = T::Epsilon;

    #[inline]
    fn default_epsilon() -> Self::Epsilon {
        T::default_epsilon()
    }

    #[inline]
    fn default_max_relative() -> Self::Epsilon {
        T::default_max_relative()
    }

    #[inline]
    fn default_max_ulps() -> u32 {
        T::default_max_ulps()
    }

    #[inline]
    fn relative_eq(&self, other: &&'a mut T, epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool {
        T::relative_eq(*self, *other, epsilon, max_relative)
    }

    #[inline]
    fn ulps_eq(&self, other: &&'a mut T, epsilon: T::Epsilon, max_ulps: u32) -> bool {
        T::ulps_eq(*self, *other, epsilon, max_ulps)
    }
}
<|endoftext|>


<commit_before>extern crate num;

mod color;
<commit_msg>Make doctests in color.rs pass<commit_after>extern crate num;

pub use color::{Color, Hue, Lightness};

mod color;
<|endoftext|>


<commit_before>//! A TOML-parsing library
//!
//! This library is an implementation in Rust of a parser for TOML configuration
//! files [1]. It is focused around high quality errors including specific spans
//! and detailed error messages when things go wrong.
//!
//! This implementation currently passes the language agnostic [test suite][2].
//!
//! # Example
//!
//! ```
//! let toml = r#"
//!     [test]
//!     foo = "bar"
//! "#;
//!
//! let value = toml::Parser::new(toml).parse().unwrap();
//! println!("{}", value);
//! ```
//!
//! # Conversions
//!
//! This library also supports using the standard `Encodable` and `Decodable`
//! traits with TOML values. This library provides the following conversion
//! capabilities:
//!
//! * `String` => `toml::Value` - via `Parser`
//! * `toml::Value` => `String` - via `Show`
//! * `toml::Value` => rust object - via `Decoder`
//! * rust object => `toml::Value` - via `Encoder`
//!
//! Convenience functions for performing multiple conversions at a time are also
//! provided.
//!
//! [1]: https://github.com/mojombo/toml
//! [2]: https://github.com/BurntSushi/toml-test
//!

#![crate_name = "toml"]
#![crate_type = "lib"]
#![feature(macro_rules)]
#![deny(warnings, missing_doc)]

extern crate serialize;

use std::collections::TreeMap;
use std::from_str::FromStr;
use std::string;

pub use parser::{Parser,ParserError};
pub use serialization::{Encoder, encode, encode_str};
pub use serialization::{Decoder, decode, decode_str};
pub use serialization::{Error, NeedsKey, NoValue};
pub use serialization::{InvalidMapKeyLocation, InvalidMapKeyType};

mod parser;
mod show;
mod serialization;
#[cfg(test)]mod test;
/// Representation of a TOML value.
#[deriving(PartialEq, Clone)]
#[allow(missing_doc)]
pub enum Value {
    String(string::String),
    Integer(i64),
    Float(f64),
    Boolean(bool),
    Datetime(string::String),
    Array(TomlArray),
    Table(TomlTable),
}

pub type TomlArray = Vec<Value>;
pub type TomlTable = TreeMap<string::String, Value>;

impl Value {
    /// Tests whether this and another value have the same type.
    pub fn same_type(&self, other: &Value) -> bool {
        match (self, other) {
            (&String(..), &String(..)) |
            (&Integer(..), &Integer(..)) |
            (&Float(..), &Float(..)) |
            (&Boolean(..), &Boolean(..)) |
            (&Datetime(..), &Datetime(..)) |
            (&Array(..), &Array(..)) |
            (&Table(..), &Table(..)) => true,

            _ => false,
        }
    }

    /// Returns a human-readable representation of the type of this value.
    pub fn type_str(&self) -> &'static str {
        match *self {
            String(..) => "string",
            Integer(..) => "integer",
            Float(..) => "float",
            Boolean(..) => "boolean",
            Datetime(..) => "datetime",
            Array(..) => "array",
            Table(..) => "table",
        }
    }

    /// Extracts the string of this value if it is a string.
    pub fn as_str<'a>(&'a self) -> Option<&'a str> {
        match *self { String(ref s) => Some(s.as_slice()), _ => None }
    }

    /// Extracts the integer value if it is an integer.
    pub fn as_integer(&self) -> Option<i64> {
        match *self { Integer(i) => Some(i), _ => None }
    }

    /// Extracts the float value if it is a float.
    pub fn as_float(&self) -> Option<f64> {
        match *self { Float(f) => Some(f), _ => None }
    }

    /// Extracts the boolean value if it is a boolean.
    pub fn as_bool(&self) -> Option<bool> {
        match *self { Boolean(b) => Some(b), _ => None }
    }

    /// Extracts the datetime value if it is a datetime.
    ///
    /// Note that a parsed TOML value will only contain ISO 8601 dates. An
    /// example date is:
    ///
    /// ```notrust
    /// 1979-05-27T07:32:00Z
    /// ```
    pub fn as_datetime<'a>(&'a self) -> Option<&'a str> {
        match *self { Datetime(ref s) => Some(s.as_slice()), _ => None }
    }

    /// Extracts the array value if it is an array.
    pub fn as_slice<'a>(&'a self) -> Option<&'a [Value]> {
        match *self { Array(ref s) => Some(s.as_slice()), _ => None }
    }

    /// Extracts the table value if it is a table.
    pub fn as_table<'a>(&'a self) -> Option<&'a TomlTable> {
        match *self { Table(ref s) => Some(s), _ => None }
    }

    /// Lookups for value at specified path.
    ///
    /// Uses '.' as a path separator.
    ///
    /// Note: arrays have zero-based indexes.
    ///
    /// ```
    /// let toml = r#"
    ///      [test]
    ///      foo = "bar"
    ///
    ///      [[values]]
    ///      foo = "baz"
    ///
    ///      [[values]]
    ///      foo = "qux"
    /// "#;
    /// let value: toml::Value = from_str(toml).unwrap();
    ///
    /// let foo = value.lookup("test.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "bar");
    ///
    /// let foo = value.lookup("values.1.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "qux");
    ///
    /// let no_bar = value.lookup("test.bar");
    /// assert_eq!(no_bar.is_none(), true);
    /// ```
    pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a Value> {
        let mut cur_value = self;
        for key in path.split('.') {
            match cur_value {
                &Table(ref hm) => {
                    match hm.find_with(|k| key.cmp(&k.as_slice())) {
                        Some(v) => cur_value = v,
                        _ => return None
                    }
                },
                &Array(ref v) => {
                    let idx: Option<uint> = FromStr::from_str(key);
                    match idx {
                        Some(idx) if idx < v.len() => cur_value = &v[idx],
                        _ => return None
                    }
                },
                _ => return None
            }
        };

        Some(cur_value)
    }
}

impl FromStr for Value {
    fn from_str(s: &str) -> Option<Value> {
        Parser::new(s).parse().map(Table)
    }
}

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

    #[test]
    fn lookup_valid() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let value: Value = from_str(toml).unwrap();

        let test_foo = value.lookup("test.foo").unwrap();
        assert_eq!(test_foo.as_str().unwrap(), "bar");

        let foo1 = value.lookup("values.1.foo").unwrap();
        assert_eq!(foo1.as_str().unwrap(), "qux");

        let no_bar = value.lookup("test.bar");
        assert!(no_bar.is_none());
    }

    #[test]
    fn lookup_invalid_index() {
        let toml = r#"
            [[values]]
            foo = "baz"
        "#;

        let value: Value = from_str(toml).unwrap();

        let foo = value.lookup("test.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.100.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.str.foo");
        assert!(foo.is_none());
    }
}
<commit_msg>Allow warnings for now<commit_after>//! A TOML-parsing library
//!
//! This library is an implementation in Rust of a parser for TOML configuration
//! files [1]. It is focused around high quality errors including specific spans
//! and detailed error messages when things go wrong.
//!
//! This implementation currently passes the language agnostic [test suite][2].
//!
//! # Example
//!
//! ```
//! let toml = r#"
//!     [test]
//!     foo = "bar"
//! "#;
//!
//! let value = toml::Parser::new(toml).parse().unwrap();
//! println!("{}", value);
//! ```
//!
//! # Conversions
//!
//! This library also supports using the standard `Encodable` and `Decodable`
//! traits with TOML values. This library provides the following conversion
//! capabilities:
//!
//! * `String` => `toml::Value` - via `Parser`
//! * `toml::Value` => `String` - via `Show`
//! * `toml::Value` => rust object - via `Decoder`
//! * rust object => `toml::Value` - via `Encoder`
//!
//! Convenience functions for performing multiple conversions at a time are also
//! provided.
//!
//! [1]: https://github.com/mojombo/toml
//! [2]: https://github.com/BurntSushi/toml-test
//!

#![crate_name = "toml"]
#![crate_type = "lib"]
#![feature(macro_rules)]
#![deny(missing_doc)]

extern crate serialize;

use std::collections::TreeMap;
use std::from_str::FromStr;
use std::string;

pub use parser::{Parser,ParserError};
pub use serialization::{Encoder, encode, encode_str};
pub use serialization::{Decoder, decode, decode_str};
pub use serialization::{Error, NeedsKey, NoValue};
pub use serialization::{InvalidMapKeyLocation, InvalidMapKeyType};

mod parser;
mod show;
mod serialization;
#[cfg(test)]mod test;
/// Representation of a TOML value.
#[deriving(PartialEq, Clone)]
#[allow(missing_doc)]
pub enum Value {
    String(string::String),
    Integer(i64),
    Float(f64),
    Boolean(bool),
    Datetime(string::String),
    Array(TomlArray),
    Table(TomlTable),
}

pub type TomlArray = Vec<Value>;
pub type TomlTable = TreeMap<string::String, Value>;

impl Value {
    /// Tests whether this and another value have the same type.
    pub fn same_type(&self, other: &Value) -> bool {
        match (self, other) {
            (&String(..), &String(..)) |
            (&Integer(..), &Integer(..)) |
            (&Float(..), &Float(..)) |
            (&Boolean(..), &Boolean(..)) |
            (&Datetime(..), &Datetime(..)) |
            (&Array(..), &Array(..)) |
            (&Table(..), &Table(..)) => true,

            _ => false,
        }
    }

    /// Returns a human-readable representation of the type of this value.
    pub fn type_str(&self) -> &'static str {
        match *self {
            String(..) => "string",
            Integer(..) => "integer",
            Float(..) => "float",
            Boolean(..) => "boolean",
            Datetime(..) => "datetime",
            Array(..) => "array",
            Table(..) => "table",
        }
    }

    /// Extracts the string of this value if it is a string.
    pub fn as_str<'a>(&'a self) -> Option<&'a str> {
        match *self { String(ref s) => Some(s.as_slice()), _ => None }
    }

    /// Extracts the integer value if it is an integer.
    pub fn as_integer(&self) -> Option<i64> {
        match *self { Integer(i) => Some(i), _ => None }
    }

    /// Extracts the float value if it is a float.
    pub fn as_float(&self) -> Option<f64> {
        match *self { Float(f) => Some(f), _ => None }
    }

    /// Extracts the boolean value if it is a boolean.
    pub fn as_bool(&self) -> Option<bool> {
        match *self { Boolean(b) => Some(b), _ => None }
    }

    /// Extracts the datetime value if it is a datetime.
    ///
    /// Note that a parsed TOML value will only contain ISO 8601 dates. An
    /// example date is:
    ///
    /// ```notrust
    /// 1979-05-27T07:32:00Z
    /// ```
    pub fn as_datetime<'a>(&'a self) -> Option<&'a str> {
        match *self { Datetime(ref s) => Some(s.as_slice()), _ => None }
    }

    /// Extracts the array value if it is an array.
    pub fn as_slice<'a>(&'a self) -> Option<&'a [Value]> {
        match *self { Array(ref s) => Some(s.as_slice()), _ => None }
    }

    /// Extracts the table value if it is a table.
    pub fn as_table<'a>(&'a self) -> Option<&'a TomlTable> {
        match *self { Table(ref s) => Some(s), _ => None }
    }

    /// Lookups for value at specified path.
    ///
    /// Uses '.' as a path separator.
    ///
    /// Note: arrays have zero-based indexes.
    ///
    /// ```
    /// let toml = r#"
    ///      [test]
    ///      foo = "bar"
    ///
    ///      [[values]]
    ///      foo = "baz"
    ///
    ///      [[values]]
    ///      foo = "qux"
    /// "#;
    /// let value: toml::Value = from_str(toml).unwrap();
    ///
    /// let foo = value.lookup("test.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "bar");
    ///
    /// let foo = value.lookup("values.1.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "qux");
    ///
    /// let no_bar = value.lookup("test.bar");
    /// assert_eq!(no_bar.is_none(), true);
    /// ```
    pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a Value> {
        let mut cur_value = self;
        for key in path.split('.') {
            match cur_value {
                &Table(ref hm) => {
                    match hm.find_with(|k| key.cmp(&k.as_slice())) {
                        Some(v) => cur_value = v,
                        _ => return None
                    }
                },
                &Array(ref v) => {
                    let idx: Option<uint> = FromStr::from_str(key);
                    match idx {
                        Some(idx) if idx < v.len() => cur_value = &v[idx],
                        _ => return None
                    }
                },
                _ => return None
            }
        };

        Some(cur_value)
    }
}

impl FromStr for Value {
    fn from_str(s: &str) -> Option<Value> {
        Parser::new(s).parse().map(Table)
    }
}

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

    #[test]
    fn lookup_valid() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let value: Value = from_str(toml).unwrap();

        let test_foo = value.lookup("test.foo").unwrap();
        assert_eq!(test_foo.as_str().unwrap(), "bar");

        let foo1 = value.lookup("values.1.foo").unwrap();
        assert_eq!(foo1.as_str().unwrap(), "qux");

        let no_bar = value.lookup("test.bar");
        assert!(no_bar.is_none());
    }

    #[test]
    fn lookup_invalid_index() {
        let toml = r#"
            [[values]]
            foo = "baz"
        "#;

        let value: Value = from_str(toml).unwrap();

        let foo = value.lookup("test.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.100.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.str.foo");
        assert!(foo.is_none());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

#![allow(safe_extern_statics)]
#![deny(bare_trait_objects)]

// Override assert! and assert_eq! in tests
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

#[cfg(cargo_c)]
mod capi;

mod dist;
mod ec;
mod partition;
mod transform;
mod quantize;
mod predict;
mod rdo;
mod rdo_tables;
#[macro_use]
mod util;
mod context;
mod entropymode;
mod token_cdfs;
mod deblock;
mod segmentation;
mod cdef;
mod lrf;
mod encoder;
mod mc;
mod me;
mod metrics;
mod scan_order;
mod scenechange;
mod rate;
mod tiling;

mod api;
mod header;
mod frame;

use crate::encoder::*;

pub use crate::api::{Context, Config, Packet, EncoderStatus};
pub use crate::frame::Frame;
pub use crate::util::{CastFromPrimitive, Pixel};

pub mod prelude {
  pub use crate::api::*;
  pub use crate::frame::Frame;
  pub use crate::encoder::Tune;
  pub use crate::partition::BlockSize;
  pub use crate::util::{CastFromPrimitive, Pixel};
}

/// Basic data structures
pub mod data {
  pub use crate::frame::Frame;
  pub use crate::api::{
    Packet, Point, Rational, FrameType, EncoderStatus
  };
  pub use crate::util::{CastFromPrimitive, Pixel};
}

/// Color model information
pub mod color {
  pub use crate::api::{
    ChromaSamplePosition,
    ChromaSampling,
    ColorPrimaries,
    TransferCharacteristics,
    PixelRange,
    ContentLight,
    ColorDescription,
    MasteringDisplay,
    MatrixCoefficients,
  };
}

/// Encoder configuration and settings
pub mod config {
  pub use crate::api::{
    Config, EncoderConfig, SpeedSettings, PredictionModesSetting,
  };
}

/// Version information
///
/// The information is recovered from `Cargo.toml` and `git describe`, when available.
///
/// ```
/// use rav1e::version;
/// use semver::Version;
///
/// let major = version::major();
/// let minor = version::minor();
/// let patch = version::patch();
///
/// let short = version::short();
///
/// let v1 = Version::new(major, minor, patch);
/// let v2 = Version::parse(&short).unwrap();
///
/// assert_eq!(v1, v2);
///```
///
pub mod version {
  /// Major version component
  ///
  /// It is increased every time a release presents a incompatible API change.
  pub fn major() -> u64 {
    env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap()
  }
  /// Minor version component
  ///
  /// It is increased every time a release presents new functionalities are added
  /// in a backwards-compatible manner.
  pub fn minor() -> u64 {
    env!("CARGO_PKG_VERSION_MINOR").parse().unwrap()
  }
  /// Patch version component
  ///
  /// It is increased every time a release provides only backwards-compatible bugfixes.
  pub fn patch() -> u64 {
    env!("CARGO_PKG_VERSION_PATCH").parse().unwrap()
  }

  /// Version information as presented in `[package]` `version`.
  ///
  /// e.g. `0.1.0``
  ///
  /// Can be parsed by [semver](https://crates.io/crates/semver).
  pub fn short() -> String {
    env!("CARGO_PKG_VERSION").to_string()
  }

  /// Version information as presented in `[package] version` followed by the
  /// short commit hash if present.
  ///
  /// e.g. `0.1.0 - g743d464`
  ///
  pub fn long() -> String {
    let s = short();
    let hash = hash();

    if hash.is_empty() {
      s
    } else {
      format!("{} - {}", s, hash)
    }
  }

  /// Commit hash (short)
  ///
  /// Short hash of the git commit used by this build
  ///
  /// e.g. `g743d464`
  ///
  pub fn hash() -> String {
    env!("VERGEN_SHA_SHORT").to_string()
  }

  /// Version information with the information
  /// provided by `git describe --tags`.
  ///
  /// e.g. `0.1.0 (v0.1.0-1-g743d464)`
  ///
  pub fn full() -> String {
    let semver = env!("VERGEN_SEMVER_LIGHTWEIGHT");
    format!("{} ({})", short(), semver)
  }
}
#[cfg(all(test, any(feature="decode_test", feature="decode_test_dav1d")))]
mod test_encode_decode;

#[cfg(feature="bench")]
pub mod bench {
  pub mod api { pub use crate::api::*; }
  pub mod cdef { pub use crate::cdef::*; }
  pub mod context { pub use crate::context::*; }
  pub mod dist { pub use crate::dist::*; }
  pub mod ec { pub use crate::ec::*; }
  pub mod encoder { pub use crate::encoder::*; }
  pub mod partition { pub use crate::partition::*; }
  pub mod frame { pub use crate::frame::*; }
  pub mod predict { pub use crate::predict::*; }
  pub mod rdo { pub use crate::rdo::*; }
  pub mod transform { pub use crate::transform::*; }
  pub mod util { pub use crate::util::*; }
}
<commit_msg>Add the Plane to the prelude<commit_after>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

#![allow(safe_extern_statics)]
#![deny(bare_trait_objects)]

// Override assert! and assert_eq! in tests
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

#[cfg(cargo_c)]
mod capi;

mod dist;
mod ec;
mod partition;
mod transform;
mod quantize;
mod predict;
mod rdo;
mod rdo_tables;
#[macro_use]
mod util;
mod context;
mod entropymode;
mod token_cdfs;
mod deblock;
mod segmentation;
mod cdef;
mod lrf;
mod encoder;
mod mc;
mod me;
mod metrics;
mod scan_order;
mod scenechange;
mod rate;
mod tiling;

mod api;
mod header;
mod frame;

use crate::encoder::*;

pub use crate::api::{Context, Config, Packet, EncoderStatus};
pub use crate::frame::Frame;
pub use crate::util::{CastFromPrimitive, Pixel};

pub mod prelude {
  pub use crate::api::*;
  pub use crate::frame::Frame;
  pub use crate::frame::Plane;
  pub use crate::encoder::Tune;
  pub use crate::partition::BlockSize;
  pub use crate::util::{CastFromPrimitive, Pixel};
}

/// Basic data structures
pub mod data {
  pub use crate::frame::Frame;
  pub use crate::api::{
    Packet, Point, Rational, FrameType, EncoderStatus
  };
  pub use crate::util::{CastFromPrimitive, Pixel};
}

/// Color model information
pub mod color {
  pub use crate::api::{
    ChromaSamplePosition,
    ChromaSampling,
    ColorPrimaries,
    TransferCharacteristics,
    PixelRange,
    ContentLight,
    ColorDescription,
    MasteringDisplay,
    MatrixCoefficients,
  };
}

/// Encoder configuration and settings
pub mod config {
  pub use crate::api::{
    Config, EncoderConfig, SpeedSettings, PredictionModesSetting,
  };
}

/// Version information
///
/// The information is recovered from `Cargo.toml` and `git describe`, when available.
///
/// ```
/// use rav1e::version;
/// use semver::Version;
///
/// let major = version::major();
/// let minor = version::minor();
/// let patch = version::patch();
///
/// let short = version::short();
///
/// let v1 = Version::new(major, minor, patch);
/// let v2 = Version::parse(&short).unwrap();
///
/// assert_eq!(v1, v2);
///```
///
pub mod version {
  /// Major version component
  ///
  /// It is increased every time a release presents a incompatible API change.
  pub fn major() -> u64 {
    env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap()
  }
  /// Minor version component
  ///
  /// It is increased every time a release presents new functionalities are added
  /// in a backwards-compatible manner.
  pub fn minor() -> u64 {
    env!("CARGO_PKG_VERSION_MINOR").parse().unwrap()
  }
  /// Patch version component
  ///
  /// It is increased every time a release provides only backwards-compatible bugfixes.
  pub fn patch() -> u64 {
    env!("CARGO_PKG_VERSION_PATCH").parse().unwrap()
  }

  /// Version information as presented in `[package]` `version`.
  ///
  /// e.g. `0.1.0``
  ///
  /// Can be parsed by [semver](https://crates.io/crates/semver).
  pub fn short() -> String {
    env!("CARGO_PKG_VERSION").to_string()
  }

  /// Version information as presented in `[package] version` followed by the
  /// short commit hash if present.
  ///
  /// e.g. `0.1.0 - g743d464`
  ///
  pub fn long() -> String {
    let s = short();
    let hash = hash();

    if hash.is_empty() {
      s
    } else {
      format!("{} - {}", s, hash)
    }
  }

  /// Commit hash (short)
  ///
  /// Short hash of the git commit used by this build
  ///
  /// e.g. `g743d464`
  ///
  pub fn hash() -> String {
    env!("VERGEN_SHA_SHORT").to_string()
  }

  /// Version information with the information
  /// provided by `git describe --tags`.
  ///
  /// e.g. `0.1.0 (v0.1.0-1-g743d464)`
  ///
  pub fn full() -> String {
    let semver = env!("VERGEN_SEMVER_LIGHTWEIGHT");
    format!("{} ({})", short(), semver)
  }
}
#[cfg(all(test, any(feature="decode_test", feature="decode_test_dav1d")))]
mod test_encode_decode;

#[cfg(feature="bench")]
pub mod bench {
  pub mod api { pub use crate::api::*; }
  pub mod cdef { pub use crate::cdef::*; }
  pub mod context { pub use crate::context::*; }
  pub mod dist { pub use crate::dist::*; }
  pub mod ec { pub use crate::ec::*; }
  pub mod encoder { pub use crate::encoder::*; }
  pub mod partition { pub use crate::partition::*; }
  pub mod frame { pub use crate::frame::*; }
  pub mod predict { pub use crate::predict::*; }
  pub mod rdo { pub use crate::rdo::*; }
  pub mod transform { pub use crate::transform::*; }
  pub mod util { pub use crate::util::*; }
}
<|endoftext|>


<commit_before>//! # A CHIP-8 cpu simulator and instruction coding/decoding library.
//!
//! `chip8` provides tools to enable working with
//! [CHIP-8 virtual machine](https://en.wikipedia.org/wiki/CHIP-8)
//! instructions, and a CHIP-8 virtual machine simulator. No GUI is provided,
//! it is intended to be used by another crate. For example, this crate could:
//!  - encode abstract instructions into CHIP-8 codewords for a CHIP-8 assembler
//!  - decode CHIP-8 binary machine codes into abstract instruction objects for a CHIP-8 disassembler
//!  - decode instructions and execute them in a CHIP-8 virtual machine as the core of a GUI CHIP-8 emulator
//!
//! ```rust
//! use chip8::{Simulator, Simulate};
//! use chip8::instruction::Src::Register;
//! let mut chip8 = Simulator::default();
//! // A simple program: LD v6, 25  /  LD v7, 17  /  ADD v6, v7
//! chip8.load_program( &[0x66, 0x19, 0x67, 0x11, 0x86, 0x74] ).unwrap();
//! // Execute three instructions.
//! chip8.step_n(3).unwrap();
//! // Fetch the contents of register v6.
//! let result = chip8.load(Register(6)).unwrap();
//! assert_eq!( result, 25+17 );
//! ```
//!
//!
//!
//!
//! ## Configuration
//! A `Config` stores the configuration of a CHIP-8 system. It contains the A `Config` is
//! used when instantiating machine state or an instruction set.
//!
//! ## Instructions
//! A set of `Operation`s are supported by this library. These operations correspond
//! with instructions from the CHIP-8 instruction set, but are typically more flexible to allow
//! re-use.
//!
//! A `Pattern` defines how the operands required by an `Operation` will be defined by the
//! codeword.
//!
//! An `instruction::Definition` is a combination of an `Operation` and a `Pattern`.
//! These `Definition`s can be combined into an `instruction::Set` that is able to *decode* codewords
//! and return `instruction::Instruction`s and *encode* `instruction::Instruction`s into codewords.
//!
//! `Definition`s and `Instruction`s are very similar, but a key difference sets them apart - a
//! `Definition` only stores the *kind* of operands that will be used and the `Instruction` stores
//! the specific operands that will be used. When a codeword is decoded, information about the
//! operands is extracted based on the pattern in the definition. For example, a generic 'Register'
//! operand in a `Definition` could be specified as 'the v6 register' when the Instruction is
//! created.
//!
//! ## Simulation
//! The state of a CHIP-8 system, including CPU and peripherals, is represented by a `Chip8`.
//! It is able to execute instructions by providing an implementation of the `Execute` trait.
//!
//! A `Simulator` contains a `Chip8` and an `instruction::Set`, which allows it to simulate
//! a CHIP-8 machine fetching codewords from memory, decoding the codewords, and executing the
//! resulting instructions. The `Simulator` provides a mechanism for thread-safe control
//! of the machine and access to state information.

#![feature(inclusive_range_syntax, fnbox, plugin)]
#![feature(question_mark)]
#![plugin(drawbytes)]

// enable errors for some additional lints
#![deny(trivial_casts, trivial_numeric_casts, unsafe_code,
        unused_qualifications)]

#![cfg_attr(feature = "lints", warn(missing_docs))]
#![cfg_attr(feature = "lints", plugin(clippy))]
#![cfg_attr(feature = "lints", deny(clippy))]
#![cfg_attr(feature = "lints", deny(if_not_else, invalid_upcast_comparisons, items_after_statements,
                                    mem_forget, mut_mut, mutex_integer, non_ascii_literal,
                                    nonminimal_bool, shadow_reuse, shadow_same, shadow_unrelated,
                                    similar_names, single_match_else, string_add, string_add_assign,
                                    unicode_not_nfc, wrong_pub_self_convention ))]
#![cfg_attr(feature = "lints", warn(option_unwrap_used, result_unwrap_used, missing_debug_implementations,
                                    unused_import_braces,missing_copy_implementations))]
#![cfg_attr(feature = "lints", allow(doc_markdown))]

//#![cfg_attr(feature = "lints", cast_possible_truncation, cast_possible_wrap, cast_sign_loss))]

#![allow(unused_imports, unused_variables, unused_mut)]

extern crate rand;
extern crate strfmt;

pub mod config;
pub mod fonts;
pub mod instruction;
mod simulator;
mod state;
mod types;

pub use config::Config;
pub use types::*;
pub use state::Chip8;
pub use simulator::{Simulator, Simulate};

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

/*    #[test]
    fn test_chip8_system() {
        let conf = config::presets::COSMAC_VIP_STOCK;
        let chip8 = Chip8::new(&conf, None);
        let mut isa = instruction::Set::new(&conf);
        let d = instruction::Decoder::new(&conf, &isa);
        let e = instruction::Encoder::new(&conf, &isa);

        assert!(true)
    }*/
}
<commit_msg>Improved documentation<commit_after>//! # A CHIP-8 cpu simulator and instruction coding/decoding library.
//!
//! `chip8` provides tools to enable working with
//! [CHIP-8 virtual machine](https://en.wikipedia.org/wiki/CHIP-8)
//! instructions, and a CHIP-8 virtual machine simulator. No GUI is provided,
//! `chip8` is intended to be used by another crate. For example, this crate could be used to:
//!
//!  * encode abstract instructions into machine code for a CHIP-8 assembler
//!  * decode binary machine code into abstract instruction for a CHIP-8 disassembler
//!  * simulate the execution of instructions in a CHIP-8 virtual machine for a GUI CHIP-8 emulator
//!
//! ```rust
//! use chip8::{Simulator, Simulate};
//! use chip8::instruction::Src::Register;
//! let mut chip8 = Simulator::default();
//! // A simple program: LD v6, 25  /  LD v7, 17  /  ADD v6, v7
//! chip8.load_program( &[0x66, 0x19, 0x67, 0x11, 0x86, 0x74] ).unwrap();
//! // Execute three instructions.
//! chip8.step_n(3).unwrap();
//! // Fetch the contents of register v6.
//! let result = chip8.load(Register(6)).unwrap();
//! assert_eq!( result, 25+17 );
//! ```
//!
//! ## Instructions
//! An `instruction::Definition` is a combination of an `OperationKind` like *Add* or *Jump* and
//! a `Pattern` that specifies how the codword is structured.
//!
//! An `instruction::Set` contains one or more `Definition`. The `Set` can decode
//! machine codewords into `Operation`s and encode `Operation`s into codewords.
//!
//! ## Simulation
//! A `Chip8` represents the state of a CHIP-8 system, including CPU and peripherals.
//! It implements the `Execute` trait, so it is able to execute `Operation`s.
//!
//! A `Simulator` contains a `Chip8` and an `instruction::Set`, which allows it to decode
//! instructions and simulate their execution. The `Simulator` provides thread-safe mechanisms
//! for control of execution and inspection of machine state.

#![feature(inclusive_range_syntax, fnbox, plugin)]
#![feature(question_mark)]
#![plugin(drawbytes)]

// enable errors for some additional lints
#![deny(trivial_casts, trivial_numeric_casts, unsafe_code,
        unused_qualifications)]

#![cfg_attr(feature = "lints", warn(missing_docs))]
#![cfg_attr(feature = "lints", plugin(clippy))]
#![cfg_attr(feature = "lints", deny(clippy))]
#![cfg_attr(feature = "lints", deny(if_not_else, invalid_upcast_comparisons, items_after_statements,
                                    mem_forget, mut_mut, mutex_integer, non_ascii_literal,
                                    nonminimal_bool, shadow_reuse, shadow_same, shadow_unrelated,
                                    similar_names, single_match_else, string_add, string_add_assign,
                                    unicode_not_nfc, wrong_pub_self_convention ))]
#![cfg_attr(feature = "lints", warn(option_unwrap_used, result_unwrap_used, missing_debug_implementations,
                                    unused_import_braces,missing_copy_implementations))]
#![cfg_attr(feature = "lints", allow(doc_markdown))]

//#![cfg_attr(feature = "lints", cast_possible_truncation, cast_possible_wrap, cast_sign_loss))]

#![allow(unused_imports, unused_variables, unused_mut)]

extern crate rand;
extern crate strfmt;

pub mod config;
pub mod fonts;
pub mod instruction;
mod simulator;
mod state;
mod types;

pub use config::Config;
pub use types::*;
pub use state::Chip8;
pub use simulator::{Simulator, Simulate};

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

/*    #[test]
    fn test_chip8_system() {
        let conf = config::presets::COSMAC_VIP_STOCK;
        let chip8 = Chip8::new(&conf, None);
        let mut isa = instruction::Set::new(&conf);
        let d = instruction::Decoder::new(&conf, &isa);
        let e = instruction::Encoder::new(&conf, &isa);

        assert!(true)
    }*/
}
<|endoftext|>