<commit_before>#![crate_id = "base58"]
#![crate_type = "rlib"]
#![license = "Apache License, Version 2.0"]
#![deny(missing_doc)]

//! Rust-Base58 provides functions to encode and decode base58 values.

static BASE_256:u16 = 256;
static BASE_58:u16 = 58;

/// Encode a String into base58 String.
pub fn encode_base58 (input: String) -> String {
  let mut copied = input.into_bytes();
  let mut output:Vec<u8> = vec!();
  let len = copied.len();

  if len == 0 {
    return String::new();
  }

  let mut count = 0;
  while count < len {
    let modulo = divide_mode58(&mut copied, count);
    let letter = from_alphabet(modulo);
    output.push(letter);

    if *copied.get(count) == 0 {
      count += 1;
    }
  }

  output.reverse();

  match String::from_utf8(output) {
    Ok(result) => result,
    Err(e) => fail!(e)
  }
}

/// Give the letter from the base58 alphabet
fn from_alphabet(position: u16) -> u8 {
  "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".char_at(position as uint) as u8
}

/// This function make the division of a big number stored in a Vec
/// and returns the modulo of the division.
/// The given Vec is modified and becomes the result of the division.
fn divide_mode58(input: &mut Vec<u8>, start: uint) -> u16 {
  let mut remainder = 0;

  for x in input.mut_iter().skip(start) {
    let num_base256: u16 = (*x as u16) & 0xFF;
    let temp = remainder * BASE_256 + num_base256;
    *x = (temp / BASE_58) as u8;
    remainder = temp % BASE_58;
  }

  remainder
}

#[cfg(test)] // TODO Put this test to test.rs file
mod bench {
  extern crate test;
  use self::test::Bencher;
  use super::encode_base58;

  #[bench]
  fn encode_lorem_ispum(b: &mut Bencher) {
    b.iter(|| encode_base58(String::from_str("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")));
  }
}

#[cfg(test)]
mod tests {
  mod tests_encode_base58 {

    use super::super::encode_base58;

    #[test] // TODO Put this test to test.rs file
    fn should_encode_from_string_to_base58_string() {
      // Given
      let empty = String::from_str("");
      let azerty = String::from_str("azerty");
      let lorem = String::from_str("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");

      // When
      let empty_encoded = encode_base58(empty);
      let azerty_encoded = encode_base58(azerty);
      let lorem_encoded = encode_base58(lorem);

      // Then
      assert_eq!(empty_encoded, String::from_str(""));
      assert_eq!(azerty_encoded, String::from_str("qYPmmAqv"));
      assert_eq!(lorem_encoded, String::from_str("RKDitRLwUhnQCAmM9hhenQXRAiKrL3ByvJ4CYouvhmw6yV8fapqyM95bN6KQVJbKvEN3uHeMdP9G7b5HNxmwRGqGibzcjrKaRLL2Nn1GFZRRv2Q8AvQU7MtRagLLzcZcwBDzkMqEpbRy9CvGr3BE7t2rH4wXmdExSGNKqV5XxAG7QT2S4ZQ4nzom8QFmoUgkfj8ykPye3z8FU9gJzSf2cDRA1ecYwFJtNdycgKTYCQ92pcfq95DoWfTBhnJfkKZXe1Dv3guVKk5otHz4XtWFJjcSC2GLrkRhTAEtgkySmaePs5YyoQHKb8PU5paS3dxAWc7sV5rqwrJbSbj7ybK6FQDN2mgbBxy7Wc7CnX6Q3Jm4B8cmo4oGixuHKdufABEs4FM3PAhF5CTk9xFsyw3CVJGxE2sMyC5EKnAv5Zc4kGfzzTxQe7VZrm188XqGZKZVRhjSW9CeceAf9bvqefLahgGiKps13595WSErpo1HpHb6Qt22QLSMJFGB2Aq7asXXUj55wPxCfVCz8NiqewcNpxF9bvjW9xsaMGqgD4dpgrBFzUw6irds1X481DHnRDi98yAhQJVUoxP8WSm3qJ93qhq8Hx7Eg4aiy"));
    }
  }

  mod tests_divide_mode58 {
    use super::super::divide_mode58;

    #[test]
    fn should_divide_zero_without_modulo() {
      // Given
      let mut input = vec!(0u8, 0, 0, 0);

      // When
      let modulo = divide_mode58(&mut input, 0);

      // Then
      assert_eq!(*input.get(0), 0);
      assert_eq!(*input.get(1), 0);
      assert_eq!(*input.get(2), 0);
      assert_eq!(*input.get(3), 0);
      assert_eq!(modulo, 0);
    }

    #[test]
    fn should_divide_100_43_without_modulo() {
      // Given
      let mut input = vec!(100u8, 43);

      // When
      let modulo = divide_mode58(&mut input, 0);

      // Then
      assert_eq!(*input.get(0), 1);
      assert_eq!(*input.get(1), 186);
      assert_eq!(modulo, 7);
    }
  }

}
<commit_msg>A little bit of optimization : Allocate some more space to output Vec<commit_after>#![crate_id = "base58"]
#![crate_type = "rlib"]
#![license = "Apache License, Version 2.0"]
#![deny(missing_doc)]

//! Rust-Base58 provides functions to encode and decode base58 values.

static BASE_256:u16 = 256;
static BASE_58:u16 = 58;

/// Encode a String into base58 String.
pub fn encode_base58 (input: String) -> String {
  let mut copied = input.into_bytes();
  let mut output:Vec<u8> = Vec::with_capacity(copied.len() * 138 / 100 + 1);
  let len = copied.len();

  if len == 0 {
    return String::new();
  }

  let mut count = 0;
  while count < len {
    let modulo = divide_mode58(&mut copied, count);
    let letter = from_alphabet(modulo);
    output.push(letter);

    if *copied.get(count) == 0 {
      count += 1;
    }
  }

  output.reverse();

  match String::from_utf8(output) {
    Ok(result) => result,
    Err(e) => fail!(e)
  }
}

/// Give the letter from the base58 alphabet
fn from_alphabet(position: u16) -> u8 {
  "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".char_at(position as uint) as u8
}

/// This function make the division of a big number stored in a Vec
/// and returns the modulo of the division.
/// The given Vec is modified and becomes the result of the division.
fn divide_mode58(input: &mut Vec<u8>, start: uint) -> u16 {
  let mut remainder = 0;

  for x in input.mut_iter().skip(start) {
    let num_base256: u16 = (*x as u16) & 0xFF;
    let temp = remainder * BASE_256 + num_base256;
    *x = (temp / BASE_58) as u8;
    remainder = temp % BASE_58;
  }

  remainder
}

#[cfg(test)] // TODO Put this test to test.rs file
mod bench {
  extern crate test;
  use self::test::Bencher;
  use super::encode_base58;

  #[bench]
  fn encode_lorem_ispum(b: &mut Bencher) {
    b.iter(|| encode_base58(String::from_str("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")));
  }
}

#[cfg(test)]
mod tests {
  mod tests_encode_base58 {

    use super::super::encode_base58;

    #[test] // TODO Put this test to test.rs file
    fn should_encode_from_string_to_base58_string() {
      // Given
      let empty = String::from_str("");
      let azerty = String::from_str("azerty");
      let lorem = String::from_str("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");

      // When
      let empty_encoded = encode_base58(empty);
      let azerty_encoded = encode_base58(azerty);
      let lorem_encoded = encode_base58(lorem);

      // Then
      assert_eq!(empty_encoded, String::from_str(""));
      assert_eq!(azerty_encoded, String::from_str("qYPmmAqv"));
      assert_eq!(lorem_encoded, String::from_str("RKDitRLwUhnQCAmM9hhenQXRAiKrL3ByvJ4CYouvhmw6yV8fapqyM95bN6KQVJbKvEN3uHeMdP9G7b5HNxmwRGqGibzcjrKaRLL2Nn1GFZRRv2Q8AvQU7MtRagLLzcZcwBDzkMqEpbRy9CvGr3BE7t2rH4wXmdExSGNKqV5XxAG7QT2S4ZQ4nzom8QFmoUgkfj8ykPye3z8FU9gJzSf2cDRA1ecYwFJtNdycgKTYCQ92pcfq95DoWfTBhnJfkKZXe1Dv3guVKk5otHz4XtWFJjcSC2GLrkRhTAEtgkySmaePs5YyoQHKb8PU5paS3dxAWc7sV5rqwrJbSbj7ybK6FQDN2mgbBxy7Wc7CnX6Q3Jm4B8cmo4oGixuHKdufABEs4FM3PAhF5CTk9xFsyw3CVJGxE2sMyC5EKnAv5Zc4kGfzzTxQe7VZrm188XqGZKZVRhjSW9CeceAf9bvqefLahgGiKps13595WSErpo1HpHb6Qt22QLSMJFGB2Aq7asXXUj55wPxCfVCz8NiqewcNpxF9bvjW9xsaMGqgD4dpgrBFzUw6irds1X481DHnRDi98yAhQJVUoxP8WSm3qJ93qhq8Hx7Eg4aiy"));
    }
  }

  mod tests_divide_mode58 {
    use super::super::divide_mode58;

    #[test]
    fn should_divide_zero_without_modulo() {
      // Given
      let mut input = vec!(0u8, 0, 0, 0);

      // When
      let modulo = divide_mode58(&mut input, 0);

      // Then
      assert_eq!(*input.get(0), 0);
      assert_eq!(*input.get(1), 0);
      assert_eq!(*input.get(2), 0);
      assert_eq!(*input.get(3), 0);
      assert_eq!(modulo, 0);
    }

    #[test]
    fn should_divide_100_43_without_modulo() {
      // Given
      let mut input = vec!(100u8, 43);

      // When
      let modulo = divide_mode58(&mut input, 0);

      // Then
      assert_eq!(*input.get(0), 1);
      assert_eq!(*input.get(1), 186);
      assert_eq!(modulo, 7);
    }
  }

}
<|endoftext|>


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

pub fn puzzle(input: &str) -> usize {
    0
}

#[derive(Debug)]
pub enum BotOrOutput {
    Bot,
    Output
}

impl<'a> From<&'a str> for BotOrOutput {
    fn from(s: &'a str) -> BotOrOutput {
        match s {
            "bot" => BotOrOutput::Bot,
            "output" => BotOrOutput::Output,
            _ => panic!("Unknown string given to BotOrOutput"),
        }
    }
}

#[derive(Debug)]
pub struct Command {
    low_value_type: BotOrOutput,
    low_value_key: usize,
    high_value_type: BotOrOutput,
    high_value_key: usize,
}

pub struct BotCommandCenter {
    bots: HashMap<usize, Bot>,
    outputs: HashMap<usize, Vec<usize>>,
    saved_commands: HashMap<usize, Command>,
    bots_to_check: Vec<usize>,
}

impl BotCommandCenter {
    pub fn new() -> BotCommandCenter {
        BotCommandCenter {
            bots: HashMap::new(),
            outputs: HashMap::new(),
            saved_commands: HashMap::new(),
            bots_to_check: vec![],
        }
    }

    pub fn exec_command(&mut self, input: &str) {
        println!("COMMAND: {}", input);
        let pieces: Vec<&str> = input.split_whitespace().collect();

        if pieces[0] == "value" {
            self.value_to_bot(
                pieces[5].parse().expect("can't parse bot key"),
                pieces[1].parse().expect("can't parse chip value")
            );
            self.process_bots();
        } else if pieces[0] == "bot" {
            self.command_to_bot(
                pieces[1].parse().expect("can't parse bot key"),
                pieces[5],
                pieces[6].parse().expect("can't parse low key"),
                pieces[10],
                pieces[11].parse().expect("can't parse high key"),
            );
        }
    }

    pub fn value_to_bot(&mut self, bot_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to bot {}", value, bot_key);
        self.bots
            .entry(bot_key)
            .or_insert(Bot::new(bot_key))
            .receive_chip(value);
        self.bots_to_check.push(bot_key);
        println!("COMMAND CTR bots to check = {:?}", self.bots_to_check);
    }

