<commit_before>use chacha20;
use util;
use byteorder::{ByteOrder, LittleEndian};

pub struct ChaCha20Poly1305 {
    cipher: chacha20::ChaCha20,
    mac_key: [u8; 32],
}

impl ChaCha20Poly1305 {
    pub fn new(key: &[u8], nonce: &[u8]) -> Self {
        let mut chacha_poly = Self {
            cipher: chacha20::ChaCha20::new(key),
            mac_key: [0; 32],
        };
        chacha_poly.cipher.set_nonce(nonce);
        chacha_poly.key_gen();
        chacha_poly
    }

    pub fn encrypt(self, message: &[u8], data: &[u8], ciphertext: &mut [u8]) -> [u8; 16] {
        assert_eq!(message.len(), ciphertext.len());
        self.counter_mode(message, ciphertext);
        self.tag(ciphertext, data)
    }

    pub fn decrypt(self, ciphertext: &[u8], data: &[u8], tag: &[u8], message: &mut [u8]) -> bool {
        assert_eq!(message.len(), ciphertext.len());
        let expected_tag = self.tag(ciphertext, data);
        if util::verify_16(&expected_tag, tag) {
            self.counter_mode(ciphertext, message);
            true
        } else {
            false
        }
    }

    fn key_gen(&mut self) {
        let block = &mut [0; 64];
        self.cipher.write_block(0, block);
        self.mac_key.copy_from_slice(&block[..32]);
    }

    fn counter_mode(&self, input: &[u8], output: &mut [u8]) {
        for (i, (input_chunk, output_chunk)) in
            (1..).zip(input.chunks(64).zip(output.chunks_mut(64)))
        {
            let output_chunk_len = output_chunk.len();
            if output_chunk_len < 64 {
                let buffer = &mut [0; 64];
                self.cipher.write_block(i, buffer);
                output_chunk.copy_from_slice(&buffer[..output_chunk_len]);
            } else {
                self.cipher.write_block(i, output_chunk);
            }
            for (&input_byte, output_byte) in input_chunk.iter().zip(output_chunk) {
                *output_byte ^= input_byte;
            }
        }
    }

    fn tag(&self, ciphertext: &[u8], data: &[u8]) -> [u8; 16] {
        poly1305(&self.mac_key, data, ciphertext)
    }
}

fn poly1305(key: &[u8; 32], data: &[u8], ciphertext: &[u8]) -> [u8; 16] {
    let mut digest = [0; 16];
    let mut mac = Poly1305::new(key, data);
    mac.update(ciphertext);
    mac.write_digest(&mut digest);
    digest
}

struct Poly1305 {
    function: PolyFunction,
    data_len: u64,
    ciphertext_len: u64,
}

impl Poly1305 {
    fn new(key: &[u8; 32], data: &[u8]) -> Self {
        let mut poly1305 = Self {
            function: PolyFunction::new(key),
            data_len: data.len() as u64,
            ciphertext_len: 0,
        };
        poly1305.process(data);
        poly1305
    }

    fn update(&mut self, input: &[u8]) {
        self.ciphertext_len += input.len() as u64;
        self.process(input);
    }

    fn write_digest(mut self, output: &mut [u8; 16]) {
        LittleEndian::write_u64(&mut output[..8], self.data_len);
        LittleEndian::write_u64(&mut output[8..], self.ciphertext_len);
        self.function.process(output);
        self.function.value(output);
    }

    fn process(&mut self, input: &[u8]) {
        for chunk in input.chunks(16) {
            if chunk.len() < 16 {
                let buffer = &mut [0; 16];
                buffer[..chunk.len()].copy_from_slice(chunk);
                self.function.process(buffer);
            } else {
                self.function.process(chunk);
            }
        }
    }
}

struct PolyFunction {
    r: [u8; 17],
    h: [u32; 17],
    constant_term: [u8; 16],
}

impl PolyFunction {
    fn new(key: &[u8; 32]) -> Self {
        let mut poly_function = Self {
            r: load_r(key),
            h: [0; 17],
            constant_term: [0; 16],
        };
        poly_function.constant_term.copy_from_slice(&key[16..]);
        poly_function
    }

    fn value(mut self, output: &mut [u8; 16]) {
        self.freeze();
        add(&mut self.h, &self.constant_term, 0);
        for (&h_j, output_j) in self.h.iter().zip(output) {
            *output_j = h_j as u8;
        }
    }

    fn process(&mut self, input: &[u8]) {
        add(&mut self.h, input, 1);
        self.mulmod();
    }

    fn mulmod(&mut self) {
        let h_r = &mut [0; 17];
        for i in 0..17 {
            let mut u = 0;
            for j in 0..i + 1 {
                u += self.h[j] * u32::from(self.r[i - j]);
            }
            for j in i + 1..17 {
                u += 320 * self.h[j] * u32::from(self.r[i + 17 - j]);
            }
            h_r[i] = u;
        }
        self.h.copy_from_slice(h_r);
        self.squeeze();
    }

    fn squeeze(&mut self) {
        let mut u = 0;
        for h_j in self.h.iter_mut().take(16) {
            u += *h_j;
            *h_j = u & 255;
            u >>= 8;
        }
        u += self.h[16];
        self.h[16] = u & 3;
        u = 5 * (u >> 2);
        for h_j in self.h.iter_mut().take(16) {
            u += *h_j;
            *h_j = u & 255;
            u >>= 8;
        }
        self.h[16] += u;
    }

    fn freeze(&mut self) {
        let h_orig = self.h;
        add(
            &mut self.h,
            &[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            252,
        );
        let negative = (self.h[16] >> 7).wrapping_neg();
        for (h_j, &h_orig_j) in self.h.iter_mut().zip(h_orig.iter()) {
            *h_j ^= negative & (h_orig_j ^ *h_j);
        }
    }
}

fn add(h: &mut [u32; 17], c: &[u8], last_byte: u8) {
    let mut u = 0;
    for (h_j, &c_j) in h.iter_mut().zip(c) {
        u += *h_j + u32::from(c_j);
        *h_j = u & 255;
        u >>= 8;
    }
    h[16] += u + u32::from(last_byte);
}

fn load_r(key: &[u8; 32]) -> [u8; 17] {
    let mut r = [0; 17];
    r[0] = key[0];
    r[1] = key[1];
    r[2] = key[2];
    r[3] = key[3] & 15;
    r[4] = key[4] & 252;
    r[5] = key[5];
    r[6] = key[6];
    r[7] = key[7] & 15;
    r[8] = key[8] & 252;
    r[9] = key[9];
    r[10] = key[10];
    r[11] = key[11] & 15;
    r[12] = key[12] & 252;
    r[13] = key[13];
    r[14] = key[14];
    r[15] = key[15] & 15;
    r
}

#[cfg(test)]
mod tests {
    use std::vec::Vec;
    use super::*;
    use test_helpers::*;

    #[test]
    fn test_encrypt() {
        let key: &Vec<_> = &(0x80..0xa0).collect();
        let nonce = &h2b("070000004041424344454647");
        let data = &h2b("50515253c0c1c2c3c4c5c6c7");
        let message = "Ladies and Gentlemen of the class of '99: If I could offer you only one \
            tip for the future, sunscreen would be it.";
        let ciphertext = &h2b(
            "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d6\
             3dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b36\
             92ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc\
             3ff4def08e4b7a9de576d26586cec64b6116",
        );
        let tag = &h2b("1ae10b594f09e26a7e902ecbd0600691");
        let encrypted_message = &mut vec![0; message.len()];
        let decrypted_ciphertext = &mut vec![0; ciphertext.len()];

        let chacha_poly = ChaCha20Poly1305::new(key, nonce);
        let poly_key = h2b(
            "7bac2b252db447af09b67a55a4e955840ae1d6731075d9eb2a9375783ed553ff",
        );
        assert_eq!(poly_key, chacha_poly.mac_key);

        let actual_tag = chacha_poly.encrypt(message.as_bytes(), data, encrypted_message);
        assert_eq!(ciphertext, encrypted_message);
        assert_eq!(tag, &actual_tag);

        let chacha_poly = ChaCha20Poly1305::new(key, nonce);
        assert!(chacha_poly.decrypt(
            ciphertext,
            data,
            tag,
            decrypted_ciphertext,
        ));
        assert_eq!(message.as_bytes(), decrypted_ciphertext.as_slice());
        // TODO: check that bad tags cause decryption to fail
    }

    #[test]
    fn test_key_gen() {
        let key: &Vec<_> = &(0x80..0xa0).collect();
        let nonce = &[0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7];
        let expected = h2b(
            "8ad5a08b905f81cc815040274ab29471a833b637e3fd0da508dbb8e2fdd1a646",
        );
        let chacha_poly = ChaCha20Poly1305::new(key, nonce);
        assert_eq!(expected, chacha_poly.mac_key.to_vec());
    }

