<commit_before>#![feature(collections)]
#![feature(convert)]

use std::borrow::Cow;
use std::borrow::Cow::{Borrowed};

pub fn compile(sass: &str, style: &str) -> Result<String, &'static str> {
    let mut st = SassTokenizer::new(&sass);

    match style {
        "nested"     => Ok(nested_output(&mut st)),
        "compressed" => Ok(compressed_output(&mut st)),
        "expanded"   => Ok(expanded_output(&mut st)),
        "compact"    => Ok(compact_output(&mut st)),
        "debug"      => Ok(debug_output(&mut st)),
        _            => Err("Unknown style:. Please specify one of nested, compressed, expanded, or compact."),
    }
}

pub fn nested_output(tokenizer: &mut SassTokenizer) -> String {
    let mut output =  String::from_str("");
    while let Some(token) = tokenizer.next() {
        let print_token = match token {
            Event::Start(_) => continue,
            Event::Selector(name) => format!("{} {{", name),
            Event::Property(name, value) => format!("\n  {}: {};", name, value),
            Event::End(_) => format!(" }}\n"),
        };
        output.push_str(print_token.as_str());
    }
    output
}

pub fn compressed_output(tokenizer: &mut SassTokenizer) -> String {
    let mut output =  String::from_str("");
    while let Some(token) = tokenizer.next() {
        let print_token = match token {
            Event::Start(_) => continue,
            Event::Selector(name) => format!("{}{{", name),
            Event::Property(name, value) => format!("{}:{}", name, value),
            Event::End(_) => format!("}}"),
        };
        output.push_str(print_token.as_str());
    }
    output
}

pub fn expanded_output(tokenizer: &mut SassTokenizer) -> String {
    let mut output =  String::from_str("");
    while let Some(token) = tokenizer.next() {
        let print_token = match token {
            Event::Start(_) => continue,
            Event::Selector(name) => format!("{} {{", name),
            Event::Property(name, value) => format!("\n  {}: {};", name, value),
            Event::End(_) => format!("\n}}"),
        };
        output.push_str(print_token.as_str());
    }
    output
}

pub fn compact_output(tokenizer: &mut SassTokenizer) -> String {
    let mut output =  String::from_str("");
    while let Some(token) = tokenizer.next() {
        let print_token = match token {
            Event::Start(_) => continue,
            Event::Selector(name) => format!("{} {{", name),
            Event::Property(name, value) => format!(" {}: {};", name, value),
            Event::End(_) => format!(" }}"),
        };
        output.push_str(print_token.as_str());
    }
    output
}

pub fn debug_output(tokenizer: &mut SassTokenizer) -> String {
    let mut output =  String::from_str("");
    while let Some(token) = tokenizer.next() {
        output.push_str(format!("{:?}\n", token).as_str());
    }
    output
}

#[derive(PartialEq, Debug)]
pub enum State {
    StartRule,
    InSelectors,
    InProperties,
}

#[derive(Debug)]
pub enum Rule {
    SassRule,
}

#[derive(Debug)]
pub enum Event<'a> {
    Start(Rule),
    End(Rule),
    Selector(Cow<'a, str>),
    Property(Cow<'a, str>, Cow<'a, str>),
}

#[derive(Debug)]
pub struct SassTokenizer<'a> {
    sass: &'a str,
    offset: usize,
    stack: Vec<Rule>,
    state: State,
}

impl<'a> SassTokenizer<'a> {
    pub fn new(sass: &'a str) -> SassTokenizer<'a> {
        SassTokenizer {
            sass: &sass,
            offset: 0,
            stack: Vec::new(),
            state: State::StartRule,
        }
    }

    pub fn start_rule(&mut self) -> Option<Event<'a>> {
        self.state = State::InSelectors;
        self.stack.push(Rule::SassRule);

        Some(Event::Start(Rule::SassRule))
    }

    fn end(&mut self) -> Event<'a> {
        let rule = self.stack.pop().unwrap();
        self.state = State::StartRule;
        Event::End(rule)
    }

    fn scan_while<F>(&mut self, data: &str, f: F) -> usize
            where F: Fn(u8) -> bool {
        match data.as_bytes().iter().position(|&c| !f(c)) {
            Some(i) => i,
            None => data.len()
        }
    }

    fn skip_leading_whitespace(&mut self) {
        let i = self.offset;
        self.offset += self.scan_while(&self.sass[i..self.sass.len()], is_ascii_whitespace);
    }

    pub fn next_property(&mut self) -> Event<'a> {
        self.skip_leading_whitespace();

        let bytes = self.sass.as_bytes();
        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        let c = bytes[i];
        if c == b'}' {
            self.offset += 1;
            return self.end()
        }

        while i < limit {
            match bytes[i..limit].iter().position(|&c| c == b':') {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                return Event::Property(
                    Borrowed(&self.sass[name_beginning..name_end]),
                    Borrowed(&self.sass[value_beginning..value_end])
                )

            }
        }
        self.offset = self.sass.len();
        Event::Property(Borrowed(""), Borrowed(""))
    }

    pub fn next_selector(&mut self) -> Event<'a> {
        let bytes = self.sass.as_bytes();
        let beginning = self.offset;
        let mut i = beginning;
        let limit = self.sass.len();

        while i < limit {
            match bytes[i..limit].iter().position(|&c| c == b',' || c == b'{') {
                Some(pos) => { i += pos; },
                None => { i = limit; break; },
            }

            let c = bytes[i];

            if c == b',' || c == b'{' {
                let n = scan_trailing_whitespace(&self.sass[beginning..i]);
                let end = i - n;
                if end > beginning {
                    if c == b'{' {
                        self.state = State::InProperties;
                    }
                    self.offset = i + 1;
                    return Event::Selector(Borrowed(&self.sass[beginning..end]));
                }
            }

            self.offset = i;
            if i > beginning {
                return Event::Selector(Borrowed(&self.sass[beginning..i]))
            }
            i += 1;
        }

        if i > beginning {
            self.offset = i;
            Event::Selector(Borrowed(&self.sass[beginning..i]))
        } else {
            self.end()
        }
    }
}

impl<'a> Iterator for SassTokenizer<'a> {
    type Item = Event<'a>;

    fn next(&mut self) -> Option<Event<'a>> {
        if self.offset < self.sass.len() {
            match self.state {
                State::StartRule => {
                    let ret = self.start_rule();
                    if ret.is_some() {
                        return ret
                    }
                },
                State::InSelectors => return Some(self.next_selector()),
                State::InProperties => return Some(self.next_property()),
            }
        }
        None
    }
}

pub fn char_at(s: &str, byte: usize) -> char {
    s[byte..].chars().next().unwrap()
}

pub fn is_ascii_whitespace(c: u8) -> bool {
    c == b'\n' || c == b'\r' || is_ascii_whitespace_no_nl(c)
}

pub fn is_ascii_whitespace_no_nl(c: u8) -> bool {
    c == b'\t' || c == 0x0b || c == 0x0c || c == b' '
}

// unusual among "scan" functions in that it scans from the _back_ of the string
// TODO: should also scan unicode whitespace?
pub fn scan_trailing_whitespace(data: &str) -> usize {
    match data.as_bytes().iter().rev().position(|&c| !is_ascii_whitespace_no_nl(c)) {
        Some(i) => i,
        None => data.len()
    }
}
<commit_msg>And i broke empty file. But now it should be fixed.<commit_after>#![feature(collections)]
#![feature(convert)]

use std::borrow::Cow;
use std::borrow::Cow::{Borrowed};

pub fn compile(sass: &str, style: &str) -> Result<String, &'static str> {
    let mut st = SassTokenizer::new(&sass);

    match style {
        "nested"     => Ok(nested_output(&mut st)),
        "compressed" => Ok(compressed_output(&mut st)),
        "expanded"   => Ok(expanded_output(&mut st)),
        "compact"    => Ok(compact_output(&mut st)),
        "debug"      => Ok(debug_output(&mut st)),
        _            => Err("Unknown style:. Please specify one of nested, compressed, expanded, or compact."),
    }
}

pub fn nested_output(tokenizer: &mut SassTokenizer) -> String {
    let mut output =  String::from_str("");
    while let Some(token) = tokenizer.next() {
        let print_token = match token {
            Event::Start(_) => continue,
            Event::Selector(name) => format!("{} {{", name),
            Event::Property(name, value) => format!("\n  {}: {};", name, value),
            Event::End(_) => format!(" }}\n"),
        };
        output.push_str(print_token.as_str());
    }
    output
}

pub fn compressed_output(tokenizer: &mut SassTokenizer) -> String {
    let mut output =  String::from_str("");
    while let Some(token) = tokenizer.next() {
        let print_token = match token {
            Event::Start(_) => continue,
            Event::Selector(name) => format!("{}{{", name),
            Event::Property(name, value) => format!("{}:{}", name, value),
            Event::End(_) => format!("}}"),
        };
        output.push_str(print_token.as_str());
    }
    output
}

pub fn expanded_output(tokenizer: &mut SassTokenizer) -> String {
    let mut output =  String::from_str("");
    while let Some(token) = tokenizer.next() {
        let print_token = match token {
            Event::Start(_) => continue,
            Event::Selector(name) => format!("{} {{", name),
            Event::Property(name, value) => format!("\n  {}: {};", name, value),
            Event::End(_) => format!("\n}}"),
        };
        output.push_str(print_token.as_str());
    }
    output
}

pub fn compact_output(tokenizer: &mut SassTokenizer) -> String {
    let mut output =  String::from_str("");
    while let Some(token) = tokenizer.next() {
        let print_token = match token {
            Event::Start(_) => continue,
            Event::Selector(name) => format!("{} {{", name),
            Event::Property(name, value) => format!(" {}: {};", name, value),
            Event::End(_) => format!(" }}"),
        };
        output.push_str(print_token.as_str());
    }
    output
}

pub fn debug_output(tokenizer: &mut SassTokenizer) -> String {
    let mut output =  String::from_str("");
    while let Some(token) = tokenizer.next() {
        output.push_str(format!("{:?}\n", token).as_str());
    }
    output
}

#[derive(PartialEq, Debug)]
pub enum State {
    StartRule,
    InSelectors,
    InProperties,
}

#[derive(Debug)]
pub enum Rule {
    SassRule,
}

#[derive(Debug)]
pub enum Event<'a> {
    Start(Rule),
    End(Rule),
    Selector(Cow<'a, str>),
    Property(Cow<'a, str>, Cow<'a, str>),
}

#[derive(Debug)]
pub struct SassTokenizer<'a> {
    sass: &'a str,
    offset: usize,
    stack: Vec<Rule>,
    state: State,
}

impl<'a> SassTokenizer<'a> {
    pub fn new(sass: &'a str) -> SassTokenizer<'a> {
        SassTokenizer {
            sass: &sass,
            offset: 0,
            stack: Vec::new(),
            state: State::StartRule,
        }
    }

    pub fn start_rule(&mut self) -> Option<Event<'a>> {
        self.skip_leading_whitespace();

        if self.offset == self.sass.len() {
            return None
        }

        self.state = State::InSelectors;
        self.stack.push(Rule::SassRule);

        Some(Event::Start(Rule::SassRule))
    }

    fn end(&mut self) -> Event<'a> {
        let rule = self.stack.pop().unwrap();
        self.state = State::StartRule;
        Event::End(rule)
    }

    fn scan_while<F>(&mut self, data: &str, f: F) -> usize
            where F: Fn(u8) -> bool {
        match data.as_bytes().iter().position(|&c| !f(c)) {
            Some(i) => i,
            None => data.len()
        }
    }

    fn skip_leading_whitespace(&mut self) {
        let i = self.offset;
        self.offset += self.scan_while(&self.sass[i..self.sass.len()], is_ascii_whitespace);
    }

    pub fn next_property(&mut self) -> Event<'a> {
        self.skip_leading_whitespace();

        let bytes = self.sass.as_bytes();
        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        let c = bytes[i];
        if c == b'}' {
            self.offset += 1;
            return self.end()
        }

        while i < limit {
            match bytes[i..limit].iter().position(|&c| c == b':') {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                return Event::Property(
                    Borrowed(&self.sass[name_beginning..name_end]),
                    Borrowed(&self.sass[value_beginning..value_end])
                )

            }
        }
        self.offset = self.sass.len();
        Event::Property(Borrowed(""), Borrowed(""))
    }

    pub fn next_selector(&mut self) -> Event<'a> {
        let bytes = self.sass.as_bytes();
        let beginning = self.offset;
        let mut i = beginning;
        let limit = self.sass.len();

        while i < limit {
            match bytes[i..limit].iter().position(|&c| c == b',' || c == b'{') {
                Some(pos) => { i += pos; },
                None => { i = limit; break; },
            }

            let c = bytes[i];

            if c == b',' || c == b'{' {
                let n = scan_trailing_whitespace(&self.sass[beginning..i]);
                let end = i - n;
                if end > beginning {
                    if c == b'{' {
                        self.state = State::InProperties;
                    }
                    self.offset = i + 1;
                    return Event::Selector(Borrowed(&self.sass[beginning..end]));
                }
            }

            self.offset = i;
            if i > beginning {
                return Event::Selector(Borrowed(&self.sass[beginning..i]))
            }
            i += 1;
        }

        if i > beginning {
            self.offset = i;
            Event::Selector(Borrowed(&self.sass[beginning..i]))
        } else {
            self.end()
        }
    }
}