    pub fn value_to_output(&mut self, output_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to output {}", value, output_key);
        self.outputs
            .entry(output_key)
            .or_insert(vec![])
            .push(value);
    }

    pub fn get_next_bot_to_check(&mut self) -> usize {
        self.bots_to_check.remove(0)
    }

    pub fn bot_has_two_chips(&mut self, check_bot_key: usize) -> bool {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.has_two_chips()
    }

    pub fn bot_low_high(&mut self, check_bot_key: usize) -> (usize, usize) {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.low_high()
    }

    pub fn process_bots(&mut self) {
        while !self.bots_to_check.is_empty() {
            println!("COMMAND CTR process_bots, {} bots to process", self.bots_to_check.len());
            let check_bot_key = self.get_next_bot_to_check();
            println!("COMMAND CTR processing bot {}", check_bot_key);
            if self.bot_has_two_chips(check_bot_key) {
                println!("COMMAND CTR found bot {} has two chips", check_bot_key);
                let command = self.saved_commands.remove(&check_bot_key)
                    .expect("no saved command for a bot with two chips");
                println!("COMMAND CTR found command: {:?}", command);
                let (low_value, high_value) = self.bot_low_high(check_bot_key);
                println!("COMMAND CTR found low = {}, high = {}", low_value, high_value);
                match command.low_value_type {
                    BotOrOutput::Bot => self.value_to_bot(
                        command.low_value_key,
                        low_value
                    ),
                    BotOrOutput::Output => self.value_to_output(
                        command.low_value_key,
                        low_value
                    ),
                }

                match command.high_value_type {
                    BotOrOutput::Bot => self.value_to_bot(
                        command.high_value_key,
                        high_value
                    ),
                    BotOrOutput::Output => self.value_to_output(
                        command.high_value_key,
                        high_value
                    ),
                }
            }
        }
        println!("COMMAND CTR bots_to_check is empty");
    }

    pub fn command_to_bot(&mut self, bot_key: usize,
                              low_bot_or_output: &str, low_key: usize,
                              high_bot_or_output: &str, high_key: usize) {

        let command = Command {
            low_value_type: low_bot_or_output.into(),
            low_value_key: low_key,
            high_value_type: high_bot_or_output.into(),
            high_value_key: high_key,
        };
        self.saved_commands.insert(bot_key, command);
    }
}

pub struct Bot {
    key: usize,
    chip1: Option<usize>,
    chip2: Option<usize>,
}

impl Bot {
    pub fn new(key: usize) -> Bot {
        Bot {
            key: key,
            chip1: None, chip2: None,
        }
    }

    pub fn has_two_chips(&self) -> bool {
        match (self.chip1, self.chip2) {
            (Some(_), Some(_)) => true,
            _ => false,
        }
    }

    pub fn receive_chip(&mut self, chip: usize) {
        if self.chip1.is_none() {
            println!("bot {}, chip1 = {}", self.key, chip);
            self.chip1 = Some(chip);
        } else if self.chip2.is_none() {
            println!("bot {}, chip2 = {}", self.key, chip);
            self.chip2 = Some(chip);
        } else {
            panic!("Cannot hold more than two chips");
        }
    }

    pub fn low_high(&mut self) -> (usize, usize) {
        let (low, high) = match (self.chip1, self.chip2) {
            (Some(c1), Some(c2)) => {
                if c1 < c2 {
                    (c1, c2)
                } else {
                    (c2, c1)
                }
            }
            _ => panic!("Tried to get low and high from bot, something is wrong"),
        };
        self.chip1 = None;
        self.chip2 = None;
        (low, high)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn new_bot_does_not_have_two_chips() {
        let bot = Bot::new(0);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_a_chip_still_not_two() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_two_chips() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        bot.receive_chip(4);
        assert!(bot.has_two_chips());
    }

    #[test]
    fn test_sample() {
        let mut br = BotCommandCenter::new();

        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 3 goes to bot 1");
        br.exec_command("bot 1 gives low to output 1 and high to bot 0");
        br.exec_command("bot 0 gives low to output 2 and high to output 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.outputs.get(&0),
            Some(&vec![5])
        );

        assert_eq!(
            br.outputs.get(&1),
            Some(&vec![2])
        );

        assert_eq!(
            br.outputs.get(&2),
            Some(&vec![3])
        );
    }
}
<commit_msg>Sometimes commands come after a bot has two chips<commit_after>use std::collections::HashMap;

pub fn puzzle(input: &str) -> usize {
    let mut br = BotCommandCenter::new();

    for line in input.lines() {
        br.exec_command(line);
    }
    0
}

#[derive(Debug)]
pub enum BotOrOutput {
    Bot,
    Output
}

impl<'a> From<&'a str> for BotOrOutput {
    fn from(s: &'a str) -> BotOrOutput {
        match s {
            "bot" => BotOrOutput::Bot,
            "output" => BotOrOutput::Output,
            _ => panic!("Unknown string given to BotOrOutput"),
        }
    }
}

#[derive(Debug)]
pub struct Command {
    low_value_type: BotOrOutput,
    low_value_key: usize,
    high_value_type: BotOrOutput,
    high_value_key: usize,
}

pub struct BotCommandCenter {
    bots: HashMap<usize, Bot>,
    outputs: HashMap<usize, Vec<usize>>,
    saved_commands: HashMap<usize, Command>,
    bots_to_check: Vec<usize>,
}

impl BotCommandCenter {
    pub fn new() -> BotCommandCenter {
        BotCommandCenter {
            bots: HashMap::new(),
            outputs: HashMap::new(),
            saved_commands: HashMap::new(),
            bots_to_check: vec![],
        }
    }

    pub fn exec_command(&mut self, input: &str) {
        println!("COMMAND: {}", input);
        let pieces: Vec<&str> = input.split_whitespace().collect();

        if pieces[0] == "value" {
            self.value_to_bot(
                pieces[5].parse().expect("can't parse bot key"),
                pieces[1].parse().expect("can't parse chip value")
            );
            self.process_bots();
        } else if pieces[0] == "bot" {
            self.command_to_bot(
                pieces[1].parse().expect("can't parse bot key"),
                pieces[5],
                pieces[6].parse().expect("can't parse low key"),
                pieces[10],
                pieces[11].parse().expect("can't parse high key"),
            );
            self.process_bots();
        }
    }

    pub fn value_to_bot(&mut self, bot_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to bot {}", value, bot_key);
        self.bots
            .entry(bot_key)
            .or_insert(Bot::new(bot_key))
            .receive_chip(value);
        self.bots_to_check.push(bot_key);
        println!("COMMAND CTR bots to check = {:?}", self.bots_to_check);
    }

    pub fn value_to_output(&mut self, output_key: usize, value: usize) {
        println!("COMMAND CTR sending value {} to output {}", value, output_key);
        self.outputs
            .entry(output_key)
            .or_insert(vec![])
            .push(value);
    }

    pub fn get_next_bot_to_check(&mut self) -> usize {
        self.bots_to_check.remove(0)
    }

    pub fn bot_has_two_chips(&mut self, check_bot_key: usize) -> bool {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.has_two_chips()
    }

    pub fn bot_low_high(&mut self, check_bot_key: usize) -> (usize, usize) {
        let bot = self.bots.entry(check_bot_key)
                           .or_insert(Bot::new(check_bot_key));
        bot.low_high()
    }

    pub fn process_bots(&mut self) {
        while !self.bots_to_check.is_empty() {
            println!("COMMAND CTR process_bots, {} bots to process", self.bots_to_check.len());
            let check_bot_key = self.get_next_bot_to_check();
            println!("COMMAND CTR processing bot {}", check_bot_key);
            if self.bot_has_two_chips(check_bot_key) {
                println!("COMMAND CTR found bot {} has two chips", check_bot_key);

                if let Some(command) = self.saved_commands.remove(&check_bot_key) {
                    println!("COMMAND CTR found command: {:?}", command);
                    let (low_value, high_value) = self.bot_low_high(check_bot_key);
                    println!("COMMAND CTR found low = {}, high = {}", low_value, high_value);
                    match command.low_value_type {
                        BotOrOutput::Bot => self.value_to_bot(
                            command.low_value_key,
                            low_value
                        ),
                        BotOrOutput::Output => self.value_to_output(
                            command.low_value_key,
                            low_value
                        ),
                    }

                    match command.high_value_type {
                        BotOrOutput::Bot => self.value_to_bot(
                            command.high_value_key,
                            high_value
                        ),
                        BotOrOutput::Output => self.value_to_output(
                            command.high_value_key,
                            high_value
                        ),
                    }
                } else {
                    println!("COMMAND CTR found no saved command for bot {} that has two chips", check_bot_key);
                }

            }
        }
        println!("COMMAND CTR bots_to_check is empty");
    }

    pub fn command_to_bot(&mut self, bot_key: usize,
                              low_bot_or_output: &str, low_key: usize,
                              high_bot_or_output: &str, high_key: usize) {

        let command = Command {
            low_value_type: low_bot_or_output.into(),
            low_value_key: low_key,
            high_value_type: high_bot_or_output.into(),
            high_value_key: high_key,
        };
        self.saved_commands.insert(bot_key, command);
        self.bots_to_check.push(bot_key);
        println!("COMMAND CTR bots to check = {:?}", self.bots_to_check);
    }
}

pub struct Bot {
    key: usize,
    chip1: Option<usize>,
    chip2: Option<usize>,
}

impl Bot {
    pub fn new(key: usize) -> Bot {
        Bot {
            key: key,
            chip1: None, chip2: None,
        }
    }

    pub fn has_two_chips(&self) -> bool {
        match (self.chip1, self.chip2) {
            (Some(_), Some(_)) => true,
            _ => false,
        }
    }

    pub fn receive_chip(&mut self, chip: usize) {
        if self.chip1.is_none() {
            println!("bot {}, chip1 = {}", self.key, chip);
            self.chip1 = Some(chip);
        } else if self.chip2.is_none() {
            println!("bot {}, chip2 = {}", self.key, chip);
            self.chip2 = Some(chip);
        } else {
            panic!("Cannot hold more than two chips");
        }
    }

    pub fn low_high(&mut self) -> (usize, usize) {
        let (low, high) = match (self.chip1, self.chip2) {
            (Some(c1), Some(c2)) => {
                if c1 < c2 {
                    println!("Bot {} found {} < {}", self.key, c1, c2);
                    if c1 == 17 && c2 == 61 {
                        panic!("The bot you are looking for is {}", self.key);
                    }
                    (c1, c2)
                } else {
                    println!("Bot {} found {} < {}", self.key, c2, c1);
                    if c2 == 17 && c1 == 61 {
                        panic!("The bot you are looking for is {}", self.key);
                    }
                    (c2, c1)
                }
            }
            _ => panic!("Tried to get low and high from bot, something is wrong"),
        };
        self.chip1 = None;
        self.chip2 = None;
        (low, high)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn new_bot_does_not_have_two_chips() {
        let bot = Bot::new(0);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_a_chip_still_not_two() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_two_chips() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        bot.receive_chip(4);
        assert!(bot.has_two_chips());
    }

    #[test]
    fn test_sample() {
        let mut br = BotCommandCenter::new();

        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 3 goes to bot 1");
        br.exec_command("bot 1 gives low to output 1 and high to bot 0");
        br.exec_command("bot 0 gives low to output 2 and high to output 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.outputs.get(&0),
            Some(&vec![5])
        );

        assert_eq!(
            br.outputs.get(&1),
            Some(&vec![2])
        );

        assert_eq!(
            br.outputs.get(&2),
            Some(&vec![3])
        );
    }
}
<|endoftext|>


<commit_before>// TODO
//!#[warn(missing_docs)]

use std::collections::HashMap;

use js_int::UInt;
use ruma_events::EventType;
use ruma_identifiers::{EventId, RoomId, UserId};
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;

#[derive(Deserialize, Serialize)]
pub struct RoomV3Pdu {
    pub room_id: RoomId,
    pub sender: UserId,
    pub origin: String,
    pub origin_server_ts: UInt,

