<commit_before>extern crate discord;

use discord::Discord;
use std::env;

fn main() {
	let discord = Discord::new(
		&env::var("DISCORD_EMAIL").expect("DISCORD_EMAIL"),
		&env::var("DISCORD_PASSWORD").expect("DISCORD_PASSWORD")
	).expect("login failed");

	let test_zone = discord::ChannelId("".into());
	//println!("{:#?}", discord.send_message(&test_zone, "Hello from Rust", &[], "", false));
	discord.broadcast_typing(&test_zone).expect("broadcast typing failed");

	let mut connection = discord.connect().expect("connect failed");
	let closed;
	loop {
		match connection.recv_event() {
			Ok(discord::Event::Closed(n)) => { closed = n; break },
			Ok(discord::Event::Ready { .. }) => { println!("Ready."); continue },
			Ok(discord::Event::MessageCreate(message)) => {
				let (server, channel) = match connection.state.find_public_channel(&message.channel_id) {
					Some(info) => info,
					None => { println!("PRIVMSG {:?}", message); continue },
				};
				println!("[{} #{}] {}: {}", server.name, channel.name, message.author.name, message.content);
				if message.content == "/test" || message.content.starts_with("/test ") {
					warn(discord.send_message(&message.channel_id, "This is a reply to the test.", &[], "", false));
				} else if message.content == "/quit" {
					closed = 200;
					break
				}
			}
			Ok(discord::Event::Unknown(name, data)) => println!("--- {}: {:?}", name, data),
			Ok(_) => {}, // println!("--- {:?}", other),
			Err(err) => println!("Recv error: {:?}", err),
		}
	}
	println!("Closed upon with status '{}'", closed);

	discord.logout().expect("logout failed");
}

fn warn<T, E: ::std::fmt::Debug>(result: Result<T, E>) {
	match result {
		Ok(_) => {},
		Err(err) => println!("[warn] {:?}", err)
	}
}
<commit_msg>Removed typing broadcast from bot example<commit_after>extern crate discord;

use discord::Discord;
use std::env;

fn main() {
	let discord = Discord::new(
		&env::var("DISCORD_EMAIL").expect("DISCORD_EMAIL"),
		&env::var("DISCORD_PASSWORD").expect("DISCORD_PASSWORD")
	).expect("login failed");

	let mut connection = discord.connect().expect("connect failed");
	let closed;
	loop {
		match connection.recv_event() {
			Ok(discord::Event::Closed(n)) => { closed = n; break },
			Ok(discord::Event::Ready { .. }) => { println!("Ready."); continue },
			Ok(discord::Event::MessageCreate(message)) => {
				let (server, channel) = match connection.state.find_public_channel(&message.channel_id) {
					Some(info) => info,
					None => { println!("PRIVMSG {:?}", message); continue },
				};
				println!("[{} #{}] {}: {}", server.name, channel.name, message.author.name, message.content);
				if message.content == "/test" || message.content.starts_with("/test ") {
					warn(discord.send_message(&message.channel_id, "This is a reply to the test.", &[], "", false));
				} else if message.content == "/quit" {
					closed = 200;
					break
				}
			}
			Ok(discord::Event::Unknown(name, data)) => println!("--- {}: {:?}", name, data),
			Ok(_) => {}, // println!("--- {:?}", other),
			Err(err) => println!("Recv error: {:?}", err),
		}
	}
	println!("Closed upon with status '{}'", closed);

	discord.logout().expect("logout failed");
}

fn warn<T, E: ::std::fmt::Debug>(result: Result<T, E>) {
	match result {
		Ok(_) => {},
		Err(err) => println!("[warn] {:?}", err)
	}
}
<|endoftext|>


<commit_before>#![crate_name = "uu_factor"]

/*
* This file is part of the uutils coreutils package.
*
* (c) T. Jameson Little <t.jameson.little@gmail.com>
* (c) Wiktor Kuropatwa <wiktor.kuropatwa@gmail.com>
*     20150223 added Pollard rho method implementation
* (c) kwantam <kwantam@gmail.com>
*     20150429 sped up trial division by adding table of prime inverses
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

extern crate rand;

#[macro_use]
extern crate uucore;

use numeric::*;
use rand::distributions::{Distribution, Uniform};
use rand::rngs::SmallRng;
use rand::{thread_rng, SeedableRng};
use std::cmp::{max, min};
use std::io::{stdin, BufRead};
use std::mem::swap;
use std::num::Wrapping;

mod numeric;

include!(concat!(env!("OUT_DIR"), "/prime_table.rs"));

static SYNTAX: &str = "[OPTION] [NUMBER]...";
static SUMMARY: &str = "Print the prime factors of the given number(s).
 If none are specified, read from standard input.";
static LONG_HELP: &str = "";

fn rho_pollard_pseudorandom_function(x: u64, a: u64, b: u64, num: u64) -> u64 {
    if num < 1 << 63 {
        (sm_mul(a, sm_mul(x, x, num), num) + b) % num
    } else {
        big_add(big_mul(a, big_mul(x, x, num), num), b, num)
    }
}

fn gcd(mut a: u64, mut b: u64) -> u64 {
    while b > 0 {
        a %= b;
        swap(&mut a, &mut b);
    }
    a
}

fn rho_pollard_find_divisor(num: u64) -> u64 {
    #![allow(clippy::many_single_char_names)]
    let range = Uniform::new(1, num);
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    let mut x = range.sample(&mut rng);
    let mut y = x;
    let mut a = range.sample(&mut rng);
    let mut b = range.sample(&mut rng);

    loop {
        x = rho_pollard_pseudorandom_function(x, a, b, num);
        y = rho_pollard_pseudorandom_function(y, a, b, num);
        y = rho_pollard_pseudorandom_function(y, a, b, num);
        let d = gcd(num, max(x, y) - min(x, y));
        if d == num {
            // Failure, retry with different function
            x = range.sample(&mut rng);
            y = x;
            a = range.sample(&mut rng);
            b = range.sample(&mut rng);
        } else if d > 1 {
            return d;
        }
    }
}

fn rho_pollard_factor(num: u64, factors: &mut Vec<u64>) {
    if is_prime(num) {
        factors.push(num);
        return;
    }
    let divisor = rho_pollard_find_divisor(num);
    rho_pollard_factor(divisor, factors);
    rho_pollard_factor(num / divisor, factors);
}

fn table_division(mut num: u64, factors: &mut Vec<u64>) {
    if num < 2 {
        return;
    }
    while num % 2 == 0 {
        num /= 2;
        factors.push(2);
    }
    if num == 1 {
        return;
    }
    if is_prime(num) {
        factors.push(num);
        return;
    }
    for &(prime, inv, ceil) in P_INVS_U64 {
        if num == 1 {
            break;
        }

        // inv = prime^-1 mod 2^64
        // ceil = floor((2^64-1) / prime)
        // if (num * inv) mod 2^64 <= ceil, then prime divides num
        // See http://math.stackexchange.com/questions/1251327/
        // for a nice explanation.
        loop {
            let Wrapping(x) = Wrapping(num) * Wrapping(inv); // x = num * inv mod 2^64
            if x <= ceil {
                num = x;
                factors.push(prime);
                if is_prime(num) {
                    factors.push(num);
                    return;
                }
            } else {
                break;
            }
        }
    }

    // do we still have more factoring to do?
    // Decide whether to use Pollard Rho or slow divisibility based on
    // number's size:
    //if num >= 1 << 63 {
    // number is too big to use rho pollard without overflowing
    //trial_division_slow(num, factors);
    //} else if num > 1 {
    // number is still greater than 1, but not so big that we have to worry
    rho_pollard_factor(num, factors);
    //}
}

fn print_factors(num: u64) {
    print!("{}:", num);

    let mut factors = Vec::new();
    // we always start with table division, and go from there
    table_division(num, &mut factors);
    factors.sort();

    for fac in &factors {
        print!(" {}", fac);
    }
    println!();
}

fn print_factors_str(num_str: &str) {
    if let Err(e) = num_str.parse::<u64>().and_then(|x| {
        print_factors(x);
        Ok(())
    }) {
        show_warning!("{}: {}", num_str, e);
    }
}

pub fn uumain(args: Vec<String>) -> i32 {
    let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP).parse(args);

    if matches.free.is_empty() {
        let stdin = stdin();
        for line in stdin.lock().lines() {
            for number in line.unwrap().split_whitespace() {
                print_factors_str(number);
            }
        }
    } else {
        for num_str in &matches.free {
            print_factors_str(num_str);
        }
    }
    0
}
<commit_msg>factor: Refactor (eheh) around a `Factors` datatype<commit_after>#![crate_name = "uu_factor"]

/*
* This file is part of the uutils coreutils package.
*
* (c) T. Jameson Little <t.jameson.little@gmail.com>
* (c) Wiktor Kuropatwa <wiktor.kuropatwa@gmail.com>
*     20150223 added Pollard rho method implementation
* (c) kwantam <kwantam@gmail.com>
*     20150429 sped up trial division by adding table of prime inverses
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

extern crate rand;

#[macro_use]
extern crate uucore;

use numeric::*;
use rand::distributions::{Distribution, Uniform};
use rand::rngs::SmallRng;
use rand::{thread_rng, SeedableRng};
use std::cmp::{max, min};
use std::collections::HashMap;
use std::fmt;
use std::io::{stdin, BufRead};
use std::mem::swap;
use std::num::Wrapping;
use std::ops;

mod numeric;

include!(concat!(env!("OUT_DIR"), "/prime_table.rs"));

static SYNTAX: &str = "[OPTION] [NUMBER]...";
static SUMMARY: &str = "Print the prime factors of the given number(s).
 If none are specified, read from standard input.";
static LONG_HELP: &str = "";

fn gcd(mut a: u64, mut b: u64) -> u64 {
    while b > 0 {
        a %= b;
        swap(&mut a, &mut b);
    }
    a
}

struct Factors {
    f: HashMap<u64, u8>,
}

impl Factors {
    fn new() -> Factors {
        Factors { f: HashMap::new() }
    }

    fn add(&mut self, prime: u64, exp: u8) {
        assert!(exp > 0);
        self.f.insert(prime, exp + self.f.get(&prime).unwrap_or(&0));
    }

    fn push(&mut self, prime: u64) {
        self.add(prime, 1)
    }
}

impl ops::MulAssign<Factors> for Factors {
    fn mul_assign(&mut self, other: Factors) {
        for (prime, exp) in &other.f {
            self.add(*prime, *exp);
        }
    }
}

impl fmt::Display for Factors {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // TODO: Use a representation with efficient in-order iteration
        let mut primes: Vec<&u64> = self.f.keys().collect();
        primes.sort();

        for p in primes {
            for _ in 0..self.f[&p] {
                write!(f, " {}", p)?
            }
        }

        Ok(())
    }
}

fn rho_pollard_pseudorandom_function(x: u64, a: u64, b: u64, num: u64) -> u64 {
    if num < 1 << 63 {
        (sm_mul(a, sm_mul(x, x, num), num) + b) % num
    } else {
        big_add(big_mul(a, big_mul(x, x, num), num), b, num)
    }
}

fn rho_pollard_find_divisor(num: u64) -> u64 {
    #![allow(clippy::many_single_char_names)]
    let range = Uniform::new(1, num);
    let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
    let mut x = range.sample(&mut rng);
    let mut y = x;
    let mut a = range.sample(&mut rng);
    let mut b = range.sample(&mut rng);

    loop {
        x = rho_pollard_pseudorandom_function(x, a, b, num);
        y = rho_pollard_pseudorandom_function(y, a, b, num);
        y = rho_pollard_pseudorandom_function(y, a, b, num);
        let d = gcd(num, max(x, y) - min(x, y));
        if d == num {
            // Failure, retry with different function
            x = range.sample(&mut rng);
            y = x;
            a = range.sample(&mut rng);
            b = range.sample(&mut rng);
        } else if d > 1 {
            return d;
        }
    }
}

fn rho_pollard_factor(num: u64, factors: &mut Factors) {
    if is_prime(num) {
        factors.push(num);
        return;
    }

    let divisor = rho_pollard_find_divisor(num);
    rho_pollard_factor(divisor, factors);
    rho_pollard_factor(num / divisor, factors);
}

fn table_division(mut num: u64) -> Factors {
    let mut factors = Factors::new();

    if num < 2 {
        factors.push(num);
        return factors
    }

    while num % 2 == 0 {
        num /= 2;
        factors.push(2);
    }

    if num == 1 {
        return factors;
    }

    if is_prime(num) {
        factors.push(num);
        return factors;
    }

    for &(prime, inv, ceil) in P_INVS_U64 {
        if num == 1 {
            break;
        }

        // inv = prime^-1 mod 2^64
        // ceil = floor((2^64-1) / prime)
        // if (num * inv) mod 2^64 <= ceil, then prime divides num
        // See http://math.stackexchange.com/questions/1251327/
        // for a nice explanation.
        loop {
            let Wrapping(x) = Wrapping(num) * Wrapping(inv); // x = num * inv mod 2^64
            if x <= ceil {
                num = x;
                factors.push(prime);
                if is_prime(num) {
                    factors.push(num);
                    return factors;
                }
            } else {
                break;
            }
        }
    }

    // do we still have more factoring to do?
    // Decide whether to use Pollard Rho or slow divisibility based on
    // number's size:
    //if num >= 1 << 63 {
    // number is too big to use rho pollard without overflowing
    //trial_division_slow(num, factors);
    //} else if num > 1 {
    // number is still greater than 1, but not so big that we have to worry
    rho_pollard_factor(num, &mut factors);
    factors
    //}
}

fn print_factors(num: u64) {
    print!("{}:{}", num, table_division(num));
    println!();
}

fn print_factors_str(num_str: &str) {
    if let Err(e) = num_str.parse::<u64>().and_then(|x| {
        print_factors(x);
        Ok(())
    }) {
        show_warning!("{}: {}", num_str, e);
    }
}

pub fn uumain(args: Vec<String>) -> i32 {
    let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP).parse(args);

    if matches.free.is_empty() {
        let stdin = stdin();
        for line in stdin.lock().lines() {
            for number in line.unwrap().split_whitespace() {
                print_factors_str(number);
            }
        }
    } else {
        for num_str in &matches.free {
            print_factors_str(num_str);
        }
    }
    0
}
<|endoftext|>


<commit_before>#![no_std]
/**
 * This example shows a repeated timer combined with reading and displaying the current time in
 * clock ticks.
 **/