impl<'a> Iterator for SassTokenizer<'a> {
    type Item = Event<'a>;

    fn next(&mut self) -> Option<Event<'a>> {
        if self.offset < self.sass.len() {
            match self.state {
                State::StartRule => {
                    let ret = self.start_rule();
                    if ret.is_some() {
                        return ret
                    }
                },
                State::InSelectors => return Some(self.next_selector()),
                State::InProperties => return Some(self.next_property()),
            }
        }
        None
    }
}

pub fn char_at(s: &str, byte: usize) -> char {
    s[byte..].chars().next().unwrap()
}

pub fn is_ascii_whitespace(c: u8) -> bool {
    c == b'\n' || c == b'\r' || is_ascii_whitespace_no_nl(c)
}

pub fn is_ascii_whitespace_no_nl(c: u8) -> bool {
    c == b'\t' || c == 0x0b || c == 0x0c || c == b' '
}

// unusual among "scan" functions in that it scans from the _back_ of the string
// TODO: should also scan unicode whitespace?
pub fn scan_trailing_whitespace(data: &str) -> usize {
    match data.as_bytes().iter().rev().position(|&c| !is_ascii_whitespace_no_nl(c)) {
        Some(i) => i,
        None => data.len()
    }
}
<|endoftext|>


<commit_before>#[test]
fn test_sorting () {
	let mut unsorted = vec! [3, 2, 1];

	let sorted = vec! [1, 2, 3];

	unsorted.sort_by (|a, b| a.cmp (b));

	assert_eq! (unsorted, sorted);
}

#[test]
pub fn it_works() {
	let mut world = World::new_half_adder ();
	println! ("Constructed world");
	// This has to be done for initialization, it should be automated
	world.step_gates ();

	world.step_to_settled ();

	assert_eq! (world.junctions [3], false);
	assert_eq! (world.junctions [7], false);

	world.delays.push (Delay {
		junction: 0,
		level: true,
		time: world.time,
	});

	world.step_to_settled ();

	assert_eq! (world.junctions [3], false);
	assert_eq! (world.junctions [7], true);

	world.delays.push (Delay {
		junction: 8,
		level: true,
		time: world.time,
	});

	world.step_to_settled ();

	assert_eq! (world.junctions [3], true);
	assert_eq! (world.junctions [7], false);

	world.delays.push (Delay {
		junction: 0,
		level: false,
		time: world.time,
	});

	world.step_to_settled ();

	assert_eq! (world.junctions [3], false);
	assert_eq! (world.junctions [7], true);
}

// 2 billion junctions is good enough for now
type JunctionIndex = usize;
type ElementIndex = u32;
type OutputIndex = u8;
type Time = i64;
type Level = bool;

enum GateBehavior {
	Inverter,
	And,
	Xor,
}

// In the future, at time "time", junction "junction" will be set to level "level".
#[derive (Clone, Copy)]
pub struct Delay {
	junction: JunctionIndex,
	level: Level,
	time: Time,
}

#[derive (Clone, Copy)]
pub struct Wire {
	input: JunctionIndex,
	output: JunctionIndex,
	delay: Time,
}

pub struct Gate {
	inputs: Vec <JunctionIndex>,
	output: JunctionIndex,
	behavior: GateBehavior,
}

pub struct World {
	wires: Vec <Wire>,
	gates: Vec <Gate>,

	junctions: Vec <bool>,
	time: Time,
	delays: Vec <Delay>,
}

impl Wire {
	fn new (input: JunctionIndex, output: JunctionIndex, delay: Time) -> Wire {
		Wire {
			input: input,
			output: output,
			delay: delay,
		}
	}
}

enum JunctionDestiny {
	Settled (Level),
	Eventually (Delay),
}

impl World {
	fn new_half_adder () -> World {
		World {
			time: 0,
			delays: vec![],
			junctions: vec![false; 10],
			wires: vec![
				Wire::new (0, 1, 4),
				Wire::new (0, 5, 8),
				Wire::new (2, 3, 4),
				Wire::new (6, 7, 3),
				Wire::new (8, 4, 8),
				Wire::new (8, 9, 4),
			],
			gates: vec![
				Gate {
					inputs: vec![1, 4],
					output: 2,
					behavior: GateBehavior::And,
				},
				Gate {
					inputs: vec![5, 9],
					output: 6,
					behavior: GateBehavior::Xor,
				},
			],
		}
	}

	fn is_settled (& self) -> bool {
		self.delays.len () == 0
	}

	fn sort_delays (&mut self) {
		// This step is just a safety since we should be insertion sorting the delays already
		self.delays.sort_by (|a, b| a.time.cmp (&b.time));
	}

	fn step_gates (&mut self) {
		let mut new_delays = Vec::<Delay>::new ();

		// TODO: Optimize to only touch gates whose inputs have changed
		for gate in self.gates.iter () {
			let inputs: Vec <bool> = gate.inputs.iter ().map (|i| self.junctions [*i]).collect ();

			let output = match gate.behavior {
				GateBehavior::And => inputs.iter ().fold (true, |sum, a| sum && *a),
				GateBehavior::Xor => inputs.iter ().fold (false, |sum, a| sum ^ *a),
				GateBehavior::Inverter => inputs [0],
			};

			let destiny = self.get_junction_destiny (gate.output);
			let destinyLevel = match destiny {
				JunctionDestiny::Settled (level) => level,
				JunctionDestiny::Eventually (delay) => delay.level,
			};

			if destinyLevel != output {
				new_delays.push (Delay {
					junction: gate.output,
					time: self.time,
					level: output,
				});

				println! ("Gate {} set to {}", gate.output, output);
			}
		};

		for delay in new_delays {
			self.delays.push (delay);
		}

		// TODO: Proper insertion sorting
		self.sort_delays ();
	}

	fn get_junction_destiny (& self, junction: JunctionIndex) -> JunctionDestiny {
		if self.delays.len () > 0 {
			//println! ("Delays:");

			for i in 0 .. self.delays.len () {
				let delay: Delay = self.delays [self.delays.len () - i - 1];

				//println! ("At {} junction {} will be {}", delay.time, delay.junction, delay.level);

				if delay.junction == junction {
					return JunctionDestiny::Eventually (delay);
				}
			}
		}

		JunctionDestiny::Settled (self.junctions [junction])
	}

	fn step_wires (&mut self) {
		for wire in self.wires.iter () {
			let input = self.junctions [wire.input];

			// Don't push redundant delays
			let destiny = self.get_junction_destiny (wire.output);
			let destinyLevel = match destiny {
				JunctionDestiny::Settled (level) => level,
				JunctionDestiny::Eventually (delay) => delay.level,
			};

			if input != destinyLevel {
				self.delays.push (Delay {
					junction: wire.output,
					time: self.time + wire.delay,
					level: input,
				});

				let destiny_type = match destiny {
					JunctionDestiny::Settled (_) => "Settled",
					JunctionDestiny::Eventually (_) => "Eventually",
				};

				//println! ("Wire {} set to {}", wire.output, input);
			}
		};

		// TODO: Proper insertion sorting
		self.sort_delays ();
	}

	fn propagate_delays (&mut self) {
		let next_time = self.delays [0].time;

		for delay in self.delays.iter () {
			if delay.time == next_time {
				self.junctions [delay.junction] = delay.level;

				println! ("Junction {} set to {}", delay.junction, delay.level);
			}
		}

		self.delays.retain (|delay| delay.time > next_time);

		self.time = next_time;
	}

	fn step (&mut self) {
		if self.is_settled () {
			return;
		}

		self.sort_delays ();

		self.propagate_delays ();

		self.step_gates ();
		self.step_wires ();
	}

	fn step_to_settled (&mut self) {
		while ! self.is_settled () {
			self.step ();
		}
	}
}<commit_msg>Removing all compiler warnings<commit_after>#[test]
fn test_sorting () {
	let mut unsorted = vec! [3, 2, 1];

	let sorted = vec! [1, 2, 3];

	unsorted.sort_by (|a, b| a.cmp (b));

	assert_eq! (unsorted, sorted);
}

#[test]
pub fn it_works() {
	let mut world = World::new_half_adder ();
	println! ("Constructed world");
	// This has to be done for initialization, it should be automated
	world.step_gates ();

	world.step_to_settled ();

	assert_eq! (world.junctions [3], false);
	assert_eq! (world.junctions [7], false);

	world.set_junction (0, true);

	world.step_to_settled ();

	assert_eq! (world.junctions [3], false);
	assert_eq! (world.junctions [7], true);

	world.set_junction (8, true);

	world.step_to_settled ();

	assert_eq! (world.junctions [3], true);
	assert_eq! (world.junctions [7], false);

	world.set_junction (0, false);

	world.step_to_settled ();

	assert_eq! (world.junctions [3], false);
	assert_eq! (world.junctions [7], true);
}

// 2 billion junctions is good enough for now
pub type JunctionIndex = usize;
pub type Time = i64;
pub type Level = bool;

pub enum GateBehavior {
	Inverter,
	And,
	Xor,
}

// In the future, at time "time", junction "junction" will be set to level "level".
#[derive (Clone, Copy)]
pub struct Delay {
	junction: JunctionIndex,
	level: Level,
	time: Time,
}

#[derive (Clone, Copy)]
pub struct Wire {
	input: JunctionIndex,
	output: JunctionIndex,
	delay: Time,
}

pub struct Gate {
	inputs: Vec <JunctionIndex>,
	output: JunctionIndex,
	behavior: GateBehavior,
}

pub struct World {
	wires: Vec <Wire>,
	gates: Vec <Gate>,

	junctions: Vec <bool>,
	time: Time,
	delays: Vec <Delay>,
}

impl Wire {
	fn new (input: JunctionIndex, output: JunctionIndex, delay: Time) -> Wire {
		Wire {
			input: input,
			output: output,
			delay: delay,
		}
	}
}

enum JunctionDestiny {
	Settled (Level),
	Eventually (Delay),
}

impl World {
	pub fn new_half_adder () -> World {
		World {
			time: 0,
			delays: vec![],
			junctions: vec![false; 10],
			wires: vec![
				Wire::new (0, 1, 4),
				Wire::new (0, 5, 8),
				Wire::new (2, 3, 4),
				Wire::new (6, 7, 3),
				Wire::new (8, 4, 8),
				Wire::new (8, 9, 4),
			],
			gates: vec![
				Gate {
					inputs: vec![1, 4],
					output: 2,
					behavior: GateBehavior::And,
				},
				Gate {
					inputs: vec![5, 9],
					output: 6,
					behavior: GateBehavior::Xor,
				},
			],
		}
	}

	pub fn is_settled (& self) -> bool {
		self.delays.len () == 0
	}

	fn sort_delays (&mut self) {
		// This step is just a safety since we should be insertion sorting the delays already
		self.delays.sort_by (|a, b| a.time.cmp (&b.time));
	}

	fn step_gates (&mut self) {
		let mut new_delays = Vec::<Delay>::new ();

		// TODO: Optimize to only touch gates whose inputs have changed
		for gate in self.gates.iter () {
			let inputs: Vec <bool> = gate.inputs.iter ().map (|i| self.junctions [*i]).collect ();

			let output = match gate.behavior {
				GateBehavior::And => inputs.iter ().fold (true, |sum, a| sum && *a),
				GateBehavior::Xor => inputs.iter ().fold (false, |sum, a| sum ^ *a),
				GateBehavior::Inverter => ! inputs [0],
			};

			let destiny = self.get_junction_destiny (gate.output);
			let destiny_level = match destiny {
				JunctionDestiny::Settled (level) => level,
				JunctionDestiny::Eventually (delay) => delay.level,
			};

			if destiny_level != output {
				new_delays.push (Delay {
					junction: gate.output,
					time: self.time,
					level: output,
				});

				println! ("Gate {} set to {}", gate.output, output);
			}
		};

		for delay in new_delays {
			self.delays.push (delay);
		}

		// TODO: Proper insertion sorting
		self.sort_delays ();
	}