    // TODO: Replace with event content collection from ruma-events once that exists
    #[serde(rename = "type")]
    pub kind: EventType,
    pub content: JsonValue,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub state_key: Option<String>,
    pub prev_events: Vec<EventId>,
    pub depth: UInt,
    pub auth_events: Vec<EventId>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub redacts: Option<EventId>,
    #[serde(default, skip_serializing_if = "serde_json::Map::is_empty")]
    pub unsigned: serde_json::Map<String, JsonValue>,
    pub hashes: EventHash,
    pub signatures: HashMap<String, HashMap<String, String>>,
}

#[derive(Deserialize, Serialize)]
pub struct EventHash {
    pub sha256: String,
}
<commit_msg>Fix accidental doc comment<commit_after>// TODO
// !#[warn(missing_docs)]

use std::collections::HashMap;

use js_int::UInt;
use ruma_events::EventType;
use ruma_identifiers::{EventId, RoomId, UserId};
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;

#[derive(Deserialize, Serialize)]
pub struct RoomV3Pdu {
    pub room_id: RoomId,
    pub sender: UserId,
    pub origin: String,
    pub origin_server_ts: UInt,

    // TODO: Replace with event content collection from ruma-events once that exists
    #[serde(rename = "type")]
    pub kind: EventType,
    pub content: JsonValue,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub state_key: Option<String>,
    pub prev_events: Vec<EventId>,
    pub depth: UInt,
    pub auth_events: Vec<EventId>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub redacts: Option<EventId>,
    #[serde(default, skip_serializing_if = "serde_json::Map::is_empty")]
    pub unsigned: serde_json::Map<String, JsonValue>,
    pub hashes: EventHash,
    pub signatures: HashMap<String, HashMap<String, String>>,
}

#[derive(Deserialize, Serialize)]
pub struct EventHash {
    pub sha256: String,
}
<|endoftext|>


<commit_before>//! A generic [Markov chain](https://en.wikipedia.org/wiki/Markov_chain) for almost any type. This
//! uses HashMaps internally, and so Eq and Hash are both required.
//!
//! # Examples
//!
//! ```
//! use markov::Chain;
//!
//! let mut chain = Chain::new();
//! chain.feed_str("I like cats and I like dogs.");
//! println!("{}", chain.generate_str());
//! ```
//!
//! ```
//! use markov::Chain;
//!
//! let mut chain = Chain::new();
//! chain.feed(vec![1u8, 2, 3, 5]).feed(vec![3u8, 9, 2]);
//! println!("{:?}", chain.generate());
//! ```
#![warn(missing_docs)]

extern crate rand;

use std::borrow::ToOwned;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::fs::File;
use std::hash::Hash;
use std::io::BufReader;
use std::io::prelude::*;
use std::iter::Map;
use std::path::Path;
use std::rc::Rc;
use rand::{Rng, thread_rng};

/// The definition of all types that can be used in a Chain.
pub trait Chainable: Eq + Hash {}
impl<T> Chainable for T where T: Eq + Hash {}

/// A generic [Markov chain](https://en.wikipedia.org/wiki/Markov_chain) for almost any type. This
/// uses HashMaps internally, and so Eq and Hash are both required.
#[derive(PartialEq, Debug)]
pub struct Chain<T> where T: Chainable {
    map: HashMap<Vec<Option<Rc<T>>>, HashMap<Option<Rc<T>>, usize>>,
    order: usize,
}

impl<T> Chain<T> where T: Chainable {
    /// Constructs a new Markov chain.
    pub fn new() -> Chain<T> {
        Chain {
            map: {
                let mut map = HashMap::new();
                map.insert(vec!(None; 1), HashMap::new());
                map
            },
            order: 1,
        }
    }

    /// Choose a specific Markov chain order. The order is the number of previous tokens to use
    /// as the index into the map.
    pub fn order(&mut self, order: usize) -> &mut Chain<T> {
        assert!(order > 0);
        self.order = order;
        self.map.insert(vec!(None; self.order), HashMap::new());
        self
    }

    /// Determines whether or not the chain is empty. A chain is considered empty if nothing has
    /// been fed into it.
    pub fn is_empty(&self) -> bool {
        self.map[&vec!(None; self.order)].is_empty()
    }

    /// Feeds the chain a collection of tokens. This operation is O(n) where n is the number of
    /// tokens to be fed into the chain.
    pub fn feed(&mut self, tokens: Vec<T>) -> &mut Chain<T> {
        if tokens.len() == 0 { return self }
        let mut toks = vec!(None; self.order);
        toks.extend(tokens.into_iter().map(|token| {
            Some(Rc::new(token))
        }));
        toks.push(None);
        for p in toks.windows(self.order + 1) {
            if !self.map.contains_key(&p[0..self.order].to_vec()) {
                self.map.insert(p[0..self.order].to_vec(), HashMap::new());
            }
            self.map.get_mut(&p[0..self.order].to_vec()).unwrap().add(p[self.order].clone());
        }
        self
    }

    /// Generates a collection of tokens from the chain. This operation is O(mn) where m is the
    /// length of the generated collection, and n is the number of possible states from a given
    /// state.
    pub fn generate(&self) -> Vec<Rc<T>> {
        let mut ret = Vec::new();
        let mut curs = vec!(None; self.order);
        loop {
            let next = self.map[&curs].next();
            curs = curs[1..self.order].to_vec();
            curs.push(next.clone());
            if let Some(next) = next { ret.push(next) };
            if curs[self.order - 1].is_none() { break }
        }
        ret
    }

    /// Generates a collection of tokens from the chain, starting with the given token. This
    /// operation is O(mn) where m is the length of the generated collection, and n is the number
    /// of possible states from a given state. This returns an empty vector if the token is not
    /// found.
    pub fn generate_from_token(&self, token: T) -> Vec<Rc<T>> {
        let token = Rc::new(token);
        if !self.map.contains_key(&vec!(Some(token.clone()); self.order)) { return Vec::new() }
        let mut ret = vec![token.clone()];
        let mut curs = vec!(Some(token.clone()); self.order);
        loop {
            let next = self.map[&curs].next();
            curs = curs[1..self.order].to_vec();
            curs.push(next.clone());
            if let Some(next) = next { ret.push(next) };
            if curs[self.order - 1].is_none() { break }
        }
        ret
    }

    /// Produces an infinite iterator of generated token collections.
    pub fn iter(&self) -> InfiniteChainIterator<T> {
        InfiniteChainIterator { chain: self }
    }

    /// Produces an iterator for the specified number of generated token collections.
    pub fn iter_for(&self, size: usize) -> SizedChainIterator<T> {
        SizedChainIterator { chain: self, size: size }
    }
}

impl Chain<String> {
    /// Feeds a string of text into the chain.
    pub fn feed_str(&mut self, string: &str) -> &mut Chain<String> {
        self.feed(string.split(" ").map(|s| s.to_owned()).collect())
    }

    /// Feeds a properly formatted file into the chain. This file should be formatted such that
    /// each line is a new sentence. Punctuation may be included if it is desired.
    pub fn feed_file(&mut self, path: &Path) -> &mut Chain<String> {
        let reader = BufReader::new(File::open(path).unwrap());
        for line in reader.lines() {
            let line = line.unwrap();
            let words: Vec<_> = line.split_whitespace()
                                    .filter(|word| !word.is_empty())
                                    .collect();
            self.feed(words.iter().map(|&s| s.to_owned()).collect());
        }
        self
    }

    /// Converts the output of generate(...) on a String chain to a single String.
    fn vec_to_string(vec: Vec<Rc<String>>) -> String {
        let mut ret = String::new();
        for s in vec.iter() {
            ret.push_str(&s);
            ret.push_str(" ");
        }
        let len = ret.len();
        if len > 0 {
            ret.truncate(len - 1);
        }
        ret
    }

    /// Generates a random string of text.
    pub fn generate_str(&self) -> String {
        Chain::vec_to_string(self.generate())
    }

    /// Generates a random string of text starting with the desired token. This returns an empty
    /// string if the token is not found.
    pub fn generate_str_from_token(&self, string: &str) -> String {
        Chain::vec_to_string(self.generate_from_token(string.to_owned()))
    }

    /// Produces an infinite iterator of generated strings.
    pub fn str_iter(&self) -> InfiniteChainStringIterator {
        let vec_to_string: fn(Vec<Rc<String>>) -> String = Chain::vec_to_string;
        self.iter().map(vec_to_string)
    }

    /// Produces a sized iterator of generated strings.
    pub fn str_iter_for(&self, size: usize) -> SizedChainStringIterator {
        let vec_to_string: fn(Vec<Rc<String>>) -> String = Chain::vec_to_string;
        self.iter_for(size).map(vec_to_string)
    }
}

/// A sized iterator over a Markov chain of strings.
pub type SizedChainStringIterator<'a> =
Map<SizedChainIterator<'a, String>, fn(Vec<Rc<String>>) -> String>;

/// A sized iterator over a Markov chain.
pub struct SizedChainIterator<'a, T: Chainable + 'a> {
    chain: &'a Chain<T>,
    size: usize,
}

impl<'a, T> Iterator for SizedChainIterator<'a, T> where T: Chainable + 'a {
    type Item = Vec<Rc<T>>;
    fn next(&mut self) -> Option<Vec<Rc<T>>> {
        if self.size > 0 {
            self.size -= 1;
            Some(self.chain.generate())
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.size, Some(self.size))
    }
}

/// An infinite iterator over a Markov chain of strings.
pub type InfiniteChainStringIterator<'a> =
Map<InfiniteChainIterator<'a, String>, fn(Vec<Rc<String>>) -> String>;

/// An infinite iterator over a Markov chain.
pub struct InfiniteChainIterator<'a, T: Chainable + 'a> {
    chain: &'a Chain<T>
}

impl<'a, T> Iterator for InfiniteChainIterator<'a, T> where T: Chainable + 'a {
    type Item = Vec<Rc<T>>;
    fn next(&mut self) -> Option<Vec<Rc<T>>> {
        Some(self.chain.generate())
    }
}

/// A collection of states for the Markov chain.
trait States<T: PartialEq> {
    /// Adds a state to this states collection.
    fn add(&mut self, token: Option<Rc<T>>);
    /// Gets the next state from this collection of states.
    fn next(&self) -> Option<Rc<T>>;
}

impl<T> States<T> for HashMap<Option<Rc<T>>, usize> where T: Chainable {
    fn add(&mut self, token: Option<Rc<T>>) {
        match self.entry(token) {
            Occupied(mut e) => *e.get_mut() += 1,
            Vacant(e) => { e.insert(1); },
        }
    }