    #[test]
    fn test_poly() {
        let key = &mut [0; 32];
        key.copy_from_slice(&h2b(
            "7bac2b252db447af09b67a55a4e955840ae1d6731075d9eb2a9375783ed553ff",
        ));
        let data = &h2b("50515253c0c1c2c3c4c5c6c7");
        let ciphertext = &h2b(
            "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d6\
             3dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b36\
             92ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc\
             3ff4def08e4b7a9de576d26586cec64b6116",
        );
        let tag = &h2b("1ae10b594f09e26a7e902ecbd0600691");
        let actual = poly1305(key, data, ciphertext);
        assert_eq!(tag, &actual);

        let input = h2b(
            "50515253c0c1c2c3c4c5c6c700000000d31a8d34648e60db7b86afbc53ef7ec2\
             a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b\
             1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58\
             fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b\
             611600000000000000000000000000000c000000000000007200000000000000",
        );
        let mut poly_function = PolyFunction::new(key);
        for chunk in input.chunks(16) {
            poly_function.process(chunk);
        }
        let actual = &mut [0; 16];
        poly_function.value(actual);
        assert_eq!(tag, actual);
    }
}
<commit_msg>poly1035: allow a different nonce per message<commit_after>use chacha20;
use util;
use byteorder::{ByteOrder, LittleEndian};

pub struct ChaCha20Poly1305 {
    cipher: chacha20::ChaCha20,
}

impl ChaCha20Poly1305 {
    pub fn new(key: &[u8]) -> Self {
        Self { cipher: chacha20::ChaCha20::new(key) }
    }

    pub fn encrypt(
        &mut self,
        message: &[u8],
        data: &[u8],
        nonce: &[u8],
        ciphertext: &mut [u8],
    ) -> [u8; 16] {
        assert_eq!(12, nonce.len());
        assert_eq!(message.len(), ciphertext.len());
        self.cipher.set_nonce(nonce);
        self.counter_mode(message, ciphertext);
        self.tag(ciphertext, data)
    }

    pub fn decrypt(
        &mut self,
        ciphertext: &[u8],
        data: &[u8],
        tag: &[u8],
        nonce: &[u8],
        message: &mut [u8],
    ) -> bool {
        assert_eq!(12, nonce.len());
        assert_eq!(message.len(), ciphertext.len());
        self.cipher.set_nonce(nonce);
        let expected_tag = self.tag(ciphertext, data);
        if util::verify_16(&expected_tag, tag) {
            self.counter_mode(ciphertext, message);
            true
        } else {
            false
        }
    }

    fn key_gen(&self) -> [u8; 32] {
        let block = &mut [0; 64];
        self.cipher.write_block(0, block);

        let mut poly_key = [0; 32];
        poly_key.copy_from_slice(&block[..32]);
        poly_key
    }

    fn counter_mode(&self, input: &[u8], output: &mut [u8]) {
        for (i, (input_chunk, output_chunk)) in
            (1..).zip(input.chunks(64).zip(output.chunks_mut(64)))
        {
            let output_chunk_len = output_chunk.len();
            if output_chunk_len < 64 {
                let buffer = &mut [0; 64];
                self.cipher.write_block(i, buffer);
                output_chunk.copy_from_slice(&buffer[..output_chunk_len]);
            } else {
                self.cipher.write_block(i, output_chunk);
            }
            for (&input_byte, output_byte) in input_chunk.iter().zip(output_chunk) {
                *output_byte ^= input_byte;
            }
        }
    }

    fn tag(&self, ciphertext: &[u8], data: &[u8]) -> [u8; 16] {
        let poly_key = &self.key_gen();
        poly1305(poly_key, data, ciphertext)
    }
}

fn poly1305(key: &[u8; 32], data: &[u8], ciphertext: &[u8]) -> [u8; 16] {
    let mut digest = [0; 16];
    let mut mac = Poly1305::new(key, data);
    mac.update(ciphertext);
    mac.write_digest(&mut digest);
    digest
}

struct Poly1305 {
    function: PolyFunction,
    data_len: u64,
    ciphertext_len: u64,
}

impl Poly1305 {
    fn new(key: &[u8; 32], data: &[u8]) -> Self {
        let mut poly1305 = Self {
            function: PolyFunction::new(key),
            data_len: data.len() as u64,
            ciphertext_len: 0,
        };
        poly1305.process(data);
        poly1305
    }

    fn update(&mut self, input: &[u8]) {
        self.ciphertext_len += input.len() as u64;
        self.process(input);
    }

    fn write_digest(mut self, output: &mut [u8; 16]) {
        LittleEndian::write_u64(&mut output[..8], self.data_len);
        LittleEndian::write_u64(&mut output[8..], self.ciphertext_len);
        self.function.process(output);
        self.function.value(output);
    }

    fn process(&mut self, input: &[u8]) {
        for chunk in input.chunks(16) {
            if chunk.len() < 16 {
                let buffer = &mut [0; 16];
                buffer[..chunk.len()].copy_from_slice(chunk);
                self.function.process(buffer);
            } else {
                self.function.process(chunk);
            }
        }
    }
}

struct PolyFunction {
    r: [u8; 17],
    h: [u32; 17],
    constant_term: [u8; 16],
}

impl PolyFunction {
    fn new(key: &[u8; 32]) -> Self {
        let mut poly_function = Self {
            r: load_r(key),
            h: [0; 17],
            constant_term: [0; 16],
        };
        poly_function.constant_term.copy_from_slice(&key[16..]);
        poly_function
    }

    fn value(mut self, output: &mut [u8; 16]) {
        self.freeze();
        add(&mut self.h, &self.constant_term, 0);
        for (&h_j, output_j) in self.h.iter().zip(output) {
            *output_j = h_j as u8;
        }
    }

    fn process(&mut self, input: &[u8]) {
        add(&mut self.h, input, 1);
        self.mulmod();
    }

    fn mulmod(&mut self) {
        let h_r = &mut [0; 17];
        for i in 0..17 {
            let mut u = 0;
            for j in 0..i + 1 {
                u += self.h[j] * u32::from(self.r[i - j]);
            }
            for j in i + 1..17 {
                u += 320 * self.h[j] * u32::from(self.r[i + 17 - j]);
            }
            h_r[i] = u;
        }
        self.h.copy_from_slice(h_r);
        self.squeeze();
    }

    fn squeeze(&mut self) {
        let mut u = 0;
        for h_j in self.h.iter_mut().take(16) {
            u += *h_j;
            *h_j = u & 255;
            u >>= 8;
        }
        u += self.h[16];
        self.h[16] = u & 3;
        u = 5 * (u >> 2);
        for h_j in self.h.iter_mut().take(16) {
            u += *h_j;
            *h_j = u & 255;
            u >>= 8;
        }
        self.h[16] += u;
    }

    fn freeze(&mut self) {
        let h_orig = self.h;
        add(
            &mut self.h,
            &[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            252,
        );
        let negative = (self.h[16] >> 7).wrapping_neg();
        for (h_j, &h_orig_j) in self.h.iter_mut().zip(h_orig.iter()) {
            *h_j ^= negative & (h_orig_j ^ *h_j);
        }
    }
}

fn add(h: &mut [u32; 17], c: &[u8], last_byte: u8) {
    let mut u = 0;
    for (h_j, &c_j) in h.iter_mut().zip(c) {
        u += *h_j + u32::from(c_j);
        *h_j = u & 255;
        u >>= 8;
    }
    h[16] += u + u32::from(last_byte);
}

fn load_r(key: &[u8; 32]) -> [u8; 17] {
    let mut r = [0; 17];
    r[0] = key[0];
    r[1] = key[1];
    r[2] = key[2];
    r[3] = key[3] & 15;
    r[4] = key[4] & 252;
    r[5] = key[5];
    r[6] = key[6];
    r[7] = key[7] & 15;
    r[8] = key[8] & 252;
    r[9] = key[9];
    r[10] = key[10];
    r[11] = key[11] & 15;
    r[12] = key[12] & 252;
    r[13] = key[13];
    r[14] = key[14];
    r[15] = key[15] & 15;
    r
}

#[cfg(test)]
mod tests {
    use std::vec::Vec;
    use super::*;
    use test_helpers::*;

    #[test]
    fn test_encrypt() {
        let key: &Vec<_> = &(0x80..0xa0).collect();
        let nonce = &h2b("070000004041424344454647");
        let data = &h2b("50515253c0c1c2c3c4c5c6c7");
        let message = "Ladies and Gentlemen of the class of '99: If I could offer you only one \
            tip for the future, sunscreen would be it.";
        let ciphertext = &h2b(
            "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d6\
             3dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b36\
             92ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc\
             3ff4def08e4b7a9de576d26586cec64b6116",
        );
        let tag = &h2b("1ae10b594f09e26a7e902ecbd0600691");
        let encrypted_message = &mut vec![0; message.len()];
        let decrypted_ciphertext = &mut vec![0; ciphertext.len()];

        let mut chacha_poly = ChaCha20Poly1305::new(key);
        chacha_poly.cipher.set_nonce(nonce);
        let expected_poly_key = h2b(
            "7bac2b252db447af09b67a55a4e955840ae1d6731075d9eb2a9375783ed553ff",
        );
        let poly_key = chacha_poly.key_gen();
        assert_eq!(expected_poly_key, poly_key);

        let actual_tag = chacha_poly.encrypt(message.as_bytes(), data, nonce, encrypted_message);
        assert_eq!(ciphertext, encrypted_message);
        assert_eq!(tag, &actual_tag);
        assert!(chacha_poly.decrypt(
            ciphertext,
            data,
            tag,
            nonce,
            decrypted_ciphertext,
        ));
        assert_eq!(message.as_bytes(), decrypted_ciphertext.as_slice());
        // TODO: check that bad tags cause decryption to fail
    }

    #[test]
    fn test_key_gen() {
        let key: &Vec<_> = &(0x80..0xa0).collect();
        let nonce = &[0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7];
        let expected = h2b(
            "8ad5a08b905f81cc815040274ab29471a833b637e3fd0da508dbb8e2fdd1a646",
        );
        let mut chacha_poly = ChaCha20Poly1305::new(key);
        chacha_poly.cipher.set_nonce(nonce);
        let poly_key = chacha_poly.key_gen();
        assert_eq!(expected, poly_key);
    }

