<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, nonce),
            mac_key: [0; 32],
        };
        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) {
        self.mac_key.copy_from_slice(&self.cipher.block(0)[..32]);
    }

    fn counter_mode(&self, input: &[u8], output: &mut [u8]) {
        for (i, (mi, oi)) in (1..).zip(input.chunks(64).zip(output.chunks_mut(64))) {
            for (o, (x, y)) in oi.iter_mut().zip(
                mi.iter().zip(self.cipher.block(i).iter()),
            )
            {
                *o = x ^ y;
            }
        }
    }

    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 hash_function = Poly1305::new(key, data);
    hash_function.update(ciphertext);
    hash_function.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]) {
        let buffer = &mut [0; 17];
        LittleEndian::write_u64(&mut buffer[..8], self.data_len);
        LittleEndian::write_u64(&mut buffer[8..], self.ciphertext_len);
        buffer[16] = 1;
        self.function.process(buffer);
        self.function.value(output);
    }

    fn process(&mut self, input: &[u8]) {
        let buffer = &mut [0; 17];
        for chunk in input.chunks(16) {
            buffer[..chunk.len()].copy_from_slice(chunk);
            for c_j in buffer.iter_mut().take(16).skip(chunk.len()) {
                *c_j = 0;
            }
            buffer[16] = 1;
            self.function.process(buffer);
        }
    }
}

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

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

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

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

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

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

/// Carries coefficients in the expansion of `h` so that each one is less than 256.
fn squeeze(h: &mut [u32; 17]) {
    let mut u = 0;
    for h_j in h.iter_mut().take(16) {
        u += *h_j;
        *h_j = u & 255;
        u >>= 8;
    }
    u += h[16];
    h[16] = u & 3;
    u = 5 * (u >> 2);
    for h_j in h.iter_mut().take(16) {
        u += *h_j;
        *h_j = u & 255;
        u >>= 8;
    }
    u += h[16];
    h[16] = u;
}

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

fn load_r(key: &[u8]) -> [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[16] = 0;
    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 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_digest() {
        let key = &h2b(
            "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b",
        );
        let message = b"Cryptographic Forum Research Group";
        let tag = h2b("a8061dc1305136c6c22b8baf0c0127a9");
        let actual = &mut [0; 16];
        poly1305(key, message, actual);
        assert_eq!(tag, actual.to_vec());
    }
    */
}
<commit_msg>poly1305: stop copying into 17-byte buffers<commit_after>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, nonce),
            mac_key: [0; 32],
        };
        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) {
        self.mac_key.copy_from_slice(&self.cipher.block(0)[..32]);
    }

    fn counter_mode(&self, input: &[u8], output: &mut [u8]) {
        for (i, (mi, oi)) in (1..).zip(input.chunks(64).zip(output.chunks_mut(64))) {
            for (o, (x, y)) in oi.iter_mut().zip(
                mi.iter().zip(self.cipher.block(i).iter()),
            )
            {
                *o = x ^ y;
            }
        }
    }

    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 hash_function = Poly1305::new(key, data);
    hash_function.update(ciphertext);
    hash_function.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]) {
        freeze(&mut self.h);
        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);
        mulmod(&mut self.h, &self.r);
    }
}

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 mulmod(h: &mut [u32; 17], r: &[u8; 17]) {
    let h_r = &mut [0; 17];
    for i in 0..17 {
        let mut u = 0;
        for j in 0..i + 1 {
            u += h[j] * u32::from(r[i - j]);
        }
        for j in i + 1..17 {
            u += 320 * h[j] * u32::from(r[i + 17 - j]);
        }
        h_r[i] = u;
    }
    h.copy_from_slice(h_r);
    squeeze(h);
}

/// Carries coefficients in the expansion of `h` so that each one is less than 256.
fn squeeze(h: &mut [u32; 17]) {
    let mut u = 0;
    for h_j in h.iter_mut().take(16) {
        u += *h_j;
        *h_j = u & 255;
        u >>= 8;
    }
    u += h[16];
    h[16] = u & 3;
    u = 5 * (u >> 2);
    for h_j in h.iter_mut().take(16) {
        u += *h_j;
        *h_j = u & 255;
        u >>= 8;
    }
    u += h[16];
    h[16] = u;
}

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

fn load_r(key: &[u8]) -> [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[16] = 0;
    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 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_digest() {
        let key = &h2b(
            "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b",
        );
        let message = b"Cryptographic Forum Research Group";
        let tag = h2b("a8061dc1305136c6c22b8baf0c0127a9");
        let actual = &mut [0; 16];
        poly1305(key, message, actual);
        assert_eq!(tag, actual.to_vec());
    }
    */
}
<|endoftext|>


<commit_before>
use graphics::*;
use piston::*;

use aabb::AABB;
use ai::AI;
use ball::Ball;
use settings;
use player::Player;

pub struct App {
    background_image: Option<Image>,
    ball_image: Option<Image>,
    player_image: Option<Image>,

    player1: Option<Player>,
    player2: Option<Player>,
    ball: Option<Ball>,
    ai: Option<AI>,

    top_wall_aabb: AABB,
    bottom_wall_aabb: AABB,
    left_wall_aabb: AABB,
    right_wall_aabb: AABB,

    is_up_holding: bool,
    is_down_holding: bool,
}

impl App {
    pub fn new() -> App {
        App {
            background_image: None,
            ball_image: None,
            player_image: None,

            player1: None,
            player2: None,
            ball: None,
            ai: None,

            top_wall_aabb: AABB::new(
                settings::WINDOW_SIZE[0] as f64 / 2.0,
                settings::WALL_RADIUS,
                settings::WINDOW_SIZE[0] as f64,
                settings::WALL_RADIUS * 2.0
            ),
            bottom_wall_aabb: AABB::new(
                settings::WINDOW_SIZE[0] as f64 / 2.0,
                settings::WINDOW_SIZE[1] as f64 - settings::WALL_RADIUS,
                settings::WINDOW_SIZE[0] as f64,
                settings::WALL_RADIUS * 2.0
            ),
            left_wall_aabb: AABB::new(
                -settings::WALL_RADIUS,
                settings::WINDOW_SIZE[1] as f64 / 2.0,
                settings::WALL_RADIUS * 2.0,
                settings::WINDOW_SIZE[1] as f64
            ),
            right_wall_aabb: AABB::new(
                settings::WINDOW_SIZE[0] as f64 + settings::WALL_RADIUS,
                settings::WINDOW_SIZE[1] as f64 / 2.0,
                settings::WALL_RADIUS * 2.0,
                settings::WINDOW_SIZE[1] as f64
            ),

            is_up_holding: false,
            is_down_holding: false,
        }
    }
}

impl Game for App {
    fn render(&self, c: &Context, gl: &mut Gl) {
        c.view().image(self.background_image.unwrap()).draw(gl);

        self.player1.get_ref().render(c, gl);
        self.player2.get_ref().render(c, gl);
        self.ball.get_ref().render(c, gl);
    }

    fn update(&mut self, dt: f64, _asset_store: &mut AssetStore) {
        if self.is_up_holding && self.is_down_holding {
            self.player1.get_mut_ref().stop_move();
        } else if self.is_up_holding {
            self.player1.get_mut_ref().start_moving_up();
        } else if self.is_down_holding {
            self.player1.get_mut_ref().start_moving_down();
        } else {
            self.player1.get_mut_ref().stop_move();
        }

        self.ai.get_mut_ref().update(dt, self.player2.get_mut_ref(), self.ball.get_mut_ref());

        self.player1.get_mut_ref().update(dt, &self.top_wall_aabb, &self.bottom_wall_aabb);
        self.player2.get_mut_ref().update(dt, &self.top_wall_aabb, &self.bottom_wall_aabb);
        self.ball.get_mut_ref().update(dt, &self.top_wall_aabb, &self.bottom_wall_aabb, &self.left_wall_aabb, &self.right_wall_aabb, self.player1.get_mut_ref(), self.player2.get_mut_ref());
    }