    fn next(&self) -> Option<Rc<T>> {
        let mut sum = 0;
        for &value in self.values() {
            sum += value;
        }
        let mut rng = thread_rng();
        let cap = rng.gen_range(0, sum);
        sum = 0;
        for (key, &value) in self.iter() {
            sum += value;
            if sum > cap {
                return key.clone()
            }
        }
        unreachable!("The random number generator failed.")
    }
}

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

    #[test]
    fn new() {
        Chain::<u8>::new();
        Chain::<String>::new();
    }

    #[test]
    fn is_empty() {
        let mut chain = Chain::new();
        assert!(chain.is_empty());
        chain.feed(vec![1u8, 2, 3]);
        assert!(!chain.is_empty());
    }

    #[test]
    fn feed() {
        let mut chain = Chain::new();
        chain.feed(vec![3, 5, 10]).feed(vec![5, 12]);
    }

    #[test]
    fn generate() {
        let mut chain = Chain::new();
        chain.feed(vec![3u8, 5, 10]).feed(vec![5, 12]);
        let v = chain.generate().into_iter().map(|v| *v).collect();
        assert!([vec![3, 5, 10], vec![3, 5, 12], vec![5, 10], vec![5, 12]].contains(&v));
    }

    #[test]
    fn generate_for_higher_order() {
        let mut chain = Chain::new();
        chain.order(2);
        chain.feed(vec![3u8, 5, 10]).feed(vec![2, 3, 5, 12]);
        let v = chain.generate().into_iter().map(|v| *v).collect();
        assert!([vec![3, 5, 10], vec![3, 5, 12], vec![2, 3, 5, 10], vec![2, 3, 5, 12]].contains(&v));
    }

    #[test]
    fn generate_from_token() {
        let mut chain = Chain::new();
        chain.feed(vec![3u8, 5, 10]).feed(vec![5, 12]);
        let v = chain.generate_from_token(5).into_iter().map(|v| *v).collect();
        assert!([vec![5, 10], vec![5, 12]].contains(&v));
    }

    #[test]
    fn generate_from_unfound_token() {
        let mut chain = Chain::new();
        chain.feed(vec![3u8, 5, 10]).feed(vec![5, 12]);
        let v: Vec<_> = chain.generate_from_token(9).into_iter().map(|v| *v).collect();
        assert_eq!(v, vec![]);
    }

    #[test]
    fn iter() {
        let mut chain = Chain::new();
        chain.feed(vec![3u8, 5, 10]).feed(vec![5, 12]);
        assert_eq!(chain.iter().size_hint().1, None);
    }

    #[test]
    fn iter_for() {
        let mut chain = Chain::new();
        chain.feed(vec![3u8, 5, 10]).feed(vec![5, 12]);
        assert_eq!(chain.iter_for(5).collect::<Vec<_>>().len(), 5);
    }

    #[test]
    fn feed_str() {
        let mut chain = Chain::new();
        chain.feed_str("I like cats and dogs");
    }

    #[test]
    fn generate_str() {
        let mut chain = Chain::new();
        chain.feed_str("I like cats").feed_str("I hate cats");
        assert!(["I like cats", "I hate cats"].contains(&&chain.generate_str()[..]));
    }

    #[test]
    fn generate_str_from_token() {
        let mut chain = Chain::new();
        chain.feed_str("I like cats").feed_str("cats are cute");
        assert!(["cats", "cats are cute"].contains(&&chain.generate_str_from_token("cats")[..]));
    }

    #[test]
    fn generate_str_from_unfound_token() {
        let mut chain = Chain::new();
        chain.feed_str("I like cats").feed_str("cats are cute");
        assert_eq!(chain.generate_str_from_token("test"), "");
    }

    #[test]
    fn str_iter() {
        let mut chain = Chain::new();
        chain.feed_str("I like cats and I like dogs");
        assert_eq!(chain.str_iter().size_hint().1, None);
    }

    #[test]
    fn str_iter_for() {
        let mut chain = Chain::new();
        chain.feed_str("I like cats and I like dogs");
        assert_eq!(chain.str_iter_for(5).collect::<Vec<_>>().len(), 5);
    }
}
<commit_msg>Do the line transformation in one pass on file import.<commit_after>//! A generic [Markov chain](https://en.wikipedia.org/wiki/Markov_chain) for almost any type. This
//! uses HashMaps internally, and so Eq and Hash are both required.
//!
//! # Examples
//!
//! ```
//! use markov::Chain;
//!
//! let mut chain = Chain::new();
//! chain.feed_str("I like cats and I like dogs.");
//! println!("{}", chain.generate_str());
//! ```
//!
//! ```
//! use markov::Chain;
//!
//! let mut chain = Chain::new();
//! chain.feed(vec![1u8, 2, 3, 5]).feed(vec![3u8, 9, 2]);
//! println!("{:?}", chain.generate());
//! ```
#![warn(missing_docs)]

extern crate rand;

use std::borrow::ToOwned;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::fs::File;
use std::hash::Hash;
use std::io::BufReader;
use std::io::prelude::*;
use std::iter::Map;
use std::path::Path;
use std::rc::Rc;
use rand::{Rng, thread_rng};

/// The definition of all types that can be used in a Chain.
pub trait Chainable: Eq + Hash {}
impl<T> Chainable for T where T: Eq + Hash {}

/// A generic [Markov chain](https://en.wikipedia.org/wiki/Markov_chain) for almost any type. This
/// uses HashMaps internally, and so Eq and Hash are both required.
#[derive(PartialEq, Debug)]
pub struct Chain<T> where T: Chainable {
    map: HashMap<Vec<Option<Rc<T>>>, HashMap<Option<Rc<T>>, usize>>,
    order: usize,
}

impl<T> Chain<T> where T: Chainable {
    /// Constructs a new Markov chain.
    pub fn new() -> Chain<T> {
        Chain {
            map: {
                let mut map = HashMap::new();
                map.insert(vec!(None; 1), HashMap::new());
                map
            },
            order: 1,
        }
    }

    /// Choose a specific Markov chain order. The order is the number of previous tokens to use
    /// as the index into the map.
    pub fn order(&mut self, order: usize) -> &mut Chain<T> {
        assert!(order > 0);
        self.order = order;
        self.map.insert(vec!(None; self.order), HashMap::new());
        self
    }

    /// Determines whether or not the chain is empty. A chain is considered empty if nothing has
    /// been fed into it.
    pub fn is_empty(&self) -> bool {
        self.map[&vec!(None; self.order)].is_empty()
    }

    /// Feeds the chain a collection of tokens. This operation is O(n) where n is the number of
    /// tokens to be fed into the chain.
    pub fn feed(&mut self, tokens: Vec<T>) -> &mut Chain<T> {
        if tokens.len() == 0 { return self }
        let mut toks = vec!(None; self.order);
        toks.extend(tokens.into_iter().map(|token| {
            Some(Rc::new(token))
        }));
        toks.push(None);
        for p in toks.windows(self.order + 1) {
            if !self.map.contains_key(&p[0..self.order].to_vec()) {
                self.map.insert(p[0..self.order].to_vec(), HashMap::new());
            }
            self.map.get_mut(&p[0..self.order].to_vec()).unwrap().add(p[self.order].clone());
        }
        self
    }

    /// Generates a collection of tokens from the chain. This operation is O(mn) where m is the
    /// length of the generated collection, and n is the number of possible states from a given
    /// state.
    pub fn generate(&self) -> Vec<Rc<T>> {
        let mut ret = Vec::new();
        let mut curs = vec!(None; self.order);
        loop {
            let next = self.map[&curs].next();
            curs = curs[1..self.order].to_vec();
            curs.push(next.clone());
            if let Some(next) = next { ret.push(next) };
            if curs[self.order - 1].is_none() { break }
        }
        ret
    }

    /// Generates a collection of tokens from the chain, starting with the given token. This
    /// operation is O(mn) where m is the length of the generated collection, and n is the number
    /// of possible states from a given state. This returns an empty vector if the token is not
    /// found.
    pub fn generate_from_token(&self, token: T) -> Vec<Rc<T>> {
        let token = Rc::new(token);
        if !self.map.contains_key(&vec!(Some(token.clone()); self.order)) { return Vec::new() }
        let mut ret = vec![token.clone()];
        let mut curs = vec!(Some(token.clone()); self.order);
        loop {
            let next = self.map[&curs].next();
            curs = curs[1..self.order].to_vec();
            curs.push(next.clone());
            if let Some(next) = next { ret.push(next) };
            if curs[self.order - 1].is_none() { break }
        }
        ret
    }

    /// Produces an infinite iterator of generated token collections.
    pub fn iter(&self) -> InfiniteChainIterator<T> {
        InfiniteChainIterator { chain: self }
    }

    /// Produces an iterator for the specified number of generated token collections.
    pub fn iter_for(&self, size: usize) -> SizedChainIterator<T> {
        SizedChainIterator { chain: self, size: size }
    }
}

impl Chain<String> {
    /// Feeds a string of text into the chain.
    pub fn feed_str(&mut self, string: &str) -> &mut Chain<String> {
        self.feed(string.split(" ").map(|s| s.to_owned()).collect())
    }

    /// Feeds a properly formatted file into the chain. This file should be formatted such that
    /// each line is a new sentence. Punctuation may be included if it is desired.
    pub fn feed_file(&mut self, path: &Path) -> &mut Chain<String> {
        let reader = BufReader::new(File::open(path).unwrap());
        for line in reader.lines() {
            let line = line.unwrap();
            let words = line.split_whitespace()
                            .filter(|word| !word.is_empty())
                            .map(|s| s.to_owned())
                            .collect();
            self.feed(words);
        }
        self
    }

    /// Converts the output of generate(...) on a String chain to a single String.
    fn vec_to_string(vec: Vec<Rc<String>>) -> String {
        let mut ret = String::new();
        for s in vec.iter() {
            ret.push_str(&s);
            ret.push_str(" ");
        }
        let len = ret.len();
        if len > 0 {
            ret.truncate(len - 1);
        }
        ret
    }

    /// Generates a random string of text.
    pub fn generate_str(&self) -> String {
        Chain::vec_to_string(self.generate())
    }

    /// Generates a random string of text starting with the desired token. This returns an empty
    /// string if the token is not found.
    pub fn generate_str_from_token(&self, string: &str) -> String {
        Chain::vec_to_string(self.generate_from_token(string.to_owned()))
    }

    /// Produces an infinite iterator of generated strings.
    pub fn str_iter(&self) -> InfiniteChainStringIterator {
        let vec_to_string: fn(Vec<Rc<String>>) -> String = Chain::vec_to_string;
        self.iter().map(vec_to_string)
    }

    /// Produces a sized iterator of generated strings.
    pub fn str_iter_for(&self, size: usize) -> SizedChainStringIterator {
        let vec_to_string: fn(Vec<Rc<String>>) -> String = Chain::vec_to_string;
        self.iter_for(size).map(vec_to_string)
    }
}

/// A sized iterator over a Markov chain of strings.
pub type SizedChainStringIterator<'a> =
Map<SizedChainIterator<'a, String>, fn(Vec<Rc<String>>) -> String>;

/// A sized iterator over a Markov chain.
pub struct SizedChainIterator<'a, T: Chainable + 'a> {
    chain: &'a Chain<T>,
    size: usize,
}

impl<'a, T> Iterator for SizedChainIterator<'a, T> where T: Chainable + 'a {
    type Item = Vec<Rc<T>>;
    fn next(&mut self) -> Option<Vec<Rc<T>>> {
        if self.size > 0 {
            self.size -= 1;
            Some(self.chain.generate())
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.size, Some(self.size))
    }
}

/// An infinite iterator over a Markov chain of strings.
pub type InfiniteChainStringIterator<'a> =
Map<InfiniteChainIterator<'a, String>, fn(Vec<Rc<String>>) -> String>;

/// An infinite iterator over a Markov chain.
pub struct InfiniteChainIterator<'a, T: Chainable + 'a> {
    chain: &'a Chain<T>
}

impl<'a, T> Iterator for InfiniteChainIterator<'a, T> where T: Chainable + 'a {
    type Item = Vec<Rc<T>>;
    fn next(&mut self) -> Option<Vec<Rc<T>>> {
        Some(self.chain.generate())
    }
}

/// A collection of states for the Markov chain.
trait States<T: PartialEq> {
    /// Adds a state to this states collection.
    fn add(&mut self, token: Option<Rc<T>>);
    /// Gets the next state from this collection of states.
    fn next(&self) -> Option<Rc<T>>;
}

impl<T> States<T> for HashMap<Option<Rc<T>>, usize> where T: Chainable {
    fn add(&mut self, token: Option<Rc<T>>) {
        match self.entry(token) {
            Occupied(mut e) => *e.get_mut() += 1,
            Vacant(e) => { e.insert(1); },
        }
    }