    #[test]
    fn test_poly() {
        let key = &mut [0; 32];
        key.copy_from_slice(&h2b(
            "7bac2b252db447af09b67a55a4e955840ae1d6731075d9eb2a9375783ed553ff",
        ));
        let data = &h2b("50515253c0c1c2c3c4c5c6c7");
        let ciphertext = &h2b(
            "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d6\
             3dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b36\
             92ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc\
             3ff4def08e4b7a9de576d26586cec64b6116",
        );
        let tag = &h2b("1ae10b594f09e26a7e902ecbd0600691");
        let actual = poly1305(key, data, ciphertext);
        assert_eq!(tag, &actual);

        let input = h2b(
            "50515253c0c1c2c3c4c5c6c700000000d31a8d34648e60db7b86afbc53ef7ec2\
             a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b\
             1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58\
             fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b\
             611600000000000000000000000000000c000000000000007200000000000000",
        );
        let mut poly_function = PolyFunction::new(key);
        for chunk in input.chunks(16) {
            poly_function.process(chunk);
        }
        let actual = &mut [0; 16];
        poly_function.value(actual);
        assert_eq!(tag, actual);
    }
}
<|endoftext|>


<commit_before>use ram::schema::Schema;
use ram::chunk::Chunk;
use std::ptr;
use ram::io::{reader, writer};
use ram::types::{Map, Value, Id};
use std::sync::Arc;
use serde::Serialize;

pub const MAX_CELL_SIZE :usize = 1 * 1024 * 1024;

pub type DataMap = Map;

#[repr(C, packed)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct Header {
    pub version: u64,
    pub size: u32,
    pub schema: u32,
    pub partition: u64,
    pub hash: u64,
}

#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub enum WriteError {
    SchemaDoesNotExisted(u32),
    CannotAllocateSpace,
    CellIsTooLarge(usize),
    CellAlreadyExisted,
    CellDoesNotExisted,
    ReadError(ReadError),
    UserCanceledUpdate,
    DeletionPredictionFailed,
    NetworkingError,
    DataMismatchSchema,
}

#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub enum ReadError {
    SchemaDoesNotExisted(u32),
    CellDoesNotExisted,
    NetworkingError,
    CellTypeIsNotMapForSelect
}

impl Header {
    pub fn new(size: u32, schema: u32, id: &Id) -> Header {
        Header {
            version: 1,
            size: size,
            schema: schema,
            partition: id.higher,
            hash: id.lower,
        }
    }
    fn write(&self, location: usize) {
        unsafe {
            ptr::copy_nonoverlapping(self as *const Header, location as *mut Header, HEADER_SIZE);
        }
    }
    pub fn reserve(location: usize, size: usize) {
        Header {
            version: 0, // default a tombstone
            size: size as u32,
            schema: 0,
            hash: 0,
            partition: 0,
        }.write(location);
    }
    pub fn id(&self) -> Id {
        Id {
            higher: self.partition,
            lower: self.hash,
        }
    }
    pub fn set_id(&mut self, id: &Id) {
        self.partition = id.higher;
        self.hash = id.lower;
    }
}

pub const HEADER_SIZE :usize = 32;

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Cell {
    pub header: Header,
    pub data: Value
}

impl Cell {

    pub fn new_with_id(schema_id: u32, id: &Id, value: Value) -> Cell {
        Cell {
            header: Header::new(0, schema_id, id),
            data: value
        }
    }

    pub fn encode_cell_key<V>(schema_id: u32, value: &V) -> Id
        where V: Serialize {
        Id::from_obj(&(schema_id, value))
    }

    pub fn new(schema: &Arc<Schema>, value: Value) -> Option<Cell> {
        let schema_id = schema.id;
        let id = if let Value::Map(ref data) = value {
            match schema.key_field {
                Some(ref keys) => {
                    let value = data.get_in_by_ids(keys.iter());
                    match value {
                        &Value::Null => return None,
                        _ => Cell::encode_cell_key(schema_id, value)
                    }
                },
                None => {
                    Id::rand()
                }
            }
        } else {
            Id::rand()
        };
        Some(Cell::new_with_id(schema_id, &id, value))
    }

    pub fn header_from_chunk_raw(ptr: usize) -> Result<Header, ReadError> {
        if ptr == 0 {return Err(ReadError::CellDoesNotExisted)}
        Ok(unsafe {(*(ptr as *const Header))})
    }
    pub fn from_chunk_raw(ptr: usize, chunk: &Chunk) -> Result<Cell, ReadError> {
        let header = Cell::header_from_chunk_raw(ptr)?;
        let data_ptr = ptr + HEADER_SIZE;
        let schema_id = &header.schema;
        if let Some(schema) = chunk.meta.schemas.get(schema_id) {
            Ok(Cell {
                header: header,
                data: reader::read_by_schema(data_ptr, &schema)
            })
        } else {
            error!("Schema {} does not existed to read", schema_id);
            return Err(ReadError::SchemaDoesNotExisted(*schema_id));
        }
    }
    pub fn select_from_chunk_raw(ptr: usize, chunk: &Chunk, fields: &[u64]) -> Result<Value, ReadError> {
        let header = Cell::header_from_chunk_raw(ptr)?;
        let data_ptr = ptr + HEADER_SIZE;
        let schema_id = &header.schema;
        if let Some(schema) = chunk.meta.schemas.get(schema_id) {
            Ok(reader::read_by_schema_selected(data_ptr, &schema, fields))
        } else {
            error!("Schema {} does not existed to read", schema_id);
            return Err(ReadError::SchemaDoesNotExisted(*schema_id));
        }
    }
    pub fn write_to_chunk(&mut self, chunk: &Chunk) -> Result<usize, WriteError> {
        let schema_id = self.header.schema;
        if let Some(schema) = chunk.meta.schemas.get(&schema_id) {
            return self.write_to_chunk_with_schema(chunk, &schema)
        } else {
            error!("Schema {} does not existed to write", schema_id);
            return Err(WriteError::SchemaDoesNotExisted(schema_id));
        }
    }
    pub fn write_to_chunk_with_schema(&mut self, chunk: &Chunk, schema: &Schema) -> Result<usize, WriteError> {
        let mut offset: usize = 0;
        let mut instructions = Vec::<writer::Instruction>::new();
        writer::plan_write_field(&mut offset, &schema.fields, &self.data, &mut instructions)?;
        if schema.is_dynamic {
            writer::plan_write_dynamic_fields(
                &mut offset, &schema.fields,
                &self.data, &mut instructions
            )?;
        }
        let total_size = offset + HEADER_SIZE;
        if total_size > MAX_CELL_SIZE {return Err(WriteError::CellIsTooLarge(total_size))}
        let addr_opt = chunk.try_acquire(total_size);
        self.header.size = total_size as u32;
        self.header.version += 1;
        match addr_opt {
            None => {
                error!("Cannot allocate new spaces in chunk");
                return Err(WriteError::CannotAllocateSpace);
            },
            Some((addr, _lock)) => {
                self.header.write(addr);
                writer::execute_plan(addr + HEADER_SIZE, instructions);
                return Ok(addr);
            }
        }
    }
    pub fn id(&self) -> Id {
        self.header.id()
    }
    pub fn set_id(&mut self, id: &Id) {
        self.header.set_id(id)
    }
}<commit_msg>impl index for Cell struct<commit_after>use ram::schema::Schema;
use ram::chunk::Chunk;
use ram::io::{reader, writer};
use ram::types::{Map, Value, Id};
use std::sync::Arc;
use std::ops::{Index, IndexMut};
use std::ptr;
use serde::Serialize;

pub const MAX_CELL_SIZE :usize = 1 * 1024 * 1024;

pub type DataMap = Map;

#[repr(C, packed)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct Header {
    pub version: u64,
    pub size: u32,
    pub schema: u32,
    pub partition: u64,
    pub hash: u64,
}

#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub enum WriteError {
    SchemaDoesNotExisted(u32),
    CannotAllocateSpace,
    CellIsTooLarge(usize),
    CellAlreadyExisted,
    CellDoesNotExisted,
    ReadError(ReadError),
    UserCanceledUpdate,
    DeletionPredictionFailed,
    NetworkingError,
    DataMismatchSchema,
}

#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub enum ReadError {
    SchemaDoesNotExisted(u32),
    CellDoesNotExisted,
    NetworkingError,
    CellTypeIsNotMapForSelect
}

impl Header {
    pub fn new(size: u32, schema: u32, id: &Id) -> Header {
        Header {
            version: 1,
            size: size,
            schema: schema,
            partition: id.higher,
            hash: id.lower,
        }
    }
    fn write(&self, location: usize) {
        unsafe {
            ptr::copy_nonoverlapping(self as *const Header, location as *mut Header, HEADER_SIZE);
        }
    }
    pub fn reserve(location: usize, size: usize) {
        Header {
            version: 0, // default a tombstone
            size: size as u32,
            schema: 0,
            hash: 0,
            partition: 0,
        }.write(location);
    }
    pub fn id(&self) -> Id {
        Id {
            higher: self.partition,
            lower: self.hash,
        }
    }
    pub fn set_id(&mut self, id: &Id) {
        self.partition = id.higher;
        self.hash = id.lower;
    }
}

pub const HEADER_SIZE :usize = 32;

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Cell {
    pub header: Header,
    pub data: Value
}

impl Cell {

    pub fn new_with_id(schema_id: u32, id: &Id, value: Value) -> Cell {
        Cell {
            header: Header::new(0, schema_id, id),
            data: value
        }
    }

    pub fn encode_cell_key<V>(schema_id: u32, value: &V) -> Id
        where V: Serialize {
        Id::from_obj(&(schema_id, value))
    }