    fn load(&mut self, asset_store: &mut AssetStore) {
        self.background_image = Some(asset_store.load_image(settings::BACKGROUND_IMAGE));
        self.ball_image = Some(asset_store.load_image(settings::BALL_IMAGE));
        self.player_image = Some(asset_store.load_image(settings::PLAYER_IMAGE));

        self.player1 = Some(Player::new(self.player_image.unwrap()));
        self.player1.get_mut_ref().set_pos([settings::PLAYER_PADDING, settings::WINDOW_SIZE[1] as f64 / 2.0]);

        self.player2 = Some(Player::new(self.player_image.unwrap()));
        self.player2.get_mut_ref().set_pos([settings::WINDOW_SIZE[0] as f64 - settings::PLAYER_PADDING, settings::WINDOW_SIZE[1] as f64 / 2.0]);

        self.ball = Some(Ball::new(self.ball_image.unwrap()));
        self.ball.get_mut_ref().reset();

        self.ai = Some(AI::new());
    }

    fn key_press(
        &mut self,
        key: keyboard::Key,
        _asset_store: &mut AssetStore
    ) {
        if key == keyboard::Up {
            self.is_up_holding = true;
        }

        if key == keyboard::Down {
            self.is_down_holding = true;
        }

        if key == keyboard::Space {
            self.ball.get_mut_ref().emit();
        }
    }

    fn key_release(
        &mut self,
        key: keyboard::Key,
        _asset_store: &mut AssetStore
    ) {
        if key == keyboard::Up {
            self.is_up_holding = false;
        }

        if key == keyboard::Down {
            self.is_down_holding = false;
        }
    }

}

<commit_msg>Upgraded to latest Piston<commit_after>
use graphics::*;
use piston::*;

use aabb::AABB;
use ai::AI;
use ball::Ball;
use settings;
use player::Player;

pub struct App {
    background_image: Option<Image>,
    ball_image: Option<Image>,
    player_image: Option<Image>,

    player1: Option<Player>,
    player2: Option<Player>,
    ball: Option<Ball>,
    ai: Option<AI>,

    top_wall_aabb: AABB,
    bottom_wall_aabb: AABB,
    left_wall_aabb: AABB,
    right_wall_aabb: AABB,

    is_up_holding: bool,
    is_down_holding: bool,
}

impl App {
    pub fn new() -> App {
        App {
            background_image: None,
            ball_image: None,
            player_image: None,

            player1: None,
            player2: None,
            ball: None,
            ai: None,

            top_wall_aabb: AABB::new(
                settings::WINDOW_SIZE[0] as f64 / 2.0,
                settings::WALL_RADIUS,
                settings::WINDOW_SIZE[0] as f64,
                settings::WALL_RADIUS * 2.0
            ),
            bottom_wall_aabb: AABB::new(
                settings::WINDOW_SIZE[0] as f64 / 2.0,
                settings::WINDOW_SIZE[1] as f64 - settings::WALL_RADIUS,
                settings::WINDOW_SIZE[0] as f64,
                settings::WALL_RADIUS * 2.0
            ),
            left_wall_aabb: AABB::new(
                -settings::WALL_RADIUS,
                settings::WINDOW_SIZE[1] as f64 / 2.0,
                settings::WALL_RADIUS * 2.0,
                settings::WINDOW_SIZE[1] as f64
            ),
            right_wall_aabb: AABB::new(
                settings::WINDOW_SIZE[0] as f64 + settings::WALL_RADIUS,
                settings::WINDOW_SIZE[1] as f64 / 2.0,
                settings::WALL_RADIUS * 2.0,
                settings::WINDOW_SIZE[1] as f64
            ),

            is_up_holding: false,
            is_down_holding: false,
        }
    }
}

impl Game for App {
    fn render(&self, _ext_dt: f64, c: &Context, gl: &mut Gl) {
        c.view().image(self.background_image.unwrap()).draw(gl);

        self.player1.get_ref().render(c, gl);
        self.player2.get_ref().render(c, gl);
        self.ball.get_ref().render(c, gl);
    }

    fn update(&mut self, dt: f64, _asset_store: &mut AssetStore) {
        if self.is_up_holding && self.is_down_holding {
            self.player1.get_mut_ref().stop_move();
        } else if self.is_up_holding {
            self.player1.get_mut_ref().start_moving_up();
        } else if self.is_down_holding {
            self.player1.get_mut_ref().start_moving_down();
        } else {
            self.player1.get_mut_ref().stop_move();
        }

        self.ai.get_mut_ref().update(dt, self.player2.get_mut_ref(), self.ball.get_mut_ref());

        self.player1.get_mut_ref().update(dt, &self.top_wall_aabb, &self.bottom_wall_aabb);
        self.player2.get_mut_ref().update(dt, &self.top_wall_aabb, &self.bottom_wall_aabb);
        self.ball.get_mut_ref().update(dt, &self.top_wall_aabb, &self.bottom_wall_aabb, &self.left_wall_aabb, &self.right_wall_aabb, self.player1.get_mut_ref(), self.player2.get_mut_ref());
    }

    fn load(&mut self, asset_store: &mut AssetStore) {
        self.background_image = Some(asset_store.load_image(settings::BACKGROUND_IMAGE).unwrap());
        self.ball_image = Some(asset_store.load_image(settings::BALL_IMAGE).unwrap());
        self.player_image = Some(asset_store.load_image(settings::PLAYER_IMAGE).unwrap());

        self.player1 = Some(Player::new(self.player_image.unwrap()));
        self.player1.get_mut_ref().set_pos([settings::PLAYER_PADDING, settings::WINDOW_SIZE[1] as f64 / 2.0]);

        self.player2 = Some(Player::new(self.player_image.unwrap()));
        self.player2.get_mut_ref().set_pos([settings::WINDOW_SIZE[0] as f64 - settings::PLAYER_PADDING, settings::WINDOW_SIZE[1] as f64 / 2.0]);

        self.ball = Some(Ball::new(self.ball_image.unwrap()));
        self.ball.get_mut_ref().reset();

        self.ai = Some(AI::new());
    }

    fn key_press(
        &mut self,
        key: keyboard::Key,
        _asset_store: &mut AssetStore
    ) {
        if key == keyboard::Up {
            self.is_up_holding = true;
        }

        if key == keyboard::Down {
            self.is_down_holding = true;
        }

        if key == keyboard::Space {
            self.ball.get_mut_ref().emit();
        }
    }

    fn key_release(
        &mut self,
        key: keyboard::Key,
        _asset_store: &mut AssetStore
    ) {
        if key == keyboard::Up {
            self.is_up_holding = false;
        }

        if key == keyboard::Down {
            self.is_down_holding = false;
        }
    }

}

<|endoftext|>


<commit_before>const LARGE_MASTER_SECRET: i32 = 256;
const LARGE_PRIME: i32 = 1024;
const LARGE_VPRIME: i32 = 2128;

extern crate openssl;
extern crate int_traits;
use self::int_traits::IntTraits;
use self::openssl::bn::{BigNum, BigNumRef, BigNumContext, MSB_MAYBE_ZERO};
pub struct AnoncredsService {
    dummy: String
}

