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

pub struct Stream {
    chacha20: ChaCha20,
    counter: u32,
    block: [u8; 64],
    block_index: u8,
}

pub struct ChaCha20 {
    state: [u32; 16],
}

/// A ChaCha20 iterator that can be used for encryption and decryption.
///
/// Initialized with a 32-byte key and 12-byte nonce. If reusing a key for encryption, be sure to
/// generate a unique nonce so that a given (key, nonce) pair is never used twice.
///
/// # Overflow Behavior
///
/// Iterating past 256 GB of the bytestream will cause the block counter to overflow.
impl Stream {
    pub fn new(key: &[u8], nonce: &[u8]) -> Self {
        let chacha20 = ChaCha20::new(key, nonce);
        let block = chacha20.block(0);
        Self {
            chacha20: chacha20,
            counter: 0,
            block: block,
            block_index: 0,
        }
    }

    // not sure how legal it is to encrypt without starting with a fresh block
    pub fn encrypt(&mut self, message: &[u8], ciphertext: &mut [u8]) {
        self.xor(message, ciphertext)
    }

    pub fn decrypt(&mut self, ciphertext: &[u8], message: &mut [u8]) {
        self.xor(ciphertext, message)
    }

    fn xor(&mut self, input: &[u8], output: &mut [u8]) {
        for (x, (y, z)) in output.iter_mut().zip(self.take(input.len()).zip(input)) {
            *x = y ^ z;
        }
    }
}

// doing this is a bit strange but it seemed interesting
impl Iterator for Stream {
    type Item = u8;

    fn next(&mut self) -> Option<Self::Item> {
        if self.block_index == 64 {
            self.counter += 1; // could overflow
            self.block = self.chacha20.block(self.counter);
            self.block_index = 0;
        }
        let byte = self.block[self.block_index as usize];
        self.block_index += 1;
        Some(byte)
    }
}

impl ChaCha20 {
    pub fn new(key: &[u8], nonce: &[u8]) -> Self {
        assert_eq!(32, key.len());
        assert_eq!(12, nonce.len());
        let mut chacha20 = Self { state: [0; 16] };
        Self::setup_state(&mut chacha20.state, key, nonce);
        chacha20
    }

    pub fn block(&self, counter: u32) -> [u8; 64] {
        let mut state = [0; 16];
        self.transform_state(&mut state, counter);
        Self::serialize_block(state)
    }

    fn setup_state(state: &mut [u32; 16], key: &[u8], nonce: &[u8]) {
        state[0] = 0x6170_7865;
        state[1] = 0x3320_646e;
        state[2] = 0x7962_2d32;
        state[3] = 0x6b20_6574;
        LittleEndian::read_u32_into(key, &mut state[4..12]);
        LittleEndian::read_u32_into(nonce, &mut state[13..]);
    }

    fn transform_state(&self, state: &mut [u32; 16], counter: u32) {
        state.copy_from_slice(&self.state);
        state[12] = counter;
        for _ in 0..10 {
            Self::inner_block(state);
        }
        for (x, &y) in state.iter_mut().zip(&self.state) {
            *x = x.wrapping_add(y);
        }
        state[12] = state[12].wrapping_add(counter);
    }

    fn inner_block(state: &mut [u32; 16]) {
        Self::quarter_round(state, 0, 4, 8, 12);
        Self::quarter_round(state, 1, 5, 9, 13);
        Self::quarter_round(state, 2, 6, 10, 14);
        Self::quarter_round(state, 3, 7, 11, 15);
        Self::quarter_round(state, 0, 5, 10, 15);
        Self::quarter_round(state, 1, 6, 11, 12);
        Self::quarter_round(state, 2, 7, 8, 13);
        Self::quarter_round(state, 3, 4, 9, 14);
    }

    fn quarter_round(state: &mut [u32; 16], i: usize, j: usize, k: usize, l: usize) {
        let mut a = state[i];
        let mut b = state[j];
        let mut c = state[k];
        let mut d = state[l];
        a = a.wrapping_add(b);
        d ^= a;
        d = d.rotate_left(16);
        c = c.wrapping_add(d);
        b ^= c;
        b = b.rotate_left(12);
        a = a.wrapping_add(b);
        d ^= a;
        d = d.rotate_left(8);
        c = c.wrapping_add(d);
        b ^= c;
        b = b.rotate_left(7);
        state[i] = a;
        state[j] = b;
        state[k] = c;
        state[l] = d;
    }

    fn serialize_block(block: [u32; 16]) -> [u8; 64] {
        let mut bytes = [0; 64];
        LittleEndian::write_u32_into(&block, &mut bytes);
        bytes
    }
}

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

    const KEY: &str = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
    const NONCE: &[u8] = &[0, 0, 0, 0x09, 0, 0, 0, 0x4a, 0, 0, 0, 0];
    const SETUP_STATE: [u32; 16] = [
        0x61707865,
        0x3320646e,
        0x79622d32,
        0x6b206574,
        0x03020100,
        0x07060504,
        0x0b0a0908,
        0x0f0e0d0c,
        0x13121110,
        0x17161514,
        0x1b1a1918,
        0x1f1e1d1c,
        0x00000000,
        0x09000000,
        0x4a000000,
        0x00000000,
    ];
    const FINAL_STATE: [u32; 16] = [
        0xe4e7f110,
        0x15593bd1,
        0x1fdd0f50,
        0xc47120a3,
        0xc7f4d1c7,
        0x0368c033,
        0x9aaa2204,
        0x4e6cd4c3,
        0x466482d2,
        0x09aa9f07,
        0x05d7c214,
        0xa2028bd9,
        0xd19c12b5,
        0xb94e16de,
        0xe883d0cb,
        0x4e3c50a2,
    ];

    #[test]
    fn test_encrypt() {
        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 mut stream = Stream::new(&h2b(KEY), &[0, 0, 0, 0, 0, 0, 0, 0x4a, 0, 0, 0, 0]);
        stream.nth(64 - 1);
        let ciphertext = h2b(
            "6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0b\
             f91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d8\
             07ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab7793736\
             5af90bbf74a35be6b40b8eedf2785e42874d",
        );
        let encrypted_message = &mut vec![0; message.len()];
        stream.encrypt(message.as_bytes(), encrypted_message);
        assert_eq!(&ciphertext, encrypted_message);
    }

    #[test]
    fn test_new() {
        let chacha20 = ChaCha20::new(&h2b(KEY), NONCE);
        let mut state = [0; 16];
        ChaCha20::setup_state(&mut state, &h2b(KEY), NONCE);
        assert_eq!(state, chacha20.state);
    }

    fn check_serialized_block(block: &[u8]) {
        let block_one = h2b(
            "10f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4e\
             d2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e",
        );
        assert_eq!(block_one, block.to_vec());
    }

    #[test]
    fn test_get_block() {
        let mut chacha20 = ChaCha20 { state: [0; 16] };
        ChaCha20::setup_state(&mut chacha20.state, &h2b(KEY), NONCE);
        check_serialized_block(&chacha20.block(1));
    }

    #[test]
    fn test_setup_state() {
        let mut state = [0; 16];
        ChaCha20::setup_state(&mut state, &h2b(KEY), NONCE);
        assert_eq!(SETUP_STATE, state);
    }

    #[test]
    fn test_transform_state() {
        let chacha20 = ChaCha20 { state: SETUP_STATE };
        let mut state = [0; 16];
        chacha20.transform_state(&mut state, 1);
        assert_eq!(FINAL_STATE, state);
    }

    #[test]
    fn test_inner_block() {
        let mut state = SETUP_STATE;
        state[12] = 1;
        for _ in 0..10 {
            ChaCha20::inner_block(&mut state);
        }
        assert_eq!(
            [
                0x837778ab,
                0xe238d763,
                0xa67ae21e,
                0x5950bb2f,
                0xc4f2d0c7,
                0xfc62bb2f,
                0x8fa018fc,
                0x3f5ec7b7,
                0x335271c2,
                0xf29489f3,
                0xeabda8fc,
                0x82e46ebd,
                0xd19c12b4,
                0xb04e16de,
                0x9e83d0cb,
                0x4e3c50a2,
            ],
            state
        );
    }

    #[test]
    fn test_quarter_round() {
        let mut state = [0; 16];
        state[0] = 0x11111111;
        state[1] = 0x01020304;
        state[2] = 0x9b8d6f43;
        state[3] = 0x01234567;
        ChaCha20::quarter_round(&mut state, 0, 1, 2, 3);
        assert_eq!([0xea2a92f4, 0xcb1cf8ce, 0x4581472e, 0x5881c4bb], state[..4]);

        state = [
            0x879531e0,
            0xc5ecf37d,
            0x516461b1,
            0xc9a62f8a,
            0x44c20ef3,
            0x3390af7f,
            0xd9fc690b,
            0x2a5f714c,
            0x53372767,
            0xb00a5631,
            0x974c541a,
            0x359e9963,
            0x5c971061,
            0x3d631689,
            0x2098d9d6,
            0x91dbd320,
        ];
        ChaCha20::quarter_round(&mut state, 2, 7, 8, 13);
        assert_eq!(
            [
                0x879531e0,
                0xc5ecf37d,
                0xbdb886dc,
                0xc9a62f8a,
                0x44c20ef3,
                0x3390af7f,
                0xd9fc690b,
                0xcfacafd2,
                0xe46bea80,
                0xb00a5631,
                0x974c541a,
                0x359e9963,
                0x5c971061,
                0xccc07c79,
                0x2098d9d6,
                0x91dbd320,
            ],
            state
        );
    }

    #[test]
    fn test_serialize_block() {
        check_serialized_block(&ChaCha20::serialize_block(FINAL_STATE));
    }
}
<commit_msg>chacha20: test decrypt<commit_after>use byteorder::{ByteOrder, LittleEndian};

pub struct Stream {
    chacha20: ChaCha20,
    counter: u32,
    block: [u8; 64],
    block_index: u8,
}

pub struct ChaCha20 {
    state: [u32; 16],
}

/// A ChaCha20 iterator that can be used for encryption and decryption.
///
/// Initialized with a 32-byte key and 12-byte nonce. If reusing a key for encryption, be sure to
/// generate a unique nonce so that a given (key, nonce) pair is never used twice.
///
/// # Overflow Behavior
///
/// Iterating past 256 GB of the bytestream will cause the block counter to overflow.
impl Stream {
    pub fn new(key: &[u8], nonce: &[u8]) -> Self {
        let chacha20 = ChaCha20::new(key, nonce);
        let block = chacha20.block(0);
        Self {
            chacha20: chacha20,
            counter: 0,
            block: block,
            block_index: 0,
        }
    }

    // not sure how legal it is to encrypt without starting with a fresh block
    pub fn encrypt(&mut self, message: &[u8], ciphertext: &mut [u8]) {
        self.xor(message, ciphertext)
    }

    pub fn decrypt(&mut self, ciphertext: &[u8], message: &mut [u8]) {
        self.xor(ciphertext, message)
    }

    fn xor(&mut self, input: &[u8], output: &mut [u8]) {
        for (x, (y, z)) in output.iter_mut().zip(self.take(input.len()).zip(input)) {
            *x = y ^ z;
        }
    }
}