    pub fn new(schema: &Arc<Schema>, value: Value) -> Option<Cell> {
        let schema_id = schema.id;
        let id = if let Value::Map(ref data) = value {
            match schema.key_field {
                Some(ref keys) => {
                    let value = data.get_in_by_ids(keys.iter());
                    match value {
                        &Value::Null => return None,
                        _ => Cell::encode_cell_key(schema_id, value)
                    }
                },
                None => {
                    Id::rand()
                }
            }
        } else {
            Id::rand()
        };
        Some(Cell::new_with_id(schema_id, &id, value))
    }

    pub fn header_from_chunk_raw(ptr: usize) -> Result<Header, ReadError> {
        if ptr == 0 {return Err(ReadError::CellDoesNotExisted)}
        Ok(unsafe {(*(ptr as *const Header))})
    }
    pub fn from_chunk_raw(ptr: usize, chunk: &Chunk) -> Result<Cell, ReadError> {
        let header = Cell::header_from_chunk_raw(ptr)?;
        let data_ptr = ptr + HEADER_SIZE;
        let schema_id = &header.schema;
        if let Some(schema) = chunk.meta.schemas.get(schema_id) {
            Ok(Cell {
                header: header,
                data: reader::read_by_schema(data_ptr, &schema)
            })
        } else {
            error!("Schema {} does not existed to read", schema_id);
            return Err(ReadError::SchemaDoesNotExisted(*schema_id));
        }
    }
    pub fn select_from_chunk_raw(ptr: usize, chunk: &Chunk, fields: &[u64]) -> Result<Value, ReadError> {
        let header = Cell::header_from_chunk_raw(ptr)?;
        let data_ptr = ptr + HEADER_SIZE;
        let schema_id = &header.schema;
        if let Some(schema) = chunk.meta.schemas.get(schema_id) {
            Ok(reader::read_by_schema_selected(data_ptr, &schema, fields))
        } else {
            error!("Schema {} does not existed to read", schema_id);
            return Err(ReadError::SchemaDoesNotExisted(*schema_id));
        }
    }
    pub fn write_to_chunk(&mut self, chunk: &Chunk) -> Result<usize, WriteError> {
        let schema_id = self.header.schema;
        if let Some(schema) = chunk.meta.schemas.get(&schema_id) {
            return self.write_to_chunk_with_schema(chunk, &schema)
        } else {
            error!("Schema {} does not existed to write", schema_id);
            return Err(WriteError::SchemaDoesNotExisted(schema_id));
        }
    }
    pub fn write_to_chunk_with_schema(&mut self, chunk: &Chunk, schema: &Schema) -> Result<usize, WriteError> {
        let mut offset: usize = 0;
        let mut instructions = Vec::<writer::Instruction>::new();
        writer::plan_write_field(&mut offset, &schema.fields, &self.data, &mut instructions)?;
        if schema.is_dynamic {
            writer::plan_write_dynamic_fields(
                &mut offset, &schema.fields,
                &self.data, &mut instructions
            )?;
        }
        let total_size = offset + HEADER_SIZE;
        if total_size > MAX_CELL_SIZE {return Err(WriteError::CellIsTooLarge(total_size))}
        let addr_opt = chunk.try_acquire(total_size);
        self.header.size = total_size as u32;
        self.header.version += 1;
        match addr_opt {
            None => {
                error!("Cannot allocate new spaces in chunk");
                return Err(WriteError::CannotAllocateSpace);
            },
            Some((addr, _lock)) => {
                self.header.write(addr);
                writer::execute_plan(addr + HEADER_SIZE, instructions);
                return Ok(addr);
            }
        }
    }
    pub fn id(&self) -> Id {
        self.header.id()
    }
    pub fn set_id(&mut self, id: &Id) {
        self.header.set_id(id)
    }
}

impl Index<u64> for Cell {
    type Output = Value;

    fn index(&self, index: u64) -> &Self::Output {
        &self.data[index]
    }
}

impl <'a> Index<&'a str> for Cell {
    type Output = Value;

    fn index(&self, index: &'a str) -> &Self::Output {
        &self.data[index]
    }
}

impl <'a> IndexMut <&'a str> for Cell {
    fn index_mut<'b>(&'b mut self, index: &'a str) -> &'b mut Self::Output {
        &mut self.data[index]
    }
}

impl IndexMut <u64> for Cell {
    fn index_mut<'b>(&'b mut self, index:u64) -> &'b mut Self::Output {
        &mut self.data[index]
    }
}<|endoftext|>


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

//! Record audio

#![allow(missing_doc)]

use std::{task, cast};
use std::comm::Data;
use std::vec::Vec;

use record_context::RecordContext;
use record_context;
use openal::ffi;
use sndfile::{SndInfo, SndFile, FormatWav, FormatPcm16, Write};

/**
 * Record audio
 *
 * This class provide easy audio recording using. The Recorder allow the user
 * to record sound, then save it in a file, or create a SoundData object to play the
 * recorded sound in the same program.
 * A special context, RecordContext is needed to create the Recorder object.
 * The Recorder work in it's own task.
 *
 * # Examples
 * ```Rust
 * extern mod ears;
 * use ears::{RecordContext, Recorder};
 *
 * fn main() -> () {
 *     // Create a new context to record audio
 *     let context = ears::init_in().unwrap();
 *     // Create the recorder
 *     let recorder = Recorder::new(context);
 *     // Start to record something
 *     recorder.start();
 *
 *     // Do some other stuff here //
 *
 *     // Stop the recorder
 *     recorder.stop();
 *     // Then store the recorded data in a file
 *     recorder.save_to_file("hello_file");
 * }
 * ```
 */
pub struct Recorder {
    ctxt: RecordContext,
    stop_sender: Option<Sender<bool>>,
    data_receiver: Option<Receiver<Vec<i16>>>,
    samples: Vec<i16>
}

impl Recorder {
    /// Create a new audio recorder
    pub fn new(record_context: RecordContext) -> Recorder {
        Recorder {
            ctxt: record_context,
            stop_sender: None,
            data_receiver: None,
            samples: Vec::new()

        }
    }

    pub fn start(&mut self) {
        let (stop_sender, stop_receiver) = channel();
        let (data_sender, data_receiver) = channel();
        let r_c = self.ctxt.clone();

        self.stop_sender = Some(stop_sender);
        self.data_receiver = Some(data_receiver);

        task::spawn(proc() {
            let mut terminate = false;
            let ctxt = record_context::get(r_c);
            unsafe { ffi::alcCaptureStart(ctxt); }
            let mut available_samples = 0;
            let mut samples: Vec<i16> = Vec::new();

            while !terminate {
                unsafe {
                    ffi::alcGetIntegerv(ctxt,
                                        ffi::ALC_CAPTURE_SAMPLES,
                                        1,
                                        &mut available_samples)
                };

                if available_samples != 0 {
                    let tmp_buf =
                        Vec::from_elem(available_samples as uint, 0i16);
                    unsafe {
                        ffi::alcCaptureSamples(ctxt,
                                               cast::transmute(&tmp_buf.as_slice()[0]),
                                               available_samples);
                    }
                    samples.push_all_move(tmp_buf);
                }

                match stop_receiver.try_recv() {
                    Data(_) => {
                        unsafe { ffi::alcCaptureStop(ctxt); }
                        terminate = true;
                    },
                    _       => {}
                }
            }
            data_sender.send(samples);
        });
    }

    pub fn stop(&mut self) -> bool {
        match self.stop_sender {
            Some(ref s_c) => {
                s_c.send(true);
                match self.data_receiver {
                    Some(ref d_p) => {
                        self.samples = d_p.recv();
                        true
                    },
                    None          => false
                }
            },
            None      => false
        }
    }

    pub fn save_to_file(&mut self, filename: &str) -> bool {
        if self.samples.len() == 0 {
            false
        } else {
            let infos = ~SndInfo {
                frames : self.samples.len() as i64,
                samplerate : 44100,
                channels : 1,
                format : (FormatPcm16 | FormatWav) as i32,
                sections : 0,
                seekable : 0
            };

            let mut file_ext = StrBuf::from_str(filename);
            file_ext.push_str(".wav");
            match SndFile::new_with_info(file_ext.into_owned(), Write, infos) {
                Ok(mut f) => {
                    let len = self.samples.len() as i64;
                    f.write_i16(self.samples.as_mut_slice(), len);
                    f.close();
                    true
                },
                Err(e) => { println!("{}", e); false }
            }
        }
    }
}
<commit_msg>fix build with last Rust master: - try recv return Result<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! Record audio

#![allow(missing_doc)]

use std::{task, cast};
use std::vec::Vec;

use record_context::RecordContext;
use record_context;
use openal::ffi;
use sndfile::{SndInfo, SndFile, FormatWav, FormatPcm16, Write};

/**
 * Record audio
 *
 * This class provide easy audio recording using. The Recorder allow the user
 * to record sound, then save it in a file, or create a SoundData object to play the
 * recorded sound in the same program.
 * A special context, RecordContext is needed to create the Recorder object.
 * The Recorder work in it's own task.
 *
 * # Examples
 * ```Rust
 * extern mod ears;
 * use ears::{RecordContext, Recorder};
 *
 * fn main() -> () {
 *     // Create a new context to record audio
 *     let context = ears::init_in().unwrap();
 *     // Create the recorder
 *     let recorder = Recorder::new(context);
 *     // Start to record something
 *     recorder.start();
 *
 *     // Do some other stuff here //
 *
 *     // Stop the recorder
 *     recorder.stop();
 *     // Then store the recorded data in a file
 *     recorder.save_to_file("hello_file");
 * }
 * ```
 */