impl AnoncredsService {
    pub fn new() -> AnoncredsService {
        trace!(target: "AnoncredsService", "new");
        AnoncredsService { dummy: "anoncreds_dummy".to_string() }
    }
    fn generate_master_secret() -> BigNum {
        let mut ms = BigNum::new().unwrap();
        ms.rand(LARGE_MASTER_SECRET, MSB_MAYBE_ZERO, false);
        ms
    }
    fn generate_public_key() -> PublicKey {
        //let (p_prime, q_prime) = (AnoncredsService::generate_prime(), AnoncredsService::generate_prime());
        let p_prime = BigNum::from_dec_str("147210949676505370022291901638323344651935110597590993130806944871698104433042968489453214046274983960765508724336420649095413993801340223096499490318385863961435462627523137938481776395548210420546733337321351064531462114552738775282293300556323029911674068388889455348206728016707243243859948314986927502343").unwrap();
        let q_prime = BigNum::from_dec_str("135780746061008989066681842882411968289578365330121870655195830818464118363874946689390282395824911410416094765498522070170715656164604448597511036312331994824492100665472180363433381994083327828179950784236529457340933711810709515143629906739084420423785456874473704622664344722021987863690561674302204741259").unwrap();
        println!("p: {}\nq: {}", p_prime, q_prime);

        let (mut p, mut q, mut ctx, mut n, mut s, mut rms) = (
            BigNum::new().unwrap(),
            BigNum::new().unwrap(),
            BigNumContext::new().unwrap(),
            BigNum::new().unwrap(),
            BigNum::new().unwrap(),
            BigNum::new().unwrap()
        );

        p.checked_mul(&p_prime, &BigNum::from_u32(2).unwrap(), &mut ctx);
        p.add_word(1);
        q.checked_mul(&q_prime, &BigNum::from_u32(2).unwrap(), &mut ctx);
        q.add_word(1);
        println!("p: {}\nq: {}", p, q);

        let mut n = BigNum::new().unwrap();
        n.checked_mul(&p, &q, &mut ctx);
        println!("n: {}", n);

        s = AnoncredsService::random_qr(&n);
        println!("s: {}", s);

        rms.mod_exp(&s, &AnoncredsService::gen_x(&p_prime, &q_prime), &n, &mut ctx);
        println!("rms: {}", rms);

        PublicKey {n: n, s: s, rms: rms}
    }
    fn gen_x(p: &BigNum, q: &BigNum) -> BigNum {
        let mut ctx = BigNumContext::new().unwrap();
        let mut value = BigNum::new().unwrap();
        let mut result = BigNum::new().unwrap();

        value.checked_mul(&p, &q, &mut ctx);
        value.sub_word(3);

        result = AnoncredsService::random_in_range(&value);
        result.add_word(2);
        result
    }
    fn gen_u(public_key: PublicKey, ms: BigNum) -> BigNum {
        let mut ctx = BigNumContext::new().unwrap();
        let mut vprime = BigNum::new().unwrap();
        vprime.rand(LARGE_VPRIME, MSB_MAYBE_ZERO, false);

        let mut result_mul_one = BigNum::new().unwrap();
        result_mul_one.mod_exp(&public_key.s, &vprime, &public_key.n, &mut ctx);

        let mut result_mul_two = BigNum::new().unwrap();
        result_mul_two.mod_exp(&public_key.rms, &ms, &public_key.n, &mut ctx);

        let mut u = &result_mul_one * &result_mul_two;
        u = &u % &public_key.n;
        u
    }
    fn random_in_range(n: &BigNum) -> BigNum {
        let mut random_number = BigNum::new().unwrap();
        random_number.rand(n.num_bits(), MSB_MAYBE_ZERO, false).unwrap();

        while random_number > *n {
            random_number.rand(n.num_bits(), MSB_MAYBE_ZERO, false).unwrap();
        }

        random_number
    }
    fn random_qr(n: &BigNum) -> BigNum {
        let (mut ctx, mut random_qr) = (BigNumContext::new().unwrap(), BigNum::new().unwrap());
        random_qr.sqr(&AnoncredsService::random_in_range(&n), &mut ctx);
        random_qr
    }
    fn count_rounds_for_prime_check(prime: &BigNum) -> i32 {
        let prime_len = prime.to_dec_str().unwrap().len();
        prime_len.log2() as i32
    }
    fn generate_prime() -> BigNum {
        let mut ctx = BigNumContext::new().unwrap();
        let mut prime = BigNum::new().unwrap();
        let (mut is_prime, mut iteration) = (false, 0);

        while !is_prime {
            iteration += 1;
            prime.generate_prime(LARGE_PRIME, false, None, None);
            let checks = AnoncredsService::count_rounds_for_prime_check(&prime);
            let mut prime_for_check = BigNum::new().unwrap();
            prime_for_check.checked_mul(&prime, &BigNum::from_u32(2).unwrap(), &mut ctx).unwrap();
            prime_for_check.add_word(1);
            is_prime = prime_for_check.is_prime(checks, &mut ctx).unwrap();
            println!("Iteration: {}\nFound prime: {}\nis_prime: {}\n", iteration, prime, is_prime);
        }

        println!("Generated prime: {}", prime);
        prime
    }
    fn create_claim_request() -> ClaimRequest {
        let public_key = AnoncredsService::generate_public_key();
        let master_secret = AnoncredsService::generate_master_secret();
        let u = AnoncredsService::gen_u(public_key, master_secret);
        let claim_request = ClaimRequest {u: u};
        claim_request
    }
}

#[derive(Debug)]
struct PublicKey {
    n: BigNum,
    s: BigNum,
    rms: BigNum
}

#[derive(Debug)]
struct ClaimRequest {
    u: BigNum
}

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

    #[test]
    fn service_creation_is_possible() {
        let anoncreds_service = AnoncredsService::new();
        assert_eq!("anoncreds_dummy", anoncreds_service.dummy, "Dummy field is filled by constructor");
    }
    #[test]
    fn master_secret_generator_works() {
        let ms: BigNum = AnoncredsService::generate_master_secret();
        assert_eq!(LARGE_MASTER_SECRET/8, ms.num_bytes());
    }
//    #[test]
//    fn generate_prime_works() {
//        let prime = AnoncredsService::generate_prime();
//        let mut ctx = BigNumContext::new().unwrap();
//        let checks = AnoncredsService::count_rounds_for_prime_check(&prime);
//        let is_prime = prime.is_prime(checks, &mut ctx).unwrap();
//        assert_eq!(is_prime, true);
//    }
    #[test]
    fn create_claim_request_works() {
        let claim_request = AnoncredsService::create_claim_request();
        println!("{:?}", claim_request)
    }
}<commit_msg>added generate_prime_in_range function<commit_after>const LARGE_MASTER_SECRET: i32 = 256;
const LARGE_PRIME: i32 = 1024;
const LARGE_VPRIME: i32 = 2128;
const LARGE_E_START: i32 = 596;
const LARGE_E_END_RANGE: i32 = 119;

extern crate openssl;
extern crate int_traits;
use self::int_traits::IntTraits;
use self::openssl::bn::{BigNum, BigNumRef, BigNumContext, MSB_MAYBE_ZERO};
pub struct AnoncredsService {
    dummy: String
}