	fn get_junction_destiny (& self, junction: JunctionIndex) -> JunctionDestiny {
		if self.delays.len () > 0 {
			//println! ("Delays:");

			for i in 0 .. self.delays.len () {
				let delay: Delay = self.delays [self.delays.len () - i - 1];

				//println! ("At {} junction {} will be {}", delay.time, delay.junction, delay.level);

				if delay.junction == junction {
					return JunctionDestiny::Eventually (delay);
				}
			}
		}

		JunctionDestiny::Settled (self.junctions [junction])
	}

	fn step_wires (&mut self) {
		for wire in self.wires.iter () {
			let input = self.junctions [wire.input];

			// Don't push redundant delays
			let destiny = self.get_junction_destiny (wire.output);
			let destiny_level = match destiny {
				JunctionDestiny::Settled (level) => level,
				JunctionDestiny::Eventually (delay) => delay.level,
			};

			if input != destiny_level {
				self.delays.push (Delay {
					junction: wire.output,
					time: self.time + wire.delay,
					level: input,
				});
			}
		};

		// TODO: Proper insertion sorting
		self.sort_delays ();
	}

	fn propagate_delays (&mut self) {
		let next_time = self.delays [0].time;

		for delay in self.delays.iter () {
			if delay.time == next_time {
				self.junctions [delay.junction] = delay.level;

				println! ("Junction {} set to {}", delay.junction, delay.level);
			}
		}

		self.delays.retain (|delay| delay.time > next_time);

		self.time = next_time;
	}

	pub fn set_junction (&mut self, junction: JunctionIndex, level: Level) {
		self.delays.push (Delay {
			junction: junction,
			level: level,
			time: self.time,
		});
	}

	pub fn step (&mut self) {
		if self.is_settled () {
			return;
		}

		self.sort_delays ();

		self.propagate_delays ();

		self.step_gates ();
		self.step_wires ();
	}

	pub fn step_to_settled (&mut self) {
		while ! self.is_settled () {
			self.step ();
		}
	}
}<|endoftext|>


<commit_before>#![feature(proc_macro, custom_derive, custom_attribute)]
#![feature(box_syntax)]
#[macro_use] extern crate serde_derive;
extern crate serde_json;
extern crate hyper;
pub mod dictionaries;
pub mod thesaureses;
pub use dictionaries::{Definition, Dictionary};
pub use thesaureses::Thesaurus;
mod error {
    use std::error;
    use std::fmt;
    #[derive(Debug)]
    pub enum Error {
        Hyper(::hyper::Error),
        Serde(::serde_json::Error),
        Error(Box<error::Error>)
    }
    impl fmt::Display for Error {
        fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            fmt.write_str(self.description())?;
            Ok(())
        }
    }
    impl error::Error for Error {
        fn description(&self) -> &str {
            match *self {
                Error::Hyper(ref hyper) => hyper.description(),
                Error::Serde(ref serde) => serde.description(),
                Error::Error(ref err) => err.description()
            }
        }
        fn cause(&self) -> Option<&::std::error::Error> { None }
    }
}

pub use error::Error;

<commit_msg>Add from implementations<commit_after>#![feature(proc_macro, custom_derive, custom_attribute)]
#![feature(box_syntax)]
#[macro_use] extern crate serde_derive;
extern crate serde_json;
extern crate hyper;
pub mod dictionaries;
pub mod thesaureses;
pub use dictionaries::{Definition, Dictionary};
pub use thesaureses::Thesaurus;
mod error {
    use std::error;
    use std::error::Error as ErrorT;
    use std::fmt;
    #[derive(Debug)]
    pub enum Error {
        Hyper(::hyper::Error),
        Serde(::serde_json::Error),
        Error(Box<error::Error>)
    }
    impl error::Error for Error {
        fn description(&self) -> &str {
            match *self {
                Error::Hyper(ref hyper) => hyper.description(),
                Error::Serde(ref serde) => serde.description(),
                Error::Error(ref err) => err.description()
            }
        }
        fn cause(&self) -> Option<&::std::error::Error> { None }
    }
    impl fmt::Display for Error {
        fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            fmt.write_str(self.description())?;
            Ok(())
        }
    }
    impl From<::hyper::Error> for Error {
        fn from(val: ::hyper::Error) -> Self {
            Error::Hyper(val)
        }
    }
    impl From<::serde_json::Error> for Error {
        fn from(val: ::serde_json::Error) -> Self {
            Error::Serde(val)
        }
    }
}

pub use error::Error;
pub type Result<T> = std::result::Result<T, Error>;
<|endoftext|>


<commit_before>#![no_std]
#![feature(asm)]
#![feature(const_fn)]
#![feature(use_extern_macros)]
#![feature(integer_atomics)]
#![feature(lang_items)]

#![allow(unknown_lints)]

#[macro_use]
extern crate log;
extern crate spin;

pub mod vmx;
pub mod runtime;

#[cfg(not(test))]
mod serial_logger;
#[cfg(not(test))]
use serial_logger as logger;

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

#[repr(C)]
pub struct PerCoreData {
    task: *const u8,
    vmxon_region: *mut u8,
    vmcs: *mut u8,
    vmxon_region_phys: u64,
    vmcs_phys: u64,
    vmxon_region_size: usize,
    vmcs_size: usize,
    loaded_successfully: bool,
}

#[no_mangle]
pub extern "C" fn rustyvisor_load() -> i32 {
    #[cfg(not(test))]
    {
        match logger::init() {
            Ok(()) => {}
            Err(_) => return 1,
        }
    }

    info!("{}", VERSION);

    #[cfg(feature = "runtime_tests")] runtime_tests();

    0
}

#[no_mangle]
pub extern "C" fn rustyvisor_core_load(data: *const PerCoreData) -> i32 {
    if data.is_null() {
        return 1;
    }

    unsafe {
        if vmx::enable(
            (*data).vmxon_region,
            (*data).vmxon_region_phys,
            (*data).vmxon_region_size,
        ) != Ok(())
        {
            error!("Failed to enable VMX");
            return 1;
        }
    }

    unsafe {
        if vmx::load_vm((*data).vmcs, (*data).vmcs_phys, (*data).vmcs_size) != Ok(()) {
            error!("Failed to load VMX");
            return 1;
        }
    }

    info!("Successfully launched VM");
    0
}

#[no_mangle]
pub extern "C" fn rustyvisor_core_unload() {
    info!("core unload");
    vmx::unload_vm();
    vmx::disable();
}

#[no_mangle]
pub extern "C" fn rustyvisor_unload() {

    info!("Hypervisor unloaded.");

    #[cfg(not(test))]
    {
        let _ = logger::fini();
    }
}

#[cfg(feature = "runtime_tests")]
fn runtime_tests() {
    info!("Executing runtime tests...");
    info!("Runtime tests succeeded");
}
<commit_msg>Remove unused feature<commit_after>#![no_std]
#![feature(asm)]
#![feature(const_fn)]
#![feature(use_extern_macros)]
#![feature(lang_items)]

#![allow(unknown_lints)]

#[macro_use]
extern crate log;
extern crate spin;

pub mod vmx;
pub mod runtime;

#[cfg(not(test))]
mod serial_logger;
#[cfg(not(test))]
use serial_logger as logger;

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

#[repr(C)]
pub struct PerCoreData {
    task: *const u8,
    vmxon_region: *mut u8,
    vmcs: *mut u8,
    vmxon_region_phys: u64,
    vmcs_phys: u64,
    vmxon_region_size: usize,
    vmcs_size: usize,
    loaded_successfully: bool,
}

#[no_mangle]
pub extern "C" fn rustyvisor_load() -> i32 {
    #[cfg(not(test))]
    {
        match logger::init() {
            Ok(()) => {}
            Err(_) => return 1,
        }
    }

    info!("{}", VERSION);

    #[cfg(feature = "runtime_tests")] runtime_tests();

    0
}

#[no_mangle]
pub extern "C" fn rustyvisor_core_load(data: *const PerCoreData) -> i32 {
    if data.is_null() {
        return 1;
    }

    unsafe {
        if vmx::enable(
            (*data).vmxon_region,
            (*data).vmxon_region_phys,
            (*data).vmxon_region_size,
        ) != Ok(())
        {
            error!("Failed to enable VMX");
            return 1;
        }
    }

    unsafe {
        if vmx::load_vm((*data).vmcs, (*data).vmcs_phys, (*data).vmcs_size) != Ok(()) {
            error!("Failed to load VMX");
            return 1;
        }
    }

    info!("Successfully launched VM");
    0
}

#[no_mangle]
pub extern "C" fn rustyvisor_core_unload() {
    info!("core unload");
    vmx::unload_vm();
    vmx::disable();
}

#[no_mangle]
pub extern "C" fn rustyvisor_unload() {

    info!("Hypervisor unloaded.");

    #[cfg(not(test))]
    {
        let _ = logger::fini();
    }
}

#[cfg(feature = "runtime_tests")]
fn runtime_tests() {
    info!("Executing runtime tests...");
    info!("Runtime tests succeeded");
}
<|endoftext|>


<commit_before>use std::str::Chars;
use std::iter::Peekable;

pub struct StateFn<T: PartialEq>(fn(&mut Lexer<T>) -> Option<StateFn<T>>);

#[derive(Debug, PartialEq)]
pub struct Item<'a, T> {
    pub typ: T,
    pub val: &'a str
}

pub struct Lexer<'a, T: PartialEq> {
    input: &'a str,
    chars_iter: Peekable<Chars<'a>>,
    start: usize,
    pos: usize,
    items: Vec<Item<'a, T>>
}

impl<'a, T: PartialEq> Lexer<'a, T> {
    fn new(input: &'a str) -> Lexer<'a, T> {
        Lexer {
            input: input,
            chars_iter: input.chars().peekable(),
            start: 0,
            pos: 0,
            items: Vec::new()
        }
    }

    fn run(&mut self, start_state: fn(&mut Lexer<T>) -> Option<StateFn<T>>) {
        let mut state = start_state;

        loop {
            match state(self) {
                Some(StateFn(next)) => state = next,
                None => break,
            }
        }
    }

    pub fn next(&mut self) -> Option<char> {
        self.chars_iter.next().map(|c| {
            self.pos += 1;
            c
        })
    }

    pub fn ignore(&mut self) {
        self.start = self.pos;
    }

    pub fn peek(&mut self) -> Option<char> {
        self.chars_iter.peek().cloned()
    }

    pub fn accept(&mut self, valid: &str) -> bool {
        self.peek()
            .map_or(false, |c| if valid.contains(c) { self.next(); true } else { false })
    }

    pub fn accept_run(&mut self, valid: &str) {
        loop {
            match self.peek() {
                Some(c) => if valid.contains(c) { self.next(); } else { break; },
                None => break,
            }
        }
    }

    pub fn emit(&mut self, typ: T) {
        self.items.push(Item {
            typ: typ,
            val: &self.input[self.start .. self.pos]
        });
        self.start = self.pos;
    }

    pub fn finish_started(&mut self, typ: T) {
        if self.pos >= self.start {
            self.emit(typ);
        }
    }

    pub fn remaining_input(&self) -> &str {
        &self.input[self.pos ..]
    }
}

pub fn lex<'a, T: PartialEq>(input: &'a str, start_state: fn(&mut Lexer<T>) -> Option<StateFn<T>>) -> Vec<Item<'a, T>> {
    let mut l = Lexer::new(input);
    l.run(start_state);

    l.items
}
<commit_msg>fixed visibility issue for StateFn type<commit_after>use std::str::Chars;
use std::iter::Peekable;

pub struct StateFn<T: PartialEq>(pub fn(&mut Lexer<T>) -> Option<StateFn<T>>);

#[derive(Debug, PartialEq)]
pub struct Item<'a, T> {
    pub typ: T,
    pub val: &'a str
}

pub struct Lexer<'a, T: PartialEq> {
    input: &'a str,
    chars_iter: Peekable<Chars<'a>>,
    start: usize,
    pos: usize,
    items: Vec<Item<'a, T>>
}