// doing this is a bit strange but it seemed interesting
impl Iterator for Stream {
    type Item = u8;

    fn next(&mut self) -> Option<Self::Item> {
        if self.block_index == 64 {
            self.counter += 1; // could overflow
            self.block = self.chacha20.block(self.counter);
            self.block_index = 0;
        }
        let byte = self.block[self.block_index as usize];
        self.block_index += 1;
        Some(byte)
    }
}

impl ChaCha20 {
    pub fn new(key: &[u8], nonce: &[u8]) -> Self {
        assert_eq!(32, key.len());
        assert_eq!(12, nonce.len());
        let mut chacha20 = Self { state: [0; 16] };
        Self::setup_state(&mut chacha20.state, key, nonce);
        chacha20
    }

    pub fn block(&self, counter: u32) -> [u8; 64] {
        let mut state = [0; 16];
        self.transform_state(&mut state, counter);
        Self::serialize_block(state)
    }

    fn setup_state(state: &mut [u32; 16], key: &[u8], nonce: &[u8]) {
        state[0] = 0x6170_7865;
        state[1] = 0x3320_646e;
        state[2] = 0x7962_2d32;
        state[3] = 0x6b20_6574;
        LittleEndian::read_u32_into(key, &mut state[4..12]);
        LittleEndian::read_u32_into(nonce, &mut state[13..]);
    }

    fn transform_state(&self, state: &mut [u32; 16], counter: u32) {
        state.copy_from_slice(&self.state);
        state[12] = counter;
        for _ in 0..10 {
            Self::inner_block(state);
        }
        for (x, &y) in state.iter_mut().zip(&self.state) {
            *x = x.wrapping_add(y);
        }
        state[12] = state[12].wrapping_add(counter);
    }

    fn inner_block(state: &mut [u32; 16]) {
        Self::quarter_round(state, 0, 4, 8, 12);
        Self::quarter_round(state, 1, 5, 9, 13);
        Self::quarter_round(state, 2, 6, 10, 14);
        Self::quarter_round(state, 3, 7, 11, 15);
        Self::quarter_round(state, 0, 5, 10, 15);
        Self::quarter_round(state, 1, 6, 11, 12);
        Self::quarter_round(state, 2, 7, 8, 13);
        Self::quarter_round(state, 3, 4, 9, 14);
    }

    fn quarter_round(state: &mut [u32; 16], i: usize, j: usize, k: usize, l: usize) {
        let mut a = state[i];
        let mut b = state[j];
        let mut c = state[k];
        let mut d = state[l];
        a = a.wrapping_add(b);
        d ^= a;
        d = d.rotate_left(16);
        c = c.wrapping_add(d);
        b ^= c;
        b = b.rotate_left(12);
        a = a.wrapping_add(b);
        d ^= a;
        d = d.rotate_left(8);
        c = c.wrapping_add(d);
        b ^= c;
        b = b.rotate_left(7);
        state[i] = a;
        state[j] = b;
        state[k] = c;
        state[l] = d;
    }

    fn serialize_block(block: [u32; 16]) -> [u8; 64] {
        let mut bytes = [0; 64];
        LittleEndian::write_u32_into(&block, &mut bytes);
        bytes
    }
}

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

    const KEY: &str = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
    const NONCE: &[u8] = &[0, 0, 0, 0x09, 0, 0, 0, 0x4a, 0, 0, 0, 0];
    const SETUP_STATE: [u32; 16] = [
        0x61707865,
        0x3320646e,
        0x79622d32,
        0x6b206574,
        0x03020100,
        0x07060504,
        0x0b0a0908,
        0x0f0e0d0c,
        0x13121110,
        0x17161514,
        0x1b1a1918,
        0x1f1e1d1c,
        0x00000000,
        0x09000000,
        0x4a000000,
        0x00000000,
    ];
    const FINAL_STATE: [u32; 16] = [
        0xe4e7f110,
        0x15593bd1,
        0x1fdd0f50,
        0xc47120a3,
        0xc7f4d1c7,
        0x0368c033,
        0x9aaa2204,
        0x4e6cd4c3,
        0x466482d2,
        0x09aa9f07,
        0x05d7c214,
        0xa2028bd9,
        0xd19c12b5,
        0xb94e16de,
        0xe883d0cb,
        0x4e3c50a2,
    ];

    #[test]
    fn test_encrypt() {
        let key = &h2b(KEY);
        let nonce = &[0, 0, 0, 0, 0, 0, 0, 0x4a, 0, 0, 0, 0];
        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(
            "6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0b\
             f91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d8\
             07ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab7793736\
             5af90bbf74a35be6b40b8eedf2785e42874d",
        );
        let encrypted_message = &mut vec![0; message.len()];
        let decrypted_ciphertext = &mut vec![0; ciphertext.len()];

        let mut stream = Stream::new(key, nonce);
        stream.nth(64 - 1);
        stream.encrypt(message.as_bytes(), encrypted_message);
        assert_eq!(&ciphertext, encrypted_message);

        stream = Stream::new(key, nonce);
        stream.nth(64 - 1);
        stream.decrypt(&ciphertext, decrypted_ciphertext);
        assert_eq!(message.as_bytes(), decrypted_ciphertext.as_slice());
    }

    #[test]
    fn test_new() {
        let chacha20 = ChaCha20::new(&h2b(KEY), NONCE);
        let mut state = [0; 16];
        ChaCha20::setup_state(&mut state, &h2b(KEY), NONCE);
        assert_eq!(state, chacha20.state);
    }

    fn check_serialized_block(block: &[u8]) {
        let block_one = h2b(
            "10f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4e\
             d2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e",
        );
        assert_eq!(block_one, block.to_vec());
    }

    #[test]
    fn test_get_block() {
        let mut chacha20 = ChaCha20 { state: [0; 16] };
        ChaCha20::setup_state(&mut chacha20.state, &h2b(KEY), NONCE);
        check_serialized_block(&chacha20.block(1));
    }

    #[test]
    fn test_setup_state() {
        let mut state = [0; 16];
        ChaCha20::setup_state(&mut state, &h2b(KEY), NONCE);
        assert_eq!(SETUP_STATE, state);
    }

    #[test]
    fn test_transform_state() {
        let chacha20 = ChaCha20 { state: SETUP_STATE };
        let mut state = [0; 16];
        chacha20.transform_state(&mut state, 1);
        assert_eq!(FINAL_STATE, state);
    }

    #[test]
    fn test_inner_block() {
        let mut state = SETUP_STATE;
        state[12] = 1;
        for _ in 0..10 {
            ChaCha20::inner_block(&mut state);
        }
        assert_eq!(
            [
                0x837778ab,
                0xe238d763,
                0xa67ae21e,
                0x5950bb2f,
                0xc4f2d0c7,
                0xfc62bb2f,
                0x8fa018fc,
                0x3f5ec7b7,
                0x335271c2,
                0xf29489f3,
                0xeabda8fc,
                0x82e46ebd,
                0xd19c12b4,
                0xb04e16de,
                0x9e83d0cb,
                0x4e3c50a2,
            ],
            state
        );
    }

    #[test]
    fn test_quarter_round() {
        let mut state = [0; 16];
        state[0] = 0x11111111;
        state[1] = 0x01020304;
        state[2] = 0x9b8d6f43;
        state[3] = 0x01234567;
        ChaCha20::quarter_round(&mut state, 0, 1, 2, 3);
        assert_eq!([0xea2a92f4, 0xcb1cf8ce, 0x4581472e, 0x5881c4bb], state[..4]);

        state = [
            0x879531e0,
            0xc5ecf37d,
            0x516461b1,
            0xc9a62f8a,
            0x44c20ef3,
            0x3390af7f,
            0xd9fc690b,
            0x2a5f714c,
            0x53372767,
            0xb00a5631,
            0x974c541a,
            0x359e9963,
            0x5c971061,
            0x3d631689,
            0x2098d9d6,
            0x91dbd320,
        ];
        ChaCha20::quarter_round(&mut state, 2, 7, 8, 13);
        assert_eq!(
            [
                0x879531e0,
                0xc5ecf37d,
                0xbdb886dc,
                0xc9a62f8a,
                0x44c20ef3,
                0x3390af7f,
                0xd9fc690b,
                0xcfacafd2,
                0xe46bea80,
                0xb00a5631,
                0x974c541a,
                0x359e9963,
                0x5c971061,
                0xccc07c79,
                0x2098d9d6,
                0x91dbd320,
            ],
            state
        );
    }

    #[test]
    fn test_serialize_block() {
        check_serialized_block(&ChaCha20::serialize_block(FINAL_STATE));
    }
}
<|endoftext|>


<commit_before>#[macro_use]
pub mod macros;
pub mod error;
pub mod arguments;
pub mod configuration;
pub mod engines;

extern crate std;
extern crate config;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::collections::HashMap;
use config::types::Config;
use bins::error::*;
use bins::arguments::Arguments;
use bins::engines::Engine;
use bins::engines::gist::Gist;
use bins::engines::hastebin::Hastebin;
use bins::engines::pastie::Pastie;
use bins::engines::pastebin::Pastebin;

#[derive(Clone)]
pub struct PasteFile {
  pub name: String,
  pub data: String
}

impl PasteFile {
  fn new(name: String, data: String) -> Self {
    PasteFile { name: name, data: data }
  }
}

pub struct Bins {
  pub config: Config,
  pub arguments: Arguments
}

impl Bins {
  pub fn new(config: Config, arguments: Arguments) -> Self {
    Bins {
      config: config,
      arguments: arguments
    }
  }

  pub fn get_engine(&self) -> Result<Box<Engine>> {
    let service = match self.arguments.service {
      Some(ref s) => s,
      None => return Err("no service was specified and no default service was set.".into())
    };
    match service.to_lowercase().as_ref() {
      "gist" => Ok(Box::new(Gist::new())),
      "hastebin" => Ok(Box::new(Hastebin::new())),
      "pastie" => Ok(Box::new(Pastie::new())),
      "pastebin" => Ok(Box::new(Pastebin::new())),
      _ => Err(format!("unknown service \"{}\"", service).into())
    }
  }

  fn read_file<P: AsRef<Path>>(&self, p: P) -> Result<String> {
    let path = p.as_ref();
    let name = match path.to_str() {
      Some(s) => s,
      None => return Err(String::from("file name was not valid unicode").into())
    };
    if !path.exists() {
      return Err(format!("{} does not exist", name).into());
    }
    if !path.is_file() {
      return Err(format!("{} is not a file", name).into());
    }
    let mut file = match File::open(path) {
      Ok(f) => f,
      Err(e) => {
        return Err(format!("could not open {}: {}", name, e).into());
      }
    };
    let mut s = String::new();
    if let Err(e) = file.read_to_string(&mut s) {
      return Err(format!("could not read {}: {}", name, e).into());
    }
    Ok(s)
  }