impl AnoncredsService {
    pub fn new() -> AnoncredsService {
        trace!(target: "AnoncredsService", "new");
        AnoncredsService { dummy: "anoncreds_dummy".to_string() }
    }
    fn generate_master_secret() -> BigNum {
        let mut ms = BigNum::new().unwrap();
        ms.rand(LARGE_MASTER_SECRET, MSB_MAYBE_ZERO, false);
        ms
    }
    fn generate_public_key() -> PublicKey {
        //let (p_prime, q_prime) = (AnoncredsService::generate_prime(), AnoncredsService::generate_prime());
        let p_prime = BigNum::from_dec_str("147210949676505370022291901638323344651935110597590993130806944871698104433042968489453214046274983960765508724336420649095413993801340223096499490318385863961435462627523137938481776395548210420546733337321351064531462114552738775282293300556323029911674068388889455348206728016707243243859948314986927502343").unwrap();
        let q_prime = BigNum::from_dec_str("135780746061008989066681842882411968289578365330121870655195830818464118363874946689390282395824911410416094765498522070170715656164604448597511036312331994824492100665472180363433381994083327828179950784236529457340933711810709515143629906739084420423785456874473704622664344722021987863690561674302204741259").unwrap();
        //println!("p: {}\nq: {}", p_prime, q_prime);

        let (mut p, mut q, mut ctx, mut n, mut s, mut rms) = (
            BigNum::new().unwrap(),
            BigNum::new().unwrap(),
            BigNumContext::new().unwrap(),
            BigNum::new().unwrap(),
            BigNum::new().unwrap(),
            BigNum::new().unwrap()
        );

        p.checked_mul(&p_prime, &BigNum::from_u32(2).unwrap(), &mut ctx);
        p.add_word(1);
        q.checked_mul(&q_prime, &BigNum::from_u32(2).unwrap(), &mut ctx);
        q.add_word(1);
        //println!("p: {}\nq: {}", p, q);

        let mut n = BigNum::new().unwrap();
        n.checked_mul(&p, &q, &mut ctx);
        //println!("n: {}", n);

        s = AnoncredsService::random_qr(&n);
        //println!("s: {}", s);

        rms.mod_exp(&s, &AnoncredsService::gen_x(&p_prime, &q_prime), &n, &mut ctx);
        //println!("rms: {}", rms);

        PublicKey {n: n, s: s, rms: rms}
    }
    fn gen_x(p: &BigNum, q: &BigNum) -> BigNum {
        let mut ctx = BigNumContext::new().unwrap();
        let mut value = BigNum::new().unwrap();
        let mut result = BigNum::new().unwrap();

        value.checked_mul(&p, &q, &mut ctx);
        value.sub_word(3);

        result = AnoncredsService::random_in_range(&BigNum::from_u32(0).unwrap(), &value);
        result.add_word(2);
        result
    }
    fn gen_u(public_key: PublicKey, ms: BigNum) -> BigNum {
        let mut ctx = BigNumContext::new().unwrap();
        let mut vprime = BigNum::new().unwrap();
        vprime.rand(LARGE_VPRIME, MSB_MAYBE_ZERO, false);

        let mut result_mul_one = BigNum::new().unwrap();
        result_mul_one.mod_exp(&public_key.s, &vprime, &public_key.n, &mut ctx);

        let mut result_mul_two = BigNum::new().unwrap();
        result_mul_two.mod_exp(&public_key.rms, &ms, &public_key.n, &mut ctx);

        let mut u = &result_mul_one * &result_mul_two;
        u = &u % &public_key.n;
        u
    }
    fn random_in_range(start: &BigNum, end: &BigNum) -> BigNum {
        let mut random_number = BigNum::new().unwrap();
        let sub = end - start;

        random_number.rand(sub.num_bits(), MSB_MAYBE_ZERO, false).unwrap();
        while (&random_number + start) > *end {
            random_number.rand(sub.num_bits(), MSB_MAYBE_ZERO, false).unwrap();
        }

        &random_number + start
    }
    fn random_qr(n: &BigNum) -> BigNum {
        let (mut ctx, mut random_qr) = (BigNumContext::new().unwrap(), BigNum::new().unwrap());
        random_qr.sqr(&AnoncredsService::random_in_range(&BigNum::from_u32(0).unwrap(), &n), &mut ctx);
        random_qr
    }
    fn count_rounds_for_prime_check(prime: &BigNum) -> i32 {
        let prime_len = prime.to_dec_str().unwrap().len();
        prime_len.log2() as i32
    }
    fn generate_prime() -> BigNum {
        let mut ctx = BigNumContext::new().unwrap();
        let mut prime = BigNum::new().unwrap();
        let (mut is_prime, mut iteration) = (false, 0);

        while !is_prime {
            iteration += 1;
            prime.generate_prime(LARGE_PRIME, false, None, None);
            let checks = AnoncredsService::count_rounds_for_prime_check(&prime);
            let mut prime_for_check = BigNum::new().unwrap();
            prime_for_check.checked_mul(&prime, &BigNum::from_u32(2).unwrap(), &mut ctx).unwrap();
            prime_for_check.add_word(1);
            is_prime = prime_for_check.is_prime(checks, &mut ctx).unwrap();
            println!("Iteration: {}\nFound prime: {}\nis_prime: {}\n", iteration, prime, is_prime);
        }

        //println!("Generated prime: {}", prime);
        prime
    }
    fn generate_prime_in_range(start: &BigNum, end: &BigNum) -> Result<BigNum, &'static str>{
        let (mut iteration, max_iterations, mut prime_is_found, mut prime, mut ctx) = (
            0,
            100000,
            false,
            BigNum::new().unwrap(),
            BigNumContext::new().unwrap()
        );

        while (iteration < max_iterations) && !prime_is_found {
            prime = AnoncredsService::random_in_range(&start, &end);
            let checks = AnoncredsService::count_rounds_for_prime_check(&prime);

            if prime.is_prime(checks, &mut ctx).unwrap() {
                prime_is_found = true;
                println!("Found prime in {} iteration", iteration);
            }
            iteration += 1;
        }

        if !prime_is_found {
            println!("Cannot find prime in {} iterations", max_iterations);
            Err("Prime is not found")
        } else {
            Ok(prime)
        }
    }
    fn create_claim_request() -> ClaimRequest {
        let public_key = AnoncredsService::generate_public_key();
        let master_secret = AnoncredsService::generate_master_secret();
        let u = AnoncredsService::gen_u(public_key, master_secret);
        let claim_request = ClaimRequest {u: u};
        claim_request
    }
    fn issue_primary_claim(attributes: &Vec<AttributeType>, u: &BigNum) {
        let mut ctx = BigNumContext::new().unwrap();
        println!("{}\n{:?}", u, attributes);
        //calc vprimeprime
        let (mut e_start, mut e_end) = (BigNum::new().unwrap(), BigNum::new().unwrap());
        e_start.exp(&BigNum::from_u32(2).unwrap(), &BigNum::from_u32(LARGE_E_START as u32).unwrap(), &mut ctx);
        e_end.exp(&BigNum::from_u32(2).unwrap(), &BigNum::from_u32(LARGE_E_END_RANGE as u32).unwrap(), &mut ctx);
        e_end = &e_start + &e_end;
        let e = AnoncredsService::generate_prime_in_range(&e_start, &e_end).unwrap();
    }
}

#[derive(Debug)]
struct PublicKey {
    n: BigNum,
    s: BigNum,
    rms: BigNum
}

#[derive(Debug)]
struct ClaimRequest {
    u: BigNum
}

#[derive(Debug)]
struct AttributeType {
    name: String,
    encode: bool
}

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

    #[test]
    fn service_creation_is_possible() {
        let anoncreds_service = AnoncredsService::new();
        assert_eq!("anoncreds_dummy", anoncreds_service.dummy, "Dummy field is filled by constructor");
    }
    #[test]
    fn master_secret_generator_works() {
        let ms: BigNum = AnoncredsService::generate_master_secret();
        assert_eq!(LARGE_MASTER_SECRET/8, ms.num_bytes());
    }
    #[test]
    fn random_in_range_works() {
        let (mut start, mut end) = (BigNum::new().unwrap(), BigNum::new().unwrap());

        start.rand(LARGE_PRIME, MSB_MAYBE_ZERO, false).unwrap();
        end.rand(LARGE_PRIME, MSB_MAYBE_ZERO, false).unwrap();

        while end < start {
            end.rand(LARGE_PRIME, MSB_MAYBE_ZERO, false).unwrap();
        }

        let random_in_range = AnoncredsService::random_in_range(&start, &end);
        assert!((random_in_range > start) && (random_in_range < end));
    }
//    #[test]
//    fn generate_prime_works() {
//        let prime = AnoncredsService::generate_prime();
//        let mut ctx = BigNumContext::new().unwrap();
//        let checks = AnoncredsService::count_rounds_for_prime_check(&prime);
//        let is_prime = prime.is_prime(checks, &mut ctx).unwrap();
//        assert_eq!(is_prime, true);
//    }
    #[test]
    fn anoncreds_works() {
        let mut attributes = vec![
            AttributeType {name: "name".to_string(), encode: true},
            AttributeType {name: "age".to_string(), encode: false},
            AttributeType {name: "height".to_string(), encode: false},
            AttributeType {name: "sex".to_string(), encode: true}
        ];
        let claim_request = AnoncredsService::create_claim_request();
        let claim = AnoncredsService::issue_primary_claim(&attributes, &claim_request.u);

    }
}<|endoftext|>