    fn next(&self) -> Option<Rc<T>> {
        let mut sum = 0;
        for &value in self.values() {
            sum += value;
        }
        let mut rng = thread_rng();
        let cap = rng.gen_range(0, sum);
        sum = 0;
        for (key, &value) in self.iter() {
            sum += value;
            if sum > cap {
                return key.clone()
            }
        }
        unreachable!("The random number generator failed.")
    }
}

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

    #[test]
    fn new() {
        Chain::<u8>::new();
        Chain::<String>::new();
    }

    #[test]
    fn is_empty() {
        let mut chain = Chain::new();
        assert!(chain.is_empty());
        chain.feed(vec![1u8, 2, 3]);
        assert!(!chain.is_empty());
    }

    #[test]
    fn feed() {
        let mut chain = Chain::new();
        chain.feed(vec![3, 5, 10]).feed(vec![5, 12]);
    }

    #[test]
    fn generate() {
        let mut chain = Chain::new();
        chain.feed(vec![3u8, 5, 10]).feed(vec![5, 12]);
        let v = chain.generate().into_iter().map(|v| *v).collect();
        assert!([vec![3, 5, 10], vec![3, 5, 12], vec![5, 10], vec![5, 12]].contains(&v));
    }

    #[test]
    fn generate_for_higher_order() {
        let mut chain = Chain::new();
        chain.order(2);
        chain.feed(vec![3u8, 5, 10]).feed(vec![2, 3, 5, 12]);
        let v = chain.generate().into_iter().map(|v| *v).collect();
        assert!([vec![3, 5, 10], vec![3, 5, 12], vec![2, 3, 5, 10], vec![2, 3, 5, 12]].contains(&v));
    }

    #[test]
    fn generate_from_token() {
        let mut chain = Chain::new();
        chain.feed(vec![3u8, 5, 10]).feed(vec![5, 12]);
        let v = chain.generate_from_token(5).into_iter().map(|v| *v).collect();
        assert!([vec![5, 10], vec![5, 12]].contains(&v));
    }

    #[test]
    fn generate_from_unfound_token() {
        let mut chain = Chain::new();
        chain.feed(vec![3u8, 5, 10]).feed(vec![5, 12]);
        let v: Vec<_> = chain.generate_from_token(9).into_iter().map(|v| *v).collect();
        assert_eq!(v, vec![]);
    }

    #[test]
    fn iter() {
        let mut chain = Chain::new();
        chain.feed(vec![3u8, 5, 10]).feed(vec![5, 12]);
        assert_eq!(chain.iter().size_hint().1, None);
    }

    #[test]
    fn iter_for() {
        let mut chain = Chain::new();
        chain.feed(vec![3u8, 5, 10]).feed(vec![5, 12]);
        assert_eq!(chain.iter_for(5).collect::<Vec<_>>().len(), 5);
    }

    #[test]
    fn feed_str() {
        let mut chain = Chain::new();
        chain.feed_str("I like cats and dogs");
    }

    #[test]
    fn generate_str() {
        let mut chain = Chain::new();
        chain.feed_str("I like cats").feed_str("I hate cats");
        assert!(["I like cats", "I hate cats"].contains(&&chain.generate_str()[..]));
    }

    #[test]
    fn generate_str_from_token() {
        let mut chain = Chain::new();
        chain.feed_str("I like cats").feed_str("cats are cute");
        assert!(["cats", "cats are cute"].contains(&&chain.generate_str_from_token("cats")[..]));
    }

    #[test]
    fn generate_str_from_unfound_token() {
        let mut chain = Chain::new();
        chain.feed_str("I like cats").feed_str("cats are cute");
        assert_eq!(chain.generate_str_from_token("test"), "");
    }

    #[test]
    fn str_iter() {
        let mut chain = Chain::new();
        chain.feed_str("I like cats and I like dogs");
        assert_eq!(chain.str_iter().size_hint().1, None);
    }

    #[test]
    fn str_iter_for() {
        let mut chain = Chain::new();
        chain.feed_str("I like cats and I like dogs");
        assert_eq!(chain.str_iter_for(5).collect::<Vec<_>>().len(), 5);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate log;

pub mod constants;
pub use constants::{
    // LOG_FORMAT, LOG_LEVEL,
    APRSIS_SW_VERSION, APRSIS_HTTP_HEADERS, APRSIS_SERVERS,
    APRSIS_FILTER_PORT, APRSIS_RX_PORT, APRSIS_URL,
    AX25_FLAG, AX25_CONTROL_FIELD, AX25_PROTOCOL_ID,
    RECV_BUFFER, DEFAULT_TOCALL,
    ADDR_INFO_DELIM, DATA_TYPE_MAP, KISS_DATA_FRAME
};

pub mod util;
pub use util::{valid_callsign};

pub mod geo_util;
pub use geo_util::{dec2dm_lat, dec2dm_lng, ambiguate};

pub mod fcs;
pub use fcs::{FCS};

pub mod functions;
pub use functions::{
    parse_frame, parse_callsign,
    parse_callsign_ax25, parse_info_field
};

pub mod structs;
pub use structs::{
    Frame, Callsign, APRS, TCP, UDP,
    HTTP, InformationField, PositionFrame
};

pub mod decimaldegrees;
pub mod kiss_structs;
<commit_msg>APRS: docs and credits. Still filling out information; will do when crate is more complete.<commit_after>//! This crate provides connectivity to the APRS amateur radio network over the internet.
//!
//! APRS (Automatic Packet Reporting System) is a packet-based, internet- and rf-connected
//! communication network for amateur radio operators and enthusiasts that allows transport
//! of location data, weather reports and more among operators. See the [APRS website][1]
//! for a detailed description of the network.
//!
//! Credits:
//! --------
//! APRS (c) Bob Bruninga, WB4APR
//! [Original Python module][2] by Greg Albrecht, W2GMD
//! Rust port by Jeffrey Hoover, KI6SGV
//!
//! This library is licensed under the Apache 2.0 license. See [LICENSE][2] for full terms.
//!
//! [1]: http://www.aprs.org/
//! [2]: https://www.github.com/ampledata/aprs
//! [3]: https://www.apache.org/licenses/LICENSE-2.0

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate log;

pub mod constants;
pub mod util;
pub mod geo_util;
pub mod fcs;
pub mod functions;
pub mod structs;
pub mod decimaldegrees;
pub mod kiss_structs;
<|endoftext|>


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

pub fn puzzle(input: &str) -> String {
    let mut lines = input.lines();
    let first_line = lines.next().expect("There were no lines!");

    let mut columns: Vec<Column> = first_line.chars().map(|ch| {
        let mut c = Column { freqs: HashMap::new() };
        c.add_char(ch);
        c
    }).collect();

    for line in lines {
        for (i, ch) in line.chars().enumerate() {
            columns[i].add_char(ch);
        }
    }

    let mut answer = String::new();
    for col in columns {
        answer.push(col.least_common_char())
    }
    answer
}

pub struct Column {
    freqs: HashMap<char, u32>,
}

impl Column {
    fn add_char(&mut self, ch: char) {
        let count = self.freqs.entry(ch).or_insert(0);
        *count += 1;
    }

    fn least_common_char(&self) -> char {
        let mut f: Vec<(&char, &u32)> = self.freqs.iter().collect();
        f.sort_by(|a, b| a.1.cmp(&b.1));
        *f[0].0
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn least_common_char_seen_in_column() {
        let mut c = Column { freqs: HashMap::new() };
        c.add_char('a');
        c.add_char('b');
        c.add_char('a');
        assert_eq!(c.least_common_char(), 'b');
    }

    #[test]
    fn sample() {
        let input = "\
eedadn
drvtee
eandsr
raavrd
atevrs
tsrnev
sdttsa
rasrtv
nssdts
ntnada
svetve
tesnvt
vntsnd
vrdear
dvrsen
enarar";
        assert_eq!(puzzle(input), String::from("advent"));
    }
}
<commit_msg>Setup for day 7<commit_after>
pub fn puzzle(input: &str) -> u32 {
    0
}

#[cfg(test)]
mod test {
    use super::*;
}
<|endoftext|>


<commit_before>#![cfg(target_os = "linux")]
//! EventFD binding
//!
//! This crate implements a simple binding for Linux eventfd(). See
//! eventfd(2) for specific details of behaviour.

extern crate nix;

use nix::sys::eventfd::eventfd;
pub use nix::sys::eventfd::EfdFlags; // {EfdFlags, EFD_CLOEXEC, EFD_NONBLOCK, EFD_SEMAPHORE};
use nix::unistd::{close, dup, read, write};

use std::io;
use std::mem;
use std::os::unix::io::{AsRawFd, RawFd};
use std::sync::mpsc;
use std::thread;

pub struct EventFD {
    fd: RawFd,
    flags: EfdFlags,
}

unsafe impl Send for EventFD {}
unsafe impl Sync for EventFD {}

impl EventFD {
    /// Create a new EventFD. Flags is the bitwise OR of EFD_* constants, or 0 for no flags.
    /// The underlying file descriptor is closed when the EventFD instance's lifetime ends.
    ///
    /// TODO: work out how to integrate this FD into the wider world
    /// of fds. There's currently no way to poll/select on the fd.
    pub fn new(initval: u32, flags: EfdFlags) -> io::Result<EventFD> {
        Ok(EventFD {
            fd: eventfd(initval, flags)?,
            flags,
        })
    }

    /// Read the current value of the eventfd. This will block until
    /// the value is non-zero. In semaphore mode this will only ever
    /// decrement the count by 1 and return 1; otherwise it atomically
    /// returns the current value and sets it to zero.
    pub fn read(&self) -> io::Result<u64> {
        let mut buf = [0u8; 8];
        let _ = read(self.fd, &mut buf)?;
        let val = u64::from_ne_bytes(buf);
        Ok(val)
    }

    /// Add to the current value. Blocks if the value would wrap u64.
    pub fn write(&self, val: u64) -> io::Result<()> {
        let buf: [u8; 8] = val.to_ne_bytes();
        write(self.fd, &buf)?;
        Ok(())
    }

    /// Return a stream of events.
    ///
    /// The channel has a synchronous sender because there's no point in building up a queue of
    /// events; if this task blocks on send, the event state will still update.
    ///
    /// The task will exit if the receiver end is shut down.
    ///
    /// This will be a CPU-spin loop if the EventFD is created non-blocking.
    ///
    /// XXX FIXME This has no way of terminating except if the other end closes the connection, and
    /// only then if we're not blocked in the read()...
    pub fn events(&self) -> mpsc::Receiver<u64> {
        let (tx, rx) = mpsc::sync_channel(1);
        let c = self.clone();

        thread::spawn(move || loop {
            match c.read() {
                Ok(v) => match tx.send(v) {
                    Ok(_) => (),
                    Err(_) => break,
                },
                Err(e) => panic!("read failed: {}", e),
            }
        });

        rx
    }
}

impl AsRawFd for EventFD {
    /// Return the raw underlying fd. The caller must make sure self's
    /// lifetime is longer than any users of the fd.
    fn as_raw_fd(&self) -> RawFd {
        self.fd as RawFd
    }
}

impl Drop for EventFD {
    fn drop(&mut self) {
        let _ = close(self.fd);
    }
}

/// Construct a linked clone of an existing EventFD. Once created, the
/// new instance interacts with the original in a way that's
/// indistinguishable from the original.
impl Clone for EventFD {
    fn clone(&self) -> EventFD {
        EventFD {
            fd: dup(self.fd).unwrap(),
            flags: self.flags,
        }
    }
}

#[cfg(test)]
mod test {
    extern crate std;
    use super::{EfdFlags, EventFD};
    use std::thread;

    #[test]
    fn test_basic() {
        let (tx, rx) = std::sync::mpsc::channel();
        let efd = match EventFD::new(10, EfdFlags::empty()) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };
        let cefd = efd.clone();

        assert_eq!(efd.read().unwrap(), 10);

        thread::spawn(move || {
            assert_eq!(cefd.read().unwrap(), 7);
            assert_eq!(cefd.write(1).unwrap(), ());
            assert_eq!(cefd.write(2).unwrap(), ());
            assert!(tx.send(()).is_ok());
        });

        assert_eq!(efd.write(7).unwrap(), ());
        let _ = rx.recv();
        assert_eq!(efd.read().unwrap(), 3);
    }

    #[test]
    fn test_sema() {
        let efd = match EventFD::new(0, EfdFlags::EFD_SEMAPHORE | EfdFlags::EFD_NONBLOCK) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };

        match efd.read() {
            Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => (), // ok
            Err(e) => panic!("unexpected error {}", e),
            Ok(v) => panic!("unexpected success {}", v),
        }

        assert_eq!(efd.write(5).unwrap(), ());

        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        match efd.read() {
            Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => (), // ok
            Err(e) => panic!("unexpected error {}", e),
            Ok(v) => panic!("unexpected success {}", v),
        }
    }

    #[test]
    fn test_stream() {
        let efd = match EventFD::new(11, EfdFlags::EFD_SEMAPHORE) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };
        let mut count = 0;

        // only take 10 of 11 so the stream task doesn't block in read and hang the test
        for v in efd.events().iter().take(10) {
            assert_eq!(v, 1);
            count += v;
        }

        assert_eq!(count, 10)
    }

    #[test]
    fn test_chan() {
        let (tx, rx) = std::sync::mpsc::channel();
        let efd = match EventFD::new(10, EfdFlags::empty()) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };

        assert_eq!(efd.write(1).unwrap(), ());
        assert!(tx.send(efd).is_ok());

        let t = thread::spawn(move || {
            let efd = rx.recv().unwrap();
            assert_eq!(efd.read().unwrap(), 11)
        })
        .join();

        match t {
            Ok(_) => println!("ok"),
            Err(_) => panic!("failed"),
        }
    }
}
<commit_msg>update docs and clean warnings<commit_after>#![cfg(target_os = "linux")]
//! EventFD binding
//!
//! This crate implements a simple binding for Linux eventfd(). See
//! eventfd(2) for specific details of behaviour.