  fn read_file_to_pastefile<P: AsRef<Path>>(&self, p: P) -> Result<PasteFile> {
    let path = p.as_ref();
    match self.read_file(path) {
      Ok(s) => {
        let n = match path.file_name() {
          Some(x) => x,
          None => return Err("not a valid file name".into())
        };
        Ok(PasteFile::new(n.to_string_lossy().into_owned(), s))
      },
      Err(s) => return Err(s)
    }
  }

  pub fn get_to_paste(&self) -> Result<Vec<PasteFile>> {
    let arguments = &self.arguments;
    let message = &arguments.message;
    let paste_files: Vec<PasteFile> = if !message.is_empty() {
      vec![PasteFile::new(String::from("message"), message.to_owned())]
    } else if !arguments.files.is_empty() {
      let files = arguments.files.clone();
      let results = files.iter()
        .map(|s| Path::new(s))
        .map(|p| self.read_file_to_pastefile(p))
        .map(|r| r.map_err(|e| e.iter().map(|x| x.to_string()).collect::<Vec<_>>().join("\n")))
        .collect::<Vec<_>>();
      for res in results.iter().cloned() {
        if res.is_err() {
          return Err(res.err().unwrap().into());
        }
      }
      let mut pastes = results.iter().cloned().map(|r| r.unwrap()).collect::<Vec<_>>();
      self.handle_duplicate_file_names(&mut pastes);
      pastes
    } else {
      let mut buffer = String::new();
      if let Err(e) = std::io::stdin().read_to_string(&mut buffer) {
        return Err(format!("error reading stdin: {}", e).into());
      }
      vec![PasteFile::new(String::from("stdin"), buffer)]
    };
    Ok(paste_files)
  }

  fn handle_duplicate_file_names(&self, pastes: &mut Vec<PasteFile>) {
    let mut names_map: HashMap<String, i32> = HashMap::new();
    for mut paste in pastes {
      let name = paste.name.clone();
      if names_map.contains_key(&name) {
        let number = names_map.entry(name.clone()).or_insert(1);
        paste.name = format!("{}_{}", name, number);
        *number += 1;
      }
      names_map.entry(name.clone()).or_insert(1);
    }
  }
}
<commit_msg>fix(bins): filter out empty files<commit_after>#[macro_use]
pub mod macros;
pub mod error;
pub mod arguments;
pub mod configuration;
pub mod engines;

extern crate std;
extern crate config;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::collections::HashMap;
use config::types::Config;
use bins::error::*;
use bins::arguments::Arguments;
use bins::engines::Engine;
use bins::engines::gist::Gist;
use bins::engines::hastebin::Hastebin;
use bins::engines::pastie::Pastie;
use bins::engines::pastebin::Pastebin;

#[derive(Clone)]
pub struct PasteFile {
  pub name: String,
  pub data: String
}

impl PasteFile {
  fn new(name: String, data: String) -> Self {
    PasteFile { name: name, data: data }
  }
}

pub struct Bins {
  pub config: Config,
  pub arguments: Arguments
}

impl Bins {
  pub fn new(config: Config, arguments: Arguments) -> Self {
    Bins {
      config: config,
      arguments: arguments
    }
  }

  pub fn get_engine(&self) -> Result<Box<Engine>> {
    let service = match self.arguments.service {
      Some(ref s) => s,
      None => return Err("no service was specified and no default service was set.".into())
    };
    match service.to_lowercase().as_ref() {
      "gist" => Ok(Box::new(Gist::new())),
      "hastebin" => Ok(Box::new(Hastebin::new())),
      "pastie" => Ok(Box::new(Pastie::new())),
      "pastebin" => Ok(Box::new(Pastebin::new())),
      _ => Err(format!("unknown service \"{}\"", service).into())
    }
  }

  fn read_file<P: AsRef<Path>>(&self, p: P) -> Result<String> {
    let path = p.as_ref();
    let name = match path.to_str() {
      Some(s) => s,
      None => return Err(String::from("file name was not valid unicode").into())
    };
    if !path.exists() {
      return Err(format!("{} does not exist", name).into());
    }
    if !path.is_file() {
      return Err(format!("{} is not a file", name).into());
    }
    let mut file = match File::open(path) {
      Ok(f) => f,
      Err(e) => {
        return Err(format!("could not open {}: {}", name, e).into());
      }
    };
    let mut s = String::new();
    if let Err(e) = file.read_to_string(&mut s) {
      return Err(format!("could not read {}: {}", name, e).into());
    }
    Ok(s)
  }

  fn read_file_to_pastefile<P: AsRef<Path>>(&self, p: P) -> Result<PasteFile> {
    let path = p.as_ref();
    match self.read_file(path) {
      Ok(s) => {
        let n = match path.file_name() {
          Some(x) => x,
          None => return Err("not a valid file name".into())
        };
        Ok(PasteFile::new(n.to_string_lossy().into_owned(), s))
      },
      Err(s) => return Err(s)
    }
  }

  pub fn get_to_paste(&self) -> Result<Vec<PasteFile>> {
    let arguments = &self.arguments;
    let message = &arguments.message;
    let paste_files: Vec<PasteFile> = if !message.is_empty() {
      vec![PasteFile::new(String::from("message"), message.to_owned())]
    } else if !arguments.files.is_empty() {
      let files = arguments.files.clone();
      let results = files.iter()
        .map(|s| Path::new(s))
        .map(|p| self.read_file_to_pastefile(p))
        .map(|r| r.map_err(|e| e.iter().map(|x| x.to_string()).collect::<Vec<_>>().join("\n")))
        .collect::<Vec<_>>();
      for res in results.iter().cloned() {
        if res.is_err() {
          return Err(res.err().unwrap().into());
        }
      }
      let mut pastes = results.iter().cloned().map(|r| r.unwrap()).filter(|p| !p.data.trim().is_empty()).collect::<Vec<_>>();
      if pastes.len() < 1 {
        return Err("no files (or all empty files) to paste".into());
      }
      self.handle_duplicate_file_names(&mut pastes);
      pastes
    } else {
      let mut buffer = String::new();
      if let Err(e) = std::io::stdin().read_to_string(&mut buffer) {
        return Err(format!("error reading stdin: {}", e).into());
      }
      vec![PasteFile::new(String::from("stdin"), buffer)]
    };
    Ok(paste_files)
  }

  fn handle_duplicate_file_names(&self, pastes: &mut Vec<PasteFile>) {
    let mut names_map: HashMap<String, i32> = HashMap::new();
    for mut paste in pastes {
      let name = paste.name.clone();
      if names_map.contains_key(&name) {
        let number = names_map.entry(name.clone()).or_insert(1);
        paste.name = format!("{}_{}", name, number);
        *number += 1;
      }
      names_map.entry(name.clone()).or_insert(1);
    }
  }
}
<|endoftext|>


<commit_before>use std::io::Write;
use std::any::Any;
use std::io::Read;
use std::io::BufReader;
use std::io::BufRead;
use std::fs::File;
use std::error::Error;
use std::iter::Peekable;
use std::io::CharsError;
use std::cell::Cell;
use std::cell::RefCell;

static DEFAULT_SM: &'static str = "{{";
static DEFAULT_EM: &'static str = "}}";

#[derive(Eq)]
struct TemplateContext {
    sm: String,
    em: String,
    file: String,
    line: i64,
    start_of_line: bool
}

impl PartialEq for TemplateContext {
    fn eq(&self, other: &TemplateContext) -> bool {
        self.sm == other.sm &&
        self.em == other.em &&
        self.file == other.file &&
        self.line == other.line &&
        self.start_of_line == other.start_of_line
    }
}

struct Code {
    name: String,
    identity: String,
    appended: String,
    mustache: Mustache,
}

struct Mustache {
    codes: Vec<Box<IsCode>>,
}

pub trait IsCode {
    fn execute<'a>(&self, writer: &'a Write, scopes: &'a Vec<Box<Any>>) -> &'a Write;
}

impl IsCode for Mustache {
    fn execute<'a>(&self, writer: &'a Write, scopes: &'a Vec<Box<Any>>) -> &'a Write {
        for code in self.codes.iter() {
            code.execute(writer, scopes);
        }
        writer
    }
}

pub fn compile(file: &str) -> Result<Box<IsCode>, String> {
    compile_read(&mut try!(File::open(file).map_err(|e| e.to_string())), file)
}

pub fn compile_read(reader: &mut Read, file: &str) -> Result<Box<IsCode>, String> {
    let mut buf = &mut BufReader::new(reader).chars();
    let iter = &mut buf.take_while(|c| {
        c.is_ok()
    }).map(|c| {
        c.ok().unwrap()
    });
    let chars = Lookahead::new(iter);

    compile_internal(&chars, None, &Cell::new(0), file, DEFAULT_SM, DEFAULT_EM, true)
}

struct Lookahead<'a> {
    iter: RefCell<&'a mut Iterator<Item = char>>,
    peeked: Cell<Option<char>>,
}

impl <'a> Lookahead<'a>  {
    fn new(iter: &mut Iterator<Item = char>) -> Lookahead {
        Lookahead { iter: RefCell::new(iter), peeked: Cell::new(None) }
    }

    fn peek(&self) -> Option<char> {
        match self.peeked.get() {
            None => {
                self.peeked.set(self.iter.borrow_mut().next());
                self.peeked.get()
            }
            Some(c) => {
                self.peeked.set(None);
                Some(c)
            }
        }
    }
    fn next(&self) -> Option<char> {
        match self.peeked.get() {
            None => self.iter.borrow_mut().next(),
            Some(p) => {
                self.peeked.set(None);
                Some(p)
            }
        }
    }
}