<commit_before>/*
 * chamkho - a word breaker written in Rust
 * Copyright (C) 2015  Vee Satayamas
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

use std::collections::HashSet;

#[derive(Debug, PartialEq)]
enum State {
    Init,
    Space,
    SpaceFinal,
    Text,
    TextFinal
}

#[derive(Debug)]
pub struct PuncAcc {
    i: usize,
    pub start: usize,
    state: State,
    split_char: HashSet<char>
}

impl PuncAcc {
    pub fn new() -> PuncAcc {
        let mut split_char = HashSet::new();
        split_char.insert(' ');
        split_char.insert('\n');
        split_char.insert('\t');
        split_char.insert('\r');
        PuncAcc{start:0, i:0, state:State::Init, split_char: split_char}
    }

    fn is_split_char(&self, ch: char) -> bool {
        self.split_char.contains(&ch)
    }

    fn to_text_state(&mut self, nch: Option<char>) -> State {
        match nch {
            Some(_nch) => if self.is_split_char(_nch) {
                State::TextFinal
            } else {
                State::Text
            },
            None => State::TextFinal
        }
    }

    fn to_space_state(&mut self, nch: Option<char>) -> State {
        match nch {
            Some(_nch) => if self.is_split_char(_nch) {
                State::Space
            } else {
                State::SpaceFinal
            },
            None => State::SpaceFinal
        }
    }

    fn to_another_state(&mut self, ch: char, nch: Option<char>) -> State {
        if self.is_split_char(ch) {
            self.to_space_state(nch)
        } else {
            self.to_text_state(nch)
        }
    }

    pub fn transit(&mut self, ch: char, nch: Option<char>) {
        match self.state {
            State::Init => {
                self.start = self.i;
                self.state = self.to_another_state(ch, nch)
            },
            State::Text => { self.state = self.to_another_state(ch, nch); },
            State::TextFinal => {
                self.start = self.i;
                self.state = self.to_space_state(nch);
            }
            State::SpaceFinal => {
                self.start = self.i;
                self.state = self.to_text_state(nch)
            }
            State::Space => {
                self.state = self.to_another_state(ch, nch);
            }
        };
        self.i += 1;
    }

    pub fn is_space_final(&self) -> bool {
        self.state == State::SpaceFinal
    }
}
<commit_msg>handle more puncuations<commit_after>/*
 * chamkho - a word breaker written in Rust
 * Copyright (C) 2015  Vee Satayamas
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

use std::collections::HashSet;

#[derive(Debug, PartialEq)]
enum State {
    Init,
    Space,
    SpaceFinal,
    Text,
    TextFinal
}

#[derive(Debug)]
pub struct PuncAcc {
    i: usize,
    pub start: usize,
    state: State,
    split_char: HashSet<char>
}

impl PuncAcc {
    pub fn new() -> PuncAcc {
        let mut split_char = HashSet::new();
        split_char.insert(' ');
        split_char.insert('\n');
        split_char.insert('\t');
        split_char.insert('\r');
        split_char.insert('"');
        split_char.insert('(');
        split_char.insert(')');
        split_char.insert('“');
        split_char.insert('”');
        PuncAcc{start:0, i:0, state:State::Init, split_char: split_char}
    }

    fn is_split_char(&self, ch: char) -> bool {
        self.split_char.contains(&ch)
    }

    fn to_text_state(&mut self, nch: Option<char>) -> State {
        match nch {
            Some(_nch) => if self.is_split_char(_nch) {
                State::TextFinal
            } else {
                State::Text
            },
            None => State::TextFinal
        }
    }

    fn to_space_state(&mut self, nch: Option<char>) -> State {
        match nch {
            Some(_nch) => if self.is_split_char(_nch) {
                State::Space
            } else {
                State::SpaceFinal
            },
            None => State::SpaceFinal
        }
    }

    fn to_another_state(&mut self, ch: char, nch: Option<char>) -> State {
        if self.is_split_char(ch) {
            self.to_space_state(nch)
        } else {
            self.to_text_state(nch)
        }
    }

    pub fn transit(&mut self, ch: char, nch: Option<char>) {
        match self.state {
            State::Init => {
                self.start = self.i;
                self.state = self.to_another_state(ch, nch)
            },
            State::Text => { self.state = self.to_another_state(ch, nch); },
            State::TextFinal => {
                self.start = self.i;
                self.state = self.to_space_state(nch);
            }
            State::SpaceFinal => {
                self.start = self.i;
                self.state = self.to_text_state(nch)
            }
            State::Space => {
                self.state = self.to_another_state(ch, nch);
            }
        };
        self.i += 1;
    }

    pub fn is_space_final(&self) -> bool {
        self.state == State::SpaceFinal
    }
}
<|endoftext|>


<commit_before>/// The query resolver that operates on the AST and the TOML object

use std::ops::Deref;
use std::ops::IndexMut;

use toml::Value;
use tokenizer::Token;
use error::*;

fn resolve<'doc>(toml: &'doc mut Value, tokens: &Token) -> Result<&'doc mut Value> {
    match toml {
        &mut Value::Table(ref mut t) => {
            match tokens {
                &Token::Identifier { ident: ref ident, .. } => {
                    match t.get_mut(ident) {
                        None    => {
                            let ek = ErrorKind::IdentifierNotFoundInDocument(ident.clone());
                            Err(Error::from(ek))
                        },
                        Some(sub_document) => {
                            if tokens.has_next() {
                                resolve(sub_document, tokens.next().unwrap().deref())
                            } else {
                                Ok(sub_document)
                            }
                        },
                    }
                },

                &Token::Index { .. } => unimplemented!(),
            }
        },

        &mut Value::Array(ref mut ary) => {
            match tokens {
                &Token::Index { idx: i, .. } => {
                    if tokens.has_next() {
                        resolve(ary.get_mut(i).unwrap(), tokens.next().unwrap().deref())
                    } else {
                        Ok(ary.index_mut(i))
                    }
                },
                &Token::Identifier { .. } => unimplemented!(),
            }
        },

        _ => {
            match tokens {
                &Token::Identifier { ident: ref ident, .. } => {
                    Err(Error::from(ErrorKind::IdentifierNotFoundInDocument(ident.clone())))
                },

                &Token::Index { .. } => unimplemented!(),
            }
        }
    }
}

#[cfg(test)]
mod test {
    use toml::from_str as toml_from_str;
    use toml::Value;
    use tokenizer::*;
    use error::*;
    use super::resolve;

    macro_rules! do_resolve {
        ( $toml:ident => $query:expr ) => {
            resolve(&mut $toml, &tokenize_with_seperator(&String::from($query), '.').unwrap())
        }
    }

    #[test]
    fn test_resolve_empty_toml_simple_query() {
        let mut toml = toml_from_str("").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_err());
        let result = result.unwrap_err();

        let errkind = result.kind();
        assert!(is_match!(errkind, &ErrorKind::IdentifierNotFoundInDocument { .. }));
    }

    #[test]
    fn test_resolve_present_bool() {
        let mut toml = toml_from_str("example = true").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Boolean(true)));
    }

    #[test]
    fn test_resolve_present_integer() {
        let mut toml = toml_from_str("example = 1").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(1)));
    }

    #[test]
    fn test_resolve_present_float() {
        let mut toml = toml_from_str("example = 1.0").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Float(1.0)));
    }

    #[test]
    fn test_resolve_present_string() {
        let mut toml = toml_from_str("example = 'string'").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::String(_)));
        match result {
            &mut Value::String(ref s) => assert_eq!("string", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_present_array_bools() {
        let mut toml = toml_from_str("example = [ true, false ]").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Boolean(true));
                assert_eq!(ary[1], Value::Boolean(false));
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_present_array_integers() {
        let mut toml = toml_from_str("example = [ 1, 1337 ]").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Integer(1));
                assert_eq!(ary[1], Value::Integer(1337));
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_present_array_floats() {
        let mut toml = toml_from_str("example = [ 1.0, 133.25 ]").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Float(1.0));
                assert_eq!(ary[1], Value::Float(133.25));
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_array_index_query_1() {
        let mut toml = toml_from_str("example = [ 1 ]").unwrap();
        let result = do_resolve!(toml => "example.[0]");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(1)));
    }

    #[test]
    fn test_resolve_array_index_query_2() {
        let mut toml = toml_from_str("example = [ 1, 2, 3, 4, 5 ]").unwrap();
        let result = do_resolve!(toml => "example.[4]");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(5)));
    }

    #[test]
    fn test_resolve_table_element_query() {
        let mut toml = toml_from_str(r#"
        [table]
        value = 42
        "#).unwrap();
        let result = do_resolve!(toml => "table.value");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(42)));
    }

    #[test]
    fn test_resolve_table_with_many_elements_element_query() {
        let mut toml = toml_from_str(r#"
        [table]
        value1 = 42
        value2 = 43
        value3 = 44
        value4 = 45
        value5 = 46
        "#).unwrap();
        let result = do_resolve!(toml => "table.value1");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(42)));
    }

    #[test]
    fn test_resolve_table_array_query() {
        let mut toml = toml_from_str(r#"
        [table]
        value1 = [ 42.0, 50.0 ]
        "#).unwrap();
        let result = do_resolve!(toml => "table.value1");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Float(42.0));
                assert_eq!(ary[1], Value::Float(50.0));
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_table_array_element_query() {
        let mut toml = toml_from_str(r#"
        [table]
        value1 = [ 42 ]
        "#).unwrap();
        let result = do_resolve!(toml => "table.value1.[0]");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(42)));
    }

    #[test]
    fn test_resolve_multi_table_query() {
        let mut toml = toml_from_str(r#"
        [table0]
        value = [ 1 ]
        [table1]
        value = [ "Foo" ]
        [table2]
        value = [ 42.0 ]
        [table3]
        value = [ true ]
        "#).unwrap();
        let result = do_resolve!(toml => "table1.value.[0]");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::String(_)));
        match result {
            &mut Value::String(ref s) => assert_eq!("Foo", s),
            _ => panic!("What just happened?"),
        }
    }

    static FRUIT_TABLE : &'static str = r#"
    [[fruit.blah]]
      name = "apple"

      [fruit.blah.physical]
        color = "red"
        shape = "round"

    [[fruit.blah]]
      name = "banana"

      [fruit.blah.physical]
        color = "yellow"
        shape = "bent"
    "#;

    #[test]
    fn test_resolve_array_table_query_1() {
        let mut toml = toml_from_str(FRUIT_TABLE).unwrap();
        let result = do_resolve!(toml => "fruit.blah.[0].name");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::String(_)));
        match result {
            &mut Value::String(ref s) => assert_eq!("apple", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_array_table_query_2() {
        let mut toml = toml_from_str(FRUIT_TABLE).unwrap();
        let result = do_resolve!(toml => "fruit.blah.[0].physical");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Table(_)));
        match result {
            &mut Value::Table(ref tab) => {
                match tab.get("color") {
                    Some(&Value::String(ref s)) => assert_eq!("red", s),
                    _ => assert!(false),
                }
                match tab.get("shape") {
                    Some(&Value::String(ref s)) => assert_eq!("round", s),
                    _ => assert!(false),
                }
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_query_on_result() {
        let mut toml = toml_from_str(FRUIT_TABLE).unwrap();
        let result = do_resolve!(toml => "fruit.blah.[1].physical");

        assert!(result.is_ok());
        let mut result = result.unwrap();

        let tokens = tokenize_with_seperator(&String::from("color"), '.').unwrap();
        let result = resolve(result, &tokens);

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::String(_)));
        match result {
            &mut Value::String(ref s) => assert_eq!("yellow", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_query_empty_table() {
        let mut toml = toml_from_str(r#"
        [example]
        "#).unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Table(_)));
        match result {
            &mut Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_query_member_of_empty_table() {
        let mut toml = toml_from_str(r#"
        [example]
        "#).unwrap();
        let result = do_resolve!(toml => "example.foo");

        assert!(result.is_err());
        let result = result.unwrap_err();

        let errkind = result.kind();
        assert!(is_match!(errkind, &ErrorKind::IdentifierNotFoundInDocument { .. }));
    }

    #[test]
    fn test_resolve_query_index_in_table() {
        let mut toml = toml_from_str(r#"
        [example]
        "#).unwrap();
        let result = do_resolve!(toml => "example.[0]");

        assert!(result.is_err());
        let result = result.unwrap_err();

        let errkind = result.kind();
        assert!(is_match!(errkind, &ErrorKind::NoIndexInTable { .. }));
    }

    #[test]
    fn test_resolve_query_identifier_in_array() {
        let mut toml = toml_from_str(r#"
        [example]
        foo = [ 1, 2, 3 ]
        "#).unwrap();
        let result = do_resolve!(toml => "example.foo.bar");

        assert!(result.is_err());
        let result = result.unwrap_err();

        let errkind = result.kind();
        assert!(is_match!(errkind, &ErrorKind::NoIdentifierInArray { .. }));
    }

}
<commit_msg>Impl resolve to fix test_resolve_query_index_in_table<commit_after>/// The query resolver that operates on the AST and the TOML object

use std::ops::Deref;
use std::ops::IndexMut;

use toml::Value;
use tokenizer::Token;
use error::*;

fn resolve<'doc>(toml: &'doc mut Value, tokens: &Token) -> Result<&'doc mut Value> {
    match toml {
        &mut Value::Table(ref mut t) => {
            match tokens {
                &Token::Identifier { ident: ref ident, .. } => {
                    match t.get_mut(ident) {
                        None    => {
                            let ek = ErrorKind::IdentifierNotFoundInDocument(ident.clone());
                            Err(Error::from(ek))
                        },
                        Some(sub_document) => {
                            if tokens.has_next() {
                                resolve(sub_document, tokens.next().unwrap().deref())
                            } else {
                                Ok(sub_document)
                            }
                        },
                    }
                },

                &Token::Index { idx: i, .. } => {
                    let kind = ErrorKind::NoIndexInTable(i);
                    Err(Error::from(kind))
                },
            }
        },

        &mut Value::Array(ref mut ary) => {
            match tokens {
                &Token::Index { idx: i, .. } => {
                    if tokens.has_next() {
                        resolve(ary.get_mut(i).unwrap(), tokens.next().unwrap().deref())
                    } else {
                        Ok(ary.index_mut(i))
                    }
                },
                &Token::Identifier { .. } => unimplemented!(),
            }
        },

        _ => {
            match tokens {
                &Token::Identifier { ident: ref ident, .. } => {
                    Err(Error::from(ErrorKind::IdentifierNotFoundInDocument(ident.clone())))
                },

                &Token::Index { .. } => unimplemented!(),
            }
        }
    }
}

#[cfg(test)]
mod test {
    use toml::from_str as toml_from_str;
    use toml::Value;
    use tokenizer::*;
    use error::*;
    use super::resolve;

    macro_rules! do_resolve {
        ( $toml:ident => $query:expr ) => {
            resolve(&mut $toml, &tokenize_with_seperator(&String::from($query), '.').unwrap())
        }
    }

    #[test]
    fn test_resolve_empty_toml_simple_query() {
        let mut toml = toml_from_str("").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_err());
        let result = result.unwrap_err();

        let errkind = result.kind();
        assert!(is_match!(errkind, &ErrorKind::IdentifierNotFoundInDocument { .. }));
    }

    #[test]
    fn test_resolve_present_bool() {
        let mut toml = toml_from_str("example = true").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Boolean(true)));
    }

    #[test]
    fn test_resolve_present_integer() {
        let mut toml = toml_from_str("example = 1").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(1)));
    }

    #[test]
    fn test_resolve_present_float() {
        let mut toml = toml_from_str("example = 1.0").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Float(1.0)));
    }

    #[test]
    fn test_resolve_present_string() {
        let mut toml = toml_from_str("example = 'string'").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::String(_)));
        match result {
            &mut Value::String(ref s) => assert_eq!("string", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_present_array_bools() {
        let mut toml = toml_from_str("example = [ true, false ]").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Boolean(true));
                assert_eq!(ary[1], Value::Boolean(false));
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_present_array_integers() {
        let mut toml = toml_from_str("example = [ 1, 1337 ]").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Integer(1));
                assert_eq!(ary[1], Value::Integer(1337));
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_present_array_floats() {
        let mut toml = toml_from_str("example = [ 1.0, 133.25 ]").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Float(1.0));
                assert_eq!(ary[1], Value::Float(133.25));
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_array_index_query_1() {
        let mut toml = toml_from_str("example = [ 1 ]").unwrap();
        let result = do_resolve!(toml => "example.[0]");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(1)));
    }

    #[test]
    fn test_resolve_array_index_query_2() {
        let mut toml = toml_from_str("example = [ 1, 2, 3, 4, 5 ]").unwrap();
        let result = do_resolve!(toml => "example.[4]");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(5)));
    }

    #[test]
    fn test_resolve_table_element_query() {
        let mut toml = toml_from_str(r#"
        [table]
        value = 42
        "#).unwrap();
        let result = do_resolve!(toml => "table.value");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(42)));
    }

    #[test]
    fn test_resolve_table_with_many_elements_element_query() {
        let mut toml = toml_from_str(r#"
        [table]
        value1 = 42
        value2 = 43
        value3 = 44
        value4 = 45
        value5 = 46
        "#).unwrap();
        let result = do_resolve!(toml => "table.value1");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(42)));
    }

    #[test]
    fn test_resolve_table_array_query() {
        let mut toml = toml_from_str(r#"
        [table]
        value1 = [ 42.0, 50.0 ]
        "#).unwrap();
        let result = do_resolve!(toml => "table.value1");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Float(42.0));
                assert_eq!(ary[1], Value::Float(50.0));
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_table_array_element_query() {
        let mut toml = toml_from_str(r#"
        [table]
        value1 = [ 42 ]
        "#).unwrap();
        let result = do_resolve!(toml => "table.value1.[0]");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(42)));
    }

    #[test]
    fn test_resolve_multi_table_query() {
        let mut toml = toml_from_str(r#"
        [table0]
        value = [ 1 ]
        [table1]
        value = [ "Foo" ]
        [table2]
        value = [ 42.0 ]
        [table3]
        value = [ true ]
        "#).unwrap();
        let result = do_resolve!(toml => "table1.value.[0]");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::String(_)));
        match result {
            &mut Value::String(ref s) => assert_eq!("Foo", s),
            _ => panic!("What just happened?"),
        }
    }

    static FRUIT_TABLE : &'static str = r#"
    [[fruit.blah]]
      name = "apple"

      [fruit.blah.physical]
        color = "red"
        shape = "round"

    [[fruit.blah]]
      name = "banana"

      [fruit.blah.physical]
        color = "yellow"
        shape = "bent"
    "#;

    #[test]
    fn test_resolve_array_table_query_1() {
        let mut toml = toml_from_str(FRUIT_TABLE).unwrap();
        let result = do_resolve!(toml => "fruit.blah.[0].name");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::String(_)));
        match result {
            &mut Value::String(ref s) => assert_eq!("apple", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_array_table_query_2() {
        let mut toml = toml_from_str(FRUIT_TABLE).unwrap();
        let result = do_resolve!(toml => "fruit.blah.[0].physical");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Table(_)));
        match result {
            &mut Value::Table(ref tab) => {
                match tab.get("color") {
                    Some(&Value::String(ref s)) => assert_eq!("red", s),
                    _ => assert!(false),
                }
                match tab.get("shape") {
                    Some(&Value::String(ref s)) => assert_eq!("round", s),
                    _ => assert!(false),
                }
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_query_on_result() {
        let mut toml = toml_from_str(FRUIT_TABLE).unwrap();
        let result = do_resolve!(toml => "fruit.blah.[1].physical");

        assert!(result.is_ok());
        let mut result = result.unwrap();

        let tokens = tokenize_with_seperator(&String::from("color"), '.').unwrap();
        let result = resolve(result, &tokens);

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::String(_)));
        match result {
            &mut Value::String(ref s) => assert_eq!("yellow", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_query_empty_table() {
        let mut toml = toml_from_str(r#"
        [example]
        "#).unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Table(_)));
        match result {
            &mut Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_query_member_of_empty_table() {
        let mut toml = toml_from_str(r#"
        [example]
        "#).unwrap();
        let result = do_resolve!(toml => "example.foo");

        assert!(result.is_err());
        let result = result.unwrap_err();

        let errkind = result.kind();
        assert!(is_match!(errkind, &ErrorKind::IdentifierNotFoundInDocument { .. }));
    }

    #[test]
    fn test_resolve_query_index_in_table() {
        let mut toml = toml_from_str(r#"
        [example]
        "#).unwrap();
        let result = do_resolve!(toml => "example.[0]");

        assert!(result.is_err());
        let result = result.unwrap_err();

        let errkind = result.kind();
        assert!(is_match!(errkind, &ErrorKind::NoIndexInTable { .. }));
    }

    #[test]
    fn test_resolve_query_identifier_in_array() {
        let mut toml = toml_from_str(r#"
        [example]
        foo = [ 1, 2, 3 ]
        "#).unwrap();
        let result = do_resolve!(toml => "example.foo.bar");

        assert!(result.is_err());
        let result = result.unwrap_err();

        let errkind = result.kind();
        assert!(is_match!(errkind, &ErrorKind::NoIdentifierInArray { .. }));
    }

}
<|endoftext|>


<commit_before>use std::sync::RWLock;
use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};
use std::io::{IoResult, File};
use std::io::util::copy;
use std::path::BytesContainer;
use serialize::Encodable;
use http;
use http::server::ResponseWriter;
use time;
use mimes;
use mustache;
use mustache::{Template, Encoder, Error};

pub type TemplateCache = RWLock<HashMap<&'static str, Template>>;

///A container for the response
pub struct Response<'a, 'b: 'a> {
    ///the original `http::server::ResponseWriter`
    pub origin: &'a mut ResponseWriter<'b>,
    templates: &'a TemplateCache
}

impl<'a, 'b> Response<'a, 'b> {
    pub fn from_internal<'c, 'd>(response: &'c mut ResponseWriter<'d>,
                                 templates: &'c TemplateCache)
                                -> Response<'c, 'd> {
        Response {
            origin: response,
            templates: templates
        }
    }

    /// Sets the content type by it's short form.
    /// Returns the response for chaining.
    ///
    /// # Example
    /// ```{rust}
    /// # use nickel::{Request, Response};
    /// use nickel::mimes::MediaType;
    /// fn handler(request: &Request, response: &mut Response) {
    ///     response.content_type(MediaType::Html);
    /// }
    /// ```
    pub fn content_type(&mut self, mt: mimes::MediaType) -> &mut Response<'a,'b> {
        self.origin.headers.content_type = Some(mimes::get_media_type(mt));
        self
    }

    /// Sets the status code and returns the response for chaining
    ///
    /// # Example
    /// ```{rust}
    /// # extern crate http;
    /// # extern crate nickel;
    /// # use nickel::{Request, Response};
    /// # fn main() {
    /// fn handler(request: &Request, response: &mut Response) {
    ///     response.status_code(http::status::NotFound);
    /// }
    /// # }
    /// ```
    pub fn status_code(&mut self, status: http::status::Status) -> &mut Response<'a,'b> {
        self.origin.status = status;
        self
    }

    /// Writes a response
    ///
    /// # Example
    /// ```{rust}
    /// # use nickel::{Request, Response};
    /// fn handler(request: &Request, response: &mut Response) {
    ///     response.send("hello world");
    /// }
    /// ```
    pub fn send<T: BytesContainer> (&mut self, text: T) {
        // TODO: This needs to be more sophisticated to return the correct headers
        // not just "some headers" :)
        Response::set_headers(self.origin);
        let _ = self.origin.write(text.container_as_bytes());
    }

    fn set_headers(response_writer: &mut http::server::ResponseWriter) {
        let ref mut headers = response_writer.headers;
        headers.date = Some(time::now_utc());

        // we don't need to set this https://github.com/Ogeon/rustful/issues/3#issuecomment-44787613
        headers.content_length = None;

        headers.server = Some(String::from_str("Nickel"));
    }

    /// Writes a file to the output.
    ///
    /// # Example
    /// ```{rust}
    /// # use nickel::{Request, Response};
    /// fn handler(request: &Request, response: &mut Response) {
    ///     let favicon = Path::new("/assets/favicon.ico");
    ///     response.send_file(&favicon).ok().expect("Failed to send favicon");
    /// }
    /// ```
    pub fn send_file(&mut self, path: &Path) -> IoResult<()> {
        let mut file = try!(File::open(path));
        self.origin.headers.content_length = None;

        self.origin.headers.content_type = path.extension_str()
                                               .and_then(from_str)
                                               .map(mimes::get_media_type);
        self.origin.headers.server = Some(String::from_str("Nickel"));
        copy(&mut file, self.origin)
    }

    /// Renders the given template bound with the given data.
    ///
    /// # Example
    /// ```{rust}
    /// # use nickel::{Request, Response};
    /// # use std::collections::HashMap;
    /// fn handler(request: &Request, response: &mut Response) {
    ///     let mut data = HashMap::new();
    ///     data.insert("name", "user");
    ///     response.render("examples/assets/template.tpl", &data);
    /// }
    /// ```
    pub fn render<'a, T: Encodable<Encoder<'a>, Error>>
        (&mut self, path: &'static str, data: &T) {
            // Fast path doesn't need writer lock
            match self.templates.read().get(&path) {
                Some(t) => {
                    let _ = t.render(self.origin, data);
                    return
                },
                None => {}
            }

            // We didn't find the template, get writers lock
            let mut templates = self.templates.write();
            // Search again incase there was a race to compile the template
            let template = match templates.entry(path) {
                Vacant(entry) => {
                    let mut file = File::open(&Path::new(path));
                    let raw_template =
                        file.read_to_string()
                            .ok()
                            .expect(format!("Couldn't open the template file: {}",
                                            path).as_slice());

                    entry.set(mustache::compile_str(raw_template.as_slice()))
                },
                Occupied(entry) => entry.into_mut()
            };

            let _ = template.render(self.origin, data);
    }
}

#[test]
fn matches_content_type () {
    let path = &Path::new("test.txt");
    let content_type = path.extension_str().and_then(from_str);

    assert_eq!(content_type, Some(mimes::MediaType::Txt));
    let content_type = content_type.map(mimes::get_media_type).unwrap();

    assert_eq!(content_type.type_.as_slice(), "text");
    assert_eq!(content_type.subtype.as_slice(), "plain");
}
<commit_msg>fix(response): Remove warning by not shadowing lifetime.<commit_after>use std::sync::RWLock;
use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};
use std::io::{IoResult, File};
use std::io::util::copy;
use std::path::BytesContainer;
use serialize::Encodable;
use http;
use http::server::ResponseWriter;
use time;
use mimes;
use mustache;
use mustache::{Template, Encoder, Error};

pub type TemplateCache = RWLock<HashMap<&'static str, Template>>;

///A container for the response
pub struct Response<'a, 'b: 'a> {
    ///the original `http::server::ResponseWriter`
    pub origin: &'a mut ResponseWriter<'b>,
    templates: &'a TemplateCache
}

impl<'a, 'b> Response<'a, 'b> {
    pub fn from_internal<'c, 'd>(response: &'c mut ResponseWriter<'d>,
                                 templates: &'c TemplateCache)
                                -> Response<'c, 'd> {
        Response {
            origin: response,
            templates: templates
        }
    }

    /// Sets the content type by it's short form.
    /// Returns the response for chaining.
    ///
    /// # Example
    /// ```{rust}
    /// # use nickel::{Request, Response};
    /// use nickel::mimes::MediaType;
    /// fn handler(request: &Request, response: &mut Response) {
    ///     response.content_type(MediaType::Html);
    /// }
    /// ```
    pub fn content_type(&mut self, mt: mimes::MediaType) -> &mut Response<'a,'b> {
        self.origin.headers.content_type = Some(mimes::get_media_type(mt));
        self
    }

    /// Sets the status code and returns the response for chaining
    ///
    /// # Example
    /// ```{rust}
    /// # extern crate http;
    /// # extern crate nickel;
    /// # use nickel::{Request, Response};
    /// # fn main() {
    /// fn handler(request: &Request, response: &mut Response) {
    ///     response.status_code(http::status::NotFound);
    /// }
    /// # }
    /// ```
    pub fn status_code(&mut self, status: http::status::Status) -> &mut Response<'a,'b> {
        self.origin.status = status;
        self
    }

    /// Writes a response
    ///
    /// # Example
    /// ```{rust}
    /// # use nickel::{Request, Response};
    /// fn handler(request: &Request, response: &mut Response) {
    ///     response.send("hello world");
    /// }
    /// ```
    pub fn send<T: BytesContainer> (&mut self, text: T) {
        // TODO: This needs to be more sophisticated to return the correct headers
        // not just "some headers" :)
        Response::set_headers(self.origin);
        let _ = self.origin.write(text.container_as_bytes());
    }

    fn set_headers(response_writer: &mut http::server::ResponseWriter) {
        let ref mut headers = response_writer.headers;
        headers.date = Some(time::now_utc());

        // we don't need to set this https://github.com/Ogeon/rustful/issues/3#issuecomment-44787613
        headers.content_length = None;

        headers.server = Some(String::from_str("Nickel"));
    }

    /// Writes a file to the output.
    ///
    /// # Example
    /// ```{rust}
    /// # use nickel::{Request, Response};
    /// fn handler(request: &Request, response: &mut Response) {
    ///     let favicon = Path::new("/assets/favicon.ico");
    ///     response.send_file(&favicon).ok().expect("Failed to send favicon");
    /// }
    /// ```
    pub fn send_file(&mut self, path: &Path) -> IoResult<()> {
        let mut file = try!(File::open(path));
        self.origin.headers.content_length = None;

        self.origin.headers.content_type = path.extension_str()
                                               .and_then(from_str)
                                               .map(mimes::get_media_type);
        self.origin.headers.server = Some(String::from_str("Nickel"));
        copy(&mut file, self.origin)
    }

    /// Renders the given template bound with the given data.
    ///
    /// # Example
    /// ```{rust}
    /// # use nickel::{Request, Response};
    /// # use std::collections::HashMap;
    /// fn handler(request: &Request, response: &mut Response) {
    ///     let mut data = HashMap::new();
    ///     data.insert("name", "user");
    ///     response.render("examples/assets/template.tpl", &data);
    /// }
    /// ```
    pub fn render<'c, T: Encodable<Encoder<'c>, Error>>
        (&mut self, path: &'static str, data: &T) {
            // Fast path doesn't need writer lock
            match self.templates.read().get(&path) {
                Some(t) => {
                    let _ = t.render(self.origin, data);
                    return
                },
                None => {}
            }

            // We didn't find the template, get writers lock
            let mut templates = self.templates.write();
            // Search again incase there was a race to compile the template
            let template = match templates.entry(path) {
                Vacant(entry) => {
                    let mut file = File::open(&Path::new(path));
                    let raw_template =
                        file.read_to_string()
                            .ok()
                            .expect(format!("Couldn't open the template file: {}",
                                            path).as_slice());

                    entry.set(mustache::compile_str(raw_template.as_slice()))
                },
                Occupied(entry) => entry.into_mut()
            };

            let _ = template.render(self.origin, data);
    }
}

#[test]
fn matches_content_type () {
    let path = &Path::new("test.txt");
    let content_type = path.extension_str().and_then(from_str);

    assert_eq!(content_type, Some(mimes::MediaType::Txt));
    let content_type = content_type.map(mimes::get_media_type).unwrap();

    assert_eq!(content_type.type_.as_slice(), "text");
    assert_eq!(content_type.subtype.as_slice(), "plain");
}
<|endoftext|>