impl<'a, T: PartialEq> Lexer<'a, T> {
    fn new(input: &'a str) -> Lexer<'a, T> {
        Lexer {
            input: input,
            chars_iter: input.chars().peekable(),
            start: 0,
            pos: 0,
            items: Vec::new()
        }
    }

    fn run(&mut self, start_state: fn(&mut Lexer<T>) -> Option<StateFn<T>>) {
        let mut state = start_state;

        loop {
            match state(self) {
                Some(StateFn(next)) => state = next,
                None => break,
            }
        }
    }

    pub fn next(&mut self) -> Option<char> {
        self.chars_iter.next().map(|c| {
            self.pos += 1;
            c
        })
    }

    pub fn ignore(&mut self) {
        self.start = self.pos;
    }

    pub fn peek(&mut self) -> Option<char> {
        self.chars_iter.peek().cloned()
    }

    pub fn accept(&mut self, valid: &str) -> bool {
        self.peek()
            .map_or(false, |c| if valid.contains(c) { self.next(); true } else { false })
    }

    pub fn accept_run(&mut self, valid: &str) {
        loop {
            match self.peek() {
                Some(c) => if valid.contains(c) { self.next(); } else { break; },
                None => break,
            }
        }
    }

    pub fn emit(&mut self, typ: T) {
        self.items.push(Item {
            typ: typ,
            val: &self.input[self.start .. self.pos]
        });
        self.start = self.pos;
    }

    pub fn finish_started(&mut self, typ: T) {
        if self.pos >= self.start {
            self.emit(typ);
        }
    }

    pub fn remaining_input(&self) -> &str {
        &self.input[self.pos ..]
    }
}

pub fn lex<'a, T: PartialEq>(input: &'a str, start_state: fn(&mut Lexer<T>) -> Option<StateFn<T>>) -> Vec<Item<'a, T>> {
    let mut l = Lexer::new(input);
    l.run(start_state);

    l.items
}
<|endoftext|>


<commit_before>// extern crate futures;
// extern crate bus;

/// Something that can be used to find/create a resource
pub trait Key {
    fn as_cache_id(&self) -> CacheId;
}

// TODO: Make a more generic strategy for keys
/// The identifier that the cache uses to make resources unique
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum CacheId {
    USize(usize),
    U32(u32),
    U64(u64),
    ISize(isize),
    I32(i32),
    I64(i64),
    Str(String),
}

impl Key for u32 { fn as_cache_id(&self) -> CacheId { CacheId::U32(*self) } }
impl Key for u64 { fn as_cache_id(&self) -> CacheId { CacheId::U64(*self) } }
impl Key for usize { fn as_cache_id(&self) -> CacheId { CacheId::USize(*self) } }
impl Key for i32 { fn as_cache_id(&self) -> CacheId { CacheId::I32(*self) } }
impl Key for i64 { fn as_cache_id(&self) -> CacheId { CacheId::I64(*self) } }
impl Key for isize { fn as_cache_id(&self) -> CacheId { CacheId::ISize(*self) } }
impl Key for String { fn as_cache_id(&self) -> CacheId { CacheId::Str(self.clone()) } }

/// Something that provides a resource
pub trait ResourceProvider<R> {
    /// The key this loader uses to load/create the resource
    type Key: Key; // Type of key used to load resource
    /// The error type returned when the resource loader fails to load/create the resource
    type Error; // How we indicate loading failed
    /// Loads/creates the resource
    fn load<K: Into<Self::Key>>(&self, k: K) -> Result<R, Self::Error>;
}

use std::rc::Rc;
use std::collections::HashMap;
use std::collections::hash_map::Entry;

/// A store of loaded resources
pub struct Cache<R> {
    // TODO: Provide Resource keeping strategies
    cache: HashMap<CacheId, Rc<R>>,

    // TODO: Add handling for async requests using futures and (maybe) bus
}

impl<R> Cache<R> {
    /// Creates a new Cache
    pub fn new() -> Cache<R> {
        Cache {
            cache: HashMap::new(),
            requested: 0,
            loaded: 0
        }
    }

    /// Use the specified ResourceLoader to load/create an resource, and cache it
    pub fn load<L: ResourceProvider<R>>(&mut self, provider: &L, key: L::Key) -> Result<Rc<R>, L::Error> {
        let cache_id = key.as_cache_id();
        match provider.load(key) {
            Ok(resource) => {
                let pointer = Rc::new(resource);
                match self.cache.entry(cache_id) {
                    Entry::Occupied(occ) => Ok(occ.get().clone()),
                    Entry::Vacant(vac) => {
                        vac.insert(pointer.clone());
                        Ok(pointer)
                    },
                }
            },
            Err(e) => Err(e)
        }
    }
}
<commit_msg>Remove initialization of unused variables<commit_after>// extern crate futures;
// extern crate bus;

/// Something that can be used to find/create a resource
pub trait Key {
    fn as_cache_id(&self) -> CacheId;
}

// TODO: Make a more generic strategy for keys
/// The identifier that the cache uses to make resources unique
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum CacheId {
    USize(usize),
    U32(u32),
    U64(u64),
    ISize(isize),
    I32(i32),
    I64(i64),
    Str(String),
}

impl Key for u32 { fn as_cache_id(&self) -> CacheId { CacheId::U32(*self) } }
impl Key for u64 { fn as_cache_id(&self) -> CacheId { CacheId::U64(*self) } }
impl Key for usize { fn as_cache_id(&self) -> CacheId { CacheId::USize(*self) } }
impl Key for i32 { fn as_cache_id(&self) -> CacheId { CacheId::I32(*self) } }
impl Key for i64 { fn as_cache_id(&self) -> CacheId { CacheId::I64(*self) } }
impl Key for isize { fn as_cache_id(&self) -> CacheId { CacheId::ISize(*self) } }
impl Key for String { fn as_cache_id(&self) -> CacheId { CacheId::Str(self.clone()) } }

/// Something that provides a resource
pub trait ResourceProvider<R> {
    /// The key this loader uses to load/create the resource
    type Key: Key; // Type of key used to load resource
    /// The error type returned when the resource loader fails to load/create the resource
    type Error; // How we indicate loading failed
    /// Loads/creates the resource
    fn load<K: Into<Self::Key>>(&self, k: K) -> Result<R, Self::Error>;
}

use std::rc::Rc;
use std::collections::HashMap;
use std::collections::hash_map::Entry;

/// A store of loaded resources
pub struct Cache<R> {
    // TODO: Provide Resource keeping strategies
    cache: HashMap<CacheId, Rc<R>>,

    // TODO: Add handling for async requests using futures and (maybe) bus
}

impl<R> Cache<R> {
    /// Creates a new Cache
    pub fn new() -> Cache<R> {
        Cache {
            cache: HashMap::new(),
        }
    }

    /// Use the specified ResourceLoader to load/create an resource, and cache it
    pub fn load<L: ResourceProvider<R>>(&mut self, provider: &L, key: L::Key) -> Result<Rc<R>, L::Error> {
        let cache_id = key.as_cache_id();
        match provider.load(key) {
            Ok(resource) => {
                let pointer = Rc::new(resource);
                match self.cache.entry(cache_id) {
                    Entry::Occupied(occ) => Ok(occ.get().clone()),
                    Entry::Vacant(vac) => {
                        vac.insert(pointer.clone());
                        Ok(pointer)
                    },
                }
            },
            Err(e) => Err(e)
        }
    }
}
<|endoftext|>


<commit_before>//! A simple but effective sign library, written in Rust.
//!
//! Ported from [nobi](https://github.com/cyx/nobi),
//! which itself is a port of [itsdangerous](http://pythonhosted.org/itsdangerous/).
//!
//! # Possible use cases
//!
//! * Creating an activation link for users
//! * Creating a password reset link
//!
//! # Basic Example:
//!
//! ```rust
//! use nobsign::Signer;
//! let signer = Signer::new(b"my secret");
//!
//! // Let's say the user's ID is 101
//! let signed = signer.sign("101");
//!
//! // You can now email this url to your users!
//! let url = format!("http://yoursite.com/activate/?key={}", signed);
//!
//! // Later check the signature and get the value back
//! let unsigned = signer.unsign(&signed).unwrap();
//! ```
//!
//! # Example with timestamped signatures
//!
//! ```rust
//! use nobsign::TimestampSigner;
//! let signer = TimestampSigner::new(b"my secret");
//!
//! // Let's say the user's ID is 101
//! let signed = signer.sign("101");
//!
//! // You can now email this url to your users!
//! let url = format!("http://yoursite.com/activate/?key={}", signed);
//!
//! // In your code, you can verify the expiration:
//! signer.unsign(&signed, 86400).unwrap(); // 1 day expiration
//! ```
extern crate rustc_serialize;
extern crate ring;
extern crate time;
extern crate byteorder;

// Use same EPOCH as nobi, the Ruby implementation
const EPOCH : i32 = 1293840000;

use ring::{digest, hmac};
use rustc_serialize::base64::{ToBase64, FromBase64, URL_SAFE};
use byteorder::{ByteOrder, LittleEndian};

static ALGORITHM: &'static digest::Algorithm = &digest::SHA1;

#[derive(Debug,PartialEq)]
pub enum Error {
    BadData,
    BadSignature,
    BadTimeSignature,
    SignatureExpired,
}

pub struct Signer {
    separator: char,
    s_key: hmac::SigningKey,
    v_key: hmac::VerificationKey,
}

pub struct TimestampSigner {
    signer: Signer,
}

fn int_to_bytes(n: i32) -> [u8; 4] {
    let mut out = [0; 4];

    LittleEndian::write_i32(&mut out, n);
    out
}
fn bytes_to_int(n: &[u8]) -> i32 {
    assert!(n.len() == 4);
    LittleEndian::read_i32(n)
}

impl Signer {
    pub fn new(secret: &[u8]) -> Signer {
        let initial_key = hmac::SigningKey::new(ALGORITHM, secret);
        let derived_key = hmac::sign(&initial_key, b"nobi.Signer");

        Signer {
            separator: '.',
            s_key: hmac::SigningKey::new(ALGORITHM, derived_key.as_ref()),
            v_key: hmac::VerificationKey::new(ALGORITHM, derived_key.as_ref()),
        }
    }

    pub fn sign(&self, value: &str) -> String {
        format!("{}{}{}", value, self.separator, &self.signature(value))
    }

    pub fn unsign(&self, value: &str) -> Result<String, Error> {
        let mut splitted = value.rsplitn(2, |c| c == self.separator);

        let sig = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };
        let value = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };

        let sig = try!(sig.from_base64().map_err(|_| Error::BadSignature));
        try!(hmac::verify(&self.v_key, value.as_bytes(), &sig)
                .map_err(|_| Error::BadSignature));

        Ok(value.into())
    }

    fn signature(&self, value: &str) -> String {
        let sig = hmac::sign(&self.s_key, value.as_bytes());
        sig.as_ref().to_base64(URL_SAFE)
    }
}

impl TimestampSigner {
    pub fn new(secret: &[u8]) -> TimestampSigner {
        TimestampSigner { signer: Signer::new(secret) }
    }

    fn get_timestamp(&self) -> i32 {
        let now = time::now_utc().to_timespec();
        now.sec as i32 - EPOCH
    }

    pub fn sign(&self, value: &str) -> String {
        let timestamp = self.get_timestamp();
        let timestamp = int_to_bytes(timestamp);
        let timestamp = timestamp.to_base64(URL_SAFE);
        let value = format!("{}{}{}", value, self.signer.separator, timestamp);

        format!("{}{}{}",
                value,
                self.signer.separator,
                &self.signature(&value))
    }

    pub fn unsign(&self, value: &str, max_age: u32) -> Result<String, Error> {
        let result = try!(self.signer.unsign(value));

        if !result.contains(self.signer.separator) {
            return Err(Error::BadTimeSignature);
        }

        let mut splitted = result.rsplitn(2, |c| c == self.signer.separator);

        let timestamp = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };
        let value = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };

        let timestamp = match timestamp.from_base64() {
            Err(_) => return Err(Error::BadTimeSignature),
            Ok(timestamp) => timestamp,
        };
        if timestamp.len() != 4 {
            return Err(Error::BadTimeSignature);
        }
        let timestamp = bytes_to_int(&timestamp);
        let age = self.get_timestamp() - timestamp;

        if age > max_age as i32 {
            return Err(Error::SignatureExpired);
        }

        Ok(value.into())
    }

    fn signature(&self, value: &str) -> String {
        self.signer.signature(value)
    }
}