extern crate nix;

use nix::sys::eventfd::eventfd;
pub use nix::sys::eventfd::EfdFlags;
use nix::unistd::{close, dup, read, write};

use std::io;
use std::os::unix::io::{AsRawFd, RawFd};
use std::sync::mpsc;
use std::thread;

/// An instance of an eventfd. This is a Linux-specific mechanism for publishing
/// events from the kernel.
pub struct EventFD {
    fd: RawFd,
    flags: EfdFlags,
}

unsafe impl Send for EventFD {}
unsafe impl Sync for EventFD {}

impl EventFD {
    /// Create a new [`EventFD`]. Flags is the bitwise OR of EFD_* constants, or
    /// 0 for no flags. The underlying file descriptor is closed when the
    /// `EventFD` instance's lifetime ends.
    ///
    /// TODO: work out how to integrate this FD into the wider world of fds.
    /// There's currently no way to poll/select on the fd.
    pub fn new(initval: u32, flags: EfdFlags) -> io::Result<EventFD> {
        Ok(EventFD {
            fd: eventfd(initval, flags)?,
            flags,
        })
    }

    /// Read the current value of the eventfd. This will block until the value
    /// is non-zero. In semaphore mode this will only ever decrement the count
    /// by 1 and return 1; otherwise it atomically returns the current value and
    /// sets it to zero.
    pub fn read(&self) -> io::Result<u64> {
        let mut buf = [0u8; 8];
        let _ = read(self.fd, &mut buf)?;
        let val = u64::from_ne_bytes(buf);
        Ok(val)
    }

    /// Add to the current value. Blocks if the value would wrap u64.
    pub fn write(&self, val: u64) -> io::Result<()> {
        let buf: [u8; 8] = val.to_ne_bytes();
        write(self.fd, &buf)?;
        Ok(())
    }

    /// Return a stream of events.
    ///
    /// The channel has a synchronous sender because there's no point in
    /// building up a queue of events; if this task blocks on send, the event
    /// state will still update.
    ///
    /// The task will exit if the receiver end is shut down.
    ///
    /// This will be a CPU-spin loop if the EventFD is created non-blocking.
    ///
    /// XXX FIXME This has no way of terminating except if the other end closes
    /// the connection, and only then if we're not blocked in the read()...
    pub fn events(&self) -> mpsc::Receiver<u64> {
        let (tx, rx) = mpsc::sync_channel(1);
        let c = self.clone();

        thread::spawn(move || loop {
            match c.read() {
                Ok(v) => match tx.send(v) {
                    Ok(_) => (),
                    Err(_) => break,
                },
                Err(e) => panic!("read failed: {}", e),
            }
        });

        rx
    }
}

impl AsRawFd for EventFD {
    /// Return the raw underlying fd. The caller must make sure self's lifetime
    /// is longer than any users of the fd.
    fn as_raw_fd(&self) -> RawFd {
        self.fd as RawFd
    }
}

impl Drop for EventFD {
    fn drop(&mut self) {
        let _ = close(self.fd);
    }
}

/// Construct a linked clone of an existing EventFD. Once created, the new
/// instance interacts with the original in a way that's indistinguishable from
/// the original.
impl Clone for EventFD {
    fn clone(&self) -> EventFD {
        EventFD {
            fd: dup(self.fd).unwrap(),
            flags: self.flags,
        }
    }
}

#[cfg(test)]
mod test {
    extern crate std;
    use super::{EfdFlags, EventFD};
    use std::thread;

    #[test]
    fn test_basic() {
        let (tx, rx) = std::sync::mpsc::channel();
        let efd = match EventFD::new(10, EfdFlags::empty()) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };
        let cefd = efd.clone();

        assert_eq!(efd.read().unwrap(), 10);

        thread::spawn(move || {
            assert_eq!(cefd.read().unwrap(), 7);
            assert_eq!(cefd.write(1).unwrap(), ());
            assert_eq!(cefd.write(2).unwrap(), ());
            assert!(tx.send(()).is_ok());
        });