use core::fmt::Write;
use libtock::console::Console;
use libtock::result::TockResult;
use libtock::timer;
use libtock::timer::Duration;

#[libtock::main]
async fn main() -> TockResult<()> {
    let mut console = Console::new();
    const DELAY_MS: isize = 50;

    for i in 0.. {
        let mut timer_with_callback = timer::with_callback(|_, _| {});
        let timer = timer_with_callback.init()?;
        let ticks = timer.get_current_clock()?.num_ticks();
        writeln!(
            console,
            "[{}] Waited {} ms. Now is {:#010x} ticks",
            i,
            i * DELAY_MS,
            ticks
        )?;
        timer::sleep(Duration::from_ms(DELAY_MS)).await?;
    }

    Ok(())
}
<commit_msg>Add more debugging information.<commit_after>#![no_std]
/**
 * This example shows a repeated timer combined with reading and displaying the current time in
 * clock ticks.
 **/
use core::fmt::Write;
use libtock::console::Console;
use libtock::result::TockResult;
use libtock::timer;
use libtock::timer::Duration;

#[libtock::main]
async fn main() -> TockResult<()> {
    const DELAY_MS: isize = 50;

    let mut console = Console::new();
    let mut previous_ticks = None;

    for i in 0.. {
        let mut timer_with_callback = timer::with_callback(|_, _| {});
        let timer = timer_with_callback.init()?;
        let ticks = timer.get_current_clock()?.num_ticks();
        let frequency = timer.clock_frequency().hz();
        writeln!(
            console,
            "[{}] Waited {} ms. Now is {:#010x} ticks ({} ticks since last time at {} Hz)",
            i,
            i * DELAY_MS,
            ticks,
            previous_ticks.map(|previous| ticks - previous),
            frequency
        )?;
        previous_ticks = Some(ticks);
        timer::sleep(Duration::from_ms(DELAY_MS)).await?;
    }

    Ok(())
}
<|endoftext|>


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

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

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

    pub fn parse(&mut self, assembly: &str) {
        self.split_lines(assembly);
        self.strip_comments();
    }

    fn strip_comments(&mut self) {
        let mut lines = self.lines.iter();
        while let Some(line) = lines.next() {
            let trimmed_line = line.trim();
            if !trimmed_line.is_empty() && !trimmed_line.starts_with(";") {
                let mut instruction = String::new();
                instruction.push_str(trimmed_line);
                self.instructions.push(instruction);
            }
        }
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    #[test]
    fn it_strips_single_line_comments() {
        let mut compiler = Compiler::new();
        compiler.parse("; single line comment\n0 0 0 0\n");

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

    #[test]
    fn it_strips_single_line_comments_starting_with_spaces() {
        let mut compiler = Compiler::new();
        compiler.parse(" ; single line comment\n0 0 0 0\n");

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

    #[test]
    fn it_strips_single_line_comments_starting_with_tabs() {
        let mut compiler = Compiler::new();
        compiler.parse("\t; single line comment\n0 0 0 0\n");

        assert_eq!(compiler.lines.len(), 2);
        assert_eq!(compiler.instructions.len(), 1);
    }
}
<commit_msg>Strips inline comments.<commit_after>use std::vec::Vec;
use std::string::String;

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

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

    pub fn parse(&mut self, assembly: &str) {
        self.split_lines(assembly);
        self.strip_comments();
    }

    fn strip_comments(&mut self) {
        let mut lines = self.lines.iter();
        while let Some(line) = lines.next() {
            let trimmed_line = line.trim();
            if !trimmed_line.is_empty() && !trimmed_line.starts_with(";") {
                let mut instruction = String::new();
                let stripped_instruction = match trimmed_line.find(';') {
                    Some(index) => trimmed_line.split_at(index).0,
                    None => trimmed_line,
                };
                instruction.push_str(stripped_instruction.trim());
                self.instructions.push(instruction);
            }
        }
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    #[test]
    fn it_strips_single_line_comments() {
        let mut compiler = Compiler::new();
        compiler.parse("; single line comment\n0 0 0 0\n");

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

    #[test]
    fn it_strips_single_line_comments_starting_with_spaces() {
        let mut compiler = Compiler::new();
        compiler.parse(" ; single line comment\n0 0 0 0\n");

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

    #[test]
    fn it_strips_single_line_comments_starting_with_tabs() {
        let mut compiler = Compiler::new();
        compiler.parse("\t; single line comment\n0 0 0 0\n");

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

    #[test]
    fn it_strips_inline_comments() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0; inline comment\n");

        assert_eq!(compiler.lines.len(), 1);
        assert_eq!(compiler.instructions, vec!["0 0 0 0"]);
    }

    #[test]
    fn it_strips_inline_comments_starting_with_spaces() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0 ; inline comment\n");

        assert_eq!(compiler.lines.len(), 1);
        assert_eq!(compiler.instructions, vec!["0 0 0 0"]);
    }

    #[test]
    fn it_strips_inline_comments_starting_with_tabs() {
        let mut compiler = Compiler::new();
        compiler.parse("0 0 0 0\t; inline comment\n");

        assert_eq!(compiler.lines.len(), 1);
        assert_eq!(compiler.instructions, vec!["0 0 0 0"]);
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix merge with master<commit_after><|endoftext|>


<commit_before>//! Contains implementation of ASCII FBX emitter.
extern crate rustc_serialize;

use std::io::Write;
use writer::error::{Result, Error};
use common::Property;

fn indent<W: Write>(sink: &mut W, depth: usize) -> Result<()> {
    for _ in 0..depth {
        try!(sink.write(b"\t"));
    }
    Ok(())
}

fn print_property<W: Write>(sink: &mut W, property: &Property, prop_depth: usize) -> Result<()> {
    assert!(prop_depth > 0);

    // TODO: I've never seen vector of booleans (in binary or ascii FBX)... How should it be?
    // TODO: How will it be when other properties follows a property of array value?
    // TODO: Implement folding of large array.
    match *property {
        Property::Bool(false) => {
            try!(sink.write(b"T"));
        },
        Property::Bool(true) => {
            try!(sink.write(b"Y"));
        },
        Property::I16(v) => {
            try!(sink.write_fmt(format_args!("{}", v)));
        },
        Property::I32(v) => {
            try!(sink.write_fmt(format_args!("{}", v)));
        },
        Property::I64(v) => {
            try!(sink.write_fmt(format_args!("{}", v)));
        },
        Property::F32(v) => {
            // NOTE: Is outputted data accurate enough?
            try!(sink.write_fmt(format_args!("{}", v)));
        },
        Property::F64(v) => {
            // NOTE: Is outputted data accurate enough?
            try!(sink.write_fmt(format_args!("{}", v)));
        },
        Property::VecBool(vec) => {
            warn!("ASCII representation of vector of boolean values may be wrong.");
            try!(sink.write_fmt(format_args!("*{} {{\n", vec.len())));
            try!(indent(sink, prop_depth));
            try!(sink.write(b"a: "));
            let mut iter = vec.iter();
            if let Some(&v) = iter.next() {
                try!(sink.write(if v { b"Y" } else { b"T" }));
            }
            for &v in iter {
                try!(sink.write(if v { b",Y" } else { b",T" }));
            }
            try!(sink.write(b"\n"));
            try!(indent(sink, prop_depth-1));
            try!(sink.write(b"}"));
        },
        Property::VecI32(vec) => {
            try!(sink.write_fmt(format_args!("*{} {{\n", vec.len())));
            try!(indent(sink, prop_depth));
            try!(sink.write(b"a: "));
            let mut iter = vec.iter();
            if let Some(&v) = iter.next() {
                try!(sink.write_fmt(format_args!("{}", v)));
            }
            for &v in iter {
                try!(sink.write_fmt(format_args!(",{}", v)));
            }
            try!(sink.write(b"\n"));
            try!(indent(sink, prop_depth-1));
            try!(sink.write(b"}"));
        },
        Property::VecI64(vec) => {
            try!(sink.write_fmt(format_args!("*{} {{\n", vec.len())));
            try!(indent(sink, prop_depth));
            try!(sink.write(b"a: "));
            let mut iter = vec.iter();
            if let Some(&v) = iter.next() {
                try!(sink.write_fmt(format_args!("{}", v)));
            }
            for &v in iter {
                try!(sink.write_fmt(format_args!(",{}", v)));
            }
            try!(sink.write(b"\n"));
            try!(indent(sink, prop_depth-1));
            try!(sink.write(b"}"));
        },
        Property::VecF32(vec) => {
            try!(sink.write_fmt(format_args!("*{} {{\n", vec.len())));
            try!(indent(sink, prop_depth));
            try!(sink.write(b"a: "));
            let mut iter = vec.iter();
            if let Some(&v) = iter.next() {
                try!(sink.write_fmt(format_args!("{}", v)));
            }
            for &v in iter {
                try!(sink.write_fmt(format_args!(",{}", v)));
            }
            try!(sink.write(b"\n"));
            try!(indent(sink, prop_depth-1));
            try!(sink.write(b"}"));
        },
        Property::VecF64(vec) => {
            try!(sink.write_fmt(format_args!("*{} {{\n", vec.len())));
            try!(indent(sink, prop_depth));
            try!(sink.write(b"a: "));
            let mut iter = vec.iter();
            if let Some(&v) = iter.next() {
                try!(sink.write_fmt(format_args!("{}", v)));
            }
            for &v in iter {
                try!(sink.write_fmt(format_args!(",{}", v)));
            }
            try!(sink.write(b"\n"));
            try!(indent(sink, prop_depth-1));
            try!(sink.write(b"}"));
        },
        Property::String(v) => {
            try!(sink.write(b"\""));
            for c in v.chars() {
                match c {
                    '"' => {
                        try!(sink.write(b"""));
                    },
                    '\n' => {
                        try!(sink.write(b"&lf;"));
                    },
                    '\r' => {
                        try!(sink.write(b"&cr;"));
                    },
                    _ => {
                        try!(sink.write_fmt(format_args!("{}", c)));
                    }
                }
            }
            try!(sink.write(b"\""));
        },
        Property::Binary(v) => {
            // TODO: Implement folding of long line.
            use self::rustc_serialize::base64::{ToBase64, STANDARD};
            // base64 conversion.
            try!(sink.write_fmt(format_args!("\"{}\"", v.to_base64(STANDARD))));
        },
    }
    Ok(())
}

/// A writer for ASCII FBX.
#[derive(Debug, Clone)]
pub struct AsciiEmitter {
    prop_child_existence: Vec<(bool, bool)>,
}

impl AsciiEmitter {
    /// Constructs ASCII FBX writer.
    pub fn new() -> Self {
        AsciiEmitter {
            prop_child_existence: vec![],
        }
    }

    pub fn emit_start_fbx<W: Write>(&mut self, sink: &mut W, ver: u32) -> Result<()> {
        if (ver < 7000) || (ver >= 8000) {
            error!("Unsupported version: {}", ver);
            return Err(Error::UnsupportedFbxVersion(ver));
        }
        {
            let (major, minor) = (ver / 1000, ver % 1000);
            let (minor, revision) = (minor / 100, minor % 100);
            // Write magic for ASCII FBX.
            try!(sink.write_fmt(format_args!("; FBX {}.{}.{} project file\n", major, minor, revision)));
        }

        Ok(())
    }

    pub fn emit_end_fbx<W: Write>(&mut self, _sink: &mut W) -> Result<()> {
        Ok(())
    }

    pub fn emit_start_node<W: Write>(&mut self, sink: &mut W, name: &str, properties: &[Property]) -> Result<()> {
        if let Some((prop_exist, child_exist)) = self.prop_child_existence.pop() {
            // Print brace for *parent node*, if the current node is the first child.
            // (i.e. `child_exist` of parent is `false`.)
            if !child_exist {
                try!(sink.write(b" {\n"));
            }
            self.prop_child_existence.push((prop_exist, true));
        }
        try!(indent(sink, self.prop_child_existence.len()));
        self.prop_child_existence.push((!properties.is_empty(), false));
        try!(sink.write_fmt(format_args!("{}: ", name)));

        let prop_depth = self.prop_child_existence.len();
        let mut prop_iter = properties.iter();
        if let Some(prop) = prop_iter.next() {
            //try!(sink.write_fmt(format_args!("{:?}", prop)));
            try!(print_property(sink, prop, prop_depth));
        }
        for prop in prop_iter {
            //try!(sink.write_fmt(format_args!(", {:?}", prop)));
            try!(sink.write(b", "));
            try!(print_property(sink, prop, prop_depth));
        }

        Ok(())
    }

    pub fn emit_end_node<W: Write>(&mut self, sink: &mut W) -> Result<()> {
        let (prop_exist, child_exist) = self.prop_child_existence.pop().unwrap();
        if !prop_exist || child_exist {
            if !prop_exist && !child_exist {
                try!(sink.write(b" {\n"));
            }
            try!(indent(sink, self.prop_child_existence.len()));
            try!(sink.write(b"}\n"));
        } else {
            try!(sink.write(b"\n"));
        }

        Ok(())
    }

    pub fn emit_comment<W: Write>(&mut self, sink: &mut W, comment: &str) -> Result<()> {
        for line in comment.lines() {
            try!(indent(sink, self.prop_child_existence.len()));
            try!(sink.write(line.as_bytes()));
            try!(sink.write(b"\n"));
        }

        Ok(())
    }
}
<commit_msg>Remove unnecessary comments<commit_after>//! Contains implementation of ASCII FBX emitter.
extern crate rustc_serialize;

use std::io::Write;
use writer::error::{Result, Error};
use common::Property;

fn indent<W: Write>(sink: &mut W, depth: usize) -> Result<()> {
    for _ in 0..depth {
        try!(sink.write(b"\t"));
    }
    Ok(())
}

fn print_property<W: Write>(sink: &mut W, property: &Property, prop_depth: usize) -> Result<()> {
    assert!(prop_depth > 0);

    // TODO: I've never seen vector of booleans (in binary or ascii FBX)... How should it be?
    // TODO: How will it be when other properties follows a property of array value?
    // TODO: Implement folding of large array.
    match *property {
        Property::Bool(false) => {
            try!(sink.write(b"T"));
        },
        Property::Bool(true) => {
            try!(sink.write(b"Y"));
        },
        Property::I16(v) => {
            try!(sink.write_fmt(format_args!("{}", v)));
        },
        Property::I32(v) => {
            try!(sink.write_fmt(format_args!("{}", v)));
        },
        Property::I64(v) => {
            try!(sink.write_fmt(format_args!("{}", v)));
        },
        Property::F32(v) => {
            // NOTE: Is outputted data accurate enough?
            try!(sink.write_fmt(format_args!("{}", v)));
        },
        Property::F64(v) => {
            // NOTE: Is outputted data accurate enough?
            try!(sink.write_fmt(format_args!("{}", v)));
        },
        Property::VecBool(vec) => {
            warn!("ASCII representation of vector of boolean values may be wrong.");
            try!(sink.write_fmt(format_args!("*{} {{\n", vec.len())));
            try!(indent(sink, prop_depth));
            try!(sink.write(b"a: "));
            let mut iter = vec.iter();
            if let Some(&v) = iter.next() {
                try!(sink.write(if v { b"Y" } else { b"T" }));
            }
            for &v in iter {
                try!(sink.write(if v { b",Y" } else { b",T" }));
            }
            try!(sink.write(b"\n"));
            try!(indent(sink, prop_depth-1));
            try!(sink.write(b"}"));
        },
        Property::VecI32(vec) => {
            try!(sink.write_fmt(format_args!("*{} {{\n", vec.len())));
            try!(indent(sink, prop_depth));
            try!(sink.write(b"a: "));
            let mut iter = vec.iter();
            if let Some(&v) = iter.next() {
                try!(sink.write_fmt(format_args!("{}", v)));
            }
            for &v in iter {
                try!(sink.write_fmt(format_args!(",{}", v)));
            }
            try!(sink.write(b"\n"));
            try!(indent(sink, prop_depth-1));
            try!(sink.write(b"}"));
        },
        Property::VecI64(vec) => {
            try!(sink.write_fmt(format_args!("*{} {{\n", vec.len())));
            try!(indent(sink, prop_depth));
            try!(sink.write(b"a: "));
            let mut iter = vec.iter();
            if let Some(&v) = iter.next() {
                try!(sink.write_fmt(format_args!("{}", v)));
            }
            for &v in iter {
                try!(sink.write_fmt(format_args!(",{}", v)));
            }
            try!(sink.write(b"\n"));
            try!(indent(sink, prop_depth-1));
            try!(sink.write(b"}"));
        },
        Property::VecF32(vec) => {
            try!(sink.write_fmt(format_args!("*{} {{\n", vec.len())));
            try!(indent(sink, prop_depth));
            try!(sink.write(b"a: "));
            let mut iter = vec.iter();
            if let Some(&v) = iter.next() {
                try!(sink.write_fmt(format_args!("{}", v)));
            }
            for &v in iter {
                try!(sink.write_fmt(format_args!(",{}", v)));
            }
            try!(sink.write(b"\n"));
            try!(indent(sink, prop_depth-1));
            try!(sink.write(b"}"));
        },
        Property::VecF64(vec) => {
            try!(sink.write_fmt(format_args!("*{} {{\n", vec.len())));
            try!(indent(sink, prop_depth));
            try!(sink.write(b"a: "));
            let mut iter = vec.iter();
            if let Some(&v) = iter.next() {
                try!(sink.write_fmt(format_args!("{}", v)));
            }
            for &v in iter {
                try!(sink.write_fmt(format_args!(",{}", v)));
            }
            try!(sink.write(b"\n"));
            try!(indent(sink, prop_depth-1));
            try!(sink.write(b"}"));
        },
        Property::String(v) => {
            try!(sink.write(b"\""));
            for c in v.chars() {
                match c {
                    '"' => {
                        try!(sink.write(b"""));
                    },
                    '\n' => {
                        try!(sink.write(b"&lf;"));
                    },
                    '\r' => {
                        try!(sink.write(b"&cr;"));
                    },
                    _ => {
                        try!(sink.write_fmt(format_args!("{}", c)));
                    }
                }
            }
            try!(sink.write(b"\""));
        },
        Property::Binary(v) => {
            // TODO: Implement folding of long line.
            use self::rustc_serialize::base64::{ToBase64, STANDARD};
            // base64 conversion.
            try!(sink.write_fmt(format_args!("\"{}\"", v.to_base64(STANDARD))));
        },
    }
    Ok(())
}

/// A writer for ASCII FBX.
#[derive(Debug, Clone)]
pub struct AsciiEmitter {
    prop_child_existence: Vec<(bool, bool)>,
}

impl AsciiEmitter {
    /// Constructs ASCII FBX writer.
    pub fn new() -> Self {
        AsciiEmitter {
            prop_child_existence: vec![],
        }
    }

    pub fn emit_start_fbx<W: Write>(&mut self, sink: &mut W, ver: u32) -> Result<()> {
        if (ver < 7000) || (ver >= 8000) {
            error!("Unsupported version: {}", ver);
            return Err(Error::UnsupportedFbxVersion(ver));
        }
        {
            let (major, minor) = (ver / 1000, ver % 1000);
            let (minor, revision) = (minor / 100, minor % 100);
            // Write magic for ASCII FBX.
            try!(sink.write_fmt(format_args!("; FBX {}.{}.{} project file\n", major, minor, revision)));
        }

        Ok(())
    }

    pub fn emit_end_fbx<W: Write>(&mut self, _sink: &mut W) -> Result<()> {
        Ok(())
    }

    pub fn emit_start_node<W: Write>(&mut self, sink: &mut W, name: &str, properties: &[Property]) -> Result<()> {
        if let Some((prop_exist, child_exist)) = self.prop_child_existence.pop() {
            // Print brace for *parent node*, if the current node is the first child.
            // (i.e. `child_exist` of parent is `false`.)
            if !child_exist {
                try!(sink.write(b" {\n"));
            }
            self.prop_child_existence.push((prop_exist, true));
        }
        try!(indent(sink, self.prop_child_existence.len()));
        self.prop_child_existence.push((!properties.is_empty(), false));
        try!(sink.write_fmt(format_args!("{}: ", name)));

        let prop_depth = self.prop_child_existence.len();
        let mut prop_iter = properties.iter();
        if let Some(prop) = prop_iter.next() {
            try!(print_property(sink, prop, prop_depth));
        }
        for prop in prop_iter {
            try!(sink.write(b", "));
            try!(print_property(sink, prop, prop_depth));
        }

        Ok(())
    }

    pub fn emit_end_node<W: Write>(&mut self, sink: &mut W) -> Result<()> {
        let (prop_exist, child_exist) = self.prop_child_existence.pop().unwrap();
        if !prop_exist || child_exist {
            if !prop_exist && !child_exist {
                try!(sink.write(b" {\n"));
            }
            try!(indent(sink, self.prop_child_existence.len()));
            try!(sink.write(b"}\n"));
        } else {
            try!(sink.write(b"\n"));
        }

        Ok(())
    }

    pub fn emit_comment<W: Write>(&mut self, sink: &mut W, comment: &str) -> Result<()> {
        for line in comment.lines() {
            try!(indent(sink, self.prop_child_existence.len()));
            try!(sink.write(line.as_bytes()));
            try!(sink.write(b"\n"));
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>use regex::Regex;
use std::error::Error;
/// Create a program that downloads the time from this URL: http://tycho.usno.navy.mil/cgi-bin/timer.pl
/// and then prints the current UTC time by extracting just the UTC time from the web page's HTML.
/// For an introduction to the ecosystem of web scraping in Rust,
/// read https://kadekillary.work/post/webscraping-rust/

const A_URL: &str = "http://tycho.usno.navy.mil/cgi-bin/timer.pl";
fn extract_timestamp(raw_html: &str) -> Option<regex::Match> {
    // unicode below is points for < and >
    let pattern = Regex::new(r"\u003CBR\u003E(?P<time>.*) UTC").unwrap();
    pattern.captures(raw_html).unwrap().name("time")
}

fn main() -> Result<(), Box<dyn Error>> {
    let raw_html = reqwest::get(A_URL)?.text()?;
    if let Some(timestamp) = extract_timestamp(&raw_html) {
        print!("{}", timestamp.as_str());
    } else {
        eprint!("Error: Could not parse URL for getting current time.");
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use crate::extract_timestamp;

    #[test]
    fn test_extract_timestamp() {
        let body = r#"<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final"//EN>

            <TITLE>What time is it?</TITLE>

 US Naval Observatory Master Clock Time

Aug. 12, 23:55:08 UTC		Universal Time

Aug. 12, 07:55:08 PM EDT		Eastern Time

Aug. 12, 06:55:08 PM CDT		Central Time

Aug. 12, 05:55:08 PM MDT		Mountain Time

Aug. 12, 04:55:08 PM PDT		Pacific Time

Aug. 12, 03:55:08 PM AKDT	Alaska Time

Aug. 12, 01:55:08 PM HAST	Hawaii-Aleutian Time

 US Naval Observatory

            "#;
        assert_eq!(
            extract_timestamp(&body).unwrap().as_str(),
            "Aug. 12, 23:55:08"
        );
    }
}
<commit_msg>use literal characters<commit_after>use regex::Regex;
use std::error::Error;
/// Create a program that downloads the time from this URL: http://tycho.usno.navy.mil/cgi-bin/timer.pl
/// and then prints the current UTC time by extracting just the UTC time from the web page's HTML.
/// For an introduction to the ecosystem of web scraping in Rust,
/// read https://kadekillary.work/post/webscraping-rust/

const A_URL: &str = "http://tycho.usno.navy.mil/cgi-bin/timer.pl";
fn extract_timestamp(raw_html: &str) -> Option<regex::Match> {
    let pattern = Regex::new(r"
(?P<time>.*) UTC").unwrap();
    pattern.captures(raw_html).unwrap().name("time")
}

fn main() -> Result<(), Box<dyn Error>> {
    let raw_html = reqwest::get(A_URL)?.text()?;
    if let Some(timestamp) = extract_timestamp(&raw_html) {
        print!("{}", timestamp.as_str());
    } else {
        eprint!("Error: Could not parse URL for getting current time.");
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use crate::extract_timestamp;

    #[test]
    fn test_extract_timestamp() {
        let body = r#"<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final"//EN>

            <TITLE>What time is it?</TITLE>

 US Naval Observatory Master Clock Time

Aug. 12, 23:55:08 UTC		Universal Time

Aug. 12, 07:55:08 PM EDT		Eastern Time

Aug. 12, 06:55:08 PM CDT		Central Time

Aug. 12, 05:55:08 PM MDT		Mountain Time

Aug. 12, 04:55:08 PM PDT		Pacific Time

Aug. 12, 03:55:08 PM AKDT	Alaska Time

Aug. 12, 01:55:08 PM HAST	Hawaii-Aleutian Time

 US Naval Observatory

            "#;
        assert_eq!(
            extract_timestamp(&body).unwrap().as_str(),
            "Aug. 12, 23:55:08"
        );
    }
}
<|endoftext|>


<commit_before>// 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/.

use std::{
    cell::RefCell,
    collections::{hash_map::RandomState, HashSet},
    iter::FromIterator,
    path::Path,
    rc::Rc,
};

use crate::{
    engine::{
        engine::{Engine, Eventable, Pool},
        shared::create_pool_idempotent_or_err,
        sim_engine::{pool::SimPool, randomization::Randomizer},
        structures::Table,
        types::{CreateAction, DeleteAction, Name, PoolUuid, RenameAction},
    },
    stratis::{ErrorEnum, StratisError, StratisResult},
};

#[derive(Debug, Default)]
pub struct SimEngine {
    pools: Table<SimPool>,
    rdm: Rc<RefCell<Randomizer>>,
}

impl SimEngine {}

impl Engine for SimEngine {
    fn create_pool(
        &mut self,
        name: &str,
        blockdev_paths: &[&Path],
        redundancy: Option<u16>,
    ) -> StratisResult<CreateAction<PoolUuid>> {
        let redundancy = calculate_redundancy!(redundancy);

        match self.pools.get_by_name(name) {
            Some((_, pool)) => create_pool_idempotent_or_err(pool, name, blockdev_paths),
            None => {
                if blockdev_paths.is_empty() {
                    Err(StratisError::Engine(
                        ErrorEnum::Invalid,
                        "At least one blockdev is required to create a pool.".to_string(),
                    ))
                } else {
                    let device_set: HashSet<_, RandomState> = HashSet::from_iter(blockdev_paths);
                    let devices = device_set.into_iter().cloned().collect::<Vec<&Path>>();

                    let (pool_uuid, pool) =
                        SimPool::new(&Rc::clone(&self.rdm), &devices, redundancy);

                    if self.rdm.borrow_mut().throw_die() {
                        return Err(StratisError::Engine(ErrorEnum::Error, "X".into()));
                    }

                    self.pools
                        .insert(Name::new(name.to_owned()), pool_uuid, pool);

                    Ok(CreateAction::Created(pool_uuid))
                }
            }
        }
    }

    fn handle_event(&mut self, _event: &libudev::Event) -> Option<(PoolUuid, &mut dyn Pool)> {
        None
    }

    fn destroy_pool(&mut self, uuid: PoolUuid) -> StratisResult<DeleteAction<PoolUuid>> {
        if let Some((_, pool)) = self.pools.get_by_uuid(uuid) {
            if pool.has_filesystems() {
                return Err(StratisError::Engine(
                    ErrorEnum::Busy,
                    "filesystems remaining on pool".into(),
                ));
            };
        } else {
            return Ok(DeleteAction::Identity);
        }
        self.pools
            .remove_by_uuid(uuid)
            .expect("Must succeed since self.pool.get_by_uuid() returned a value")
            .1
            .destroy()?;
        Ok(DeleteAction::Deleted(uuid))
    }

    fn rename_pool(
        &mut self,
        uuid: PoolUuid,
        new_name: &str,
    ) -> StratisResult<RenameAction<PoolUuid>> {
        rename_pool_pre_idem!(self; uuid; new_name);

        let (_, pool) = self
            .pools
            .remove_by_uuid(uuid)
            .expect("Must succeed since self.pools.get_by_uuid() returned a value");

        self.pools
            .insert(Name::new(new_name.to_owned()), uuid, pool);
        Ok(RenameAction::Renamed(uuid))
    }

    fn get_pool(&self, uuid: PoolUuid) -> Option<(Name, &dyn Pool)> {
        get_pool!(self; uuid)
    }

    fn get_mut_pool(&mut self, uuid: PoolUuid) -> Option<(Name, &mut dyn Pool)> {
        get_mut_pool!(self; uuid)
    }

    /// Set properties of the simulator
    fn configure_simulator(&mut self, denominator: u32) -> StratisResult<()> {
        self.rdm.borrow_mut().set_probability(denominator);
        Ok(())
    }

    fn pools(&self) -> Vec<(Name, PoolUuid, &dyn Pool)> {
        self.pools
            .iter()
            .map(|(name, uuid, pool)| (name.clone(), *uuid, pool as &dyn Pool))
            .collect()
    }

    fn pools_mut(&mut self) -> Vec<(Name, PoolUuid, &mut dyn Pool)> {
        self.pools
            .iter_mut()
            .map(|(name, uuid, pool)| (name.clone(), *uuid, pool as &mut dyn Pool))
            .collect()
    }

    fn get_eventable(&self) -> Option<&'static dyn Eventable> {
        None
    }

    fn evented(&mut self) -> StratisResult<()> {
        Ok(())
    }
}

#[cfg(test)]
mod tests {

    use std::{self, path::Path};

    use proptest::prelude::any;
    use uuid::Uuid;

    use crate::{
        engine::{
            types::{EngineAction, RenameAction},
            Engine,
        },
        stratis::{ErrorEnum, StratisError},
    };

    use super::*;

    proptest! {
        #[test]
        /// This method should always return Ok.
        fn configure_simulator_runs(denominator in any::<u32>()) {
            prop_assert!(SimEngine::default()
                .configure_simulator(denominator)
                .is_ok())
        }

    }

    #[test]
    /// When an engine has no pools, any name lookup should fail
    fn get_pool_err() {
        assert_matches!(SimEngine::default().get_pool(Uuid::new_v4()), None);
    }

    #[test]
    /// When an engine has no pools, destroying any pool must succeed
    fn destroy_pool_empty() {
        assert_matches!(SimEngine::default().destroy_pool(Uuid::new_v4()), Ok(_));
    }

    #[test]
    /// Destroying an empty pool should succeed.
    fn destroy_empty_pool() {
        let mut engine = SimEngine::default();
        let uuid = engine
            .create_pool(
                "name",
                strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
                None,
            )
            .unwrap()
            .changed()
            .unwrap();
        assert_matches!(engine.destroy_pool(uuid), Ok(_));
    }

    #[test]
    /// Destroying a pool with devices should succeed
    fn destroy_pool_w_devices() {
        let mut engine = SimEngine::default();
        let uuid = engine
            .create_pool("name", &[Path::new("/s/d")], None)
            .unwrap()
            .changed()
            .unwrap();
        assert_matches!(engine.destroy_pool(uuid), Ok(_));
    }

    #[test]
    /// Destroying a pool with filesystems should fail
    fn destroy_pool_w_filesystem() {
        let mut engine = SimEngine::default();
        let pool_name = "pool_name";
        let uuid = engine
            .create_pool(pool_name, &[Path::new("/s/d")], None)
            .unwrap()
            .changed()
            .unwrap();
        {
            let pool = engine.get_mut_pool(uuid).unwrap().1;
            pool.create_filesystems(uuid, pool_name, &[("test", None)])
                .unwrap();
        }
        assert_matches!(engine.destroy_pool(uuid), Err(_));
    }

    #[test]
    #[ignore]
    /// Creating a new pool identical to the previous should succeed
    fn create_new_pool_twice() {
        let name = "name";
        let mut engine = SimEngine::default();
        engine.create_pool(name, &[], None).unwrap();
        assert!(match engine
            .create_pool(name, &[], None)
            .ok()
            .and_then(|uuid| uuid.changed())
        {
            Some(uuid) => engine.get_pool(uuid).unwrap().1.blockdevs().is_empty(),
            _ => false,
        });
    }

    #[test]
    /// Creating a new pool with the same name and arguments should return identity
    fn create_pool_name_collision() {
        let name = "name";
        let mut engine = SimEngine::default();
        engine
            .create_pool(name, &[Path::new("/s/d")], None)
            .unwrap();
        assert_matches!(
            engine.create_pool(name, &[Path::new("/s/d")], None),
            Ok(CreateAction::Identity)
        );
    }

    #[test]
    /// Creating a new pool with the same name and different arguments should fail
    fn create_pool_name_collision_different_args() {
        let name = "name";
        let mut engine = SimEngine::default();
        engine
            .create_pool(name, &[Path::new("/s/d")], None)
            .unwrap();
        assert_matches!(
            engine.create_pool(
                name,
                strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
                None,
            ),
            Err(StratisError::Engine(ErrorEnum::Invalid, _))
        );
    }

    #[test]
    /// Creating a pool with duplicate devices should succeed
    fn create_pool_duplicate_devices() {
        let path = "/s/d";
        let mut engine = SimEngine::default();
        let devices = vec![Path::new(path), Path::new(path)];
        assert_matches!(
            engine
                .create_pool("name", &devices, None)
                .unwrap()
                .changed()
                .map(|uuid| engine.get_pool(uuid).unwrap().1.blockdevs().len()),
            Some(1)
        );
    }

    #[test]
    /// Creating a pool with an impossible raid level should fail
    fn create_pool_max_u16_raid() {
        let mut engine = SimEngine::default();
        assert_matches!(engine.create_pool("name", &[], Some(std::u16::MAX)), Err(_));
    }

    #[test]
    /// Renaming a pool on an empty engine always works
    fn rename_empty() {
        let mut engine = SimEngine::default();
        assert_matches!(
            engine.rename_pool(Uuid::new_v4(), "new_name"),
            Ok(RenameAction::NoSource)
        );
    }

    #[test]
    /// Renaming a pool to itself always works
    fn rename_identity() {
        let name = "name";
        let mut engine = SimEngine::default();
        let uuid = engine
            .create_pool(
                name,
                strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
                None,
            )
            .unwrap()
            .changed()
            .unwrap();
        assert_eq!(
            engine.rename_pool(uuid, name).unwrap(),
            RenameAction::Identity
        );
    }

    #[test]
    /// Renaming a pool to another pool should work if new name not taken
    fn rename_happens() {
        let mut engine = SimEngine::default();
        let uuid = engine
            .create_pool(
                "old_name",
                strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
                None,
            )
            .unwrap()
            .changed()
            .unwrap();
        assert_eq!(
            engine.rename_pool(uuid, "new_name").unwrap(),
            RenameAction::Renamed(uuid)
        );
    }

    #[test]
    /// Renaming a pool to another pool should fail if new name taken
    fn rename_fails() {
        let new_name = "new_name";
        let mut engine = SimEngine::default();
        let uuid = engine
            .create_pool(
                "old_name",
                strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
                None,
            )
            .unwrap()
            .changed()
            .unwrap();
        engine
            .create_pool(
                new_name,
                strs_to_paths!(["/dev/four", "/dev/five", "/dev/six"]),
                None,
            )
            .unwrap();
        assert_matches!(
            engine.rename_pool(uuid, new_name),
            Err(StratisError::Engine(ErrorEnum::AlreadyExists, _))
        );
    }

    #[test]
    /// Renaming should succeed if old_name absent, new present
    fn rename_no_op() {
        let new_name = "new_name";
        let mut engine = SimEngine::default();
        engine
            .create_pool(
                new_name,
                strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
                None,
            )
            .unwrap();
        assert_matches!(
            engine.rename_pool(Uuid::new_v4(), new_name),
            Ok(RenameAction::NoSource)
        );
    }
}
<commit_msg>Combine two tests<commit_after>// 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/.

use std::{
    cell::RefCell,
    collections::{hash_map::RandomState, HashSet},
    iter::FromIterator,
    path::Path,
    rc::Rc,
};

use crate::{
    engine::{
        engine::{Engine, Eventable, Pool},
        shared::create_pool_idempotent_or_err,
        sim_engine::{pool::SimPool, randomization::Randomizer},
        structures::Table,
        types::{CreateAction, DeleteAction, Name, PoolUuid, RenameAction},
    },
    stratis::{ErrorEnum, StratisError, StratisResult},
};

#[derive(Debug, Default)]
pub struct SimEngine {
    pools: Table<SimPool>,
    rdm: Rc<RefCell<Randomizer>>,
}

impl SimEngine {}

impl Engine for SimEngine {
    fn create_pool(
        &mut self,
        name: &str,
        blockdev_paths: &[&Path],
        redundancy: Option<u16>,
    ) -> StratisResult<CreateAction<PoolUuid>> {
        let redundancy = calculate_redundancy!(redundancy);

        match self.pools.get_by_name(name) {
            Some((_, pool)) => create_pool_idempotent_or_err(pool, name, blockdev_paths),
            None => {
                if blockdev_paths.is_empty() {
                    Err(StratisError::Engine(
                        ErrorEnum::Invalid,
                        "At least one blockdev is required to create a pool.".to_string(),
                    ))
                } else {
                    let device_set: HashSet<_, RandomState> = HashSet::from_iter(blockdev_paths);
                    let devices = device_set.into_iter().cloned().collect::<Vec<&Path>>();

                    let (pool_uuid, pool) =
                        SimPool::new(&Rc::clone(&self.rdm), &devices, redundancy);

                    if self.rdm.borrow_mut().throw_die() {
                        return Err(StratisError::Engine(ErrorEnum::Error, "X".into()));
                    }

                    self.pools
                        .insert(Name::new(name.to_owned()), pool_uuid, pool);

                    Ok(CreateAction::Created(pool_uuid))
                }
            }
        }
    }

    fn handle_event(&mut self, _event: &libudev::Event) -> Option<(PoolUuid, &mut dyn Pool)> {
        None
    }

    fn destroy_pool(&mut self, uuid: PoolUuid) -> StratisResult<DeleteAction<PoolUuid>> {
        if let Some((_, pool)) = self.pools.get_by_uuid(uuid) {
            if pool.has_filesystems() {
                return Err(StratisError::Engine(
                    ErrorEnum::Busy,
                    "filesystems remaining on pool".into(),
                ));
            };
        } else {
            return Ok(DeleteAction::Identity);
        }
        self.pools
            .remove_by_uuid(uuid)
            .expect("Must succeed since self.pool.get_by_uuid() returned a value")
            .1
            .destroy()?;
        Ok(DeleteAction::Deleted(uuid))
    }

    fn rename_pool(
        &mut self,
        uuid: PoolUuid,
        new_name: &str,
    ) -> StratisResult<RenameAction<PoolUuid>> {
        rename_pool_pre_idem!(self; uuid; new_name);

        let (_, pool) = self
            .pools
            .remove_by_uuid(uuid)
            .expect("Must succeed since self.pools.get_by_uuid() returned a value");

        self.pools
            .insert(Name::new(new_name.to_owned()), uuid, pool);
        Ok(RenameAction::Renamed(uuid))
    }

    fn get_pool(&self, uuid: PoolUuid) -> Option<(Name, &dyn Pool)> {
        get_pool!(self; uuid)
    }

    fn get_mut_pool(&mut self, uuid: PoolUuid) -> Option<(Name, &mut dyn Pool)> {
        get_mut_pool!(self; uuid)
    }

    /// Set properties of the simulator
    fn configure_simulator(&mut self, denominator: u32) -> StratisResult<()> {
        self.rdm.borrow_mut().set_probability(denominator);
        Ok(())
    }

    fn pools(&self) -> Vec<(Name, PoolUuid, &dyn Pool)> {
        self.pools
            .iter()
            .map(|(name, uuid, pool)| (name.clone(), *uuid, pool as &dyn Pool))
            .collect()
    }

    fn pools_mut(&mut self) -> Vec<(Name, PoolUuid, &mut dyn Pool)> {
        self.pools
            .iter_mut()
            .map(|(name, uuid, pool)| (name.clone(), *uuid, pool as &mut dyn Pool))
            .collect()
    }

    fn get_eventable(&self) -> Option<&'static dyn Eventable> {
        None
    }

    fn evented(&mut self) -> StratisResult<()> {
        Ok(())
    }
}

#[cfg(test)]
mod tests {

    use std::{self, path::Path};

    use proptest::prelude::any;
    use uuid::Uuid;

    use crate::{
        engine::{
            types::{EngineAction, RenameAction},
            Engine,
        },
        stratis::{ErrorEnum, StratisError},
    };

    use super::*;

    proptest! {
        #[test]
        /// This method should always return Ok.
        fn configure_simulator_runs(denominator in any::<u32>()) {
            prop_assert!(SimEngine::default()
                .configure_simulator(denominator)
                .is_ok())
        }

    }

    #[test]
    /// When an engine has no pools, any name lookup should fail
    fn get_pool_err() {
        assert_matches!(SimEngine::default().get_pool(Uuid::new_v4()), None);
    }

    #[test]
    /// When an engine has no pools, destroying any pool must succeed
    fn destroy_pool_empty() {
        assert_matches!(SimEngine::default().destroy_pool(Uuid::new_v4()), Ok(_));
    }

    #[test]
    /// Destroying an empty pool should succeed.
    fn destroy_empty_pool() {
        let mut engine = SimEngine::default();
        let uuid = engine
            .create_pool(
                "name",
                strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
                None,
            )
            .unwrap()
            .changed()
            .unwrap();
        assert_matches!(engine.destroy_pool(uuid), Ok(_));
    }

    #[test]
    /// Destroying a pool with devices should succeed
    fn destroy_pool_w_devices() {
        let mut engine = SimEngine::default();
        let uuid = engine
            .create_pool("name", &[Path::new("/s/d")], None)
            .unwrap()
            .changed()
            .unwrap();
        assert_matches!(engine.destroy_pool(uuid), Ok(_));
    }

    #[test]
    /// Destroying a pool with filesystems should fail
    fn destroy_pool_w_filesystem() {
        let mut engine = SimEngine::default();
        let pool_name = "pool_name";
        let uuid = engine
            .create_pool(pool_name, &[Path::new("/s/d")], None)
            .unwrap()
            .changed()
            .unwrap();
        {
            let pool = engine.get_mut_pool(uuid).unwrap().1;
            pool.create_filesystems(uuid, pool_name, &[("test", None)])
                .unwrap();
        }
        assert_matches!(engine.destroy_pool(uuid), Err(_));
    }

    #[test]
    /// Creating a new pool with the same name and arguments should return
    /// identity.
    fn create_pool_name_collision() {
        let name = "name";
        let mut engine = SimEngine::default();
        let devices = [Path::new("/s/d")];
        engine.create_pool(name, &devices, None).unwrap();
        assert_matches!(
            engine.create_pool(name, &devices, None),
            Ok(CreateAction::Identity)
        );
    }

    #[test]
    /// Creating a new pool with the same name and different arguments should fail
    fn create_pool_name_collision_different_args() {
        let name = "name";
        let mut engine = SimEngine::default();
        engine
            .create_pool(name, &[Path::new("/s/d")], None)
            .unwrap();
        assert_matches!(
            engine.create_pool(
                name,
                strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
                None,
            ),
            Err(StratisError::Engine(ErrorEnum::Invalid, _))
        );
    }

    #[test]
    /// Creating a pool with duplicate devices should succeed
    fn create_pool_duplicate_devices() {
        let path = "/s/d";
        let mut engine = SimEngine::default();
        let devices = vec![Path::new(path), Path::new(path)];
        assert_matches!(
            engine
                .create_pool("name", &devices, None)
                .unwrap()
                .changed()
                .map(|uuid| engine.get_pool(uuid).unwrap().1.blockdevs().len()),
            Some(1)
        );
    }

    #[test]
    /// Creating a pool with an impossible raid level should fail
    fn create_pool_max_u16_raid() {
        let mut engine = SimEngine::default();
        assert_matches!(engine.create_pool("name", &[], Some(std::u16::MAX)), Err(_));
    }

    #[test]
    /// Renaming a pool on an empty engine always works
    fn rename_empty() {
        let mut engine = SimEngine::default();
        assert_matches!(
            engine.rename_pool(Uuid::new_v4(), "new_name"),
            Ok(RenameAction::NoSource)
        );
    }

    #[test]
    /// Renaming a pool to itself always works
    fn rename_identity() {
        let name = "name";
        let mut engine = SimEngine::default();
        let uuid = engine
            .create_pool(
                name,
                strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
                None,
            )
            .unwrap()
            .changed()
            .unwrap();
        assert_eq!(
            engine.rename_pool(uuid, name).unwrap(),
            RenameAction::Identity
        );
    }

    #[test]
    /// Renaming a pool to another pool should work if new name not taken
    fn rename_happens() {
        let mut engine = SimEngine::default();
        let uuid = engine
            .create_pool(
                "old_name",
                strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
                None,
            )
            .unwrap()
            .changed()
            .unwrap();
        assert_eq!(
            engine.rename_pool(uuid, "new_name").unwrap(),
            RenameAction::Renamed(uuid)
        );
    }

    #[test]
    /// Renaming a pool to another pool should fail if new name taken
    fn rename_fails() {
        let new_name = "new_name";
        let mut engine = SimEngine::default();
        let uuid = engine
            .create_pool(
                "old_name",
                strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
                None,
            )
            .unwrap()
            .changed()
            .unwrap();
        engine
            .create_pool(
                new_name,
                strs_to_paths!(["/dev/four", "/dev/five", "/dev/six"]),
                None,
            )
            .unwrap();
        assert_matches!(
            engine.rename_pool(uuid, new_name),
            Err(StratisError::Engine(ErrorEnum::AlreadyExists, _))
        );
    }

    #[test]
    /// Renaming should succeed if old_name absent, new present
    fn rename_no_op() {
        let new_name = "new_name";
        let mut engine = SimEngine::default();
        engine
            .create_pool(
                new_name,
                strs_to_paths!(["/dev/one", "/dev/two", "/dev/three"]),
                None,
            )
            .unwrap();
        assert_matches!(
            engine.rename_pool(Uuid::new_v4(), new_name),
            Ok(RenameAction::NoSource)
        );
    }
}
<|endoftext|>


<commit_before>use std::io::{File};
use std::io::fs::PathExtensions;
use data::DataStore;

pub struct Document{
    id: u64,
    version: u64,
    hash: String,
}

pub struct Transaction{
    version: u64,
}

pub struct VersionIndex{
    document_id: u64,
    versions: Vec<Document>,
}

pub struct DocumentIndex {
    documents: Vec<VersionIndex>,
}

impl DocumentIndex {
    fn new() -> DocumentIndex{
        DocumentIndex {
            documents: Vec::new(),
        }
    }

    fn dump(&self, w: &mut Writer) {
        w.write_be_u64(self.documents.len().to_u64().unwrap());
        for &ref index in self.documents.iter() {
            w.write_be_u64(index.document_id);
            w.write_be_u64(index.versions.len().to_u64().unwrap());
            for &ref doc in index.versions.iter() {
                w.write_be_u64(doc.version);
                w.write_str(doc.hash.as_slice());
            }
        }
    }

    fn load(&mut self, r: &mut Reader) {
        let document_count = r.read_be_u64().unwrap();
        for i in range(0, document_count) {
            let id = r.read_be_u64().unwrap();
            let version_count = r.read_be_u64().unwrap();
            let mut index = VersionIndex {
                document_id: id,
                versions: Vec::new(),
            };
            for j in range(0, version_count) {
                let version = r.read_be_u64().unwrap();
                let hash = r.read_exact(32).unwrap();  // hex encoded md5
                let doc = Document {
                    id: id,
                    version: version,
                    hash: String::from_utf8(hash).unwrap(),
                };
                index.versions.push(doc);
            }
            self.documents.push(index);
        }
    }

    fn get_version_index(&self, id: u64) -> &VersionIndex {
        self.documents.index(&(id - 1).to_uint().unwrap())
    }

    fn get_version_index_mut(&mut self, id: u64) -> &mut VersionIndex {
        self.documents.index_mut(&(id - 1).to_uint().unwrap())
    }

    fn get_next_id(&self) -> u64 {
        self.documents.len().to_u64().expect("document id overflow") + 1
    }

    fn add(&mut self, doc: Document) {
        let mut index = VersionIndex {
            document_id: doc.id,
            versions: Vec::new(),
        };
        index.versions.push(doc);
        self.documents.push(index);
    }

}

pub struct Icecore<'a>{
    path: Path,
    index_file_path: Path,
    store: Box<DataStore + 'a>,
    transaction_log: Vec<Transaction>,
    document_index: DocumentIndex,
}

impl<'a> Icecore<'a>{
    pub fn new(path: Path, data_store: Box<DataStore + 'a>) -> Icecore<'a>{
        let index_file_path = path.clone().join("_documents.index");
        Icecore {
            path: path,
            index_file_path: index_file_path,
            store: data_store,
            transaction_log: Vec::new(),
            document_index: DocumentIndex::new(),
        }
    }

    pub fn load(&mut self) {
        if !self.index_file_path.exists() {
            println!("no document index file found");
            return;
        }
        let mut reader = File::open(&self.index_file_path).unwrap();
        self.document_index.load(&mut reader);
    }

    pub fn dump(&mut self) {
        let mut writer = File::create(&self.index_file_path).unwrap();
        self.document_index.dump(&mut writer);
    }

    fn get_next_transaction_id(&self) -> u64 {
        self.transaction_log.len().to_u64().expect("transaction id overflow") + 1
    }

    pub fn insert(&mut self, data: String) -> u64 {
        let hash = self.store.write(data);
        let id = self.document_index.get_next_id();
        let doc = Document {
            id: id,
            version: self.get_next_transaction_id(),
            hash: hash,
        };
        self.document_index.add(doc);

        id
    }

    pub fn get(&self, id: u64, version: Option<u64>) -> String {
        let index = self.document_index.get_version_index(id);
        let doc = match version {
            Some(v) => &index.versions[v.to_uint().unwrap() - 1],
            None => index.versions.last().expect("no document versions found"),
        };
        self.store.read(&doc.hash)
    }

    pub fn update(&mut self, id: u64, data: String) -> u64 {
        let hash = self.store.write(data);
        let version = self.get_next_transaction_id();
        let doc = Document {
            id: id,
            version: version,
            hash: hash,
        };
        let mut index = self.document_index.get_version_index_mut(id);
        index.versions.push(doc);

        version
    }
}

<commit_msg>Add binary search for version index<commit_after>use std::io::{File};
use std::io::fs::PathExtensions;
use std::slice::{Found, NotFound};
use data::DataStore;

pub struct Document{
    id: u64,
    version: u64,
    hash: String,
}

impl Document {
    pub fn cmp_version(&self, other: u64) -> Ordering {
        if self.version == other {
            Equal
        } else if self.version < other {
            Less
        } else {
            Greater
        }
    }
}

pub struct Transaction{
    version: u64,
}

pub struct VersionIndex {
    document_id: u64,
    versions: Vec<Document>,
}

impl VersionIndex {
    pub fn find_version(&self, id: u64) -> Option<&Document> {
        let index = match self.versions.binary_search(|document| document.cmp_version(id)) {
            Found(i) => i,
            NotFound(i) => {
                if i > 0 {
                    i - 1
                } else {
                    0
                }
            }
        };
        self.versions.get(index)
    }
}

pub struct DocumentIndex {
    documents: Vec<VersionIndex>,
}

impl DocumentIndex {
    fn new() -> DocumentIndex{
        DocumentIndex {
            documents: Vec::new(),
        }
    }

    fn dump(&self, w: &mut Writer) {
        w.write_be_u64(self.documents.len().to_u64().unwrap());
        for &ref index in self.documents.iter() {
            w.write_be_u64(index.document_id);
            w.write_be_u64(index.versions.len().to_u64().unwrap());
            for &ref doc in index.versions.iter() {
                w.write_be_u64(doc.version);
                w.write_str(doc.hash.as_slice());
            }
        }
    }

    fn load(&mut self, r: &mut Reader) {
        let document_count = r.read_be_u64().unwrap();
        for i in range(0, document_count) {
            let id = r.read_be_u64().unwrap();
            let version_count = r.read_be_u64().unwrap();
            let mut index = VersionIndex {
                document_id: id,
                versions: Vec::new(),
            };
            for j in range(0, version_count) {
                let version = r.read_be_u64().unwrap();
                let hash = r.read_exact(32).unwrap();  // hex encoded md5
                let doc = Document {
                    id: id,
                    version: version,
                    hash: String::from_utf8(hash).unwrap(),
                };
                index.versions.push(doc);
            }
            self.documents.push(index);
        }
    }

    fn get_version_index(&self, id: u64) -> &VersionIndex {
        self.documents.index(&(id - 1).to_uint().unwrap())
    }

    fn get_version_index_mut(&mut self, id: u64) -> &mut VersionIndex {
        self.documents.index_mut(&(id - 1).to_uint().unwrap())
    }

    fn get_next_id(&self) -> u64 {
        self.documents.len().to_u64().expect("document id overflow") + 1
    }

    fn add(&mut self, doc: Document) {
        let mut index = VersionIndex {
            document_id: doc.id,
            versions: Vec::new(),
        };
        index.versions.push(doc);
        self.documents.push(index);
    }

}

pub struct Icecore<'a>{
    path: Path,
    index_file_path: Path,
    store: Box<DataStore + 'a>,
    transaction_log: Vec<Transaction>,
    document_index: DocumentIndex,
}

impl<'a> Icecore<'a>{
    pub fn new(path: Path, data_store: Box<DataStore + 'a>) -> Icecore<'a>{
        let index_file_path = path.clone().join("_documents.index");
        Icecore {
            path: path,
            index_file_path: index_file_path,
            store: data_store,
            transaction_log: Vec::new(),
            document_index: DocumentIndex::new(),
        }
    }

    pub fn load(&mut self) {
        if !self.index_file_path.exists() {
            println!("no document index file found");
            return;
        }
        let mut reader = File::open(&self.index_file_path).unwrap();
        self.document_index.load(&mut reader);
    }

    pub fn dump(&mut self) {
        let mut writer = File::create(&self.index_file_path).unwrap();
        self.document_index.dump(&mut writer);
    }

    fn get_next_transaction_id(&self) -> u64 {
        self.transaction_log.len().to_u64().expect("transaction id overflow") + 1
    }

    pub fn insert(&mut self, data: String) -> u64 {
        let hash = self.store.write(data);
        let id = self.document_index.get_next_id();
        let doc = Document {
            id: id,
            version: self.get_next_transaction_id(),
            hash: hash,
        };
        self.document_index.add(doc);

        id
    }

    pub fn get(&self, id: u64, version: Option<u64>) -> String {
        let index = self.document_index.get_version_index(id);
        let doc = match version {
            Some(v) => index.find_version(v.to_u64().unwrap()).unwrap(),
            None => index.versions.last().expect("no document versions found"),
        };
        self.store.read(&doc.hash)
    }

    pub fn update(&mut self, id: u64, data: String) -> u64 {
        let hash = self.store.write(data);
        let version = self.get_next_transaction_id();
        let doc = Document {
            id: id,
            version: version,
            hash: hash,
        };
        let mut index = self.document_index.get_version_index_mut(id);
        index.versions.push(doc);

        version
    }
}

<|endoftext|>


<commit_before>use super::super::StreamId;
use super::frames::{
    Frame,
    Flag,
    pack_header,
    RawFrame,
    FrameHeader
};

/// An enum representing the flags that a `PingFrame` can have.
/// The integer representation associated to each variant is that flag's
/// bitmask.
///
/// HTTP/2 spec, section 6.
#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Debug)]
#[derive(Copy)]
pub enum NoFlag {
    None = 0x0,
}

impl Flag for NoFlag {
    #[inline]
    fn bitmask(&self) -> u8 {
        *self as u8
    }
}

/// The struct represents the dependency information that can be attached to a stream
/// and sent within HEADERS frame
#[derive(PartialEq)]
#[derive(Debug)]
#[derive(Clone)]
pub struct StreamDependency {
    /// The ID of the stream that a particular stream depends on
    pub stream_id: StreamId,
    /// The weight for the stream. The value exposed (and set) here is always
    /// in the range [0, 255], instead of [1, 256] so that the value fits
    /// into a `u8`.
    pub weight: u8,
    /// A flag indicating whether the stream dependency is exclusive.
    pub is_exclusive: bool,
}

impl StreamDependency {
    /// Creates a new `StreamDependency` with the given stream Id, weight, and
    /// exclusivity.
    pub fn new(stream_id: StreamId, weight: u8, is_exclusive: bool)
            -> StreamDependency {
        StreamDependency {
            stream_id: stream_id,
            weight: weight,
            is_exclusive: is_exclusive,
        }
    }

    /// Parses the 5-byte length frame
    ///
    /// # Panics
    ///
    /// If the frame is less than 5 bytes, the method will panic
    pub fn parse(buf: &[u8]) -> StreamDependency {
        // The most significant bit of the first byte is the "E" bit indicating
        // whether the dependency is exclusive.
        let is_exclusive = buf[0] & 0x80 != 0;
        let stream_id = {
            // Parse the first 4 bytes into a u32
            let mut id = unpack_octets_4!(buf, 0, u32);
            // and clear the first bit since the stream id is only 31 bits.
            id &= !(1 << 31);
            id
        };

        StreamDependency {
            stream_id: stream_id,
            weight: buf[4],
            is_exclusive: is_exclusive,
        }
    }

    /// Serializes the `StreamDependency` into a 5-byte buffer representing the
    /// dependency description.
    pub fn serialize(&self) -> [u8; 5] {
        let e_bit = if self.is_exclusive {
            1 << 7
        } else {
            0
        };
        [
            (((self.stream_id >> 24) & 0x000000FF) as u8) | e_bit,
            (((self.stream_id >> 16) & 0x000000FF) as u8),
            (((self.stream_id >>  8) & 0x000000FF) as u8),
            (((self.stream_id >>  0) & 0x000000FF) as u8),
            self.weight,
        ]
    }
}

/// A struct representing the PRIORITY frmas of HTTP/2
#[derive(PartialEq)]
#[derive(Debug)]
pub struct PriorityFrame {
    /// The id of the stream with which this frame is associated
    pub stream_id: StreamId,
    /// The stream dependency information
    pub stream_dep: StreamDependency,
}

impl PriorityFrame {
    pub fn new(stream_id: StreamId, stream_dep: StreamDependency)
            -> PriorityFrame {
        PriorityFrame {
            stream_id: stream_id,
            stream_dep: stream_dep,
        }
    }

    /// Returns the length of the payload of the current frame
    /// Priority frame must be 5 octets
    fn payload_len(&self) -> u32 {
        5
    }
}

impl Frame for PriorityFrame {
    /// `Priority` frame does not take a flag
    type FlagType = NoFlag;

    /// Creates a new `PriorityFrame` with the given `RawFrame` (i.e. header and
    /// payload), if possible.
    ///
    /// # Returns
    ///
    /// `None` if a valid `PriorityFrame` cannot be constructed from the given
    /// `RawFrame`. The stream ID *MUST NOT* be 0.
    ///
    /// Otherwise, returns a newly contructed `PriorityFrame`
    fn from_raw(raw_frame: RawFrame) -> Option<PriorityFrame> {
        // Unpack the header
        let (len, frame_type, flags, stream_id) = raw_frame.header;
        // Check that the frame type is correct for this frame implementation
        if frame_type != 0x2 {
            return None;
        }
        // Check that the length given in the header matches the payload
        // if not, soemthing went wrong and we do not consider this as
        // a valid frame.
        if (len as usize) != raw_frame.payload.len() {
            return None;
        }
        // Check that the length of the payload is 5 bytes
        // If not, this is not a valid frame
        if raw_frame.payload.len() != 5 {
            return None;
        }
        // Check that the PRIORITY frame is not associated to stream 0
        // If it is, this is not a valid frame
        if stream_id == 0 {
            return None;
        }
        // Extract the stream dependecy info from the payload
        let stream_dep = StreamDependency::parse(&raw_frame.payload);

        Some(PriorityFrame {
            stream_id: stream_id,
            stream_dep: stream_dep,
        })
    }

    /// `Priority` frame does not set any flags
    fn is_set(&self, flag: NoFlag) -> bool {
        true
    }

    /// Returns the `StreamId` of the stream to which the frame is associated
    ///
    fn get_stream_id(&self) -> StreamId {
        self.stream_id
    }

    /// Returns a `FrameHeader` based on the current state of the `Frame`.
    fn get_header(&self) -> FrameHeader {
        (self.payload_len(), 0x2, 0, self.stream_id)
    }

    /// `PriorityFrame` does not set any flags
    fn set_flag(&mut self, flag: NoFlag) {
    }

    /// Returns a `Vec` with the serialized representation of the frame.
    fn serialize(&self) -> Vec<u8> {
        let mut buf = Vec::with_capacity(self.payload_len() as usize);
        // The header
        buf.extend(pack_header(&self.get_header()).to_vec().into_iter());
        // and then the body
        buf.extend(self.stream_dep.serialize().to_vec().into_iter());

        buf
    }
}

<commit_msg>(feat) Implement tests for Priority Frame<commit_after>use super::super::StreamId;
use super::frames::{
    Frame,
    Flag,
    pack_header,
    RawFrame,
    FrameHeader
};

/// An enum representing the flags that a `PingFrame` can have.
/// The integer representation associated to each variant is that flag's
/// bitmask.
///
/// HTTP/2 spec, section 6.
#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Debug)]
#[derive(Copy)]
pub enum NoFlag {
    None = 0x0,
}

impl Flag for NoFlag {
    #[inline]
    fn bitmask(&self) -> u8 {
        *self as u8
    }
}

/// The struct represents the dependency information that can be attached to a stream
/// and sent within HEADERS frame
#[derive(PartialEq)]
#[derive(Debug)]
#[derive(Clone)]
pub struct StreamDependency {
    /// The ID of the stream that a particular stream depends on
    pub stream_id: StreamId,
    /// The weight for the stream. The value exposed (and set) here is always
    /// in the range [0, 255], instead of [1, 256] so that the value fits
    /// into a `u8`.
    pub weight: u8,
    /// A flag indicating whether the stream dependency is exclusive.
    pub is_exclusive: bool,
}

impl StreamDependency {
    /// Creates a new `StreamDependency` with the given stream Id, weight, and
    /// exclusivity.
    pub fn new(stream_id: StreamId, weight: u8, is_exclusive: bool)
            -> StreamDependency {
        StreamDependency {
            stream_id: stream_id,
            weight: weight,
            is_exclusive: is_exclusive,
        }
    }

    /// Parses the 5-byte length frame
    ///
    /// # Panics
    ///
    /// If the frame is less than 5 bytes, the method will panic
    pub fn parse(buf: &[u8]) -> StreamDependency {
        // The most significant bit of the first byte is the "E" bit indicating
        // whether the dependency is exclusive.
        let is_exclusive = buf[0] & 0x80 != 0;
        let stream_id = {
            // Parse the first 4 bytes into a u32
            let mut id = unpack_octets_4!(buf, 0, u32);
            // and clear the first bit since the stream id is only 31 bits.
            id &= !(1 << 31);
            id
        };

        StreamDependency {
            stream_id: stream_id,
            weight: buf[4],
            is_exclusive: is_exclusive,
        }
    }

    /// Serializes the `StreamDependency` into a 5-byte buffer representing the
    /// dependency description.
    pub fn serialize(&self) -> [u8; 5] {
        let e_bit = if self.is_exclusive {
            1 << 7
        } else {
            0
        };
        [
            (((self.stream_id >> 24) & 0x000000FF) as u8) | e_bit,
            (((self.stream_id >> 16) & 0x000000FF) as u8),
            (((self.stream_id >>  8) & 0x000000FF) as u8),
            (((self.stream_id >>  0) & 0x000000FF) as u8),
            self.weight,
        ]
    }
}

/// A struct representing the PRIORITY frmas of HTTP/2
#[derive(PartialEq)]
#[derive(Debug)]
pub struct PriorityFrame {
    /// The id of the stream with which this frame is associated
    pub stream_id: StreamId,
    /// The stream dependency information
    pub stream_dep: StreamDependency,
    /// `Priority` frame does not define any flags
    flags: u8,
}

impl PriorityFrame {
    pub fn new(stream_id: StreamId, stream_dep: StreamDependency)
            -> PriorityFrame {
        PriorityFrame {
            stream_id: stream_id,
            stream_dep: stream_dep,
            flags: 0,
        }
    }

    /// Returns the length of the payload of the current frame
    /// Priority frame must be 5 octets
    fn payload_len(&self) -> u32 {
        5
    }
}

impl Frame for PriorityFrame {
    /// `Priority` frame does not take a flag
    type FlagType = NoFlag;

    /// Creates a new `PriorityFrame` with the given `RawFrame` (i.e. header and
    /// payload), if possible.
    ///
    /// # Returns
    ///
    /// `None` if a valid `PriorityFrame` cannot be constructed from the given
    /// `RawFrame`. The stream ID *MUST NOT* be 0.
    ///
    /// Otherwise, returns a newly contructed `PriorityFrame`
    fn from_raw(raw_frame: RawFrame) -> Option<PriorityFrame> {
        // Unpack the header
        let (len, frame_type, flags, stream_id) = raw_frame.header;
        // Check that the frame type is correct for this frame implementation
        if frame_type != 0x2 {
            return None;
        }
        // Check that the length given in the header matches the payload
        // if not, soemthing went wrong and we do not consider this as
        // a valid frame.
        if (len as usize) != raw_frame.payload.len() {
            return None;
        }
        // Check that the length of the payload is 5 bytes
        // If not, this is not a valid frame
        if raw_frame.payload.len() != 5 {
            return None;
        }
        // Check that the PRIORITY frame is not associated to stream 0
        // If it is, this is not a valid frame
        if stream_id == 0 {
            return None;
        }
        // Extract the stream dependecy info from the payload
        let stream_dep = StreamDependency::parse(&raw_frame.payload);

        Some(PriorityFrame {
            stream_id: stream_id,
            stream_dep: stream_dep,
            flags: flags,
        })
    }

    /// `Priority` frame does not set any flags
    fn is_set(&self, flag: NoFlag) -> bool {
        true
    }

    /// Returns the `StreamId` of the stream to which the frame is associated
    ///
    fn get_stream_id(&self) -> StreamId {
        self.stream_id
    }

    /// Returns a `FrameHeader` based on the current state of the `Frame`.
    fn get_header(&self) -> FrameHeader {
        (self.payload_len(), 0x2, 0, self.stream_id)
    }

    /// `PriorityFrame` does not set any flags
    fn set_flag(&mut self, flag: NoFlag) {
    }

    /// Returns a `Vec` with the serialized representation of the frame.
    fn serialize(&self) -> Vec<u8> {
        let mut buf = Vec::with_capacity(self.payload_len() as usize);
        // The header
        buf.extend(pack_header(&self.get_header()).to_vec().into_iter());
        // and then the body
        buf.extend(self.stream_dep.serialize().to_vec().into_iter());

        buf
    }
}

#[cfg(test)]
mod tests {
    use super::super::frames::{Frame, RawFrame, pack_header};
    use super::super::test::{build_test_frame};
    use super::{PriorityFrame, NoFlag, StreamDependency};

    /// Tests that a simple PRIORITY frame is correclty parsed.
    #[test]
    fn test_priority_frame_parse() {
        let dep = StreamDependency::new(0, 5, true);
        let payload = {
            let mut buf: Vec<u8> = Vec::new();
            buf.extend(dep.serialize().to_vec().into_iter());

            buf
        };
        let header = (payload.len() as u32, 0x2, 0, 1);

        let frame = build_test_frame::<PriorityFrame>(&header, &payload);

        assert_eq!(frame.flags, 0);
        assert_eq!(frame.get_stream_id(), 1);
        assert_eq!(frame.stream_dep, dep);
    }

    /// Tests that a HEADERS with stream ID 0 is considered invalid.
    #[test]
    fn test_priority_frame_parse_invalid_stream_id() {
        let dep = StreamDependency::new(0, 5, true);
        let payload = {
            let mut buf: Vec<u8> = Vec::new();
            buf.extend(dep.serialize().to_vec().into_iter());

            buf
        };
        let header = (payload.len() as u32, 0x2, 0, 0);

        let frame: Option<PriorityFrame> = Frame::from_raw(
            RawFrame::with_payload(header, payload));

        assert!(frame.is_none());
    }

    /// Tests that the `HeadersFrame::parse` method considers any frame with
    /// a frame ID other than 1 in the frame header invalid.
    #[test]
    fn priority_frame_parse_invalid_type() {
        let dep = StreamDependency::new(0, 5, true);
        let payload = {
            let mut buf: Vec<u8> = Vec::new();
            buf.extend(dep.serialize().to_vec().into_iter());

            buf
        };
        let header = (payload.len() as u32, 0x1, 0, 1);

        let frame: Option<PriorityFrame> = Frame::from_raw(
            RawFrame::with_payload(header, payload));

        assert!(frame.is_none());
    }

    /// Tests that a HEADERS frame with priority gets correctly serialized.
    #[test]
    fn test_priority_frame_serialize() {
        let dep = StreamDependency::new(0, 5, true);
        let payload = {
            let mut buf: Vec<u8> = Vec::new();
            buf.extend(dep.serialize().to_vec().into_iter());

            buf
        };
        let header = (payload.len() as u32, 0x2, 0, 1);
        let expected = {
            let headers = pack_header(&header);
            let mut res: Vec<u8> = Vec::new();
            res.extend(headers.to_vec().into_iter());
            res.extend(payload.into_iter());

            res
        };
        let frame = PriorityFrame::new(1, dep.clone());

        let actual = frame.serialize();

        assert_eq!(expected, actual);
    }

    /// Tests that a stream dependency structure can be correctly parsed by the
    /// `StreamDependency::parse` method.
    #[test]
    fn test_parse_stream_dependency() {
        {
            let buf = [0, 0, 0, 1, 5];

            let dep = StreamDependency::parse(&buf);

            assert_eq!(dep.stream_id, 1);
            assert_eq!(dep.weight, 5);
            // This one was not exclusive!
            assert!(!dep.is_exclusive)
        }
        {
            // Most significant bit set => is exclusive!
            let buf = [128, 0, 0, 1, 5];

            let dep = StreamDependency::parse(&buf);

            assert_eq!(dep.stream_id, 1);
            assert_eq!(dep.weight, 5);
            // This one was indeed exclusive!
            assert!(dep.is_exclusive)
        }
        {
            // Most significant bit set => is exclusive!
            let buf = [255, 255, 255, 255, 5];

            let dep = StreamDependency::parse(&buf);

            assert_eq!(dep.stream_id, (1 << 31) - 1);
            assert_eq!(dep.weight, 5);
            // This one was indeed exclusive!
            assert!(dep.is_exclusive);
        }
        {
            let buf = [127, 255, 255, 255, 5];

            let dep = StreamDependency::parse(&buf);

            assert_eq!(dep.stream_id, (1 << 31) - 1);
            assert_eq!(dep.weight, 5);
            // This one was not exclusive!
            assert!(!dep.is_exclusive);
        }
    }

    /// Tests that a stream dependency structure can be correctly serialized by
    /// the `StreamDependency::serialize` method.
    #[test]
    fn test_serialize_stream_dependency() {
        {
            let buf = [0, 0, 0, 1, 5];
            let dep = StreamDependency::new(1, 5, false);

            assert_eq!(buf, dep.serialize());
        }
        {
            // Most significant bit set => is exclusive!
            let buf = [128, 0, 0, 1, 5];
            let dep = StreamDependency::new(1, 5, true);

            assert_eq!(buf, dep.serialize());
        }
        {
            // Most significant bit set => is exclusive!
            let buf = [255, 255, 255, 255, 5];
            let dep = StreamDependency::new((1 << 31) - 1, 5, true);

            assert_eq!(buf, dep.serialize());
        }
        {
            let buf = [127, 255, 255, 255, 5];
            let dep = StreamDependency::new((1 << 31) - 1, 5, false);

            assert_eq!(buf, dep.serialize());
        }
    }
}

<|endoftext|>