pub struct Recorder {
    ctxt: RecordContext,
    stop_sender: Option<Sender<bool>>,
    data_receiver: Option<Receiver<Vec<i16>>>,
    samples: Vec<i16>
}

impl Recorder {
    /// Create a new audio recorder
    pub fn new(record_context: RecordContext) -> Recorder {
        Recorder {
            ctxt: record_context,
            stop_sender: None,
            data_receiver: None,
            samples: Vec::new()

        }
    }

    pub fn start(&mut self) {
        let (stop_sender, stop_receiver) = channel();
        let (data_sender, data_receiver) = channel();
        let r_c = self.ctxt.clone();

        self.stop_sender = Some(stop_sender);
        self.data_receiver = Some(data_receiver);

        task::spawn(proc() {
            let mut terminate = false;
            let ctxt = record_context::get(r_c);
            unsafe { ffi::alcCaptureStart(ctxt); }
            let mut available_samples = 0;
            let mut samples: Vec<i16> = Vec::new();

            while !terminate {
                unsafe {
                    ffi::alcGetIntegerv(ctxt,
                                        ffi::ALC_CAPTURE_SAMPLES,
                                        1,
                                        &mut available_samples)
                };

                if available_samples != 0 {
                    let tmp_buf =
                        Vec::from_elem(available_samples as uint, 0i16);
                    unsafe {
                        ffi::alcCaptureSamples(ctxt,
                                               cast::transmute(&tmp_buf.as_slice()[0]),
                                               available_samples);
                    }
                    samples.push_all_move(tmp_buf);
                }

                match stop_receiver.try_recv() {
                    Ok(_) => {
                        unsafe { ffi::alcCaptureStop(ctxt); }
                        terminate = true;
                    },
                    _       => {}
                }
            }
            data_sender.send(samples);
        });
    }

    pub fn stop(&mut self) -> bool {
        match self.stop_sender {
            Some(ref s_c) => {
                s_c.send(true);
                match self.data_receiver {
                    Some(ref d_p) => {
                        self.samples = d_p.recv();
                        true
                    },
                    None          => false
                }
            },
            None      => false
        }
    }

    pub fn save_to_file(&mut self, filename: &str) -> bool {
        if self.samples.len() == 0 {
            false
        } else {
            let infos = ~SndInfo {
                frames : self.samples.len() as i64,
                samplerate : 44100,
                channels : 1,
                format : (FormatPcm16 | FormatWav) as i32,
                sections : 0,
                seekable : 0
            };

            let mut file_ext = StrBuf::from_str(filename);
            file_ext.push_str(".wav");
            match SndFile::new_with_info(file_ext.into_owned(), Write, infos) {
                Ok(mut f) => {
                    let len = self.samples.len() as i64;
                    f.write_i16(self.samples.as_mut_slice(), len);
                    f.close();
                    true
                },
                Err(e) => { println!("{}", e); false }
            }
        }
    }
}
<|endoftext|>


<commit_before>use Builder;
use rustbox;
use yoga;

use yoga::Renders;

pub struct Renderer<'rbox> {
    rustbox: &'rbox rustbox::RustBox,
}

impl<'rbox> Renderer<'rbox> {
    pub fn new(rustbox: &rustbox::RustBox) -> Renderer {
        Renderer { rustbox: rustbox }
    }

    fn walk(&mut self, node: &yoga::Renderable<rustbox::Color>) {
        let width = node.get_layout_width() as usize;
        let height = node.get_layout_height() as usize;
        let top = node.get_layout_top() as usize;
        let left = node.get_layout_left() as usize;

        let color = match *node.get_color() {
            Some(c) => c,
            None => rustbox::Color::White,
        };

        let background_color = match *node.get_background_color() {
            Some(yoga::style::BackgroundColor::Transparent) => rustbox::Color::Black,
            Some(yoga::style::BackgroundColor::Color(c)) => c,
            None => rustbox::Color::Black,
        };

        if let Some(text) = node.get_text() {
            self.rustbox.print(left, top, rustbox::RB_BOLD, color, background_color, text);
        } else {
            for y in top..(top + height) {
                self.rustbox.print(left,
                                   y,
                                   rustbox::RB_BOLD,
                                   color,
                                   background_color,
                                   &format!("{:1$}", "", width));
            }
        }

        for i in 0..node.get_child_count() {
            let child = node.get_child(i).unwrap();
            self.walk(child);
        }
    }
}

impl<'rbox, 'meas> yoga::Renders<'meas> for Renderer<'rbox> {
    type Color = rustbox::Color;
    type Input = Option<bool>;
    type Output = Option<bool>;
    type Builder = Builder;

    fn render(&mut self, node: &yoga::Renderable<Self::Color>, input: Self::Input) -> Self::Output {
        self.walk(node);
        self.rustbox.present();
        None
    }
}
<commit_msg>chore(warnings): clean some up<commit_after>use Builder;
use rustbox;
use yoga;

pub struct Renderer<'rbox> {
    rustbox: &'rbox rustbox::RustBox,
}

impl<'rbox> Renderer<'rbox> {
    pub fn new(rustbox: &rustbox::RustBox) -> Renderer {
        Renderer { rustbox: rustbox }
    }

    fn walk(&mut self, node: &yoga::Renderable<rustbox::Color>) {
        let width = node.get_layout_width() as usize;
        let height = node.get_layout_height() as usize;
        let top = node.get_layout_top() as usize;
        let left = node.get_layout_left() as usize;

        let color = match *node.get_color() {
            Some(c) => c,
            None => rustbox::Color::White,
        };

        let background_color = match *node.get_background_color() {
            Some(yoga::style::BackgroundColor::Transparent) => rustbox::Color::Black,
            Some(yoga::style::BackgroundColor::Color(c)) => c,
            None => rustbox::Color::Black,
        };

        if let Some(text) = node.get_text() {
            self.rustbox.print(left, top, rustbox::RB_BOLD, color, background_color, text);
        } else {
            for y in top..(top + height) {
                self.rustbox.print(left,
                                   y,
                                   rustbox::RB_BOLD,
                                   color,
                                   background_color,
                                   &format!("{:1$}", "", width));
            }
        }

        for i in 0..node.get_child_count() {
            let child = node.get_child(i).unwrap();
            self.walk(child);
        }
    }
}

impl<'rbox, 'meas> yoga::Renders<'meas> for Renderer<'rbox> {
    type Color = rustbox::Color;
    type Input = Option<bool>;
    type Output = Option<bool>;
    type Builder = Builder;

    fn render(
        &mut self,
        node: &yoga::Renderable<Self::Color>,
        _input: Self::Input
    ) -> Self::Output {
        self.walk(node);
        self.rustbox.present();
        None
    }
}
<|endoftext|>


<commit_before>//! The module that contains the code handling the HTTP response.

use std::convert::From;
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::str;

use curl::easy::Easy;
use mime::Mime;

#[cfg(feature = "rustc-serialization")]
use rustc_serialize;

#[cfg(feature = "serde-serialization")]
use serde;
#[cfg(feature = "serde-serialization")]
use serde_json;

#[cfg(any(feature = "rustc-serialization", feature = "serde-serialization"))]
use std::io::{Error, ErrorKind};

/// Represents an HTTP response.
pub struct Response {
    body: Vec<u8>,
    handle: Easy,
    headers: Vec<(String, String)>,
    status_code: u16
}

impl Response {
    /// Creates a `Response` from the results of a successful request.
    ///
    /// You usually don't create a response this way, but get one as result
    /// from `Request.send(...)`.
    pub fn new(mut easy: Easy, headers: Vec<String>, body: Vec<u8>) -> Response {
        let headers =  {
            let mut vec = Vec::new();
            for header in headers {
                let splitted: Vec<_> = header.splitn(2, ": ")
                                             .map(|part| part.trim())
                                             .filter(|part| part.len() > 0)
                                             .collect();
                if splitted.len() != 2 {
                    continue;
                }

                vec.push((splitted[0].to_owned(), splitted[1].to_owned()));
            }
            vec
        };
        let status_code = easy.response_code().expect("Failed to get the response status code from cURL.") as u16;
        Response {
            body: body,
            handle: easy,
            headers: headers,
            status_code: status_code
        }
    }

    /// Gets the response body's bytes.
    pub fn body(&self) -> &[u8] {
        &self.body
    }

    /// Gets a mutable reference to the response body's bytes.
    pub fn body_mut(&mut self) -> &mut [u8] {
        &mut self.body
    }

    /// Attempts to read the body as UTF-8 string and returns the result.
    pub fn body_str(&self) -> Option<&str> {
        str::from_utf8(self.body()).ok()
    }

    /// Retreives the content type, if there is one.
    ///
    /// This function also returns none if there has been an error parsing
    /// the mime type.
    pub fn content_type(&self) -> Option<Mime> {
        self.header("Content-Type")
            .and_then(|h| h.parse::<Mime>().ok())
    }

    /// Ensures a successful response status code.
    ///
    /// Otherwise returns `ErrorKind::InvalidData`.
    pub fn ensure_success(self) -> Result<Response, Error> {
        if self.is_success() {
            Ok(self)
        } else {
            let msg: &str = &format!("HTTP status code did not indicate success: {}.", self.status_code());
            Err(Error::new(ErrorKind::InvalidData, msg))
        }
    }