fn compile_internal(br: &Lookahead, tag: Option<&str>, currentLine: &Cell<u32>, file: &str, sm: &str, em: &str, startOfLine: bool) -> Result<Box<IsCode>, String> {
    let startLine = currentLine;

    let mut iterable = currentLine.get() != 0;
    let mut sawCR = false;
    let mut onlywhitespace = true;
    let mut trackingLine = match currentLine.get() {
        0 => 1,
        _ => currentLine.get()
    };
    let mut out = String::new();
    let mut trackingStartOfLine = startOfLine;

    loop {
        let c = match br.next() {
            Some(a) => a,
            None => break
        };
        // Next line handling
        if c == '\r' {
            sawCR = true;
            continue;
        }
        if c == '\n' {
            currentLine.set(currentLine.get() + 1);
            if !iterable || (iterable && !onlywhitespace) {
                if sawCR {
                    out.push('\r');
                }
                out.push('\n');
            }
            // WriteCode

            iterable = false;
            onlywhitespace = true;
            trackingStartOfLine = true;
            continue;
        }
        sawCR = false;

        // Mustache tag handling
        if c == sm.char_at(0) {
            let mut matches = sm.len() == 1;
            if !matches {
                {
                    let peeked = br.peek();
                    matches = peeked.map(|c| {
                        c == sm.char_at(1)
                    }).unwrap_or(false);
                }
                if matches {
                    // Consume the character from the stream
                    br.next();
                }
            }
            if matches {
                // We are in a tag! No we grab the tag name.
                let mut tagName = String::new();
                loop {
                    let c = match br.next() {
                        Some(a) => a,
                        None => break
                    };
                    if c == em.char_at(0) {
                        let mut matches = em.len() == 1;
                        if !matches {
                            {
                                let peeked = br.peek();
                                matches = peeked.map(|c| {
                                    c == em.char_at(1)
                                }).unwrap_or(false);
                            }
                            if matches {
                                // Consume the character from the stream
                                br.next();
                            }
                        }
                        if matches {
                            break;
                        }
                    }
                    tagName.push(c);
                }
                if tagName.len() == 0 {
                    return Err("Empty mustache".to_string());
                }
                let ch = tagName.char_at(0);
                let variable = tagName[1..].trim();
                println!("Matching on: {}", ch);
                match ch {
                    '#' |
                    '^' |
                    '<' |
                    '$' => {
                        let oldStartOfLine = trackingStartOfLine;
                        trackingStartOfLine = trackingStartOfLine & onlywhitespace;
                        let line = currentLine.get();
                        let mustache = compile_internal(br, Some(variable), currentLine, file, sm, em, trackingStartOfLine);
                        let lines = currentLine.get() - line;
                        if !onlywhitespace || lines == 0 {
                            println!("WriteCode: {}", out);
                        }
                        out = String::new();
                    },
                    '/' => {

                    },
                    '>' => {

                    },
                    '{' => {

                    },
                    '&' => {

                    },
                    '%' => {

                    },
                    '!' => {

                    },
                    '=' => {

                    },
                    _ => {
                        println!("WriteCode: {}", out);
                        println!("ValueCode: {}", tagName);
                    }
                }
                continue;
            }
        }
        out.push(c);
    }
    // WriteCode
    // Check if tag is set
    match tag {
        None => {
            println!("{}", out);
            // EOFCode
            // return MustacheCode
            Ok(Box::new(Mustache { codes: vec![] }))
        }
        _ => return Err("Failed to close tag".to_string()),
    }
}<commit_msg>get ready to start the tree<commit_after>use std::io::Write;
use std::any::Any;
use std::io::Read;
use std::io::BufReader;
use std::io::BufRead;
use std::fs::File;
use std::error::Error;
use std::iter::Peekable;
use std::io::CharsError;
use std::cell::Cell;
use std::cell::RefCell;

static DEFAULT_SM: &'static str = "{{";
static DEFAULT_EM: &'static str = "}}";

#[derive(Eq)]
struct TemplateContext {
    sm: String,
    em: String,
    file: String,
    line: i64,
    start_of_line: bool
}

impl PartialEq for TemplateContext {
    fn eq(&self, other: &TemplateContext) -> bool {
        self.sm == other.sm &&
        self.em == other.em &&
        self.file == other.file &&
        self.line == other.line &&
        self.start_of_line == other.start_of_line
    }
}

struct Code {
    name: String,
    identity: String,
    appended: String,
    mustache: Mustache,
}

struct Mustache {
    codes: Vec<Box<IsCode>>,
}

pub trait IsCode {
    fn execute<'a>(&self, writer: &'a Write, scopes: &'a Vec<Box<Any>>) -> &'a Write;
}

impl IsCode for Mustache {
    fn execute<'a>(&self, writer: &'a Write, scopes: &'a Vec<Box<Any>>) -> &'a Write {
        for code in self.codes.iter() {
            code.execute(writer, scopes);
        }
        writer
    }
}

pub fn compile(file: &str) -> Result<Box<IsCode>, String> {
    compile_read(&mut try!(File::open(file).map_err(|e| e.to_string())), file)
}

pub fn compile_read(reader: &mut Read, file: &str) -> Result<Box<IsCode>, String> {
    let mut buf = &mut BufReader::new(reader).chars();
    let iter = &mut buf.take_while(|c| {
        c.is_ok()
    }).map(|c| {
        c.ok().unwrap()
    });
    let chars = Lookahead::new(iter);

    compile_internal(&chars, None, &Cell::new(0), file, DEFAULT_SM, DEFAULT_EM, true)
}

struct Lookahead<'a> {
    iter: RefCell<&'a mut Iterator<Item = char>>,
    peeked: Cell<Option<char>>,
}

impl <'a> Lookahead<'a>  {
    fn new(iter: &mut Iterator<Item = char>) -> Lookahead {
        Lookahead { iter: RefCell::new(iter), peeked: Cell::new(None) }
    }

    fn peek(&self) -> Option<char> {
        match self.peeked.get() {
            None => {
                self.peeked.set(self.iter.borrow_mut().next());
                self.peeked.get()
            }
            Some(c) => {
                self.peeked.set(None);
                Some(c)
            }
        }
    }
    fn next(&self) -> Option<char> {
        match self.peeked.get() {
            None => self.iter.borrow_mut().next(),
            Some(p) => {
                self.peeked.set(None);
                Some(p)
            }
        }
    }
}

fn compile_internal(br: &Lookahead, tag: Option<&str>, currentLine: &Cell<u32>, file: &str, sm_start: &str, em_start: &str, startOfLine: bool) -> Result<Box<IsCode>, String> {
    let mut sm = sm_start;
    let mut em = em_start;
    let startLine = currentLine;

    let mut iterable = currentLine.get() != 0;
    let mut sawCR = false;
    let mut onlywhitespace = true;
    let mut trackingLine = match currentLine.get() {
        0 => 1,
        _ => currentLine.get()
    };
    let mut out = String::new();
    let mut trackingStartOfLine = startOfLine;

    loop {
        let c = match br.next() {
            Some(a) => a,
            None => break
        };
        // Next line handling
        if c == '\r' {
            sawCR = true;
            continue;
        }
        if c == '\n' {
            currentLine.set(currentLine.get() + 1);
            if !iterable || (iterable && !onlywhitespace) {
                if sawCR {
                    out.push('\r');
                }
                out.push('\n');
            }
            // WriteCode

            iterable = false;
            onlywhitespace = true;
            trackingStartOfLine = true;
            continue;
        }
        sawCR = false;

        // Mustache tag handling
        if c == sm.char_at(0) {
            let mut matches = sm.len() == 1;
            if !matches {
                {
                    let peeked = br.peek();
                    matches = peeked.map(|c| {
                        c == sm.char_at(1)
                    }).unwrap_or(false);
                }
                if matches {
                    // Consume the character from the stream
                    br.next();
                }
            }
            if matches {
                // We are in a tag! No we grab the tag name.
                let mut tagName = String::new();
                loop {
                    let c = match br.next() {
                        Some(a) => a,
                        None => break
                    };
                    if c == em.char_at(0) {
                        let mut matches = em.len() == 1;
                        if !matches {
                            {
                                let peeked = br.peek();
                                matches = peeked.map(|c| {
                                    c == em.char_at(1)
                                }).unwrap_or(false);
                            }
                            if matches {
                                // Consume the character from the stream
                                br.next();
                            }
                        }
                        if matches {
                            break;
                        }
                    }
                    tagName.push(c);
                }
                if tagName.len() == 0 {
                    return Err("Empty mustache".to_string());
                }
                let ch = tagName.char_at(0);
                let variable = tagName[1..].trim();
                println!("Matching on: {}", ch);
                match ch {
                    '#' |
                    '^' |
                    '<' |
                    '$' => {
                        let oldStartOfLine = trackingStartOfLine;
                        trackingStartOfLine = trackingStartOfLine & onlywhitespace;
                        let line = currentLine.get();
                        let mustache = compile_internal(br, Some(variable), currentLine, file, sm, em, trackingStartOfLine);
                        let lines = currentLine.get() - line;
                        if !onlywhitespace || lines == 0 {
                            println!("WriteCode: {}", out);
                        }
                        out = String::new();
                        match ch {
                            '#' => println!("Starting block: {}", variable),
                            '^' => println!("Starting not block: {}", variable),
                            '<' => println!("Starting inherit: {}", variable),
                            '$' => println!("Starting replacement: {}", variable),
                            _ => panic!("Asserting this cant happen"),
                        }
                        iterable = lines != 0;
                    },
                    '/' => {
                        if !trackingStartOfLine || !onlywhitespace {
                            println!("WriteCode: {}", out);
                        }
                        match tag {
                            None => return Err("Missing start tag".to_string()),
                            Some(t) => {
                                if t != variable {
                                    return Err("Mismatched tags".to_string())
                                }
                            }
                        }
                        println!("End tag: {}", variable)
                    },
                    '>' => {
                        println!("WriteCode: {}", out);
                        trackingStartOfLine = trackingStartOfLine & onlywhitespace;
                        println!("PartialCode: {}", variable);
                    },
                    '{' => {
                        println!("WriteCode: {}", out);
                        let mut name = variable;
                        if em.char_at(1) != '}' {
                            let length = variable.len() - 1;
                            name = &variable[0..length];
                        } else {
                            match br.next() {
                                None => break,
                                Some(c) => {
                                    if c != '}' {
                                        return Err("Improperly closed variable".to_string());
                                    }
                                }
                            }
                        }
                        println!("UnescpaedValueCode: {}", name);
                    },
                    '&' => {
                        println!("WriteCode: {}", out);
                        println!("UnescpaedValueCode: {}", variable);
                    },
                    '%' => {
                        println!("WriteCode: {}", out);
                        println!("PragmaCode: {}", variable);
                    },
                    '!' => {
                        println!("WriteCode: {}", out);
                        println!("CommentCode: {}", variable);
                    },
                    '=' => {
                        println!("WriteCode: {}", out);
                        println!("Delimiters: {}", tagName);
                    },
                    _ => {
                        println!("WriteCode: {}", out);
                        println!("ValueCode: {}", tagName);
                    }
                }
                continue;
            }
        }
        out.push(c);
    }
    // WriteCode
    // Check if tag is set
    match tag {
        None => {
            println!("{}", out);
            // EOFCode
            // return MustacheCode
            Ok(Box::new(Mustache { codes: vec![] }))
        }
        _ => return Err("Failed to close tag".to_string()),
    }
}<|endoftext|>


<commit_before>use std::vec::Vec;
use std::string::String;

struct Compiler {
    pub lines: Vec<String>,
}

impl Compiler {
    pub fn new() -> Self {
        Compiler { lines: Vec::new() }
    }

    pub fn parse(&mut self, assembly: &str) {
        let mut line = String::new();
        let mut chars = assembly.chars();

        while let Some(c) = chars.next() {
            match c {
                // Line Feed | Vertical Tab | Form Feed
                '\u{000A}' | '\u{000B}' | '\u{000C}' => {
                    self.lines.push(line);
                    line = String::new();
                }

                // Carriage Return
                '\u{000D}' => {
                    self.lines.push(line);
                    line = String::new();

                    // Carriage Return + Line Feed
                    match chars.next() {
                        Some(n) => {
                            if n != '\u{000A}' {
                                line.push(n);
                            }
                        }
                        None => {}
                    }
                }

                _ => {
                    line.push(c);
                }
            }
        }

        if !line.is_empty() {
            self.lines.push(line);
        }
    }
}

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

    #[test]
    fn it_splits_lines_by_line_feed() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\n0 0 0 0");

        assert_eq!(compiler.lines.len(), 2);
    }

    #[test]
    fn it_splits_lines_by_vertical_tab() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\x0B0 0 0 0");

        assert_eq!(compiler.lines.len(), 2);
    }

    #[test]
    fn it_splits_lines_by_form_feed() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\x0C0 0 0 0");

        assert_eq!(compiler.lines.len(), 2);
    }

    #[test]
    fn it_splits_lines_by_carriage_return() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\r0 0 0 0");

        assert_eq!(compiler.lines.len(), 2);
    }

    #[test]
    fn it_splits_lines_by_carriage_return_line_feed() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\r\n0 0 0 0");

        assert_eq!(compiler.lines.len(), 2);
    }

    #[test]
    fn it_ignors_trailing_separators() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\r\n0 0 0 0\r\n");

        assert_eq!(compiler.lines.len(), 2);
    }
}
<commit_msg>Splits assembly on next lines.<commit_after>use std::vec::Vec;
use std::string::String;