#[test]
fn signs() {
    let signer = Signer::new(b"my-key");

    let signed = signer.sign("value");
    assert_eq!("value.EWkF3-80sipsPgLQ01NuTuPb0jQ".to_owned(), signed);

    assert_eq!("value".to_owned(), signer.unsign(&signed).unwrap());
}

#[test]
fn bad_unsign() {
    let signer = Signer::new(b"my-key");

    let signed = "value.ABCDEF";
    assert_eq!(Err(Error::BadSignature), signer.unsign(&signed));
}

#[test]
fn signs_with_timestamp() {
    let signer = TimestampSigner::new(b"my-key");

    let signed = signer.sign("value");

    assert_eq!("value".to_owned(), signer.unsign(&signed, 100).unwrap());
}

#[test]
fn bad_unsign_with_timestamp() {
    let signer = TimestampSigner::new(b"my-key");

    let signed = "value.ABCDEF";
    assert_eq!(Err(Error::BadSignature), signer.unsign(&signed, 10));

    let signed = "value.EWkF3-80sipsPgLQ01NuTuPb0jQ";
    assert_eq!(Err(Error::BadTimeSignature), signer.unsign(&signed, 10));

    let signed = "value.AB.HHdWpuF7QVDZ_02wvECHvtV8vIc";
    assert_eq!(Err(Error::BadTimeSignature), signer.unsign(&signed, 10));
}

#[test]
fn unsign_expired() {
    use std::thread::sleep_ms;
    let signer = TimestampSigner::new(b"my-key");
    let signed = signer.sign("value");
    sleep_ms(1000);
    assert_eq!(Err(Error::SignatureExpired), signer.unsign(&signed, 0));
}

#[test]
fn with_secure_secret() {
    use ring::rand;
    let mut key = vec![0u8; ALGORITHM.digest_len];
    rand::fill_secure_random(&mut key).unwrap();

    let signer = Signer::new(&key);
    let signed = signer.sign("Hello world!");

    assert_eq!("Hello world!", signer.unsign(&signed).unwrap());
}
<commit_msg>refactor: Move tests into module<commit_after>//! A simple but effective sign library, written in Rust.
//!
//! Ported from [nobi](https://github.com/cyx/nobi),
//! which itself is a port of [itsdangerous](http://pythonhosted.org/itsdangerous/).
//!
//! # Possible use cases
//!
//! * Creating an activation link for users
//! * Creating a password reset link
//!
//! # Basic Example:
//!
//! ```rust
//! use nobsign::Signer;
//! let signer = Signer::new(b"my secret");
//!
//! // Let's say the user's ID is 101
//! let signed = signer.sign("101");
//!
//! // You can now email this url to your users!
//! let url = format!("http://yoursite.com/activate/?key={}", signed);
//!
//! // Later check the signature and get the value back
//! let unsigned = signer.unsign(&signed).unwrap();
//! ```
//!
//! # Example with timestamped signatures
//!
//! ```rust
//! use nobsign::TimestampSigner;
//! let signer = TimestampSigner::new(b"my secret");
//!
//! // Let's say the user's ID is 101
//! let signed = signer.sign("101");
//!
//! // You can now email this url to your users!
//! let url = format!("http://yoursite.com/activate/?key={}", signed);
//!
//! // In your code, you can verify the expiration:
//! signer.unsign(&signed, 86400).unwrap(); // 1 day expiration
//! ```
extern crate rustc_serialize;
extern crate ring;
extern crate time;
extern crate byteorder;

// Use same EPOCH as nobi, the Ruby implementation
const EPOCH : i32 = 1293840000;

use ring::{digest, hmac};
use rustc_serialize::base64::{ToBase64, FromBase64, URL_SAFE};
use byteorder::{ByteOrder, LittleEndian};

static ALGORITHM: &'static digest::Algorithm = &digest::SHA1;

#[derive(Debug,PartialEq)]
pub enum Error {
    BadData,
    BadSignature,
    BadTimeSignature,
    SignatureExpired,
}

pub struct Signer {
    separator: char,
    s_key: hmac::SigningKey,
    v_key: hmac::VerificationKey,
}

pub struct TimestampSigner {
    signer: Signer,
}

fn int_to_bytes(n: i32) -> [u8; 4] {
    let mut out = [0; 4];

    LittleEndian::write_i32(&mut out, n);
    out
}
fn bytes_to_int(n: &[u8]) -> i32 {
    assert!(n.len() == 4);
    LittleEndian::read_i32(n)
}

impl Signer {
    pub fn new(secret: &[u8]) -> Signer {
        let initial_key = hmac::SigningKey::new(ALGORITHM, secret);
        let derived_key = hmac::sign(&initial_key, b"nobi.Signer");

        Signer {
            separator: '.',
            s_key: hmac::SigningKey::new(ALGORITHM, derived_key.as_ref()),
            v_key: hmac::VerificationKey::new(ALGORITHM, derived_key.as_ref()),
        }
    }

    pub fn sign(&self, value: &str) -> String {
        format!("{}{}{}", value, self.separator, &self.signature(value))
    }

    pub fn unsign(&self, value: &str) -> Result<String, Error> {
        let mut splitted = value.rsplitn(2, |c| c == self.separator);

        let sig = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };
        let value = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };

        let sig = try!(sig.from_base64().map_err(|_| Error::BadSignature));
        try!(hmac::verify(&self.v_key, value.as_bytes(), &sig)
                .map_err(|_| Error::BadSignature));

        Ok(value.into())
    }

    fn signature(&self, value: &str) -> String {
        let sig = hmac::sign(&self.s_key, value.as_bytes());
        sig.as_ref().to_base64(URL_SAFE)
    }
}

impl TimestampSigner {
    pub fn new(secret: &[u8]) -> TimestampSigner {
        TimestampSigner { signer: Signer::new(secret) }
    }

    fn get_timestamp(&self) -> i32 {
        let now = time::now_utc().to_timespec();
        now.sec as i32 - EPOCH
    }

    pub fn sign(&self, value: &str) -> String {
        let timestamp = self.get_timestamp();
        let timestamp = int_to_bytes(timestamp);
        let timestamp = timestamp.to_base64(URL_SAFE);
        let value = format!("{}{}{}", value, self.signer.separator, timestamp);

        format!("{}{}{}",
                value,
                self.signer.separator,
                &self.signature(&value))
    }

    pub fn unsign(&self, value: &str, max_age: u32) -> Result<String, Error> {
        let result = try!(self.signer.unsign(value));

        if !result.contains(self.signer.separator) {
            return Err(Error::BadTimeSignature);
        }

        let mut splitted = result.rsplitn(2, |c| c == self.signer.separator);

        let timestamp = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };
        let value = match splitted.next() {
            Some(val) => val,
            None => return Err(Error::BadSignature),
        };

        let timestamp = match timestamp.from_base64() {
            Err(_) => return Err(Error::BadTimeSignature),
            Ok(timestamp) => timestamp,
        };
        if timestamp.len() != 4 {
            return Err(Error::BadTimeSignature);
        }
        let timestamp = bytes_to_int(&timestamp);
        let age = self.get_timestamp() - timestamp;

        if age > max_age as i32 {
            return Err(Error::SignatureExpired);
        }

        Ok(value.into())
    }

    fn signature(&self, value: &str) -> String {
        self.signer.signature(value)
    }
}

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

    #[test]
    fn signs() {
        let signer = Signer::new(b"my-key");

        let signed = signer.sign("value");
        assert_eq!("value.EWkF3-80sipsPgLQ01NuTuPb0jQ".to_owned(), signed);

        assert_eq!("value".to_owned(), signer.unsign(&signed).unwrap());
    }

    #[test]
    fn bad_unsign() {
        let signer = Signer::new(b"my-key");

        let signed = "value.ABCDEF";
        assert_eq!(Err(Error::BadSignature), signer.unsign(&signed));
    }

    #[test]
    fn signs_with_timestamp() {
        let signer = TimestampSigner::new(b"my-key");

        let signed = signer.sign("value");

        assert_eq!("value".to_owned(), signer.unsign(&signed, 100).unwrap());
    }

    #[test]
    fn bad_unsign_with_timestamp() {
        let signer = TimestampSigner::new(b"my-key");

        let signed = "value.ABCDEF";
        assert_eq!(Err(Error::BadSignature), signer.unsign(&signed, 10));

        let signed = "value.EWkF3-80sipsPgLQ01NuTuPb0jQ";
        assert_eq!(Err(Error::BadTimeSignature), signer.unsign(&signed, 10));

        let signed = "value.AB.HHdWpuF7QVDZ_02wvECHvtV8vIc";
        assert_eq!(Err(Error::BadTimeSignature), signer.unsign(&signed, 10));
    }

    #[test]
    fn unsign_expired() {
        use std::thread::sleep_ms;
        let signer = TimestampSigner::new(b"my-key");
        let signed = signer.sign("value");
        sleep_ms(1000);
        assert_eq!(Err(Error::SignatureExpired), signer.unsign(&signed, 0));
    }

    #[test]
    fn with_secure_secret() {
        use ring::rand;
        let mut key = vec![0u8; ALGORITHM.digest_len];
        rand::fill_secure_random(&mut key).unwrap();

        let signer = Signer::new(&key);
        let signed = signer.sign("Hello world!");

        assert_eq!("Hello world!", signer.unsign(&signed).unwrap());
    }
}
<|endoftext|>


<commit_before>mod key;
mod rangeset;

use key::Key;
use rangeset::{Range, RangeSet};
use std::collections::HashMap;

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct VKeyMarker;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct EKeyMarker;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct FKeyMarker;
pub type VKey = Key<VKeyMarker>;
pub type EKey = Key<EKeyMarker>;
pub type FKey = Key<FKeyMarker>;
pub type FaceLen = u32;

pub struct Mesh<VData, EData> {
    verts: HashMap<VKey, Vert<VData>>,
    edges: HashMap<EKey, Edge<EData>>,
    faces: HashMap<FKey, Face>,

    vert_range_set: RangeSet,
    edge_range_set: RangeSet,
    face_range_set: RangeSet
}

// TODO
fn new_key_range_set() -> RangeSet {
    RangeSet::new(Range::new(0, 0xffffffff - 1))
}

impl<VData, EData: Clone> Mesh<VData, EData> {
    pub fn new() -> Mesh<VData, EData> {
        Mesh {
            verts: HashMap::new(),
            edges: HashMap::new(),
            faces: HashMap::new(),

            vert_range_set: new_key_range_set(),
            edge_range_set: new_key_range_set(),
            face_range_set: new_key_range_set()
        }
    }

    /// Return the edge between two verts, or None if no such edge
    /// exists.
    pub fn find_edge(&self, vk0: VKey, vk1: VKey) -> Option<EKey> {
        for ek in self.verts[&vk0].edges.iter() {
            if self.edges[ek].is_vert_adjacent(vk1) {
                return Some(*ek)
            }
        }
        None
    }

    /// Add a new isolated vertex and return its key. Fail and return
    /// None if there are no more vertex keys available.
    pub fn add_vert(&mut self, vdata: VData) -> Option<VKey> {
        if let Some(val) = self.vert_range_set.take_any_one() {
            let vkey = VKey::new(val);
            self.verts.insert(vkey, Vert::new(vdata));
            Some(vkey)
        } else {
            None
        }
    }

    pub fn add_edge(&mut self, vk0: VKey, vk1: VKey, edata: EData) -> Option<EKey> {
        // TODO(nicholasbishop): check that the verts are in the mesh,
        if vk0 == vk1 {
            None
        } else if let Some(ek) = self.find_edge(vk0, vk1) {
            Some(ek)
        } else {
            if let Some(val) = self.edge_range_set.take_any_one() {
                let ekey = EKey::new(val);
                self.verts.get_mut(&vk0).unwrap().push_edge(ekey);
                self.verts.get_mut(&vk1).unwrap().push_edge(ekey);
                self.edges.insert(ekey, Edge::new(vk0, vk1, edata));
                Some(ekey)
            } else {
                None
            }
        }
    }