        assert_eq!(efd.write(7).unwrap(), ());
        let _ = rx.recv();
        assert_eq!(efd.read().unwrap(), 3);
    }

    #[test]
    fn test_sema() {
        let efd = match EventFD::new(0, EfdFlags::EFD_SEMAPHORE | EfdFlags::EFD_NONBLOCK) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };

        match efd.read() {
            Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => (), // ok
            Err(e) => panic!("unexpected error {}", e),
            Ok(v) => panic!("unexpected success {}", v),
        }

        assert_eq!(efd.write(5).unwrap(), ());

        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        match efd.read() {
            Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => (), // ok
            Err(e) => panic!("unexpected error {}", e),
            Ok(v) => panic!("unexpected success {}", v),
        }
    }

    #[test]
    fn test_stream() {
        let efd = match EventFD::new(11, EfdFlags::EFD_SEMAPHORE) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };
        let mut count = 0;

        // only take 10 of 11 so the stream task doesn't block in read and hang the test
        for v in efd.events().iter().take(10) {
            assert_eq!(v, 1);
            count += v;
        }

        assert_eq!(count, 10)
    }

    #[test]
    fn test_chan() {
        let (tx, rx) = std::sync::mpsc::channel();
        let efd = match EventFD::new(10, EfdFlags::empty()) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };

        assert_eq!(efd.write(1).unwrap(), ());
        assert!(tx.send(efd).is_ok());

        let t = thread::spawn(move || {
            let efd = rx.recv().unwrap();
            assert_eq!(efd.read().unwrap(), 11)
        })
        .join();

        match t {
            Ok(_) => println!("ok"),
            Err(_) => panic!("failed"),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

//! SimpleStream crate.

extern crate libc;
extern crate errno;

use std::{mem, ptr};
use std::result::Result;
use std::net::TcpStream;
use std::os::unix::io::AsRawFd;

use self::errno::errno;
use self::libc::consts::os::posix88;
use self::libc::{size_t, c_void, c_int, ssize_t};

use util::*;
use readbuffer::ReadBuffer;

pub mod util;
mod message;
mod readbuffer;

extern "C" {
    fn read(fd: c_int, buffer: *mut c_void, count: size_t) -> ssize_t;
    fn write(fd: c_int, buffer: *const c_void, cout: size_t) -> ssize_t;
}

/// Represents the result of trying to create a new SimpleStream
pub type CreateResult = Result<SimpleStream, FnctlError>;

/// Represents the result of attempting a read on the underlying file descriptor
pub type ReadResult = Result<(), ReadError>;

/// Represents the result attempting a write on the underlying fild descriptor
pub type WriteResult = Result<u16, WriteError>;

/// States the current stream can be in
#[derive(PartialEq, Clone)]
pub enum ReadState {
    /// Currently reading the payload length
    PayloadLen,
    /// Currently reading the payload
    Payload
}

/// Struct representing a simple messaging protocol over Tcp sockets
pub struct SimpleStream {
    /// Current state
    state: ReadState,
    /// Underlying std::net::TcpStream
    stream: TcpStream,
    /// Message buffer
    buffer: ReadBuffer
}

impl SimpleStream {

    /// Attempts to create a new SimpleStream from a TcpStream
    pub fn new(stream: TcpStream) -> CreateResult {
        let fd = stream.as_raw_fd();
        let mut response;
        unsafe {
            response = libc::fcntl(
                fd,
                libc::consts::os::posix01::F_SETFL,
                libc::consts::os::extra::O_NONBLOCK);
        }

        if response < 0 {
            let errno = errno().0 as i32;
            return match errno {
                posix88::EAGAIN     => Err(FnctlError::EAGAIN),
                posix88::EBADF      => Err(FnctlError::EBADF),
                posix88::EDEADLK    => Err(FnctlError::EDEADLK),
                posix88::EFAULT     => Err(FnctlError::EFAULT),
                posix88::EINTR      => Err(FnctlError::EINTR),
                posix88::EINVAL     => Err(FnctlError::EINVAL),
                posix88::EMFILE     => Err(FnctlError::EMFILE),
                posix88::ENOLCK     => Err(FnctlError::ENOLCK),
                posix88::EPERM      => Err(FnctlError::EPERM),
                _ => panic!("Unexpected errno: {}", errno)
            };
        }

        Ok(SimpleStream {
            state: ReadState::PayloadLen,
            stream: stream,
            buffer: ReadBuffer::new()
        })
    }

    /// Performs a read on the underlying fd. Places all received messages into
    /// the queue in the ReadBuffer. Reads until EAGAIN is hit.
    pub fn read(&mut self) -> ReadResult {
        // We need to loop until EAGAIN is hit from read_num_bytes.
        // Epoll is set to EdgeTrigged mode, which will let us known when there
        // is data to be read on the file descriptor, but if we do not clear it
        // all in this run we will lose whatever we do not grab.
        loop {
            let count = self.buffer.remaining();
            let result = self.read_num_bytes(count);
            if result.is_err() {
                let err = result.unwrap_err();
                match err {
                    ReadError::EAGAIN => {
                        return Ok(())
                    }
                    ReadError::EWOULDBLOCK => {
                        return Ok(())
                    }
                    _ => return Err(err)
                }
            }

            if self.buffer.remaining() == 0 {
                if self.state == ReadState::PayloadLen {
                    self.buffer.calc_payload_len();
                    let p_len = self.buffer.payload_len();
                    self.buffer.set_capacity(p_len);
                    self.state = ReadState::Payload;
                } else { // Payload completely read
                    self.buffer.reset();
                    self.state = ReadState::PayloadLen;
                }
            }
        }
    }

    /// Attempts to read num bytes from the underlying file descriptor.
    fn read_num_bytes(&mut self, num: u16) -> ReadResult {
        let fd = self.stream.as_raw_fd();

        // Create a buffer, size num
        let mut buffer;
        unsafe {
            buffer = libc::calloc(num as size_t,
                mem::size_of::<u8>() as size_t);
        }

        // Ensure system gave up dynamic memory
        if buffer.is_null() {
            return Err(ReadError::ENOMEM)
        }

        // Attempt to read available data into buffer
        let mut num_read;
        unsafe {
            num_read = read(fd, buffer, num as size_t);
        }

        // Return on error
        if num_read < 0 {
            unsafe { libc::free(buffer); }
            let errno = errno().0 as i32;
            return match errno {
                posix88::ENOMEM         => Err(ReadError::ENOMEM),
                posix88::EBADF          => Err(ReadError::EBADF),
                posix88::EFAULT         => Err(ReadError::EFAULT),
                posix88::EINTR          => Err(ReadError::EINTR),
                posix88::EINVAL         => Err(ReadError::EINVAL),
                posix88::EIO            => Err(ReadError::EIO),
                posix88::EISDIR         => Err(ReadError::EISDIR),

                // These two constants can have the same value on some systems,
                // but different values on others, so we can't use a match
                // clause
                x if x == posix88::EAGAIN || x == posix88::EWOULDBLOCK =>
                    Err(ReadError::EAGAIN),

                _ => panic!("Unexpected errno during read: {}", errno)
            };
        }

        // Check for EOF
        if num_read == 0 {
            unsafe { libc::free(buffer); }
            return Err(ReadError::EOF);
        }

        // Add bytes to msg buffer
        for x in 0..num_read as isize {
            unsafe {
                self.buffer.push(ptr::read(buffer.offset(x)) as u8);
            }
        }

        // Free buffer and return Ok
        unsafe { libc::free(buffer); }
        Ok(())
    }

    ///
    pub fn write(&mut self, buffer: &Vec<u8>) -> WriteResult {
        let mut plen_buf = [0u8; 2];
        plen_buf[0] = (buffer.len() as u16 & 0b1111_1111u16 << 8) as u8;
        plen_buf[1] = (buffer.len() as u16 & 0b1111_1111u16) as u8;

        let mut n_buffer = Vec::<u8>::with_capacity(buffer.len() + 2);
        n_buffer.push(plen_buf[0]);
        n_buffer.push(plen_buf[1]);

        for x in 0..buffer.len() {
            n_buffer.push(buffer[x]);
        }

        self.write_bytes(&mut n_buffer)
    }

    ///
    fn write_bytes(&mut self, buffer: &mut Vec<u8>) -> WriteResult {
        let fd = self.stream.as_raw_fd();

        let mut num_written;
        unsafe {
            let buf_slc = &buffer[..];
            let buf_ptr = buf_slc.as_ptr();
            let v_ptr: *const c_void = mem::transmute(buf_ptr);
            num_written = write(fd,
                v_ptr,
                buffer.len() as size_t);
        }

        if num_written < 0 {
            let errno = errno().0 as i32;
            return match errno {
                posix88::EBADF          => Err(WriteError::EBADF),
                posix88::EDESTADDRREQ   => Err(WriteError::EDESTADDRREQ),
                posix88::EDQUOT         => Err(WriteError::EDQUOT),
                posix88::EFAULT         => Err(WriteError::EFAULT),
                posix88::EFBIG          => Err(WriteError::EFBIG),
                posix88::EINTR          => Err(WriteError::EINTR),
                posix88::EINVAL         => Err(WriteError::EINVAL),
                posix88::EIO            => Err(WriteError::EIO),
                posix88::ENOSPC         => Err(WriteError::ENOSPC),
                posix88::EPIPE          => Err(WriteError::EPIPE),

                // These two constants can have the same value on some systems,
                // but different values on others, so we can't use a match
                // clause
                x if x == posix88::EAGAIN || x == posix88::EWOULDBLOCK =>
                    Err(WriteError::EAGAIN),

                _ => panic!("Unknown errno during write: {}", errno),
            }
        }

        Ok(num_written as u16)
    }
}

impl Clone for SimpleStream {
    fn clone(&self) -> SimpleStream {
        SimpleStream {
            state: self.state.clone(),
            stream: self.stream.try_clone().unwrap(),
            buffer: self.buffer.clone()
        }
    }
}
<commit_msg>Added access to underlying file descriptor<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

//! SimpleStream crate.

extern crate libc;
extern crate errno;

use std::{mem, ptr};
use std::result::Result;
use std::net::TcpStream;
use std::os::unix::io::AsRawFd;

use self::errno::errno;
use self::libc::consts::os::posix88;
use self::libc::{size_t, c_void, c_int, ssize_t};

use util::*;
use readbuffer::ReadBuffer;

pub mod util;
mod message;
mod readbuffer;

extern "C" {
    fn read(fd: c_int, buffer: *mut c_void, count: size_t) -> ssize_t;
    fn write(fd: c_int, buffer: *const c_void, cout: size_t) -> ssize_t;
}

/// Represents the result of trying to create a new SimpleStream
pub type CreateResult = Result<SimpleStream, FnctlError>;

/// Represents the result of attempting a read on the underlying file descriptor
pub type ReadResult = Result<(), ReadError>;

/// Represents the result attempting a write on the underlying fild descriptor
pub type WriteResult = Result<u16, WriteError>;

/// States the current stream can be in
#[derive(PartialEq, Clone)]
pub enum ReadState {
    /// Currently reading the payload length
    PayloadLen,
    /// Currently reading the payload
    Payload
}

/// Struct representing a simple messaging protocol over Tcp sockets
pub struct SimpleStream {
    /// Current state
    state: ReadState,
    /// Underlying std::net::TcpStream
    stream: TcpStream,
    /// Message buffer
    buffer: ReadBuffer
}

impl SimpleStream {

    /// Attempts to create a new SimpleStream from a TcpStream
    pub fn new(stream: TcpStream) -> CreateResult {
        let fd = stream.as_raw_fd();
        let mut response;
        unsafe {
            response = libc::fcntl(
                fd,
                libc::consts::os::posix01::F_SETFL,
                libc::consts::os::extra::O_NONBLOCK);
        }

        if response < 0 {
            let errno = errno().0 as i32;
            return match errno {
                posix88::EAGAIN     => Err(FnctlError::EAGAIN),
                posix88::EBADF      => Err(FnctlError::EBADF),
                posix88::EDEADLK    => Err(FnctlError::EDEADLK),
                posix88::EFAULT     => Err(FnctlError::EFAULT),
                posix88::EINTR      => Err(FnctlError::EINTR),
                posix88::EINVAL     => Err(FnctlError::EINVAL),
                posix88::EMFILE     => Err(FnctlError::EMFILE),
                posix88::ENOLCK     => Err(FnctlError::ENOLCK),
                posix88::EPERM      => Err(FnctlError::EPERM),
                _ => panic!("Unexpected errno: {}", errno)
            };
        }

        Ok(SimpleStream {
            state: ReadState::PayloadLen,
            stream: stream,
            buffer: ReadBuffer::new()
        })
    }

    /// Performs a read on the underlying fd. Places all received messages into
    /// the queue in the ReadBuffer. Reads until EAGAIN is hit.
    pub fn read(&mut self) -> ReadResult {
        // We need to loop until EAGAIN is hit from read_num_bytes.
        // Epoll is set to EdgeTrigged mode, which will let us known when there
        // is data to be read on the file descriptor, but if we do not clear it
        // all in this run we will lose whatever we do not grab.
        loop {
            let count = self.buffer.remaining();
            let result = self.read_num_bytes(count);
            if result.is_err() {
                let err = result.unwrap_err();
                match err {
                    ReadError::EAGAIN => {
                        return Ok(())
                    }
                    ReadError::EWOULDBLOCK => {
                        return Ok(())
                    }
                    _ => return Err(err)
                }
            }

            if self.buffer.remaining() == 0 {
                if self.state == ReadState::PayloadLen {
                    self.buffer.calc_payload_len();
                    let p_len = self.buffer.payload_len();
                    self.buffer.set_capacity(p_len);
                    self.state = ReadState::Payload;
                } else { // Payload completely read
                    self.buffer.reset();
                    self.state = ReadState::PayloadLen;
                }
            }
        }
    }

    /// Attempts to read num bytes from the underlying file descriptor.
    fn read_num_bytes(&mut self, num: u16) -> ReadResult {
        let fd = self.stream.as_raw_fd();

        // Create a buffer, size num
        let mut buffer;
        unsafe {
            buffer = libc::calloc(num as size_t,
                mem::size_of::<u8>() as size_t);
        }

        // Ensure system gave up dynamic memory
        if buffer.is_null() {
            return Err(ReadError::ENOMEM)
        }

        // Attempt to read available data into buffer
        let mut num_read;
        unsafe {
            num_read = read(fd, buffer, num as size_t);
        }

        // Return on error
        if num_read < 0 {
            unsafe { libc::free(buffer); }
            let errno = errno().0 as i32;
            return match errno {
                posix88::ENOMEM         => Err(ReadError::ENOMEM),
                posix88::EBADF          => Err(ReadError::EBADF),
                posix88::EFAULT         => Err(ReadError::EFAULT),
                posix88::EINTR          => Err(ReadError::EINTR),
                posix88::EINVAL         => Err(ReadError::EINVAL),
                posix88::EIO            => Err(ReadError::EIO),
                posix88::EISDIR         => Err(ReadError::EISDIR),

                // These two constants can have the same value on some systems,
                // but different values on others, so we can't use a match
                // clause
                x if x == posix88::EAGAIN || x == posix88::EWOULDBLOCK =>
                    Err(ReadError::EAGAIN),

                _ => panic!("Unexpected errno during read: {}", errno)
            };
        }

        // Check for EOF
        if num_read == 0 {
            unsafe { libc::free(buffer); }
            return Err(ReadError::EOF);
        }

        // Add bytes to msg buffer
        for x in 0..num_read as isize {
            unsafe {
                self.buffer.push(ptr::read(buffer.offset(x)) as u8);
            }
        }

        // Free buffer and return Ok
        unsafe { libc::free(buffer); }
        Ok(())
    }

    ///
    pub fn write(&mut self, buffer: &Vec<u8>) -> WriteResult {
        let mut plen_buf = [0u8; 2];
        plen_buf[0] = (buffer.len() as u16 & 0b1111_1111u16 << 8) as u8;
        plen_buf[1] = (buffer.len() as u16 & 0b1111_1111u16) as u8;

        let mut n_buffer = Vec::<u8>::with_capacity(buffer.len() + 2);
        n_buffer.push(plen_buf[0]);
        n_buffer.push(plen_buf[1]);

        for x in 0..buffer.len() {
            n_buffer.push(buffer[x]);
        }

        self.write_bytes(&mut n_buffer)
    }

    ///
    fn write_bytes(&mut self, buffer: &mut Vec<u8>) -> WriteResult {
        let fd = self.stream.as_raw_fd();

        let mut num_written;
        unsafe {
            let buf_slc = &buffer[..];
            let buf_ptr = buf_slc.as_ptr();
            let v_ptr: *const c_void = mem::transmute(buf_ptr);
            num_written = write(fd,
                v_ptr,
                buffer.len() as size_t);
        }

        if num_written < 0 {
            let errno = errno().0 as i32;
            return match errno {
                posix88::EBADF          => Err(WriteError::EBADF),
                posix88::EDESTADDRREQ   => Err(WriteError::EDESTADDRREQ),
                posix88::EDQUOT         => Err(WriteError::EDQUOT),
                posix88::EFAULT         => Err(WriteError::EFAULT),
                posix88::EFBIG          => Err(WriteError::EFBIG),
                posix88::EINTR          => Err(WriteError::EINTR),
                posix88::EINVAL         => Err(WriteError::EINVAL),
                posix88::EIO            => Err(WriteError::EIO),
                posix88::ENOSPC         => Err(WriteError::ENOSPC),
                posix88::EPIPE          => Err(WriteError::EPIPE),

                // These two constants can have the same value on some systems,
                // but different values on others, so we can't use a match
                // clause
                x if x == posix88::EAGAIN || x == posix88::EWOULDBLOCK =>
                    Err(WriteError::EAGAIN),

                _ => panic!("Unknown errno during write: {}", errno),
            }
        }

        Ok(num_written as u16)
    }

    /// Returns the underlying file descriptor
    pub fn raw_fd(&self) -> RawFd {
        self.stream.as_raw_fd()
    }
}

impl Clone for SimpleStream {
    fn clone(&self) -> SimpleStream {
        SimpleStream {
            state: self.state.clone(),
            stream: self.stream.try_clone().unwrap(),
            buffer: self.buffer.clone()
        }
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use std::ffi::CString;
use libc::types::os::arch::c95::{c_char, time_t};

// C function definitions
#[link(name = "raw")]
extern {
    fn libraw_init(flags: u32) -> *mut LibrawData;
    fn libraw_open_file(imgdat: *mut LibrawData, fpath: *const libc::c_char) -> i32;
    fn libraw_open_buffer(imgdat: *mut LibrawData, buffer: &[u8], bufsize: libc::size_t) -> i32;
    fn libraw_unpack(imgdat: *mut LibrawData) -> i32;
    fn libraw_unpack_thumb(imgdat: *mut LibrawData) -> i32;
}

// C struct definitions
#[repr(C)]
pub struct LibrawData {
    image: [*mut u16; 4],
    sizes: LibrawImageSizes,
    idata: LibrawIparams,
    progress_flags: u32,
    process_warnings: u32,
    color: LibrawColorData,
    other: LibrawImgOther,
    thumbnail: LibrawThumb,
    rawdata: LibrawRawData,
    parent_class: *mut libc::c_void,
}

#[repr(C)]
pub struct LibrawImageSizes {
    raw_height: u16,
    raw_width: u16,
    height: u16,
    width: u16,
    top_margin: u16,
    left_margin: u16,
    iheight: u16,
    iwidth: u16,
    raw_pitch: u32,
    pixel_aspect: f64,
    flip: i32,
    mask: [[u32; 8]; 4],
}

#[repr(C)]
pub struct LibrawIparams {
    make: [c_char; 64],
    model: [c_char; 64],
    raw_count: u32,
    dng_version: u32,
    is_foveon: u32,
    colors: i32,
    filters: u32,
    xtrans: [[c_char; 6]; 6],
    cdesc: [c_char; 5],
}

#[repr(C)]
pub struct LibrawColorData {
    make: [c_char; 64],
    model: [c_char; 64],
    raw_count: u32,
    dng_version: u32,
    is_foveon: u32,
    colors: i32,
    filters: u32,
    xtrans: [[c_char; 6]; 6],
    cdesc: [c_char; 5],
    phase_one_data: LibrawPh1,
    flash_used: f32,
    canon_ev: f32,
    model2: [c_char; 64],
    profile: *mut libc::c_void,
    profile_length: u32,
    black_stat: [u32; 8],
}

#[repr(C)]
pub struct LibrawPh1 {
    format: i32,
    key_off: i32,
    t_black: i32,
    black_off: i32,
    split_col: i32,
    tag_21a: i32,
    tag_210: f32,
}

#[repr(C)]
pub struct LibrawImgOther {
    iso_speed: f32,
    shutter: f32,
    aperture: f32,
    focal_len: f32,
    timestamp: time_t,
    shot_order: u32,
    gpsdata: [u32; 32],
    desc: [c_char; 512],
    artist: [c_char; 64],
}

#[repr(C)]
pub struct LibrawThumb {
    tformat: LibrawThumbnailFormat,
    twidth: u16,
    theight: u16,
    tlength: u32,
    tcolors: i32,
    thumb: *mut c_char,
}

#[repr(C)]
pub struct LibrawRawData {
    raw_alloc: *mut libc::c_void,
    raw_image: *mut u16,
    color4_image: [*mut u16; 4],
    color3_image: [*mut u16; 3],
    ph1_black: [*mut i16; 2],
    iparams: LibrawIparams,
    sizes: LibrawImageSizes,
    ioparams: LibrawInternalOutputParams,
    color: LibrawColorData,
}

#[repr(C)]
pub struct LibrawInternalOutputParams {
    mix_green: u32,
    raw_color: u32,
    zero_is_bad: u32,
    shrink: u16,
    fuji_width: u16,
}

// C enum definitions
#[repr(C)]
enum LibrawThumbnailFormat {
    Unknown = 0,
    Jpeg = 1,
    Bitmap = 2,
    Layer = 4,
    Rollei = 5,
}
<commit_msg>Add high-level functions for allocation and load from path<commit_after>extern crate libc;

use std::error;
use std::fmt;
use std::ffi::CString;
use libc::types::os::arch::c95::{c_char, time_t};

// C function definitions
#[link(name = "raw")]
extern {
    fn libraw_init(flags: u32) -> *mut LibrawData;
    fn libraw_open_file(imgdat: *mut LibrawData, fpath: *const libc::c_char) -> i32;
    fn libraw_open_buffer(imgdat: *mut LibrawData, buffer: &[u8], bufsize: libc::size_t) -> i32;
    fn libraw_unpack(imgdat: *mut LibrawData) -> i32;
    fn libraw_unpack_thumb(imgdat: *mut LibrawData) -> i32;
}

// C struct definitions
#[repr(C)]
pub struct LibrawData {
    image: [*mut u16; 4],
    sizes: LibrawImageSizes,
    idata: LibrawIparams,
    progress_flags: u32,
    process_warnings: u32,
    color: LibrawColorData,
    other: LibrawImgOther,
    thumbnail: LibrawThumb,
    rawdata: LibrawRawData,
    parent_class: *mut libc::c_void,
}

#[repr(C)]
struct LibrawImageSizes {
    raw_height: u16,
    raw_width: u16,
    height: u16,
    width: u16,
    top_margin: u16,
    left_margin: u16,
    iheight: u16,
    iwidth: u16,
    raw_pitch: u32,
    pixel_aspect: f64,
    flip: i32,
    mask: [[u32; 8]; 4],
}

#[repr(C)]
struct LibrawIparams {
    make: [c_char; 64],
    model: [c_char; 64],
    raw_count: u32,
    dng_version: u32,
    is_foveon: u32,
    colors: i32,
    filters: u32,
    xtrans: [[c_char; 6]; 6],
    cdesc: [c_char; 5],
}

#[repr(C)]
struct LibrawColorData {
    make: [c_char; 64],
    model: [c_char; 64],
    raw_count: u32,
    dng_version: u32,
    is_foveon: u32,
    colors: i32,
    filters: u32,
    xtrans: [[c_char; 6]; 6],
    cdesc: [c_char; 5],
    phase_one_data: LibrawPh1,
    flash_used: f32,
    canon_ev: f32,
    model2: [c_char; 64],
    profile: *mut libc::c_void,
    profile_length: u32,
    black_stat: [u32; 8],
}

#[repr(C)]
struct LibrawPh1 {
    format: i32,
    key_off: i32,
    t_black: i32,
    black_off: i32,
    split_col: i32,
    tag_21a: i32,
    tag_210: f32,
}

#[repr(C)]
struct LibrawImgOther {
    iso_speed: f32,
    shutter: f32,
    aperture: f32,
    focal_len: f32,
    timestamp: time_t,
    shot_order: u32,
    gpsdata: [u32; 32],
    desc: [c_char; 512],
    artist: [c_char; 64],
}

#[repr(C)]
struct LibrawThumb {
    tformat: LibrawThumbnailFormat,
    twidth: u16,
    theight: u16,
    tlength: u32,
    tcolors: i32,
    thumb: *mut c_char,
}

#[repr(C)]
struct LibrawRawData {
    raw_alloc: *mut libc::c_void,
    raw_image: *mut u16,
    color4_image: [*mut u16; 4],
    color3_image: [*mut u16; 3],
    ph1_black: [*mut i16; 2],
    iparams: LibrawIparams,
    sizes: LibrawImageSizes,
    ioparams: LibrawInternalOutputParams,
    color: LibrawColorData,
}

#[repr(C)]
struct LibrawInternalOutputParams {
    mix_green: u32,
    raw_color: u32,
    zero_is_bad: u32,
    shrink: u16,
    fuji_width: u16,
}

// C enum definitions
#[repr(C)]
enum LibrawThumbnailFormat {
    Unknown = 0,
    Jpeg = 1,
    Bitmap = 2,
    Layer = 4,
    Rollei = 5,
}

// Errors
pub enum LibrawError {
    NulError(std::ffi::NulError),
    AllocError(LibrawAllocError),
    IOError(std::io::Error),
    LibError(LibrawLibraryError),
}

#[derive(Debug)]
pub struct LibrawAllocError;

impl fmt::Display for LibrawAllocError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        "image data allocation failed".fmt(f)
    }
}

impl error::Error for LibrawAllocError {
    fn description(&self) -> &str {
        "image data allocation failed"
    }
}

#[derive(Debug)]
pub struct LibrawLibraryError;

impl fmt::Display for LibrawLibraryError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        "internal libraw library error".fmt(f)
    }
}