struct Compiler {
    pub lines: Vec<String>,
}

impl Compiler {
    pub fn new() -> Self {
        Compiler { lines: Vec::new() }
    }

    pub fn parse(&mut self, assembly: &str) {
        let mut line = String::new();
        let mut chars = assembly.chars();

        while let Some(c) = chars.next() {
            match c {
                // Line Feed | Vertical Tab | Form Feed | Next Line
                '\u{000A}' | '\u{000B}' | '\u{000C}' | '\u{0085}' => {
                    self.lines.push(line);
                    line = String::new();
                }

                // Carriage Return
                '\u{000D}' => {
                    self.lines.push(line);
                    line = String::new();

                    // Carriage Return + Line Feed
                    match chars.next() {
                        Some(n) => {
                            if n != '\u{000A}' {
                                line.push(n);
                            }
                        }
                        None => {}
                    }
                }

                _ => {
                    line.push(c);
                }
            }
        }

        if !line.is_empty() {
            self.lines.push(line);
        }
    }
}

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

    #[test]
    fn it_splits_lines_by_line_feed() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\n0 0 0 0");

        assert_eq!(compiler.lines.len(), 2);
    }

    #[test]
    fn it_splits_lines_by_vertical_tab() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\x0B0 0 0 0");

        assert_eq!(compiler.lines.len(), 2);
    }

    #[test]
    fn it_splits_lines_by_form_feed() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\x0C0 0 0 0");

        assert_eq!(compiler.lines.len(), 2);
    }

    #[test]
    fn it_splits_lines_by_carriage_return() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\r0 0 0 0");

        assert_eq!(compiler.lines.len(), 2);
    }

    #[test]
    fn it_splits_lines_by_carriage_return_line_feed() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\r\n0 0 0 0");

        assert_eq!(compiler.lines.len(), 2);
    }

    #[test]
    fn it_splits_lines_by_next_line() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\u{0085}0 0 0 0");

        assert_eq!(compiler.lines.len(), 2);
    }

    #[test]
    fn it_ignors_trailing_separators() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\r\n0 0 0 0\r\n");

        assert_eq!(compiler.lines.len(), 2);
    }
}
<|endoftext|>


<commit_before>
use clap::{App, Arg};

use loader;

pub fn cli_clap() {

    // Once all App settings (including all arguments) have been set, you call get_matches() which
    // parses the string provided by the user, and returns all the valid matches to the ones you
    // specified.
    //
    // You can then query the matches struct to get information about how the user ran the program
    // at startup.
    //
    // For this example, let's assume you created an App which accepts three arguments (plus two
    // generated by clap), a flag to display debugging information triggered with "-d" or
    // "--debug" as well as an option argument which specifies a custom configuration file to use
    // triggered with "-c file" or "--config file" or "--config=file" and finally a positional
    // argument which is the input file we want to work with, this will be the only required
    // argument.
    let matches = App::new("whenenv")
                        .about("Parses an input file to do awesome things")
                        .version("0.0.1")
                        .author("Owen Synge <osynge@googlemail.com>")
                        .arg(Arg::with_name("verbose")
                                    .help("Increase log output.")
                                    .short("v")
                                    .multiple(true)
                                    .long("verbose"))
                        .arg(Arg::with_name("quiet")
                                    .help("Decrease log output.")
                                    .short("q")
                                    .multiple(true)
                                    .long("quiet"))
                        .arg(Arg::with_name("env")
                                    .short("e")
                                    .long("env")
                                    .value_name("ENVIROMENT_VARIABLE")
                                    .help("Which enviroment variables to process")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("dir-jobs")
                                    .long("dir-jobs")
                                    .value_name("DIR_JOB")
                                    .help("directory storing json jobs.")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("dir-sh")
                                    .long("dir-sh")
                                    .value_name("DIR_SHELL")
                                    .help("directory storing jobs shell scripts.")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("config")
                                    .short("c")
                                    .long("config")
                                    .value_name("FILE")
                                    .help("Sets a custom config file")
                                    .takes_value(true))
                        .get_matches();

    // We can find out whether or not debugging was turned on
    if matches.is_present("debug") {
        println!("Debugging is turned on");
    }

    // If we wanted to some custom initialization based off some configuration file provided
    // by the user, we could get the file (A string of the file)
    if let Some(ref file) = matches.value_of("config") {
        println!("Using config file: {}", file);
    }
    if let Some(ref env) = matches.value_of("env") {
        println!("Using config file: {}", env);
    }
    // Continued program logic goes here...
    loader::deligate(matches)

}
<commit_msg>expanded soem rust<commit_after>use clap::Arg;
use clap::App;
use loader;

pub fn cli_clap() {

    // Once all App settings (including all arguments) have been set, you call get_matches() which
    // parses the string provided by the user, and returns all the valid matches to the ones you
    // specified.
    //
    // You can then query the matches struct to get information about how the user ran the program
    // at startup.
    //
    // For this example, let's assume you created an App which accepts three arguments (plus two
    // generated by clap), a flag to display debugging information triggered with "-d" or
    // "--debug" as well as an option argument which specifies a custom configuration file to use
    // triggered with "-c file" or "--config file" or "--config=file" and finally a positional
    // argument which is the input file we want to work with, this will be the only required
    // argument.
    let application = App::new("whenenv")
                        .about("Parses an input file to do awesome things")
                        .version("0.0.1")
                        .author("Owen Synge <osynge@googlemail.com>")
                        .arg(Arg::with_name("verbose")
                                    .help("Increase log output.")
                                    .short("v")
                                    .multiple(true)
                                    .long("verbose"))
                        .arg(Arg::with_name("quiet")
                                    .help("Decrease log output.")
                                    .short("q")
                                    .multiple(true)
                                    .long("quiet"))
                        .arg(Arg::with_name("env")
                                    .short("e")
                                    .long("env")
                                    .value_name("ENVIROMENT_VARIABLE")
                                    .help("Which enviroment variables to process")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("dir-jobs")
                                    .long("dir-jobs")
                                    .value_name("DIR_JOB")
                                    .help("directory storing json jobs.")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("dir-sh")
                                    .long("dir-sh")
                                    .value_name("DIR_SHELL")
                                    .help("directory storing jobs shell scripts.")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("config")
                                    .short("c")
                                    .long("config")
                                    .value_name("FILE")
                                    .help("Sets a custom config file")
                                    .takes_value(true));
    let matches = application.get_matches();

    // We can find out whether or not debugging was turned on
    if matches.is_present("debug") {
        println!("Debugging is turned on");
    }

    // If we wanted to some custom initialization based off some configuration file provided
    // by the user, we could get the file (A string of the file)
    if let Some(ref file) = matches.value_of("config") {
        println!("Using config file: {}", file);
    }
    if let Some(ref env) = matches.value_of("env") {
        println!("Using config file: {}", env);
    }
    // Continued program logic goes here...
    loader::deligate(matches);
}
<|endoftext|>


<commit_before>use na::{self, Isometry2, Vector2};
use ncollide2d::query;
use ncollide2d::shape::{Ball, Cuboid};

#[test]
fn ball_cuboid_toi() {
    let cuboid = Cuboid::new(Vector2::new(1.0, 1.0));
    let ball = Ball::new(1.0);

    let cuboid_pos = Isometry2::identity();
    let ball_pos_intersecting = Isometry2::new(Vector2::new(1.0, 1.0), na::zero());
    let ball_pos_will_touch = Isometry2::new(Vector2::new(2.0, 2.0), na::zero());
    let ball_pos_wont_touch = Isometry2::new(Vector2::new(3.0, 3.0), na::zero());

    let box_vel1 = Vector2::new(-1.0, 1.0);
    let box_vel2 = Vector2::new(1.0, 1.0);

    let ball_vel1 = Vector2::new(2.0, 2.0);
    let ball_vel2 = Vector2::new(-0.5, -0.5);

    let toi_intersecting = query::time_of_impact(
        &ball_pos_intersecting,
        &ball_vel1,
        &ball,
        &cuboid_pos,
        &box_vel1,
        &cuboid,
    );
    let toi_will_touch = query::time_of_impact(
        &ball_pos_will_touch,
        &ball_vel2,
        &ball,
        &cuboid_pos,
        &box_vel2,
        &cuboid,
    );
    let toi_wont_touch = query::time_of_impact(
        &ball_pos_wont_touch,
        &ball_vel1,
        &ball,
        &cuboid_pos,
        &box_vel1,
        &cuboid,
    );

    assert_eq!(toi_intersecting, Some(0.0));
    assert!(relative_eq!(
        toi_will_touch.unwrap(),
        (2.0_f32.sqrt() - 1.0) / (ball_vel2 - box_vel2).norm()
    ));
    assert_eq!(toi_wont_touch, None);
}
<commit_msg>Add test for issue #214.<commit_after>use na::{self, Isometry2, Vector2};
use ncollide2d::query;
use ncollide2d::shape::{Ball, Cuboid};

#[test]
fn ball_cuboid_toi() {
    let cuboid = Cuboid::new(Vector2::new(1.0, 1.0));
    let ball = Ball::new(1.0);

    let cuboid_pos = Isometry2::identity();
    let ball_pos_intersecting = Isometry2::new(Vector2::new(1.0, 1.0), na::zero());
    let ball_pos_will_touch = Isometry2::new(Vector2::new(2.0, 2.0), na::zero());
    let ball_pos_wont_touch = Isometry2::new(Vector2::new(3.0, 3.0), na::zero());

    let box_vel1 = Vector2::new(-1.0, 1.0);
    let box_vel2 = Vector2::new(1.0, 1.0);

    let ball_vel1 = Vector2::new(2.0, 2.0);
    let ball_vel2 = Vector2::new(-0.5, -0.5);

    let toi_intersecting = query::time_of_impact(
        &ball_pos_intersecting,
        &ball_vel1,
        &ball,
        &cuboid_pos,
        &box_vel1,
        &cuboid,
    );
    let toi_will_touch = query::time_of_impact(
        &ball_pos_will_touch,
        &ball_vel2,
        &ball,
        &cuboid_pos,
        &box_vel2,
        &cuboid,
    );
    let toi_wont_touch = query::time_of_impact(
        &ball_pos_wont_touch,
        &ball_vel1,
        &ball,
        &cuboid_pos,
        &box_vel1,
        &cuboid,
    );

    assert_eq!(toi_intersecting, Some(0.0));
    assert!(relative_eq!(
        toi_will_touch.unwrap(),
        (2.0_f32.sqrt() - 1.0) / (ball_vel2 - box_vel2).norm()
    ));
    assert_eq!(toi_wont_touch, None);
}