    /// Attempts to get a single header value.
    ///
    /// If there are multiple headers with the same name, this method returns
    /// the first one. If you need to get access to the other values, use
    /// [`Response::headers()`](struct.Response.html#method.headers).
    pub fn header(&self, name: &str) -> Option<&String> {
        self.headers.iter().filter(|kvp| kvp.0 == name)
                           .nth(0)
                           .map(|kvp| &kvp.1)
    }

    /// Gets all response headers.
    pub fn headers(&self) -> &Vec<(String, String)> {
        &self.headers
    }

    /// Checks whether the returned status code represents a success
    /// (HTTP status code 2xx) or not.
    pub fn is_success(&self) -> bool {
        match self.status_code {
            200...299 => true,
            _ => false
        }
    }

    /// Attempts to decode the response body from JSON to an
    /// object of the given type.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "rustc-serialization")]
    pub fn json<T: rustc_serialize::Decodable>(&self) -> Result<T, Error> {
        let string = try!(str::from_utf8(&self.body).map_err(|err| Error::new(ErrorKind::InvalidData, err)));
        rustc_serialize::json::decode(string).map_err(|err| Error::new(ErrorKind::InvalidData, err))
    }

    /// Attempts to decode the response body from JSON to an
    /// object of the given type.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "serde-serialization")]
    pub fn json<T: serde::Deserialize>(&self) -> Result<T, Error> {
        serde_json::from_slice(self.body()).map_err(|err| Error::new(ErrorKind::InvalidData, err))
    }

    /// Attempts to decode the response body from JSON into an abstract
    /// JSON representation.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "rustc-serialization")]
    pub fn json_value(&self) -> Result<rustc_serialize::json::Json, Error> {
        let string = try!(str::from_utf8(&self.body).map_err(|err| Error::new(ErrorKind::InvalidData, err)));
        rustc_serialize::json::Json::from_str(string).map_err(|err| Error::new(ErrorKind::InvalidData, err))
    }

    /// Attempts to decode the response body from JSON into an abstract
    /// JSON representation.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "serde-serialization")]
    pub fn json_value(&self) -> Result<serde_json::Value, Error> {
        self.json::<serde_json::Value>()
    }

    /// Gets the response status code.
    pub fn status_code(&self) -> u16 {
        self.status_code
    }
}

impl AsRef<[u8]> for Response {
    fn as_ref(&self) -> &[u8] {
        &self.body
    }
}

impl Debug for Response {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        fmt.debug_struct(stringify!(Response))
            .field("body_str", &self.body_str())
            .field("headers", &self.headers)
            .field("status_code", &self.status_code)
            .finish()
    }
}

impl From<Response> for Easy {
    /// Consumes the response and returns the underlying cURL handle
    /// used for the request so that it can be reused.
    fn from(response: Response) -> Self {
        response.handle
    }
}

impl From<Response> for Vec<u8> {
    fn from(response: Response) -> Self {
        response.body
    }
}

#[cfg(feature = "response-to-string")]
impl ::std::convert::TryFrom<Response> for String {
    type Err = ::std::string::FromUtf8Error;

    fn try_from(response: Response) -> Result<Self, Self::Err> {
        String::from_utf8(response.body)
    }
}<commit_msg>Change Response::ensure_success to return the struct on error instead<commit_after>//! The module that contains the code handling the HTTP response.

use std::convert::From;
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::str;

use curl::easy::Easy;
use mime::Mime;

#[cfg(feature = "rustc-serialization")]
use rustc_serialize;

#[cfg(feature = "serde-serialization")]
use serde;
#[cfg(feature = "serde-serialization")]
use serde_json;

#[cfg(any(feature = "rustc-serialization", feature = "serde-serialization"))]
use std::io::{Error, ErrorKind};

/// Represents an HTTP response.
pub struct Response {
    body: Vec<u8>,
    handle: Easy,
    headers: Vec<(String, String)>,
    status_code: u16
}

impl Response {
    /// Creates a `Response` from the results of a successful request.
    ///
    /// You usually don't create a response this way, but get one as result
    /// from `Request.send(...)`.
    pub fn new(mut easy: Easy, headers: Vec<String>, body: Vec<u8>) -> Response {
        let headers =  {
            let mut vec = Vec::new();
            for header in headers {
                let splitted: Vec<_> = header.splitn(2, ": ")
                                             .map(|part| part.trim())
                                             .filter(|part| part.len() > 0)
                                             .collect();
                if splitted.len() != 2 {
                    continue;
                }

                vec.push((splitted[0].to_owned(), splitted[1].to_owned()));
            }
            vec
        };
        let status_code = easy.response_code().expect("Failed to get the response status code from cURL.") as u16;
        Response {
            body: body,
            handle: easy,
            headers: headers,
            status_code: status_code
        }
    }

    /// Gets the response body's bytes.
    pub fn body(&self) -> &[u8] {
        &self.body
    }

    /// Gets a mutable reference to the response body's bytes.
    pub fn body_mut(&mut self) -> &mut [u8] {
        &mut self.body
    }

    /// Attempts to read the body as UTF-8 string and returns the result.
    pub fn body_str(&self) -> Option<&str> {
        str::from_utf8(self.body()).ok()
    }

    /// Retreives the content type, if there is one.
    ///
    /// This function also returns none if there has been an error parsing
    /// the mime type.
    pub fn content_type(&self) -> Option<Mime> {
        self.header("Content-Type")
            .and_then(|h| h.parse::<Mime>().ok())
    }

    /// Returns `Ok` in case of a successful status code and `Err` if not.
    ///
    /// This returns the `Response` in both cases and uses the `Ok`
    /// and `Err` variants to indicate the result. See
    /// [`Response::is_success`](struct.Response.html#method.is_success)
    /// for more information.
    pub fn ensure_success(self) -> Result<Response, Response> {
        if self.is_success() {
            Ok(self)
        } else {
            Err(self)
        }
    }

    /// Attempts to get a single header value.
    ///
    /// If there are multiple headers with the same name, this method returns
    /// the first one. If you need to get access to the other values, use
    /// [`Response::headers()`](struct.Response.html#method.headers).
    pub fn header(&self, name: &str) -> Option<&String> {
        self.headers.iter().filter(|kvp| kvp.0 == name)
                           .nth(0)
                           .map(|kvp| &kvp.1)
    }

    /// Gets all response headers.
    pub fn headers(&self) -> &Vec<(String, String)> {
        &self.headers
    }

    /// Checks whether the returned status code represents a success
    /// (HTTP status code 2xx) or not.
    pub fn is_success(&self) -> bool {
        match self.status_code {
            200...299 => true,
            _ => false
        }
    }

    /// Attempts to decode the response body from JSON to an
    /// object of the given type.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "rustc-serialization")]
    pub fn json<T: rustc_serialize::Decodable>(&self) -> Result<T, Error> {
        let string = try!(str::from_utf8(&self.body).map_err(|err| Error::new(ErrorKind::InvalidData, err)));
        rustc_serialize::json::decode(string).map_err(|err| Error::new(ErrorKind::InvalidData, err))
    }

    /// Attempts to decode the response body from JSON to an
    /// object of the given type.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "serde-serialization")]
    pub fn json<T: serde::Deserialize>(&self) -> Result<T, Error> {
        serde_json::from_slice(self.body()).map_err(|err| Error::new(ErrorKind::InvalidData, err))
    }

    /// Attempts to decode the response body from JSON into an abstract
    /// JSON representation.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "rustc-serialization")]
    pub fn json_value(&self) -> Result<rustc_serialize::json::Json, Error> {
        let string = try!(str::from_utf8(&self.body).map_err(|err| Error::new(ErrorKind::InvalidData, err)));
        rustc_serialize::json::Json::from_str(string).map_err(|err| Error::new(ErrorKind::InvalidData, err))
    }

    /// Attempts to decode the response body from JSON into an abstract
    /// JSON representation.
    ///
    /// Returns `ErrorKind::InvalidData` when the server response could not
    /// be read as UTF-8 string or if it could not be deserialized from JSON.
    #[cfg(feature = "serde-serialization")]
    pub fn json_value(&self) -> Result<serde_json::Value, Error> {
        self.json::<serde_json::Value>()
    }

    /// Gets the response status code.
    pub fn status_code(&self) -> u16 {
        self.status_code
    }
}

impl AsRef<[u8]> for Response {
    fn as_ref(&self) -> &[u8] {
        &self.body
    }
}

impl Debug for Response {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        fmt.debug_struct(stringify!(Response))
            .field("body_str", &self.body_str())
            .field("headers", &self.headers)
            .field("status_code", &self.status_code)
            .finish()
    }
}

impl From<Response> for Easy {
    /// Consumes the response and returns the underlying cURL handle
    /// used for the request so that it can be reused.
    fn from(response: Response) -> Self {
        response.handle
    }
}

impl From<Response> for Vec<u8> {
    fn from(response: Response) -> Self {
        response.body
    }
}

#[cfg(feature = "response-to-string")]
impl ::std::convert::TryFrom<Response> for String {
    type Err = ::std::string::FromUtf8Error;

    fn try_from(response: Response) -> Result<Self, Self::Err> {
        String::from_utf8(response.body)
    }
}<|endoftext|>


<commit_before>use fall_tree::{NodeType, FileStats};
use lex::Token;

use tree_builder::{Node, TokenSequence, NodeFactory};

pub struct Parser<'r> {
    node_types: &'r [NodeType],
    rules: &'r [SynRule],
}

#[derive(Serialize, Deserialize)]
pub struct SynRule {
    pub ty: Option<usize>,
    pub body: Expr,
}