    pub fn add_face(&mut self, vk: &[VKey], edata: EData) -> Option<FKey> {
        let mut loops = Vec::with_capacity(vk.len());
        for i in 0..vk.len() {
            let vk0 = vk[i];
            let vk1 = vk[if i < (vk.len() - 1) { i + 1 } else { 0 }];
            // TODO(nicholasbishop): do more checking up front so that
            // edges don't get created on failure, or delete them after.
            if let Some(ek) = self.add_edge(vk0, vk1, edata.clone()) {
                loops.push(Loop { vert: vk0, edge: ek });
            } else {
                // Error: failed to create edge
                return None;
            }
        }
        if let Some(val) = self.face_range_set.take_any_one() {
            let fk = FKey::new(val);
            for lp in loops.iter() {
                self.edges.get_mut(&lp.edge).unwrap().push_face(fk);
            }
            self.faces.insert(fk, Face::new(loops));
            Some(fk)
        } else {
            None
        }
    }
}

pub struct Vert<VData> {
    vdata: VData,
    edges: Vec<EKey>
}

impl<VData> Vert<VData> {
    fn new(vdata: VData) -> Vert<VData> {
        Vert { vdata: vdata, edges: Vec::new() }
    }

    /// Check if the edge is in the set of edges adjacent to this vert.
    pub fn is_edge_adjacent(&self, ek: EKey) -> bool {
        self.edges.contains(&ek)
    }

    /// Add edge to set of edges adjacent to the vert. Does nothing if
    /// the edge is already in the set.
    fn push_edge(&mut self, ek: EKey) {
        if !self.is_edge_adjacent(ek) {
            self.edges.push(ek);
        }
    }
}

pub struct Edge<EData> {
    edata: EData,
    verts: [VKey; 2],
    faces: Vec<FKey>
}

impl<EData> Edge<EData> {
    fn new(vk0: VKey, vk1: VKey, edata: EData) -> Edge<EData> {
        Edge { edata: edata, verts: [vk0, vk1], faces: Vec::new() }
    }

    /// Check if the vert is one of the two verts adjacent to this edge.
    fn is_vert_adjacent(&self, vk: VKey) -> bool {
        self.verts.contains(&vk)
    }

    /// Check if the face is in the set of edges adjacent to this edge.
    pub fn is_face_adjacent(&self, fk: FKey) -> bool {
        self.faces.contains(&fk)
    }

    /// Add face to set of faces adjacent to the edge. Does nothing if
    /// the face is already in the set.
    fn push_face(&mut self, fk: FKey) {
        if !self.is_face_adjacent(fk) {
            self.faces.push(fk);
        }
    }
}

pub struct Loop {
    vert: VKey,
    edge: EKey,
}

pub struct Face {
    loops: Vec<Loop>
}

impl Face {
    fn new(loops: Vec<Loop>) -> Face {
        Face { loops: loops }
    }
}

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

    // Placeholder for vert/edge/face data
    const DAT: () = ();

    #[test]
    fn test_add_vert() {
        let mut mesh = Mesh::<_, ()>::new();
        assert!(mesh.add_vert(DAT).is_some());
        assert!(!mesh.verts.is_empty());
    }

    #[test]
    fn test_add_edge() {
        let mut mesh = Mesh::new();
        let a = mesh.add_vert(DAT).unwrap();
        let b = mesh.add_vert(DAT).unwrap();

        // Add a valid edge
        let e = mesh.add_edge(a, b, DAT).unwrap();
        assert!(mesh.verts[&a].edges.contains(&e));
        assert!(mesh.verts[&b].edges.contains(&e));

        // Edge from a vertex to the same vertex is not allowed
        assert!(mesh.add_edge(a, a, DAT).is_none());

        // Duplicate edge should return the existing edge
        assert_eq!(mesh.add_edge(a, b, DAT).unwrap(), e);
        assert_eq!(mesh.add_edge(b, a, DAT).unwrap(), e);
    }

    #[test]
    fn test_add_face() {
        let mut mesh = Mesh::new();
        let a = mesh.add_vert(DAT).unwrap();
        let b = mesh.add_vert(DAT).unwrap();
        let c = mesh.add_vert(DAT).unwrap();

        // Add a valid triangle
        let fk = mesh.add_face(&[a, b, c], DAT).unwrap();
        assert_eq!(mesh.edges.len(), 3);
        for lp in mesh.faces[&fk].loops.iter() {
            assert!(mesh.edges[&lp.edge].is_face_adjacent(fk));
        }

        // Add an invalid triangle with invalid edge
        assert!(mesh.add_face(&[a, b, b], DAT).is_none());
    }
}
<commit_msg>Add face data<commit_after>mod key;
mod rangeset;

use key::Key;
use rangeset::{Range, RangeSet};
use std::collections::HashMap;

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct VKeyMarker;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct EKeyMarker;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct FKeyMarker;
pub type VKey = Key<VKeyMarker>;
pub type EKey = Key<EKeyMarker>;
pub type FKey = Key<FKeyMarker>;
pub type FaceLen = u32;

pub struct Mesh<VData, EData, FData> {
    verts: HashMap<VKey, Vert<VData>>,
    edges: HashMap<EKey, Edge<EData>>,
    faces: HashMap<FKey, Face<FData>>,

    vert_range_set: RangeSet,
    edge_range_set: RangeSet,
    face_range_set: RangeSet
}

// TODO
fn new_key_range_set() -> RangeSet {
    RangeSet::new(Range::new(0, 0xffffffff - 1))
}

impl<VData: Clone, EData: Clone, FData: Clone> Mesh<VData, EData, FData> {
    pub fn new() -> Mesh<VData, EData, FData> {
        Mesh {
            verts: HashMap::new(),
            edges: HashMap::new(),
            faces: HashMap::new(),

            vert_range_set: new_key_range_set(),
            edge_range_set: new_key_range_set(),
            face_range_set: new_key_range_set()
        }
    }

    /// Return the edge between two verts, or None if no such edge
    /// exists.
    pub fn find_edge(&self, vk0: VKey, vk1: VKey) -> Option<EKey> {
        for ek in self.verts[&vk0].edges.iter() {
            if self.edges[ek].is_vert_adjacent(vk1) {
                return Some(*ek)
            }
        }
        None
    }

    /// Add a new isolated vertex and return its key. Fail and return
    /// None if there are no more vertex keys available.
    pub fn add_vert(&mut self, vdata: VData) -> Option<VKey> {
        if let Some(val) = self.vert_range_set.take_any_one() {
            let vkey = VKey::new(val);
            self.verts.insert(vkey, Vert::new(vdata));
            Some(vkey)
        } else {
            None
        }
    }

    pub fn add_edge(&mut self, vk0: VKey, vk1: VKey, edata: EData) -> Option<EKey> {
        // TODO(nicholasbishop): check that the verts are in the mesh,
        if vk0 == vk1 {
            None
        } else if let Some(ek) = self.find_edge(vk0, vk1) {
            Some(ek)
        } else {
            if let Some(val) = self.edge_range_set.take_any_one() {
                let ekey = EKey::new(val);
                self.verts.get_mut(&vk0).unwrap().push_edge(ekey);
                self.verts.get_mut(&vk1).unwrap().push_edge(ekey);
                self.edges.insert(ekey, Edge::new(vk0, vk1, edata));
                Some(ekey)
            } else {
                None
            }
        }
    }

    pub fn add_face(&mut self, vk: &[VKey], edata: EData, fdata: FData) -> Option<FKey> {
        let mut loops = Vec::with_capacity(vk.len());
        for i in 0..vk.len() {
            let vk0 = vk[i];
            let vk1 = vk[if i < (vk.len() - 1) { i + 1 } else { 0 }];
            // TODO(nicholasbishop): do more checking up front so that
            // edges don't get created on failure, or delete them after.
            if let Some(ek) = self.add_edge(vk0, vk1, edata.clone()) {
                loops.push(Loop { vert: vk0, edge: ek });
            } else {
                // Error: failed to create edge
                return None;
            }
        }
        if let Some(val) = self.face_range_set.take_any_one() {
            let fk = FKey::new(val);
            for lp in loops.iter() {
                self.edges.get_mut(&lp.edge).unwrap().push_face(fk);
            }
            self.faces.insert(fk, Face::new(loops, fdata));
            Some(fk)
        } else {
            None
        }
    }
}

pub struct Vert<VData> {
    vdata: VData,
    edges: Vec<EKey>
}

impl<VData> Vert<VData> {
    fn new(vdata: VData) -> Vert<VData> {
        Vert { vdata: vdata, edges: Vec::new() }
    }

    /// Check if the edge is in the set of edges adjacent to this vert.
    pub fn is_edge_adjacent(&self, ek: EKey) -> bool {
        self.edges.contains(&ek)
    }

    /// Add edge to set of edges adjacent to the vert. Does nothing if
    /// the edge is already in the set.
    fn push_edge(&mut self, ek: EKey) {
        if !self.is_edge_adjacent(ek) {
            self.edges.push(ek);
        }
    }
}

pub struct Edge<EData> {
    edata: EData,
    verts: [VKey; 2],
    faces: Vec<FKey>
}

impl<EData> Edge<EData> {
    fn new(vk0: VKey, vk1: VKey, edata: EData) -> Edge<EData> {
        Edge { edata: edata, verts: [vk0, vk1], faces: Vec::new() }
    }

    /// Check if the vert is one of the two verts adjacent to this edge.
    fn is_vert_adjacent(&self, vk: VKey) -> bool {
        self.verts.contains(&vk)
    }

    /// Check if the face is in the set of edges adjacent to this edge.
    pub fn is_face_adjacent(&self, fk: FKey) -> bool {
        self.faces.contains(&fk)
    }

    /// Add face to set of faces adjacent to the edge. Does nothing if
    /// the face is already in the set.
    fn push_face(&mut self, fk: FKey) {
        if !self.is_face_adjacent(fk) {
            self.faces.push(fk);
        }
    }
}

pub struct Loop {
    vert: VKey,
    edge: EKey,
}

pub struct Face<FData> {
    fdata: FData,
    loops: Vec<Loop>
}

impl<FData> Face<FData> {
    fn new(loops: Vec<Loop>, fdata: FData) -> Face<FData> {
        Face { fdata: fdata, loops: loops }
    }
}

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

    // Placeholder for vert/edge/face data
    const DAT: () = ();

    #[test]
    fn test_add_vert() {
        let mut mesh = Mesh::<_, (), ()>::new();
        assert!(mesh.add_vert(DAT).is_some());
        assert!(!mesh.verts.is_empty());
    }

    #[test]
    fn test_add_edge() {
        let mut mesh = Mesh::<_, _, ()>::new();
        let a = mesh.add_vert(DAT).unwrap();
        let b = mesh.add_vert(DAT).unwrap();

        // Add a valid edge
        let e = mesh.add_edge(a, b, DAT).unwrap();
        assert!(mesh.verts[&a].edges.contains(&e));
        assert!(mesh.verts[&b].edges.contains(&e));

        // Edge from a vertex to the same vertex is not allowed
        assert!(mesh.add_edge(a, a, DAT).is_none());

        // Duplicate edge should return the existing edge
        assert_eq!(mesh.add_edge(a, b, DAT).unwrap(), e);
        assert_eq!(mesh.add_edge(b, a, DAT).unwrap(), e);
    }

    #[test]
    fn test_add_face() {
        let mut mesh = Mesh::new();
        let a = mesh.add_vert(DAT).unwrap();
        let b = mesh.add_vert(DAT).unwrap();
        let c = mesh.add_vert(DAT).unwrap();

        // Add a valid triangle
        let fk = mesh.add_face(&[a, b, c], DAT, DAT).unwrap();
        assert_eq!(mesh.edges.len(), 3);
        for lp in mesh.faces[&fk].loops.iter() {
            assert!(mesh.edges[&lp.edge].is_face_adjacent(fk));
        }

        // Add an invalid triangle with invalid edge
        assert!(mesh.add_face(&[a, b, b], DAT, DAT).is_none());
    }
}
<|endoftext|>


<commit_before>//! This crate exposes functionality to create receivers that
//! receive notifications after a specified period of time or at
//! a specified frequency.
//!
//! # Examples
//!
//! At its simplest, oneshot_ms can be used to put the thread to
//! sleep. Unlike with std::thread::sleep, this could be used with
//! Select to be waiting for one of several Receivers to fire.
//!
//! ```
//! # use schedule_recv::oneshot_ms;
//! # fn sleep_equivalent() {
//! let timer = oneshot_ms(1500);
//! timer.recv().unwrap();
//! println!("1.5 seconds have elapsed.");
//! # }
//! ```
//!
//! Periodic Receivers can be created using periodic_ms.
//!
//! ```
//! # use schedule_recv::periodic_ms;
//! # use std::thread;
//! # fn tick_tock() {
//! let tick = periodic_ms(2000);
//! thread::sleep_ms(1000);
//! let tock = periodic_ms(2000);
//!
//! loop {
//!     tick.recv().unwrap();
//!     println!("Tick");
//!     tock.recv().unwrap();
//!     println!("Tock");
//! }
//! # }
//! ```