#[test]
fn cuboid_cuboid_toi_issue_214() {
    let shape1 = Cuboid::new(Vector2::new(1.0, 1.0));
    let shape2 = Cuboid::new(Vector2::new(1.0, 1.5));

    let pos1 = Isometry2::new(Vector2::new(0.0, 0.0), na::zero());
    let pos2 = Isometry2::new(Vector2::new(10.0, 0.0), na::zero());

    let vel1 = Vector2::new(1.0, 0.0);
    let vel2 = Vector2::new(0.0, 0.0);

    let toi = query::time_of_impact(&pos1, &vel1, &shape1, &pos2, &vel2, &shape2);
    assert!(toi.is_some());
}
<|endoftext|>


<commit_before>use iced::{canvas, mouse, Canvas, Color, Element, Length, Point, Rectangle, Sandbox, Settings, Vector};
use oppai_field::field::{self, Field, Pos};
use oppai_field::player::Player;
use oppai_field::zobrist::Zobrist;
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;

const SEED: [u8; 16] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53];

const FIELD_WIDTH: u32 = 39;
const FIELD_HEIGHT: u32 = 32;

pub fn main() {
  Game::run(Settings {
    antialiasing: true,
    ..Settings::default()
  });
}

struct Game {
  player: Player,
  field: Field,
  captures: Vec<(Vec<Pos>, Player)>,
}

#[derive(Debug, Clone, Copy)]
enum Message {
  PutPoint(Pos),
}

impl Sandbox for Game {
  type Message = Message;

  fn new() -> Self {
    let mut rng = XorShiftRng::from_seed(SEED);
    let zobrist = Zobrist::new(field::length(FIELD_WIDTH, FIELD_HEIGHT) * 2, &mut rng);
    let field = Field::new(FIELD_WIDTH, FIELD_HEIGHT, std::sync::Arc::new(zobrist));
    Game {
      player: Player::Red,
      field,
      captures: Vec::new(),
    }
  }

  fn title(&self) -> String {
    "OpPAI".into()
  }

  fn update(&mut self, message: Self::Message) {
    let Message::PutPoint(pos) = message;
    if self.field.put_point(pos, self.player) {
      self.player = self.player.next();
      let last_chain = self.field.get_last_chain();
      if let Some(&pos) = last_chain.first() {
        let player = self.field.cell(pos).get_player();
        self.captures.push((last_chain, player));
      }
    }
  }

  fn view(&mut self) -> iced::Element<'_, Self::Message> {
    let canvas = Canvas::new(self).height(Length::Fill).width(Length::Fill);
    Element::<Pos>::from(canvas).map(Message::PutPoint)
  }
}

impl canvas::Program<Pos> for Game {
  fn update(&mut self, event: canvas::Event, bounds: Rectangle, cursor: canvas::Cursor) -> Option<Pos> {
    let cursor_position = cursor.position_in(&bounds)?;
    let canvas::Event::Mouse(mouse_event) = event;
    match mouse_event {
      mouse::Event::ButtonPressed(mouse::Button::Left) => {
        let field_width = self.field.width();
        let field_height = self.field.height();
        let width = bounds
          .width
          .min(bounds.height / field_height as f32 * field_width as f32);
        let height = bounds
          .height
          .min(bounds.width / field_width as f32 * field_height as f32);
        let step_x = width / field_width as f32;
        let step_y = height / field_height as f32;
        let shift = Vector::new(
          ((bounds.width - width) / 2.0).round() + step_x / 2.0,
          ((bounds.height - height) / 2.0).round() + step_y / 2.0,
        );

        let point = cursor_position - shift;
        if point.x >= 0.0 && point.x <= width && point.y >= 0.0 && point.y <= height {
          let x = (point.x / step_x).round() as u32;
          let y = (point.y / step_y).round() as u32;
          Some(self.field.to_pos(x, y))
        } else {
          None
        }
      }
      _ => None,
    }
  }

  fn draw(&self, bounds: Rectangle, _cursor: canvas::Cursor) -> Vec<canvas::Geometry> {
    let mut frame = canvas::Frame::new(bounds.size());

    let field_width = self.field.width();
    let field_height = self.field.height();
    let width = frame
      .width()
      .min(frame.height() / field_height as f32 * field_width as f32);
    let height = frame
      .height()
      .min(frame.width() / field_width as f32 * field_height as f32);
    let step_x = width / field_width as f32;
    let step_y = height / field_height as f32;
    let shift = Vector::new(
      ((frame.width() - width) / 2.0).round(),
      ((frame.height() - height) / 2.0).round(),
    );

    let grid = canvas::Path::new(|path| {
      for x in 0..field_width {
        let offset = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
        path.move_to(Point::new(offset, 0.0) + shift);
        path.line_to(Point::new(offset, height) + shift);
      }
      for y in 0..field_height {
        let offset = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
        path.move_to(Point::new(0.0, offset) + shift);
        path.line_to(Point::new(width, offset) + shift);
      }
    });

    frame.stroke(
      &grid,
      canvas::Stroke {
        width: 1.0,
        color: Color::BLACK,
        ..canvas::Stroke::default()
      },
    );

    fn color(player: Player) -> Color {
      match player {
        Player::Red => Color::from_rgb8(0xFF, 0x00, 0x00),
        Player::Black => Color::BLACK,
      }
    }

    let pos_to_point = |pos: Pos| {
      let x = self.field.to_x(pos);
      let y = self.field.to_y(pos);
      let offset_x = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
      let offset_y = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
      Point::new(offset_x, offset_y) + shift
    };

    for &player in &[Player::Red, Player::Black] {
      let points = canvas::Path::new(|path| {
        for &pos in self
          .field
          .points_seq()
          .iter()
          .filter(|&&pos| self.field.cell(pos).is_players_point(player))
        {
          path.circle(pos_to_point(pos), 5.0)
        }
      });

      frame.fill(&points, color(player));
    }

    for (chain, player) in &self.captures {
      let path = canvas::Path::new(|path| {
        path.move_to(pos_to_point(chain[0]));
        for &pos in chain.iter().skip(1) {
          path.line_to(pos_to_point(pos));
        }
      });

      let mut color = color(*player);
      color.a = 0.5;

      frame.fill(&path, color);
    }

    vec![frame.into_geometry()]
  }
}
<commit_msg>Draw cursor point.<commit_after>use iced::{canvas, mouse, Canvas, Color, Element, Length, Point, Rectangle, Sandbox, Settings, Vector};
use oppai_field::field::{self, Field, Pos};
use oppai_field::player::Player;
use oppai_field::zobrist::Zobrist;
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;

const SEED: [u8; 16] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53];

const FIELD_WIDTH: u32 = 39;
const FIELD_HEIGHT: u32 = 32;

pub fn main() {
  Game::run(Settings {
    antialiasing: true,
    ..Settings::default()
  });
}

struct Game {
  player: Player,
  field: Field,
  captures: Vec<(Vec<Pos>, Player)>,
}

#[derive(Debug, Clone, Copy)]
enum Message {
  PutPoint(Pos),
}

impl Sandbox for Game {
  type Message = Message;

  fn new() -> Self {
    let mut rng = XorShiftRng::from_seed(SEED);
    let zobrist = Zobrist::new(field::length(FIELD_WIDTH, FIELD_HEIGHT) * 2, &mut rng);
    let field = Field::new(FIELD_WIDTH, FIELD_HEIGHT, std::sync::Arc::new(zobrist));
    Game {
      player: Player::Red,
      field,
      captures: Vec::new(),
    }
  }

  fn title(&self) -> String {
    "OpPAI".into()
  }

  fn update(&mut self, message: Self::Message) {
    let Message::PutPoint(pos) = message;
    if self.field.put_point(pos, self.player) {
      self.player = self.player.next();
      let last_chain = self.field.get_last_chain();
      if let Some(&pos) = last_chain.first() {
        let player = self.field.cell(pos).get_player();
        self.captures.push((last_chain, player));
      }
    }
  }

  fn view(&mut self) -> iced::Element<'_, Self::Message> {
    let canvas = Canvas::new(self).height(Length::Fill).width(Length::Fill);
    Element::<Pos>::from(canvas).map(Message::PutPoint)
  }
}

impl canvas::Program<Pos> for Game {
  fn update(&mut self, event: canvas::Event, bounds: Rectangle, cursor: canvas::Cursor) -> Option<Pos> {
    let cursor_position = cursor.position_in(&bounds)?;
    let canvas::Event::Mouse(mouse_event) = event;
    match mouse_event {
      mouse::Event::ButtonPressed(mouse::Button::Left) => {
        let field_width = self.field.width();
        let field_height = self.field.height();
        let width = bounds
          .width
          .min(bounds.height / field_height as f32 * field_width as f32);
        let height = bounds
          .height
          .min(bounds.width / field_width as f32 * field_height as f32);
        let step_x = width / field_width as f32;
        let step_y = height / field_height as f32;
        let shift = Vector::new(
          ((bounds.width - width) / 2.0).round() + step_x / 2.0,
          ((bounds.height - height) / 2.0).round() + step_y / 2.0,
        );

        let point = cursor_position - shift;
        if point.x >= 0.0 && point.x <= width && point.y >= 0.0 && point.y <= height {
          let x = (point.x / step_x).round() as u32;
          let y = (point.y / step_y).round() as u32;
          Some(self.field.to_pos(x, y))
        } else {
          None
        }
      }
      _ => None,
    }
  }