#[derive(Serialize, Deserialize)]
pub enum Expr {
    Or(Vec<Expr>),
    And(Vec<Expr>, Option<usize>),
    Rule(usize),
    Token(usize),
    Rep(Box<Expr>),
    Opt(Box<Expr>),
    Not(Vec<usize>),
    NotAhead(Box<Expr>),
    Eof,
    Layer(Box<Expr>, Box<Expr>),
    SkipUntil(Vec<usize>),
}

struct Ctx<'p> {
    ticks: u64,
    node_factory: &'p mut NodeFactory,
}

impl<'r> Parser<'r> {
    pub fn new(node_types: &'r [NodeType], rules: &'r [SynRule]) -> Parser<'r> {
        Parser { node_types, rules: rules }
    }

    pub fn parse(&self, tokens: TokenSequence, nf: &mut NodeFactory, stats: &mut FileStats) -> Node {
        let mut ctx = Ctx { ticks: 0, node_factory: nf };
        let (mut file_node, mut leftover) = self
            .parse_exp(&Expr::Rule(0), tokens, &mut ctx)
            .unwrap_or_else(|| {
                let ty = self.node_type(self.rules[0].ty
                    .expect("First rule must be public"));
                (ctx.node_factory.create_composite_node(Some(ty)), tokens)
            });
        let mut error = ctx.node_factory.create_error_node();
        let mut skipped = false;
        while leftover.current().is_some() {
            skipped = true;
            let p = ctx.node_factory.create_leaf_node(leftover);
            leftover = p.1;
            error.push_child(p.0)
        }
        if skipped {
            file_node.push_child(error)
        }
        stats.parsing_ticks = ctx.ticks;
        file_node
    }

    fn parse_exp<'t>(&self, expr: &Expr, tokens: TokenSequence<'t>, ctx: &mut Ctx)
                     -> Option<(Node, TokenSequence<'t>)> {
        ctx.ticks += 1;
        match *expr {
            Expr::Or(ref parts) => {
                for p in parts.iter() {
                    if let Some(result) = self.parse_exp(p, tokens, ctx) {
                        return Some(result)
                    }
                }
                None
            }

            Expr::And(ref parts, commit) => {
                let mut node = ctx.node_factory.create_composite_node(None);
                let commit = commit.unwrap_or(parts.len());
                let mut tokens = tokens;
                for (i, p) in parts.iter().enumerate() {
                    if let Some((n, ts)) = self.parse_exp(p, tokens, ctx) {
                        tokens = ts;
                        node.push_child(n);
                    } else {
                        if i < commit {
                            return None
                        }
                        let error_node = ctx.node_factory.create_error_node();
                        node.push_child(error_node);
                        break
                    }
                }
                Some((node, tokens))
            }

            Expr::Rule(id) => {
                let rule = &self.rules[id];
                let ty = rule.ty.map(|ty| self.node_type(ty));
                if let Some((node, ts)) = self.parse_exp(&rule.body, tokens, ctx) {
                    let mut result = ctx.node_factory.create_composite_node(ty);
                    result.push_child(node);
                    Some((result, ts))
                } else {
                    None
                }
            }

            Expr::Token(ty) => {
                if let Some(current) = tokens.current() {
                    if self.token_set_contains(&[ty], current) {
                        return Some(ctx.node_factory.create_leaf_node(tokens))
                    }
                }
                None
            }

            Expr::Opt(ref body) => self.parse_exp(&*body, tokens, ctx).or_else(|| {
                Some(ctx.node_factory.create_success_node(tokens))
            }),

            Expr::Not(ref ts) => {
                if let Some(current) = tokens.current() {
                    if !self.token_set_contains(ts, current) {
                        return Some(ctx.node_factory.create_leaf_node(tokens))
                    }
                }
                None
            }

            Expr::NotAhead(ref e) => if self.parse_exp(e, tokens, ctx).is_some() {
                None
            } else {
                Some(ctx.node_factory.create_success_node(tokens))
            },

            Expr::Eof => if tokens.current().is_none() {
                Some(ctx.node_factory.create_success_node(tokens))
            } else {
                None
            },

            Expr::Layer(ref l, ref e) => {
                if let Some((_, rest)) = self.parse_exp(l, tokens, ctx) {
                    let mut result = ctx.node_factory.create_composite_node(None);
                    let layer = tokens.prefix(rest);
                    if let Some((layer_contents, mut leftovers)) = self.parse_exp(e, layer, ctx) {
                        result.push_child(layer_contents);
                        if leftovers.current().is_some() {
                            let mut error = ctx.node_factory.create_error_node();
                            while leftovers.current().is_some() {
                                let p = ctx.node_factory.create_leaf_node(leftovers);
                                error.push_child(p.0);
                                leftovers = p.1;
                            }
                            result.push_child(error)
                        }
                    };
                    return Some((result, rest));
                };
                None
            }

            Expr::Rep(ref body) => {
                let mut node = ctx.node_factory.create_composite_node(None);
                let mut tokens = tokens;
                loop {
                    if let Some((n, t)) = self.parse_exp(body, tokens, ctx) {
                        node.push_child(n);
                        tokens = t;
                    } else {
                        break;
                    }
                }
                Some((node, tokens))
            }

            Expr::SkipUntil(ref ts) => {
                let mut result = ctx.node_factory.create_error_node();
                let mut skipped = false;
                let mut tokens = tokens;
                loop {
                    if let Some(t) = tokens.current() {
                        if self.token_set_contains(ts, t) {
                            break;
                        } else {
                            skipped = true;
                            let p = ctx.node_factory.create_leaf_node(tokens);
                            result.push_child(p.0);
                            tokens = p.1;
                        }
                    } else {
                        break
                    }
                }

                if !skipped {
                    return Some(ctx.node_factory.create_success_node(tokens));
                }

                Some((result, tokens))
            }
        }
    }

    fn token_set_contains(&self, ts: &[usize], token: Token) -> bool {
        ts.iter().any(|&t| self.node_type(t) == token.ty)
    }

    fn node_type(&self, idx: usize) -> NodeType {
        self.node_types[idx]
    }
}

<commit_msg>Some encapsulation<commit_after>use fall_tree::{NodeType, FileStats};
use lex::Token;

use tree_builder::{Node, TokenSequence, NodeFactory};

pub struct Parser<'r> {
    node_types: &'r [NodeType],
    rules: &'r [SynRule],
}

#[derive(Serialize, Deserialize)]
pub struct SynRule {
    pub ty: Option<usize>,
    pub body: Expr,
}

#[derive(Serialize, Deserialize)]
pub enum Expr {
    Or(Vec<Expr>),
    And(Vec<Expr>, Option<usize>),
    Rule(usize),
    Token(usize),
    Rep(Box<Expr>),
    Opt(Box<Expr>),
    Not(Vec<usize>),
    NotAhead(Box<Expr>),
    Eof,
    Layer(Box<Expr>, Box<Expr>),
    SkipUntil(Vec<usize>),
}

struct Ctx<'p> {
    ticks: u64,
    node_factory: &'p mut NodeFactory,
}

impl<'p> Ctx<'p> {
    fn create_composite_node(&mut self, ty: Option<NodeType>) -> Node {
        self.node_factory.create_composite_node(ty)
    }

    fn create_error_node(&mut self) -> Node {
        self.node_factory.create_error_node()
    }

    fn create_leaf_node<'t>(&mut self, tokens: TokenSequence<'t>) -> (Node, TokenSequence<'t>) {
        self.node_factory.create_leaf_node(tokens)
    }

    fn create_success_node<'t>(&mut self, tokens: TokenSequence<'t>) -> (Node, TokenSequence<'t>) {
        self.node_factory.create_success_node(tokens)
    }
}