#[macro_use] extern crate lazy_static;

mod scheduler;

#[cfg(test)] mod test;

pub use scheduler::{oneshot_ms, periodic_ms, oneshot, periodic, periodic_after};
<commit_msg>Update documentation to use the Duration-taking functions<commit_after>//! This crate exposes functionality to create receivers that
//! receive notifications after a specified period of time or at
//! a specified frequency.
//!
//! # Examples
//!
//! At its simplest, oneshot_ms can be used to put the thread to
//! sleep. Unlike with std::thread::sleep, this could be used with
//! Select to be waiting for one of several Receivers to fire.
//!
//! ```
//! # use schedule_recv::oneshot;
//! # use std::time::Duration;
//! # fn sleep_equivalent() {
//! let timer = oneshot(Duration::from_millis(1500));
//! timer.recv().unwrap();
//! println!("1.5 seconds have elapsed.");
//! # }
//! ```
//!
//! Periodic Receivers can be created using periodic_ms.
//!
//! ```
//! # use schedule_recv::periodic;
//! # use std::thread;
//! # use std::time::Duration;
//! # fn tick_tock() {
//! let tick = periodic(Duration::from_millis(2000));
//! thread::sleep_ms(1000);
//! let tock = periodic(Duration::from_millis(2000));
//!
//! loop {
//!     tick.recv().unwrap();
//!     println!("Tick");
//!     tock.recv().unwrap();
//!     println!("Tock");
//! }
//! # }
//! ```

#[macro_use] extern crate lazy_static;

mod scheduler;

#[cfg(test)] mod test;

pub use scheduler::{oneshot_ms, periodic_ms, oneshot, periodic, periodic_after};
<|endoftext|>


<commit_before>#![crate_name = "rusoto"]
#![crate_type = "lib"]
#![cfg_attr(feature = "unstable", feature(proc_macro))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", allow(cyclomatic_complexity, used_underscore_binding, ptr_arg, suspicious_else_formatting))]
#![allow(dead_code)]
#![cfg_attr(not(feature = "unstable"), deny(warnings))]

//! Rusoto is an [AWS](https://aws.amazon.com/) SDK for Rust.
//! A high level overview is available in `README.md` at https://github.com/rusoto/rusoto.
//!
//! # Example
//!
//! The following code shows a simple example of using Rusoto's DynamoDB API to
//! list the names of all tables in a database.
//!
//! ```rust,ignore
//! use std::default::Default;
//!
//! use rusoto::{DefaultCredentialsProvider, Region};
//! use rusoto::dynamodb::{DynamoDbClient, ListTablesInput};
//!
//! let provider = DefaultCredentialsProvider::new().unwrap();
//! let client = DynamoDbClient::new(provider, Region::UsEast1);
//! let list_tables_input: ListTablesInput = Default::default();
//!
//! match client.list_tables(&list_tables_input) {
//!     Ok(output) => {
//!         match output.table_names {
//!             Some(table_name_list) => {
//!                 println!("Tables in database:");
//!
//!                 for table_name in table_name_list {
//!                     println!("{}", table_name);
//!                 }
//!             },
//!             None => println!("No tables in database!"),
//!         }
//!     },
//!     Err(error) => {
//!         println!("Error: {:?}", error);
//!     },
//! }

extern crate chrono;
extern crate hyper;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate log;
extern crate md5;
extern crate regex;
extern crate ring;
extern crate rusoto_credential;
extern crate rustc_serialize;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate url;
extern crate xml;

#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;

pub use region::{ParseRegionError, Region};
pub use rusoto_credential::{
    AwsCredentials,
    ChainProvider,
    ContainerProvider,
    CredentialsError,
    EnvironmentProvider,
    InstanceMetadataProvider,
    ProfileProvider,
    ProvideAwsCredentials,
    DefaultCredentialsProvider,
    DefaultCredentialsProviderSync,
};
pub use request::{DispatchSignedRequest, HttpResponse, HttpDispatchError};
pub use signature::SignedRequest;

mod param;
mod region;
mod request;
mod xmlerror;
mod xmlutil;
mod serialization;
#[macro_use] mod signature;

#[cfg(test)]
mod mock;

#[cfg(feature = "acm")]
pub mod acm;
#[cfg(feature = "cloudhsm")]
pub mod cloudhsm;
#[cfg(feature = "cloudtrail")]
pub mod cloudtrail;
#[cfg(feature = "codecommit")]
pub mod codecommit;
#[cfg(feature = "codedeploy")]
pub mod codedeploy;
#[cfg(feature = "codepipeline")]
pub mod codepipeline;
#[cfg(feature = "cognito-identity")]
pub mod cognitoidentity;
#[cfg(feature = "config")]
pub mod config;
#[cfg(feature = "datapipeline")]
pub mod datapipeline;
#[cfg(feature = "devicefarm")]
pub mod devicefarm;
#[cfg(feature = "directconnect")]
pub mod directconnect;
#[cfg(feature = "ds")]
pub mod ds;
#[cfg(feature = "dynamodb")]
pub mod dynamodb;
#[cfg(feature = "dynamodbstreams")]
pub mod dynamodbstreams;
#[cfg(feature = "ec2")]
pub mod ec2;
#[cfg(feature = "ecr")]
pub mod ecr;
#[cfg(feature = "ecs")]
pub mod ecs;
#[cfg(feature = "emr")]
pub mod emr;
#[cfg(feature = "elastictranscoder")]
pub mod elastictranscoder;
#[cfg(feature = "events")]
pub mod events;
#[cfg(feature = "firehose")]
pub mod firehose;
#[cfg(feature = "iam")]
pub mod iam;
#[cfg(feature = "inspector")]
pub mod inspector;
#[cfg(feature = "iot")]
pub mod iot;
#[cfg(feature = "kinesis")]
pub mod kinesis;
#[cfg(feature = "kms")]
pub mod kms;
#[cfg(feature = "logs")]
pub mod logs;
#[cfg(feature = "machinelearning")]
pub mod machinelearning;
#[cfg(feature = "marketplacecommerceanalytics")]
pub mod marketplacecommerceanalytics;
#[cfg(feature = "opsworks")]
pub mod opsworks;
#[cfg(feature = "route53domains")]
pub mod route53domains;
#[cfg(feature = "s3")]
pub mod s3;
#[cfg(feature = "sqs")]
pub mod sqs;
#[cfg(feature = "ssm")]
pub mod ssm;
#[cfg(feature = "storagegateway")]
pub mod storagegateway;
#[cfg(feature = "swf")]
pub mod swf;
#[cfg(feature = "waf")]
pub mod waf;
#[cfg(feature = "workspaces")]
pub mod workspaces;

/*
#[cfg(feature = "gamelift")]
pub mod gamelift;
#[cfg(feature = "support")]
pub mod support;
*/
<commit_msg>fix: enable custom_attribute feature<commit_after>#![crate_name = "rusoto"]
#![crate_type = "lib"]
#![cfg_attr(feature = "unstable", feature(custom_attribute, proc_macro))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", allow(cyclomatic_complexity, used_underscore_binding, ptr_arg, suspicious_else_formatting))]
#![allow(dead_code)]
#![cfg_attr(not(feature = "unstable"), deny(warnings))]

//! Rusoto is an [AWS](https://aws.amazon.com/) SDK for Rust.
//! A high level overview is available in `README.md` at https://github.com/rusoto/rusoto.
//!
//! # Example
//!
//! The following code shows a simple example of using Rusoto's DynamoDB API to
//! list the names of all tables in a database.
//!
//! ```rust,ignore
//! use std::default::Default;
//!
//! use rusoto::{DefaultCredentialsProvider, Region};
//! use rusoto::dynamodb::{DynamoDbClient, ListTablesInput};
//!
//! let provider = DefaultCredentialsProvider::new().unwrap();
//! let client = DynamoDbClient::new(provider, Region::UsEast1);
//! let list_tables_input: ListTablesInput = Default::default();
//!
//! match client.list_tables(&list_tables_input) {
//!     Ok(output) => {
//!         match output.table_names {
//!             Some(table_name_list) => {
//!                 println!("Tables in database:");
//!
//!                 for table_name in table_name_list {
//!                     println!("{}", table_name);
//!                 }
//!             },
//!             None => println!("No tables in database!"),
//!         }
//!     },
//!     Err(error) => {
//!         println!("Error: {:?}", error);
//!     },
//! }

extern crate chrono;
extern crate hyper;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate log;
extern crate md5;
extern crate regex;
extern crate ring;
extern crate rusoto_credential;
extern crate rustc_serialize;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate url;
extern crate xml;

#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;

pub use region::{ParseRegionError, Region};
pub use rusoto_credential::{
    AwsCredentials,
    ChainProvider,
    ContainerProvider,
    CredentialsError,
    EnvironmentProvider,
    InstanceMetadataProvider,
    ProfileProvider,
    ProvideAwsCredentials,
    DefaultCredentialsProvider,
    DefaultCredentialsProviderSync,
};
pub use request::{DispatchSignedRequest, HttpResponse, HttpDispatchError};
pub use signature::SignedRequest;

mod param;
mod region;
mod request;
mod xmlerror;
mod xmlutil;
mod serialization;
#[macro_use] mod signature;

#[cfg(test)]
mod mock;

#[cfg(feature = "acm")]
pub mod acm;
#[cfg(feature = "cloudhsm")]
pub mod cloudhsm;
#[cfg(feature = "cloudtrail")]
pub mod cloudtrail;
#[cfg(feature = "codecommit")]
pub mod codecommit;
#[cfg(feature = "codedeploy")]
pub mod codedeploy;
#[cfg(feature = "codepipeline")]
pub mod codepipeline;
#[cfg(feature = "cognito-identity")]
pub mod cognitoidentity;
#[cfg(feature = "config")]
pub mod config;
#[cfg(feature = "datapipeline")]
pub mod datapipeline;
#[cfg(feature = "devicefarm")]
pub mod devicefarm;
#[cfg(feature = "directconnect")]
pub mod directconnect;
#[cfg(feature = "ds")]
pub mod ds;
#[cfg(feature = "dynamodb")]
pub mod dynamodb;
#[cfg(feature = "dynamodbstreams")]
pub mod dynamodbstreams;
#[cfg(feature = "ec2")]
pub mod ec2;
#[cfg(feature = "ecr")]
pub mod ecr;
#[cfg(feature = "ecs")]
pub mod ecs;
#[cfg(feature = "emr")]
pub mod emr;
#[cfg(feature = "elastictranscoder")]
pub mod elastictranscoder;
#[cfg(feature = "events")]
pub mod events;
#[cfg(feature = "firehose")]
pub mod firehose;
#[cfg(feature = "iam")]
pub mod iam;
#[cfg(feature = "inspector")]
pub mod inspector;
#[cfg(feature = "iot")]
pub mod iot;
#[cfg(feature = "kinesis")]
pub mod kinesis;
#[cfg(feature = "kms")]
pub mod kms;
#[cfg(feature = "logs")]
pub mod logs;
#[cfg(feature = "machinelearning")]
pub mod machinelearning;
#[cfg(feature = "marketplacecommerceanalytics")]
pub mod marketplacecommerceanalytics;
#[cfg(feature = "opsworks")]
pub mod opsworks;
#[cfg(feature = "route53domains")]
pub mod route53domains;
#[cfg(feature = "s3")]
pub mod s3;
#[cfg(feature = "sqs")]
pub mod sqs;
#[cfg(feature = "ssm")]
pub mod ssm;
#[cfg(feature = "storagegateway")]
pub mod storagegateway;
#[cfg(feature = "swf")]
pub mod swf;
#[cfg(feature = "waf")]
pub mod waf;
#[cfg(feature = "workspaces")]
pub mod workspaces;

/*
#[cfg(feature = "gamelift")]
pub mod gamelift;
#[cfg(feature = "support")]
pub mod support;
*/
<|endoftext|>