  fn draw(&self, bounds: Rectangle, cursor: canvas::Cursor) -> Vec<canvas::Geometry> {
    let mut frame = canvas::Frame::new(bounds.size());

    let field_width = self.field.width();
    let field_height = self.field.height();
    let width = frame
      .width()
      .min(frame.height() / field_height as f32 * field_width as f32);
    let height = frame
      .height()
      .min(frame.width() / field_width as f32 * field_height as f32);
    let step_x = width / field_width as f32;
    let step_y = height / field_height as f32;
    let shift = Vector::new(
      ((frame.width() - width) / 2.0).round(),
      ((frame.height() - height) / 2.0).round(),
    );

    let grid = canvas::Path::new(|path| {
      for x in 0..field_width {
        let offset = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
        path.move_to(Point::new(offset, 0.0) + shift);
        path.line_to(Point::new(offset, height) + shift);
      }
      for y in 0..field_height {
        let offset = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
        path.move_to(Point::new(0.0, offset) + shift);
        path.line_to(Point::new(width, offset) + shift);
      }
    });

    frame.stroke(
      &grid,
      canvas::Stroke {
        width: 1.0,
        color: Color::BLACK,
        ..canvas::Stroke::default()
      },
    );

    fn color(player: Player) -> Color {
      match player {
        Player::Red => Color::from_rgb8(0xFF, 0x00, 0x00),
        Player::Black => Color::BLACK,
      }
    }

    let xy_to_point = |x: u32, y: u32| {
      let offset_x = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
      let offset_y = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
      Point::new(offset_x, offset_y) + shift
    };
    let pos_to_point = |pos: Pos| {
      let x = self.field.to_x(pos);
      let y = self.field.to_y(pos);
      xy_to_point(x, y)
    };

    for &player in &[Player::Red, Player::Black] {
      let points = canvas::Path::new(|path| {
        for &pos in self
          .field
          .points_seq()
          .iter()
          .filter(|&&pos| self.field.cell(pos).is_players_point(player))
        {
          path.circle(pos_to_point(pos), 5.0)
        }
      });

      frame.fill(&points, color(player));
    }

    for (chain, player) in &self.captures {
      let path = canvas::Path::new(|path| {
        path.move_to(pos_to_point(chain[0]));
        for &pos in chain.iter().skip(1) {
          path.line_to(pos_to_point(pos));
        }
      });

      let mut color = color(*player);
      color.a = 0.5;

      frame.fill(&path, color);
    }

    if let Some(point) = cursor.position().and_then(|c| {
      let point = c - shift - Vector::new(step_x / 2.0, step_y / 2.0);
      if point.x >= 0.0 && point.x <= width && point.y >= 0.0 && point.y <= height {
        let x = (point.x / step_x).round() as u32;
        let y = (point.y / step_y).round() as u32;
        let pos = self.field.to_pos(x, y);
        if self.field.is_putting_allowed(pos) {
          Some(xy_to_point(x, y))
        } else {
          None
        }
      } else {
        None
      }
    }) {
      let cursor_point = canvas::Path::new(|path| path.circle(point, 5.0));

      let mut color = color(self.player);
      color.a = 0.5;

      frame.fill(&cursor_point, color);
    }

    vec![frame.into_geometry()]
  }
}
<|endoftext|>


<commit_before>//! Module for detecting available physical memory
//!
//! Get memory map at boot time and use it construct `RegionMap`s.
//! The BIOS calls needed have to run before we switch to protected mode,

use alloc::vec::Vec;

use core::iter::Iterator;

use super::physmem::Frame;

extern "C" {
    static memory_map_count: u32;
    static memory_map: [MemoryListEntry; 20];
}

/// Represents an entry in the list of memory regions generated by the E820
/// BIOS call.
#[repr(C, packed)]
struct MemoryListEntry {
    base_l: u32,
    base_h: u32,
    length_l: u32,
    length_h: u32,
    region_type: u32,
    acpi: u32, // extended
}

/// Represents a region of memory
struct Region {
    start: usize,
    end: usize,
    usable: bool,
}

/// Represents a map of memory regions
pub struct RegionMap {
    list: Vec<Region>,
    index: usize,
}

/// Find the length and type of the most restrictive
/// mapping for `addr` based on the E820 BIOS call
fn find(addr: usize) -> Option<(usize, usize)> {
    let mut most = 0;
    let mut length = 0;
    let mut region_start = 0;
    unsafe {
        for i in 0..(memory_map_count as usize) {
            let start = memory_map[i].base_l as usize;
            let end = if memory_map[i].base_l == 0 {
                (memory_map[i].base_l + memory_map[i].length_l) - 1
            } else {
                (memory_map[i].base_l - 1) + memory_map[i].length_l
            } as usize;
            let region_type = memory_map[i].region_type as usize;

            if start <= addr && addr <= end && region_type > most {
                length = end - start;
                most = region_type;
                region_start = start;
                if most > 1 {
                    break;
                }
            }
        }
    }

    if most == 0 {
        // not found
        None
    } else {
        Some((length + 1 - (addr - region_start), most))
    }
}

/// Find the beginning address of the next region of memory
/// based on the E820 BIOS call
fn find_next(addr: usize) -> usize {
    let mut least = 0xFFFF_FFFF;
    unsafe {
        for i in 0..(memory_map_count as usize) {
            let start = memory_map[i].base_l as usize;

            if addr < start && start < least {
                least = start;
            }
        }
    }

    least - 1
}

impl Region {
    /// Print this region for debugging purposes
    #[allow(dead_code)]
    pub fn dump(&self) {
        bootlog!(
            "0x{:08X} - 0x{:08X} : {}\n",
            self.start,
            self.end,
            if self.usable { "usable" } else { "reserved" }
        );
    }
}

impl RegionMap {
    /// Produce a map of all memory after start.
    /// This is a 32-bit OS, so we only have to deal with 4GB
    pub fn new(start_frame: *mut Frame) -> RegionMap {
        // starting at start, check if there is an available
        // memory region and add a mapping for it.

        let mut start = start_frame as usize;

        let mut rlist = Vec::new();

        loop {
            let end;

            let region = if let Some((length, region_type)) = find(start) {
                // avoid overflow and underflow
                end = if start == 0 {
                    (start + length) - 1
                } else {
                    (start - 1) + length
                };
                // bootlog!("--{:x},{:x}==\n",start, length);

                Region {
                    start: start,
                    end: end,
                    usable: region_type == 1,
                }
            } else {
                end = find_next(start);
                // bootlog!("--{:x},{:x}==\n",start, end - start + 1);

                Region {
                    start: start,
                    end: end,
                    usable: false,
                }
            };

            rlist.push(region);

            if end < 0xFFFF_FFFF {
                start = end + 1;
            } else {
                break;
            }
        }

        RegionMap {
            list: rlist,
            index: 0,
        }
    }

    /// Print out the memory map for debugging purposes
    #[allow(dead_code)]
    pub fn dump(&self) {
        for i in 0..self.list.len() {
            self.list[i].dump();
        }
    }
}

/// Make `RegionMap` iterable for convenience
impl Iterator for RegionMap {
    type Item = (usize, usize);

    /// Returns the index of the next avail frame and number of
    /// available frames OR None if there aren't any more.
    fn next(&mut self) -> Option<(usize, usize)> {
        // start and end region indices
        let mut start = self.index;
        let mut end;

        // find the next usable region
        while start < self.list.len() && !self.list[start].usable {
            start += 1;
        }

        // end of list
        if start == self.list.len() {
            return None;
        }

        // find as many contiguous usable regions as possible
        end = start + 1;

        while end < self.list.len() && self.list[end].usable {
            end += 1;
        }

        // update index
        self.index = end;

        // generate bounds
        let f_start = self.list[start].start;
        let f_end = self.list[end - 1].end;

        Some((f_start >> 12, (f_end - f_start + 1) >> 12))
    }
}
<commit_msg>Minor refactoring of region map to reduce unsafe code<commit_after>//! Module for detecting available physical memory
//!
//! Get memory map at boot time and use it construct `RegionMap`s.  The BIOS calls needed have to
//! run before we switch to protected mode. In particular, this module assumes that we are using
//! the E820 BIOS call, which is pretty commonly used.

use alloc::vec::Vec;

use core::iter::Iterator;

use super::physmem::Frame;

extern "C" {
    static memory_map_count: u32;
    static memory_map: [MemoryListEntry; 20];
}

/// Represents an entry in the list of memory regions generated by the E820 BIOS call
#[repr(C, packed)]
struct MemoryListEntry {
    base_l: u32,
    base_h: u32,
    length_l: u32,
    length_h: u32,
    region_type: u32,
    acpi: u32, // extended
}

/// Represents a region of memory
struct Region {
    start: usize,
    end: usize,
    usable: bool,
}

/// An interable map of memory regions
pub struct RegionMap {
    list: Vec<Region>,
    index: usize,
}

/// Add two 32-bit integers and subtract 1 while avoiding over/underflows. Note that at least one
/// of the numbers must be non-zero.
fn add_sub_no_ovflw(a: u32, b: u32) -> u32 {
    if a == 0 && b == 0 {
        panic!("Attempt to subtract would result in underflow");
    }

    if a == 0 {
        (a + b) - 1
    } else {
        (a - 1) + b
    }
}

/// Find the length and type of the most restrictive mapping for `addr` based on the E820 BIOS
/// call. There might be multiple mappings for an address, so we need to check them all.
fn find(addr: usize) -> Option<(usize, usize)> {
    let mmlen = unsafe { memory_map_count } as usize;

    let mut most = 0;
    let mut length = 0;
    let mut region_start = 0;

    for i in 0..mmlen {
        let start = unsafe { memory_map[i].base_l };
        let base_l = unsafe { memory_map[i].base_l };
        let len_l = unsafe { memory_map[i].length_l };
        let end = add_sub_no_ovflw(base_l, len_l);
        let region_type = unsafe { memory_map[i].region_type };

        if (start as usize) <= addr && addr <= (end as usize) && region_type > most {
            length = end - start;
            most = region_type;
            region_start = start;
            if most > 1 {
                break;
            }
        }
    }

    // Make everything a usize for convenience
    let most = most as usize;
    let length = length as usize;
    let region_start = region_start as usize;

    if most == 0 {
        // not found
        None
    } else {
        Some((length + 1 - (addr - region_start), most))
    }
}

/// Find the beginning address of the next region of memory based on the E820 BIOS call
fn find_next(addr: usize) -> usize {
    unsafe { &memory_map }
        .iter()
        .take(unsafe { memory_map_count } as usize)
        .filter_map(|entry| {
            let start = entry.base_l as usize;
            if addr < start {
                Some(start - 1)
            } else {
                None
            }
        })
        .min()
        .unwrap_or(0xFFFF_FFFF)
}

impl Region {
    /// Print this region for debugging purposes
    #[allow(dead_code)]
    pub fn dump(&self) {
        bootlog!(
            "0x{:08X} - 0x{:08X} : {}\n",
            self.start,
            self.end,
            if self.usable { "usable" } else { "reserved" }
        );
    }
}

impl RegionMap {
    /// Produce a map of all memory after `start_frame`. This is a 32-bit OS, so we only have to
    /// deal with 4GB.
    pub fn new(start_frame: *mut Frame) -> RegionMap {
        // starting at start, check if there is an available
        // memory region and add a mapping for it.

        let mut start = start_frame as usize;

        let mut rlist = Vec::new();

        loop {
            let end;

            let region = if let Some((length, region_type)) = find(start) {
                // avoid overflow and underflow
                end = if start == 0 {
                    (start + length) - 1
                } else {
                    (start - 1) + length
                };
                // bootlog!("--{:x},{:x}==\n",start, length);

                Region {
                    start: start,
                    end: end,
                    usable: region_type == 1,
                }
            } else {
                end = find_next(start);
                // bootlog!("--{:x},{:x}==\n",start, end - start + 1);

                Region {
                    start: start,
                    end: end,
                    usable: false,
                }
            };

            rlist.push(region);

            if end < 0xFFFF_FFFF {
                start = end + 1;
            } else {
                break;
            }
        }

        RegionMap {
            list: rlist,
            index: 0,
        }
    }

    /// Print out the memory map for debugging purposes
    #[allow(dead_code)]
    pub fn dump(&self) {
        for i in 0..self.list.len() {
            self.list[i].dump();
        }
    }
}