impl<'r> Parser<'r> {
    pub fn new(node_types: &'r [NodeType], rules: &'r [SynRule]) -> Parser<'r> {
        Parser { node_types, rules: rules }
    }

    pub fn parse(&self, tokens: TokenSequence, nf: &mut NodeFactory, stats: &mut FileStats) -> Node {
        let mut ctx = Ctx { ticks: 0, node_factory: nf };
        let (mut file_node, mut leftover) = self
            .parse_exp(&Expr::Rule(0), tokens, &mut ctx)
            .unwrap_or_else(|| {
                let ty = self.node_type(self.rules[0].ty
                    .expect("First rule must be public"));
                (ctx.create_composite_node(Some(ty)), tokens)
            });
        let mut error = ctx.create_error_node();
        let mut skipped = false;
        while leftover.current().is_some() {
            skipped = true;
            let p = ctx.create_leaf_node(leftover);
            leftover = p.1;
            error.push_child(p.0)
        }
        if skipped {
            file_node.push_child(error)
        }
        stats.parsing_ticks = ctx.ticks;
        file_node
    }

    fn parse_exp<'t>(&self, expr: &Expr, tokens: TokenSequence<'t>, ctx: &mut Ctx)
                     -> Option<(Node, TokenSequence<'t>)> {
        ctx.ticks += 1;
        match *expr {
            Expr::Or(ref parts) => {
                for p in parts.iter() {
                    if let Some(result) = self.parse_exp(p, tokens, ctx) {
                        return Some(result)
                    }
                }
                None
            }

            Expr::And(ref parts, commit) => {
                let mut node = ctx.create_composite_node(None);
                let commit = commit.unwrap_or(parts.len());
                let mut tokens = tokens;
                for (i, p) in parts.iter().enumerate() {
                    if let Some((n, ts)) = self.parse_exp(p, tokens, ctx) {
                        tokens = ts;
                        node.push_child(n);
                    } else {
                        if i < commit {
                            return None
                        }
                        let error_node = ctx.create_error_node();
                        node.push_child(error_node);
                        break
                    }
                }
                Some((node, tokens))
            }

            Expr::Rule(id) => {
                let rule = &self.rules[id];
                let ty = rule.ty.map(|ty| self.node_type(ty));
                if let Some((node, ts)) = self.parse_exp(&rule.body, tokens, ctx) {
                    let mut result = ctx.create_composite_node(ty);
                    result.push_child(node);
                    Some((result, ts))
                } else {
                    None
                }
            }

            Expr::Token(ty) => {
                if let Some(current) = tokens.current() {
                    if self.token_set_contains(&[ty], current) {
                        return Some(ctx.create_leaf_node(tokens))
                    }
                }
                None
            }

            Expr::Opt(ref body) => self.parse_exp(&*body, tokens, ctx).or_else(|| {
                Some(ctx.create_success_node(tokens))
            }),

            Expr::Not(ref ts) => {
                if let Some(current) = tokens.current() {
                    if !self.token_set_contains(ts, current) {
                        return Some(ctx.create_leaf_node(tokens))
                    }
                }
                None
            }

            Expr::NotAhead(ref e) => if self.parse_exp(e, tokens, ctx).is_some() {
                None
            } else {
                Some(ctx.create_success_node(tokens))
            },

            Expr::Eof => if tokens.current().is_none() {
                Some(ctx.create_success_node(tokens))
            } else {
                None
            },

            Expr::Layer(ref l, ref e) => {
                if let Some((_, rest)) = self.parse_exp(l, tokens, ctx) {
                    let mut result = ctx.create_composite_node(None);
                    let layer = tokens.prefix(rest);
                    if let Some((layer_contents, mut leftovers)) = self.parse_exp(e, layer, ctx) {
                        result.push_child(layer_contents);
                        if leftovers.current().is_some() {
                            let mut error = ctx.create_error_node();
                            while leftovers.current().is_some() {
                                let p = ctx.create_leaf_node(leftovers);
                                error.push_child(p.0);
                                leftovers = p.1;
                            }
                            result.push_child(error)
                        }
                    };
                    return Some((result, rest));
                };
                None
            }

            Expr::Rep(ref body) => {
                let mut node = ctx.create_composite_node(None);
                let mut tokens = tokens;
                loop {
                    if let Some((n, t)) = self.parse_exp(body, tokens, ctx) {
                        node.push_child(n);
                        tokens = t;
                    } else {
                        break;
                    }
                }
                Some((node, tokens))
            }

            Expr::SkipUntil(ref ts) => {
                let mut result = ctx.create_error_node();
                let mut skipped = false;
                let mut tokens = tokens;
                loop {
                    if let Some(t) = tokens.current() {
                        if self.token_set_contains(ts, t) {
                            break;
                        } else {
                            skipped = true;
                            let p = ctx.create_leaf_node(tokens);
                            result.push_child(p.0);
                            tokens = p.1;
                        }
                    } else {
                        break
                    }
                }

                if !skipped {
                    return Some(ctx.create_success_node(tokens));
                }

                Some((result, tokens))
            }
        }
    }

    fn token_set_contains(&self, ts: &[usize], token: Token) -> bool {
        ts.iter().any(|&t| self.node_type(t) == token.ty)
    }

    fn node_type(&self, idx: usize) -> NodeType {
        self.node_types[idx]
    }
}

<|endoftext|>


<commit_before>#![allow(unused_imports)]
#![allow(non_snake_case)]

use procon::*;
use std::cmp::{max, min};
use std::collections::*;
use std::ops::*;
use std::*;

pub fn main() {
    return;
}

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

    #[test]
    fn test_ok() {
        assert_eq!(7, 1 + 2 * 3);
    }
}

pub mod procon {
    use std;
    use std::cmp::*;
    use std::collections::*;
    use std::io;
    use std::mem;
    use std::str::FromStr;

    pub fn rl() -> String {
        let mut buf = String::new();
        io::stdin().read_line(&mut buf).unwrap();
        buf.trim_right().to_owned()
    }

    pub fn rw<T>() -> Vec<T>
    where
        T: std::str::FromStr,
        T::Err: std::fmt::Debug,
    {
        let mut buf = String::new();
        io::stdin().read_line(&mut buf).unwrap();
        buf.split_whitespace()
            .map(|word| T::from_str(word).unwrap())
            .collect()
    }

    // Polyfill
    #[derive(PartialEq, Eq, Clone, Debug)]
    pub struct Rev<T>(pub T);

    impl<T: PartialOrd> PartialOrd for Rev<T> {
        fn partial_cmp(&self, other: &Rev<T>) -> Option<Ordering> {
            other.0.partial_cmp(&self.0)
        }
    }

    impl<T: Ord> Ord for Rev<T> {
        fn cmp(&self, other: &Rev<T>) -> Ordering {
            other.0.cmp(&self.0)
        }
    }
}
<commit_msg>Collapse procon mod<commit_after>#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::ops::*;
use std::*;

pub fn main() {
    return;
}

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

    #[test]
    fn test_ok() {
        assert_eq!(7, 1 + 2 * 3);
    }
}

// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused)]
fn rl() -> String {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

#[allow(unused)]
fn rw<T>() -> Vec<T>
where
    T: std::str::FromStr,
    T::Err: std::fmt::Debug,
{
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    buf.split_whitespace()
        .map(|word| T::from_str(word).unwrap())
        .collect()
}

// -----------------------------------------------
// Polyfill
// -----------------------------------------------

#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Rev<T>(pub T);

impl<T: PartialOrd> PartialOrd for Rev<T> {
    fn partial_cmp(&self, other: &Rev<T>) -> Option<Ordering> {
        other.0.partial_cmp(&self.0)
    }
}

impl<T: Ord> Ord for Rev<T> {
    fn cmp(&self, other: &Rev<T>) -> Ordering {
        other.0.cmp(&self.0)
    }
}
<|endoftext|>


<commit_before>use std::comm::SharedChan;

fn main() {
    let (port, chan): (Port<int>, Chan<int>) = stream();
    let chan = SharedChan::new(chan);

    let docs: ~[~str] = ~[~"hello world", ~"hello guys", ~"world"];

    fn mapper(doc: ~str) -> ~str {
        let words: ~[~str] = doc.split_iter(' ')
            .filter(|&x| x != "")
            .map(|x| {
                x.to_owned()
            }).collect();

        for w in words.iter() {
            println(w.to_str() + ", 1");
        }

        ~"in mapper"
    }

    fn reducer(key: ~str, vals: ~[~str]) {

    }

    docs.mapreduce(mapper, reducer);

    let vals = [40, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10];
    for i in range(0, vals.len()) {
        let child_chan = chan.clone();
        do spawn {
            let res = fib(vals[i]);
            print("("+i.to_str()+")");
            child_chan.send(res);
        }
    }

    let mut result = 0;
    for i in range(0, vals.len()) {
        result += port.recv();
    }

    println("\nresult: "+result.to_str());
}

fn fib(n: int) -> int {
    match n {
        1 => 1,
        2 => 1,
        _ => fib(n-1) + fib(n-2)
    }
}

//fn mapreduce(mapper : extern fn(~str), reducer : extern fn(~str, ~[~str]) ) {

trait MapReduce {
    fn mapreduce( &self, extern fn(~str) -> ~str, extern fn(~str, ~[~str]) );
}

impl MapReduce for ~[~str] {
    fn mapreduce( &self, mapper: extern fn(~str) -> ~str, reducer: extern fn(~str, ~[~str]) ) {
        println("map reducing!!");
        for doc in self.iter() {
            mapper(doc.to_owned());
        }
    }
}<commit_msg>about to add spawn code<commit_after>use std::comm::SharedChan;

fn main() {
    let (port, chan): (Port<int>, Chan<int>) = stream();
    let chan = SharedChan::new(chan);

    let docs: ~[~str] = ~[~"hello world", ~"hello guys", ~"world"];

    fn mapper(doc: ~str) -> ~[(~str, ~str)]{
        let words: ~[~str] = doc.split_iter(' ')
            .filter(|&x| x != "")
            .map(|x| {
                x.to_owned()
            }).collect();

        let mut ret: ~[(~str, ~str)] = ~[];
        for w in words.iter() {
//            println(w.to_str() + ", 1");
            let tup: (~str, ~str) = (w.to_str(), ~"1");
            ret.push(tup);
        }

        ret
    }

    fn reducer(key: ~str, vals: ~[~str]) {

    }

    docs.mapreduce(mapper, reducer);

    let vals = [40, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10];
    for i in range(0, vals.len()) {
        let child_chan = chan.clone();
        do spawn {
            let res = fib(vals[i]);
            print("("+i.to_str()+")");
            child_chan.send(res);
        }
    }

    let mut result = 0;
    for i in range(0, vals.len()) {
        result += port.recv();
    }

    println("\nresult: "+result.to_str());
}

fn fib(n: int) -> int {
    match n {
        1 => 1,
        2 => 1,
        _ => fib(n-1) + fib(n-2)
    }
}

//fn mapreduce(mapper : extern fn(~str), reducer : extern fn(~str, ~[~str]) ) {

trait MapReduce {
    fn mapreduce( &self, extern fn(~str) -> ~[(~str, ~str)], extern fn(~str, ~[~str]) );
}

impl MapReduce for ~[~str] {
    fn mapreduce( &self, mapper: extern fn(~str) -> ~[(~str, ~str)], reducer: extern fn(~str, ~[~str]) ) {
        println("map reducing!!");
        for doc in self.iter() {
            let ivals: ~[(~str, ~str)] = mapper(doc.to_owned());
            println(fmt!("%?", ivals));
        }
    }
}<|endoftext|>