<commit_before>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is(atty::Stream::Stdout) {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt(atty::Stream::Stdout) {
//!   println!("i'm not a tty")
//! }
//! ```

extern crate libc;

/// possible stream sources
pub enum Stream {
    Stdout,
    Stderr,
    Stdin
}

/// returns true if this is a tty
#[cfg(unix)]
pub fn is(stream: Stream) -> bool {
    let fd = match stream {
        Stream::Stdout => libc::STDOUT_FILENO,
        Stream::Stderr => libc::STDERR_FILENO,
        Stream::Stdin => libc::STDERR_FILENO
    };
    unsafe { libc::isatty(fd) != 0 }
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is(stream: Stream) -> bool {
    extern crate kernel32;
    extern crate winapi;

    let handle = match stream {
        Stream::Stdout => winapi::winbase::STD_OUTPUT_HANDLE,
        Stream::Stderr => winapi::winbase::STD_ERROR_HANDLE,
        Stream::Stdin => winapi::winbase::STD_INPUT_HANDLE
    };
    unsafe {
        let handle = kernel32::GetStdHandle(handle);
        let mut out = 0;
        kernel32::GetConsoleMode(handle, &mut out) != 0
    }
}

/// returns true if this is _not_ a tty
pub fn isnt(stream: Stream) -> bool {
    !is(stream)
}

#[cfg(test)]
mod tests {
    use super::{is, Stream};

    #[test]
    fn is_test() {
        assert!(is(Stream::Stdout))
    }
}
<commit_msg>std _in_ not out here<commit_after>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is(atty::Stream::Stdout) {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt(atty::Stream::Stdout) {
//!   println!("i'm not a tty")
//! }
//! ```

extern crate libc;

/// possible stream sources
pub enum Stream {
    Stdout,
    Stderr,
    Stdin
}

/// returns true if this is a tty
#[cfg(unix)]
pub fn is(stream: Stream) -> bool {
    let fd = match stream {
        Stream::Stdout => libc::STDOUT_FILENO,
        Stream::Stderr => libc::STDERR_FILENO,
        Stream::Stdin => libc::STDIN_FILENO
    };
    unsafe { libc::isatty(fd) != 0 }
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is(stream: Stream) -> bool {
    extern crate kernel32;
    extern crate winapi;

    let handle = match stream {
        Stream::Stdout => winapi::winbase::STD_OUTPUT_HANDLE,
        Stream::Stderr => winapi::winbase::STD_ERROR_HANDLE,
        Stream::Stdin => winapi::winbase::STD_INPUT_HANDLE
    };
    unsafe {
        let handle = kernel32::GetStdHandle(handle);
        let mut out = 0;
        kernel32::GetConsoleMode(handle, &mut out) != 0
    }
}

/// returns true if this is _not_ a tty
pub fn isnt(stream: Stream) -> bool {
    !is(stream)
}

#[cfg(test)]
mod tests {
    use super::{is, Stream};

    #[test]
    fn is_test() {
        assert!(is(Stream::Stdout))
    }
}
<|endoftext|>


<commit_before>extern crate num;

use std::ops::{Add, Sub, Mul, Div, Rem};
use std::cmp::{PartialEq, Eq};
use num::{Zero, One, Num, FromPrimitive, ToPrimitive, NumCast, Bounded};

macro_rules! fixed_point_impl {
    ($name:ident: $ty:ty, $tyd:ty, $ibits:expr, $fbits:expr) => {
        struct $name {
            base: $ty,
        }

        impl Add for $name {
            type Output = Self;
            fn add(self, rhs: Self) -> Self {
                $name {
                    base: self.base + rhs.base
                }
            }
        }

        impl Sub for $name {
            type Output = Self;
            fn sub(self, rhs: Self) -> Self {
                $name {
                    base: self.base - rhs.base
                }
            }
        }

        impl Mul for $name {
            type Output = Self;
            fn mul(self, rhs: Self) -> Self {
                $name {
                    base: ((self.base as $tyd * rhs.base as $tyd) >> $fbits) as $ty,
                }
            }
        }

        impl Div for $name {
            type Output = Self;
            fn div(self, rhs: Self) -> Self {
                $name {
                    base: (((self.base as $tyd) << $fbits) / (rhs.base as $tyd)) as $ty,
                }
            }
        }

        impl Rem for $name {
            type Output = Self;
            fn rem(self, rhs: Self) -> Self {
                $name {
                    base: self.base % rhs.base,
                }
            }
        }

        impl Zero for $name {
            fn zero() -> Self {
                $name {
                    base: 0,
                }
            }

            fn is_zero(&self) -> bool {
                self.base == 0
            }
        }

        impl One for $name {
            fn one() -> Self {
                $name {
                    base: 1 << $fbits,
                }
            }
        }

        impl PartialEq for $name {
            fn eq(&self, other: &Self) -> bool {
                self.base == other.base
            }
        }

        impl Eq for $name { }

        impl Num for $name {
            type FromStrRadixErr = ();
            fn from_str_radix(_str: &str, _radix: u32) -> Result<Self, Self::FromStrRadixErr> {
                unimplemented!();
            }
        }

        impl FromPrimitive for $name {
            fn from_i64(n: i64) -> Option<Self> {
                if n < Self::min_value().to_i64().unwrap() ||
                    n > Self::max_value().to_i64().unwrap() {
                    None
                } else {
                    Some($name {
                        base: n as $ty << $fbits,
                    })
                }
            }

            fn from_u64(n: u64) -> Option<Self> {
                if n > Self::max_value().to_u64().unwrap() {
                    None
                } else {
                    Some($name {
                        base: n as $ty << $fbits,
                    })
                }
            }

            fn from_f64(n: f64) -> Option<Self> {
                if n < Self::min_value().to_f64().unwrap() ||
                    n > Self::max_value().to_f64().unwrap() {
                    None
                } else {
                    Some($name {
                        base: (n * ((1 << $fbits) as f64)) as $ty,
                    })
                }
            }
        }

        impl ToPrimitive for $name {
            fn to_i64(&self) -> Option<i64> {
                Some((self.base >> $fbits) as i64)
            }

            #[allow(unused_comparisons)]
            fn to_u64(&self) -> Option<u64> {
                if self.base < 0 {
                    None
                } else {
                    Some((self.base >> $fbits) as u64)
                }
            }

            fn to_f64(&self) -> Option<f64> {
                Some(self.base as f64 / (1 << $fbits) as f64)
            }
        }

        impl NumCast for $name {
            fn from<T: ToPrimitive>(n: T) -> Option<Self> {
                n.to_f64().and_then(|f| FromPrimitive::from_f64(f))
            }
        }

        impl Bounded for $name {
            fn min_value() -> Self {
                $name {
                    base: Bounded::min_value(),
                }
            }

            fn max_value() -> Self {
                $name {
                    base: Bounded::max_value(),
                }
            }
        }
    };
}

fixed_point_impl!(U24p8: u32, u64, 24, 8);
<commit_msg>Added Saturating and Checked* traits.<commit_after>extern crate num;

use std::ops::{Add, Sub, Mul, Div, Rem};
use std::cmp::{PartialEq, Eq};
use num::{Zero, One, Num, FromPrimitive, ToPrimitive, NumCast, Bounded, Saturating};
use num::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};

macro_rules! fixed_point_impl {
    ($name:ident: $ty:ty, $tyd:ty, $ibits:expr, $fbits:expr) => {
        struct $name {
            base: $ty,
        }

        impl Add for $name {
            type Output = Self;
            fn add(self, rhs: Self) -> Self {
                $name {
                    base: self.base + rhs.base
                }
            }
        }

        impl Sub for $name {
            type Output = Self;
            fn sub(self, rhs: Self) -> Self {
                $name {
                    base: self.base - rhs.base
                }
            }
        }

        impl Mul for $name {
            type Output = Self;
            fn mul(self, rhs: Self) -> Self {
                $name {
                    base: ((self.base as $tyd * rhs.base as $tyd) >> $fbits) as $ty,
                }
            }
        }

        impl Div for $name {
            type Output = Self;
            fn div(self, rhs: Self) -> Self {
                $name {
                    base: (((self.base as $tyd) << $fbits) / (rhs.base as $tyd)) as $ty,
                }
            }
        }

        impl Rem for $name {
            type Output = Self;
            fn rem(self, rhs: Self) -> Self {
                $name {
                    base: self.base % rhs.base,
                }
            }
        }

        impl Zero for $name {
            fn zero() -> Self {
                $name {
                    base: 0,
                }
            }

            fn is_zero(&self) -> bool {
                self.base == 0
            }
        }

        impl One for $name {
            fn one() -> Self {
                $name {
                    base: 1 << $fbits,
                }
            }
        }

        impl PartialEq for $name {
            fn eq(&self, other: &Self) -> bool {
                self.base == other.base
            }
        }

        impl Eq for $name { }

        impl Num for $name {
            type FromStrRadixErr = ();
            fn from_str_radix(_str: &str, _radix: u32) -> Result<Self, Self::FromStrRadixErr> {
                unimplemented!();
            }
        }

        impl FromPrimitive for $name {
            fn from_i64(n: i64) -> Option<Self> {
                if n < Self::min_value().to_i64().unwrap() ||
                    n > Self::max_value().to_i64().unwrap() {
                    None
                } else {
                    Some($name {
                        base: n as $ty << $fbits,
                    })
                }
            }

            fn from_u64(n: u64) -> Option<Self> {
                if n > Self::max_value().to_u64().unwrap() {
                    None
                } else {
                    Some($name {
                        base: n as $ty << $fbits,
                    })
                }
            }

            fn from_f64(n: f64) -> Option<Self> {
                if n < Self::min_value().to_f64().unwrap() ||
                    n > Self::max_value().to_f64().unwrap() {
                    None
                } else {
                    Some($name {
                        base: (n * ((1 << $fbits) as f64)) as $ty,
                    })
                }
            }
        }

        impl ToPrimitive for $name {
            fn to_i64(&self) -> Option<i64> {
                Some((self.base >> $fbits) as i64)
            }

            #[allow(unused_comparisons)]
            fn to_u64(&self) -> Option<u64> {
                if self.base < 0 {
                    None
                } else {
                    Some((self.base >> $fbits) as u64)
                }
            }

            fn to_f64(&self) -> Option<f64> {
                Some(self.base as f64 / (1 << $fbits) as f64)
            }
        }

        impl NumCast for $name {
            fn from<T: ToPrimitive>(n: T) -> Option<Self> {
                n.to_f64().and_then(|f| FromPrimitive::from_f64(f))
            }
        }

        impl Bounded for $name {
            fn min_value() -> Self {
                $name {
                    base: Bounded::min_value(),
                }
            }

            fn max_value() -> Self {
                $name {
                    base: Bounded::max_value(),
                }
            }
        }

        impl Saturating for $name {
            fn saturating_add(self, rhs: Self) -> Self {
                $name {
                    base: self.base.saturating_add(rhs.base),
                }
            }

            fn saturating_sub(self, rhs: Self) -> Self {
                $name {
                    base: self.base.saturating_sub(rhs.base),
                }
            }
        }

        impl CheckedAdd for $name {
            fn checked_add(&self, rhs: &Self) -> Option<Self> {
                self.base.checked_add(rhs.base).map(|b| $name {
                    base: b,
                })
            }
        }

        impl CheckedSub for $name {
            fn checked_sub(&self, rhs: &Self) -> Option<Self> {
                self.base.checked_sub(rhs.base).map(|b| $name {
                    base: b,
                })
            }
        }

        impl CheckedMul for $name {
            fn checked_mul(&self, rhs: &Self) -> Option<Self> {
                (self.base as $tyd).checked_mul(rhs.base as $tyd).and_then(|mut base_double| {
                    base_double = base_double >> $fbits;
                    let $name { base: max_base } = Self::max_value();
                    let $name { base: min_base } = Self::min_value();
                    if base_double > max_base as $tyd || base_double < min_base as $tyd {
                        None
                    } else {
                        Some($name {
                            base: base_double as $ty
                        })
                    }
                })
            }
        }

        impl CheckedDiv for $name {
            fn checked_div(&self, rhs: &Self) -> Option<Self> {
                ((self.base as $tyd) << $fbits).checked_div(rhs.base as $tyd)
                    .and_then(|base_double| {
                        let $name { base: max_base } = Self::max_value();
                        let $name { base: min_base } = Self::min_value();
                        if base_double > max_base as $tyd || base_double < min_base as $tyd {
                            None
                        } else {
                            Some($name {
                                base: base_double as $ty
                            })
                        }
                    })
            }
        }
    };
}

fixed_point_impl!(U24p8: u32, u64, 24, 8);
fixed_point_impl!(I24p8: i32, i64, 24, 8);
<|endoftext|>