/// Make `RegionMap` iterable for convenience
impl Iterator for RegionMap {
    type Item = (usize, usize);

    /// Returns the index of the next avail frame and number of available frames OR None if there
    /// aren't any more.
    fn next(&mut self) -> Option<(usize, usize)> {
        // start and end region indices
        let mut start = self.index;
        let mut end;

        // find the next usable region
        while start < self.list.len() && !self.list[start].usable {
            start += 1;
        }

        // end of list
        if start == self.list.len() {
            return None;
        }

        // find as many contiguous usable regions as possible
        end = start + 1;

        while end < self.list.len() && self.list[end].usable {
            end += 1;
        }

        // update index
        self.index = end;

        // generate bounds
        let f_start = self.list[start].start;
        let f_end = self.list[end - 1].end;

        Some((f_start >> 12, (f_end - f_start + 1) >> 12))
    }
}
<|endoftext|>


<commit_before>//! Tools to control view alignment.

/// Specifies the alignment along both horizontal and vertical directions.
#[derive(Debug)]
pub struct Align {
    /// Horizontal alignment policy
    pub h: HAlign,
    /// Vertical alignment policy
    pub v: VAlign,
}

impl Align {
    /// Creates a new Align object from the given alignments.
    pub fn new(h: HAlign, v: VAlign) -> Self {
        Align { h, v }
    }

    /// Creates a top-left alignment.
    pub fn top_left() -> Self {
        Align::new(HAlign::Left, VAlign::Top)
    }

    /// Creates a top-right alignment.
    pub fn top_right() -> Self {
        Align::new(HAlign::Right, VAlign::Top)
    }

    /// Creates a top-center alignment.
    pub fn top_center() -> Self {
        Align::new(HAlign::Center, VAlign::Top)
    }

    /// Creates a bottom-left alignment.
    pub fn bot_left() -> Self {
        Align::new(HAlign::Left, VAlign::Bottom)
    }

    /// Creates a bottom-right alignment.
    pub fn bot_right() -> Self {
        Align::new(HAlign::Right, VAlign::Top)
    }

    /// Creates a bottom-center alignment.
    pub fn bot_center() -> Self {
        Align::new(HAlign::Center, VAlign::Bottom)
    }

    /// Creates a center-right alignment.
    pub fn center_left() -> Self {
        Align::new(HAlign::Left, VAlign::Center)
    }

    /// Creates a center-right alignment.
    pub fn center_right() -> Self {
        Align::new(HAlign::Right, VAlign::Center)
    }

    /// Creates an alignment centered both horizontally and vertically.
    pub fn center() -> Self {
        Align::new(HAlign::Center, VAlign::Center)
    }
}

/// Horizontal alignment
#[derive(Debug)]
pub enum HAlign {
    /// Place the element to the left of available space
    Left,
    /// Place the element horizontally in the center of available space
    Center,
    /// Place the element to the right of available space
    Right,
}

/// Vertical alignment
#[derive(Debug)]
pub enum VAlign {
    /// Place the element at the top of available space
    Top,
    /// Place the element vertically in the center of available space
    Center,
    /// Place the element at the bottom of available space
    Bottom,
}

impl HAlign {
    /// Returns the offset required to position a view.
    ///
    /// When drawing a view with size `content` when the available size is
    /// `container`, printing at the resulting offset will align the view as
    /// desired.
    pub fn get_offset(&self, content: usize, container: usize) -> usize {
        if container < content {
            0
        } else {
            match *self {
                HAlign::Left => 0,
                HAlign::Center => (container - content) / 2,
                HAlign::Right => (container - content),
            }
        }
    }
}

impl VAlign {
    /// Returns the offset required to position a view.
    ///
    /// When drawing a view with size `content` when the available size is
    /// `container`, printing at the resulting offset will align the view as
    /// desired.
    pub fn get_offset(&self, content: usize, container: usize) -> usize {
        if container < content {
            0
        } else {
            match *self {
                VAlign::Top => 0,
                VAlign::Center => (container - content) / 2,
                VAlign::Bottom => (container - content),
            }
        }
    }
}
<commit_msg>Derive Clone+Copy for Align, HAlign, VAlign (#469)<commit_after>//! Tools to control view alignment.

/// Specifies the alignment along both horizontal and vertical directions.
#[derive(Debug, Clone, Copy)]
pub struct Align {
    /// Horizontal alignment policy
    pub h: HAlign,
    /// Vertical alignment policy
    pub v: VAlign,
}

impl Align {
    /// Creates a new Align object from the given alignments.
    pub fn new(h: HAlign, v: VAlign) -> Self {
        Align { h, v }
    }

    /// Creates a top-left alignment.
    pub fn top_left() -> Self {
        Align::new(HAlign::Left, VAlign::Top)
    }

    /// Creates a top-right alignment.
    pub fn top_right() -> Self {
        Align::new(HAlign::Right, VAlign::Top)
    }

    /// Creates a top-center alignment.
    pub fn top_center() -> Self {
        Align::new(HAlign::Center, VAlign::Top)
    }

    /// Creates a bottom-left alignment.
    pub fn bot_left() -> Self {
        Align::new(HAlign::Left, VAlign::Bottom)
    }

    /// Creates a bottom-right alignment.
    pub fn bot_right() -> Self {
        Align::new(HAlign::Right, VAlign::Top)
    }

    /// Creates a bottom-center alignment.
    pub fn bot_center() -> Self {
        Align::new(HAlign::Center, VAlign::Bottom)
    }

    /// Creates a center-right alignment.
    pub fn center_left() -> Self {
        Align::new(HAlign::Left, VAlign::Center)
    }

    /// Creates a center-right alignment.
    pub fn center_right() -> Self {
        Align::new(HAlign::Right, VAlign::Center)
    }

    /// Creates an alignment centered both horizontally and vertically.
    pub fn center() -> Self {
        Align::new(HAlign::Center, VAlign::Center)
    }
}

/// Horizontal alignment
#[derive(Debug, Clone, Copy)]
pub enum HAlign {
    /// Place the element to the left of available space
    Left,
    /// Place the element horizontally in the center of available space
    Center,
    /// Place the element to the right of available space
    Right,
}

/// Vertical alignment
#[derive(Debug, Clone, Copy)]
pub enum VAlign {
    /// Place the element at the top of available space
    Top,
    /// Place the element vertically in the center of available space
    Center,
    /// Place the element at the bottom of available space
    Bottom,
}

impl HAlign {
    /// Returns the offset required to position a view.
    ///
    /// When drawing a view with size `content` when the available size is
    /// `container`, printing at the resulting offset will align the view as
    /// desired.
    pub fn get_offset(&self, content: usize, container: usize) -> usize {
        if container < content {
            0
        } else {
            match *self {
                HAlign::Left => 0,
                HAlign::Center => (container - content) / 2,
                HAlign::Right => (container - content),
            }
        }
    }
}

impl VAlign {
    /// Returns the offset required to position a view.
    ///
    /// When drawing a view with size `content` when the available size is
    /// `container`, printing at the resulting offset will align the view as
    /// desired.
    pub fn get_offset(&self, content: usize, container: usize) -> usize {
        if container < content {
            0
        } else {
            match *self {
                VAlign::Top => 0,
                VAlign::Center => (container - content) / 2,
                VAlign::Bottom => (container - content),
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

extern crate word_count;

fn check_word_count(s: &str, pairs: Vec<(&str, u32)>) {
    // The reason for the awkward code in here is to ensure that the failure
    // message for assert_eq! is as informative as possible. A simpler
    // solution would simply check the length of the map, and then
    // check for the presence and value of each key in the given pairs vector.
    let mut m: HashMap<String, u32> = word_count::word_count(s);
    for &(k, v) in pairs.iter() {
        assert_eq!((k, m.remove(&k.to_string()).unwrap_or(0)), (k, v));
    }
    // may fail with a message that clearly shows all extra pairs in the map
    assert_eq!(m.iter().collect::<Vec<(&String,&u32)>>(), vec!());
}

#[test]
fn test_count_one_word() {
    check_word_count("word", vec![("word", 1)]);
}

#[test]
#[ignore]
fn test_count_one_of_each() {
    check_word_count(
        "one of each",
        vec![("one", 1),
             ("of", 1),
             ("each", 1)]);
}

#[test]
#[ignore]
fn test_count_multiple_occurrences() {
    check_word_count(
        "one fish two fish red fish blue fish",
        vec![("one", 1),
             ("fish", 4),
             ("two", 1),
             ("red", 1),
             ("blue", 1)]);
}

#[test]
#[ignore]
fn test_ignore_punctuation() {
    check_word_count(
        "car : carpet as java : javascript!!&@$%^&",
        vec![("car", 1),
             ("carpet", 1),
             ("as", 1),
             ("java", 1),
             ("javascript", 1)]);
}

#[test]
#[ignore]
fn test_include_numbers() {
    check_word_count(
        "testing, 1, 2 testing",
        vec![("testing", 2),
             ("1", 1),
             ("2", 1)]);
}

#[test]
#[ignore]
fn test_normalize_case() {
    check_word_count(
        "go Go GO Stop stop",
        vec![("go", 3),
             ("stop", 2)]);
}
<commit_msg>word-count: Use &[T] instead of &Vec<T><commit_after>use std::collections::HashMap;

extern crate word_count;

fn check_word_count(s: &str, pairs: &[(&str, u32)]) {
    // The reason for the awkward code in here is to ensure that the failure
    // message for assert_eq! is as informative as possible. A simpler
    // solution would simply check the length of the map, and then
    // check for the presence and value of each key in the given pairs vector.
    let mut m: HashMap<String, u32> = word_count::word_count(s);
    for &(k, v) in pairs.iter() {
        assert_eq!((k, m.remove(&k.to_string()).unwrap_or(0)), (k, v));
    }
    // may fail with a message that clearly shows all extra pairs in the map
    assert_eq!(m.iter().collect::<Vec<(&String,&u32)>>(), vec!());
}

#[test]
fn test_count_one_word() {
    check_word_count("word", &[("word", 1)]);
}

#[test]
#[ignore]
fn test_count_one_of_each() {
    check_word_count(
        "one of each",
        &[("one", 1),
          ("of", 1),
          ("each", 1)]);
}

#[test]
#[ignore]
fn test_count_multiple_occurrences() {
    check_word_count(
        "one fish two fish red fish blue fish",
        &[("one", 1),
          ("fish", 4),
          ("two", 1),
          ("red", 1),
          ("blue", 1)]);
}

#[test]
#[ignore]
fn test_ignore_punctuation() {
    check_word_count(
        "car : carpet as java : javascript!!&@$%^&",
        &[("car", 1),
          ("carpet", 1),
          ("as", 1),
          ("java", 1),
          ("javascript", 1)]);
}

#[test]
#[ignore]
fn test_include_numbers() {
    check_word_count(
        "testing, 1, 2 testing",
        &[("testing", 2),
          ("1", 1),
          ("2", 1)]);
}

#[test]
#[ignore]
fn test_normalize_case() {
    check_word_count(
        "go Go GO Stop stop",
        &[("go", 3),
          ("stop", 2)]);
}
<|endoftext|>