impl error::Error for LibrawLibraryError {
    fn description(&self) -> &str {
        "internal libraw library error"
    }
}

// Higher-level unsafe methods
unsafe fn init_data() -> Result<*mut LibrawData, LibrawError> {
    // 0 = no flags
    // 1 = no memory error callback
    // 2 = non data error callback
    // 3 = both
    let data = libraw_init(3);
    if data.is_null() {
        Err(LibrawError::AllocError(LibrawAllocError))
    } else {
        Ok(data)
    }
}

unsafe fn read_img(filepath: &str) -> Result<*mut LibrawData, LibrawError> {
    let fpath = match CString::new(filepath) {
        Ok(v) => v,
        Err(e) => return Err(LibrawError::NulError(e)),
    };
    let data = try!(init_data());
    let res: i32 = libraw_open_file(data, fpath.as_ptr());
    if res > 0 {
        Err(LibrawError::IOError(std::io::Error::from_raw_os_error(res)))
    } else if res < 0 {
        Err(LibrawError::LibError(LibrawLibraryError))
    } else {
        Ok(data)
    }
}
<|endoftext|>


<commit_before>use std::fmt;

mod token;
mod parser;
mod optimizer;
mod compiler;

pub use token::Token;
pub use parser::parse;

/// Intermediate representation used by isbfc
pub struct IsbfcIR {
    /// Syntax tree of tokens
    pub tokens: Vec<Token>
}

impl fmt::Debug for IsbfcIR {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.tokens.fmt(f)
    }
}
<commit_msg>Add crate level documentation with example<commit_after>//! Isbfc is an optimizing brainfuck compiler targeting x86_64 Linux
//!
//! # Examples
//! ```
//! extern crate isbfc;
//!
//! fn main() {
//!     // 2048 is the tape length to use
//!     let assembly = isbfc::parse(",[.,]").optimize().compile(2048);
//!     print!("{}", assembly);
//! }
//! ```

use std::fmt;

mod token;
mod parser;
mod optimizer;
mod compiler;

pub use token::Token;
pub use parser::parse;

/// Intermediate representation used by isbfc
pub struct IsbfcIR {
    /// Syntax tree of tokens
    pub tokens: Vec<Token>
}

impl fmt::Debug for IsbfcIR {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.tokens.fmt(f)
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

#[macro_use]
extern crate pest;

extern crate rand;

mod parse;

use pest::*;
use parse::*;

pub fn roll_dice(r: &str) -> i32 {
    let mut parser = Rdp::new(StringInput::new(r));
    parser.expression();

    parser.compute()
}

#[derive(Debug)]
pub struct Roller<'a> {
    roll: &'a str,
    total: i32,
}

impl<'a> Roller<'a> {
     fn new(roll: &str) -> Roller {
         Roller{
             roll: roll,
             total: roll_dice(roll)
         }
     }

     fn reroll(&mut self) -> i32 {
         self.total = roll_dice(self.roll);

         self.total
     }

     fn total(&self) -> i32 {
         self.total
     }
}

#[test]
fn it_works() {
    let mut roller = Roller::new("4d6");

    assert!((4 <= roller.total()) && (roller.total() <= 24));

    assert!(roller.total() != roller.reroll());
}<commit_msg>Remove lame tests<commit_after>#![allow(dead_code)]

#[macro_use]
extern crate pest;

extern crate rand;

mod parse;

use pest::*;
use parse::*;

pub fn roll_dice(r: &str) -> i32 {
    let mut parser = Rdp::new(StringInput::new(r));
    parser.expression();

    parser.compute()
}

#[derive(Debug)]
pub struct Roller<'a> {
    roll: &'a str,
    total: i32,
}

impl<'a> Roller<'a> {
     fn new(roll: &str) -> Roller {
         Roller{
             roll: roll,
             total: roll_dice(roll)
         }
     }

     fn reroll(&mut self) -> i32 {
         self.total = roll_dice(self.roll);

         self.total
     }

     fn total(&self) -> i32 {
         self.total
     }
}<|endoftext|>