<commit_before>extern crate lua53_sys as luac;

use std::ffi::CString;
use read::Read;
use write::Write;

pub type LuaPtr = *mut luac::lua_State;

pub struct Lua {
    pub ptr: LuaPtr,
}

impl Lua {
    pub fn new() -> Lua {
        let ptr = unsafe { luac::luaL_newstate() };
        Lua { ptr: ptr }
    }

    pub fn get_value<T: Read>(&self, name: &str) -> Option<T> {
        let cstr = CString::new(name).unwrap();
        let success = unsafe { luac::lua_getglobal(self.ptr, cstr.as_ptr()) != 0 };
        if !success {
            self.pop_stack(1);
            return None;
        }
        let (v, size) = unsafe { T::read_from_stack(&self, -1) };
        self.pop_stack(size as i32);
        return v;
    }

    pub fn set_value<T: Write>(&mut self, name: &str, value: T) {
        unsafe {
            value.write_to_stack(&self);
            let name = CString::new(name).unwrap();
            luac::lua_setglobal(self.ptr, name.as_ptr());
        }
    }

    pub fn remove_value(&mut self, name: &str) {
        unsafe {
            luac::lua_pushnil(self.ptr);
            let name = CString::new(name).unwrap();
            luac::lua_setglobal(self.ptr, name.as_ptr());
        }
    }

    pub fn run(&mut self, code: &str) -> Result<(), ()> {
        let nargs = 0;
        let nresults = 0;

        let cstr = CString::new(code).unwrap();
        let code = unsafe { luac::luaL_loadstring(self.ptr, cstr.as_ptr()) };
        if code != 0 {
            debug_assert!(self.current_stack_size() == 0);
            return Err(());
        }
        let code = unsafe { luac::lua_pcallk(self.ptr, nargs, nresults, 0, 0, None) };
        if code != 0 {
            debug_assert!(self.current_stack_size() == 0);
            return Err(());
        }
        debug_assert!(self.current_stack_size() == 0);
        return Ok(());
    }

    pub fn set_fn<F: FnMut() -> ()>(&mut self, name: &str, f: F) {
        use std::mem::size_of;
        use std::ptr::drop_in_place;

        unsafe extern "C" fn call_drop<F: FnMut() -> ()>(ptr: LuaPtr) -> i32 {
            let f = luac::lua_touserdata(ptr, luac::lua_upvalueindex(1)) as *mut F;
            drop_in_place(f);
            return 0;
        }

        unsafe extern "C" fn callback<F: FnMut() -> ()>(ptr: LuaPtr) -> i32 {
            let f = luac::lua_touserdata(ptr, luac::lua_upvalueindex(1)) as *mut F;
            (*f)();
            return 0;
        }

        unsafe {
            // create user data
            let size = size_of::<F>();
            let loc = luac::lua_newuserdata(self.ptr, size) as *mut F;
            debug_assert!(self.current_stack_size() == 1);
            *loc = f;
            // metatable
            let meta_table_name = format!("meta-{:p}", &call_drop::<F>);
            let meta_table_name = CString::new(meta_table_name).unwrap();
            luac::luaL_newmetatable(self.ptr, meta_table_name.as_ptr());
            debug_assert!(self.current_stack_size() == 2);
            "__gc".write_to_stack(self);
            luac::lua_pushcclosure(self.ptr, Some(call_drop::<F>), 0);
            debug_assert!(self.current_stack_size() == 4);
            luac::lua_rawset(self.ptr, -3);
            debug_assert!(self.current_stack_size() == 2);
            // set metatable
            luac::lua_setmetatable(self.ptr, -2);
            debug_assert!(self.current_stack_size() == 1);
            // TODO support finalizer
            luac::lua_pushcclosure(self.ptr, Some(callback::<F>), 1);
            let name = CString::new(name).unwrap();
            luac::lua_setglobal(self.ptr, name.as_ptr());
        }
    }

    pub fn current_stack_size(&self) -> i32 {
        unsafe { luac::lua_gettop(self.ptr) }
    }

    fn pop_stack(&self, n: i32) {
        unsafe { luac::lua_settop(self.ptr, -1 - n) }
    }
}

impl Drop for Lua {
    fn drop(&mut self) {
        unsafe {
            luac::lua_close(self.ptr);
        }
    }
}
<commit_msg>refactoring<commit_after>extern crate lua53_sys as luac;

use std::ffi::CString;
use read::Read;
use write::Write;

pub type LuaPtr = *mut luac::lua_State;

pub struct Lua {
    pub ptr: LuaPtr,
}

impl Lua {
    pub fn new() -> Lua {
        let ptr = unsafe { luac::luaL_newstate() };
        Lua { ptr: ptr }
    }

    pub fn get_value<T: Read>(&self, name: &str) -> Option<T> {
        let cstr = CString::new(name).unwrap();
        let success = unsafe { luac::lua_getglobal(self.ptr, cstr.as_ptr()) != 0 };
        if !success {
            self.pop_stack(1);
            return None;
        }
        let (v, size) = unsafe { T::read_from_stack(&self, -1) };
        self.pop_stack(size as i32);
        return v;
    }

    pub fn set_value<T: Write>(&mut self, name: &str, value: T) {
        unsafe {
            value.write_to_stack(&self);
            let name = CString::new(name).unwrap();
            luac::lua_setglobal(self.ptr, name.as_ptr());
        }
    }

    pub fn remove_value(&mut self, name: &str) {
        unsafe {
            luac::lua_pushnil(self.ptr);
            let name = CString::new(name).unwrap();
            luac::lua_setglobal(self.ptr, name.as_ptr());
        }
    }

    pub fn run(&mut self, code: &str) -> Result<(), ()> {
        let nargs = 0;
        let nresults = 0;

        let cstr = CString::new(code).unwrap();
        let code = unsafe { luac::luaL_loadstring(self.ptr, cstr.as_ptr()) };
        if code != 0 {
            debug_assert!(self.current_stack_size() == 0);
            return Err(());
        }
        let code = unsafe { luac::lua_pcallk(self.ptr, nargs, nresults, 0, 0, None) };
        if code != 0 {
            debug_assert!(self.current_stack_size() == 0);
            return Err(());
        }
        debug_assert!(self.current_stack_size() == 0);
        return Ok(());
    }

    pub fn set_fn<F: FnMut() -> ()>(&mut self, name: &str, f: F) {
        use std::mem::size_of;

        unsafe extern "C" fn callback<F: FnMut() -> ()>(ptr: LuaPtr) -> i32 {
            let f = luac::lua_touserdata(ptr, luac::lua_upvalueindex(1)) as *mut F;
            (*f)();
            return 0;
        }

        unsafe {
            // create user data
            let size = size_of::<F>();
            let loc = luac::lua_newuserdata(self.ptr, size) as *mut F;
            debug_assert!(self.current_stack_size() == 1);
            *loc = f;
            // set metatable
            self.push_metatable_for_gc::<F>();
            luac::lua_setmetatable(self.ptr, -2);
            debug_assert!(self.current_stack_size() == 1);
            // set global
            luac::lua_pushcclosure(self.ptr, Some(callback::<F>), 1);
            let name = CString::new(name).unwrap();
            luac::lua_setglobal(self.ptr, name.as_ptr());
        }
    }

    pub fn current_stack_size(&self) -> i32 {
        unsafe { luac::lua_gettop(self.ptr) }
    }

    fn pop_stack(&self, n: i32) {
        unsafe { luac::lua_settop(self.ptr, -1 - n) }
    }

    fn push_metatable_for_gc<T>(&mut self) {
        use std::ptr::drop_in_place;

        unsafe extern "C" fn call_drop<T>(ptr: LuaPtr) -> i32 {
            let item = luac::lua_touserdata(ptr, luac::lua_upvalueindex(1)) as *mut T;
            drop_in_place(item);
            return 0;
        }

        unsafe {
            let meta_table_name = format!("meta-{:p}", &call_drop::<T>);
            let meta_table_name = CString::new(meta_table_name).unwrap();
            luac::luaL_newmetatable(self.ptr, meta_table_name.as_ptr());
            debug_assert!(self.current_stack_size() == 2);
            "__gc".write_to_stack(self);
            luac::lua_pushcclosure(self.ptr, Some(call_drop::<T>), 0);
            debug_assert!(self.current_stack_size() == 4);
            luac::lua_rawset(self.ptr, -3);
            debug_assert!(self.current_stack_size() == 2);
        }
    }
}

impl Drop for Lua {
    fn drop(&mut self) {
        unsafe {
            luac::lua_close(self.ptr);
        }
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cell::Cell;
use std::sync::Arc;

/// Naive implementation of a `Counter`.
#[derive(Debug)]
pub struct StdCounter {
    /// The counter value.
    pub value: Cell<usize>,
}

/// A snapshot of the current value of a `Counter`.
#[derive(Debug)]
pub struct CounterSnapshot {
    /// The snapshot of the counter value.
    pub value: usize,
}

/// `Counter` is a `Metric` that represents a single numerical value that can
/// increases over time.
pub trait Counter {
    /// Clear the counter, setting the value to `0`.
    fn clear(&self);
    /// Increment the counter by 1.
    fn inc(&self);
    /// Increment the counter by the given amount. MUST check that v >= 0.
    fn add(&self, value: usize);
    /// Take a snapshot of the current value for use with a `Reporter`.
    fn snapshot(&self) -> CounterSnapshot;
}

impl Counter for StdCounter {
    fn clear(&self) {
        self.value.set(0);
    }

    fn inc(&self) {
        self.value.set(self.value.get() + 1);
    }

    fn add(&self, value: usize) {
        self.value.set(self.value.get() + value);
    }

    fn snapshot(&self) -> CounterSnapshot {
        CounterSnapshot { value: self.value.get() }
    }
}

impl StdCounter {
    /// Create a new `StdCounter`.
    pub fn new() -> Arc<Self> {
        Arc::new(StdCounter { value: Cell::new(0) })
    }
}

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

    #[test]
    fn a_counting_counter() {
        let c = StdCounter::new();
        c.add(1);

        assert_eq!(c.value.get(), 1);

        let c = StdCounter::new();
        c.inc();

        assert_eq!(c.value.get(), 1);
    }

    #[test]
    fn validate_snapshots() {
        let c = StdCounter::new();
        let snapshot_1 = c.snapshot();
        c.add(1);
        let snapshot_2 = c.snapshot();
        assert_eq!(c.value.get(), 1);
        assert_eq!(snapshot_1.value, 0);
        assert_eq!(snapshot_2.value, 1);
    }
}
<commit_msg>Counter: Use AtomicUsize, not Cell.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;

/// Naive implementation of a `Counter`.
#[derive(Debug)]
pub struct StdCounter {
    /// The counter value.
    pub value: AtomicUsize,
}

/// A snapshot of the current value of a `Counter`.
#[derive(Debug)]
pub struct CounterSnapshot {
    /// The snapshot of the counter value.
    pub value: usize,
}

/// `Counter` is a `Metric` that represents a single numerical value that can
/// increases over time.
pub trait Counter {
    /// Clear the counter, setting the value to `0`.
    fn clear(&self);
    /// Increment the counter by 1.
    fn inc(&self);
    /// Increment the counter by the given amount. MUST check that v >= 0.
    fn add(&self, value: usize);
    /// Take a snapshot of the current value for use with a `Reporter`.
    fn snapshot(&self) -> CounterSnapshot;
}

impl Counter for StdCounter {
    fn clear(&self) {
        self.value.store(0, Ordering::Relaxed);
    }

    fn inc(&self) {
        self.value.fetch_add(1, Ordering::Relaxed);
    }

    fn add(&self, value: usize) {
        self.value.fetch_add(value, Ordering::Relaxed);
    }

    fn snapshot(&self) -> CounterSnapshot {
        CounterSnapshot { value: self.value.load(Ordering::Relaxed) }
    }
}

impl StdCounter {
    /// Create a new `StdCounter`.
    pub fn new() -> Arc<Self> {
        Arc::new(StdCounter { value: AtomicUsize::new(0) })
    }
}

#[cfg(test)]
mod test {
    use std::sync::atomic::Ordering;
    use super::*;

    #[test]
    fn a_counting_counter() {
        let c = StdCounter::new();
        c.add(1);

        assert_eq!(c.value.load(Ordering::Relaxed), 1);

        let c = StdCounter::new();
        c.inc();

        assert_eq!(c.value.load(Ordering::Relaxed), 1);
    }

    #[test]
    fn validate_snapshots() {
        let c = StdCounter::new();
        let snapshot_1 = c.snapshot();
        c.add(1);
        let snapshot_2 = c.snapshot();
        assert_eq!(c.value.load(Ordering::Relaxed), 1);
        assert_eq!(snapshot_1.value, 0);
        assert_eq!(snapshot_2.value, 1);
    }
}
<|endoftext|>


<commit_before>use {Int, LargeInt};

macro_rules! mul {
    ($intrinsic:ident: $ty:ty) => {
        /// Returns `a * b`
        #[cfg_attr(not(test), no_mangle)]
        pub extern fn $intrinsic(a: $ty, b: $ty) -> $ty {
            let half_bits = <$ty>::bits() / 4;
            let lower_mask = !0 >> half_bits;
            let mut low = (a.low() & lower_mask) * (b.low() & lower_mask);
            let mut t = low >> half_bits;
            low &= lower_mask;
            t += (a.low() >> half_bits) * (b.low() & lower_mask);
            low += (t & lower_mask) << half_bits;
            let mut high = t >> half_bits;
            t = low >> half_bits;
            low &= lower_mask;
            t += (b.low() >> half_bits) * (a.low() & lower_mask);
            low += (t & lower_mask) << half_bits;
            high += t >> half_bits;
            high += (a.low() >> half_bits) * (b.low() >> half_bits);
            high = high.wrapping_add(a.high().wrapping_mul(b.low()).wrapping_add(a.low().wrapping_mul(b.high())));
            <$ty>::from_parts(low, high)
        }
    }
}

macro_rules! mulo {
    ($intrinsic:ident: $ty:ty) => {
        /// Returns `a * b` and sets `*overflow = 1` if `a * b` overflows
        #[cfg_attr(not(test), no_mangle)]
        pub extern fn $intrinsic(a: $ty, b: $ty, overflow: &mut i32) -> $ty {
            *overflow = 0;
            let result = a.wrapping_mul(b);
            if a == <$ty>::min_value() {
                if b != 0 && b != 1 {
                    *overflow = 1;
                }
                return result;
            }
            if b == <$ty>::min_value() {
                if a != 0 && a != 1 {
                    *overflow = 1;
                }
                return result;
            }

            let sa = a >> (<$ty>::bits() - 1);
            let abs_a = (a ^ sa) - sa;
            let sb = b >> (<$ty>::bits() - 1);
            let abs_b = (b ^ sb) - sb;
            if abs_a < 2 || abs_b < 2 {
                return result;
            }
            if sa == sb {
                if abs_a > <$ty>::max_value() / abs_b {
                    *overflow = 1;
                }
            } else {
                if abs_a > <$ty>::min_value() / -abs_b {
                    *overflow = 1;
                }
            }
            result
        }
    }
}

mul!(__muldi4: u64);
mulo!(__mulosi4: i32);
mulo!(__mulodi4: i64);

#[cfg(test)]
mod tests {
    use qc::{I32, I64, U64};

    quickcheck! {
        fn muldi(a: U64, b: U64) -> bool {
            let (a, b) = (a.0, b.0);
            let r = super::__muldi4(a, b);
            r == a.wrapping_mul(b)
        }

        fn mulosi(a: I32, b: I32) -> bool {
            let (a, b) = (a.0, b.0);
            let mut overflow = 2;
            let r = super::__mulosi4(a, b, &mut overflow);
            if overflow != 0 && overflow != 1 {
                return false;
            }
            (r, overflow != 0) == a.overflowing_mul(b)
        }

        fn mulodi(a: I64, b: I64) -> bool {
            let (a, b) = (a.0, b.0);
            let mut overflow = 2;
            let r = super::__mulodi4(a, b, &mut overflow);
            if overflow != 0 && overflow != 1 {
                return false;
            }
            (r, overflow != 0) == a.overflowing_mul(b)
        }
    }
}
<commit_msg>rename muldi4 to muldi3<commit_after>use {Int, LargeInt};

macro_rules! mul {
    ($intrinsic:ident: $ty:ty) => {
        /// Returns `a * b`
        #[cfg_attr(not(test), no_mangle)]
        pub extern fn $intrinsic(a: $ty, b: $ty) -> $ty {
            let half_bits = <$ty>::bits() / 4;
            let lower_mask = !0 >> half_bits;
            let mut low = (a.low() & lower_mask) * (b.low() & lower_mask);
            let mut t = low >> half_bits;
            low &= lower_mask;
            t += (a.low() >> half_bits) * (b.low() & lower_mask);
            low += (t & lower_mask) << half_bits;
            let mut high = t >> half_bits;
            t = low >> half_bits;
            low &= lower_mask;
            t += (b.low() >> half_bits) * (a.low() & lower_mask);
            low += (t & lower_mask) << half_bits;
            high += t >> half_bits;
            high += (a.low() >> half_bits) * (b.low() >> half_bits);
            high = high.wrapping_add(a.high().wrapping_mul(b.low()).wrapping_add(a.low().wrapping_mul(b.high())));
            <$ty>::from_parts(low, high)
        }
    }
}

macro_rules! mulo {
    ($intrinsic:ident: $ty:ty) => {
        /// Returns `a * b` and sets `*overflow = 1` if `a * b` overflows
        #[cfg_attr(not(test), no_mangle)]
        pub extern fn $intrinsic(a: $ty, b: $ty, overflow: &mut i32) -> $ty {
            *overflow = 0;
            let result = a.wrapping_mul(b);
            if a == <$ty>::min_value() {
                if b != 0 && b != 1 {
                    *overflow = 1;
                }
                return result;
            }
            if b == <$ty>::min_value() {
                if a != 0 && a != 1 {
                    *overflow = 1;
                }
                return result;
            }

            let sa = a >> (<$ty>::bits() - 1);
            let abs_a = (a ^ sa) - sa;
            let sb = b >> (<$ty>::bits() - 1);
            let abs_b = (b ^ sb) - sb;
            if abs_a < 2 || abs_b < 2 {
                return result;
            }
            if sa == sb {
                if abs_a > <$ty>::max_value() / abs_b {
                    *overflow = 1;
                }
            } else {
                if abs_a > <$ty>::min_value() / -abs_b {
                    *overflow = 1;
                }
            }
            result
        }
    }
}

mul!(__muldi3: u64);
mulo!(__mulosi4: i32);
mulo!(__mulodi4: i64);

#[cfg(test)]
mod tests {
    use qc::{I32, I64, U64};

    quickcheck! {
        fn muldi(a: U64, b: U64) -> bool {
            let (a, b) = (a.0, b.0);
            let r = super::__muldi3(a, b);
            r == a.wrapping_mul(b)
        }

        fn mulosi(a: I32, b: I32) -> bool {
            let (a, b) = (a.0, b.0);
            let mut overflow = 2;
            let r = super::__mulosi4(a, b, &mut overflow);
            if overflow != 0 && overflow != 1 {
                return false;
            }
            (r, overflow != 0) == a.overflowing_mul(b)
        }

        fn mulodi(a: I64, b: I64) -> bool {
            let (a, b) = (a.0, b.0);
            let mut overflow = 2;
            let r = super::__mulodi4(a, b, &mut overflow);
            if overflow != 0 && overflow != 1 {
                return false;
            }
            (r, overflow != 0) == a.overflowing_mul(b)
        }
    }
}
<|endoftext|>


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

fn build_rules(path: &str) -> HashMap<&str, &str> {
	let mut map_rules = HashMap::new();

	map_rules.insert("DIGIT", "[0-9]");
	map_rules.insert("ALPHABET", "[a-z]");

	map_rules
}

// s  : String
// *s : str (via Deref<Target=str>)
// &*s: &st
fn expand_definitions(s: &str, map: HashMap<&str, &str>) -> String {
	let re = Regex::new(r"(\{[:alpha:]{1,}\})").unwrap();
	let mut text = String::from(s);

	for cap in re.captures_iter(s) {
		let tmp = cap.at(1).unwrap_or("");
		let key = &tmp[1..tmp.len()-1];

		text = text.replace(tmp, map[key]);
	}
	text
}

#[test]
fn test_expand_def(){
	let rules: HashMap<&str, &str> = build_rules("");
	let formatted = expand_definitions("{DIGIT}+ not is {ALPHABET}.*", rules);

    assert_eq!(formatted, "[0-9]+ not is [a-z].*");
}<commit_msg>Input parsing | Changed HashMap &str -> String<commit_after>use regex::Regex;
use std::collections::HashMap;

fn build_rules(path: &str) -> HashMap<String, String> {
	let mut map_rules = HashMap::new();

	//ASCII character classes
	map_rules.insert("alnum".to_string(), "[0-9A-Za-z]".to_string());
	map_rules.insert("alpha".to_string(), "[A-Za-z]".to_string());
	map_rules.insert("ascii".to_string(), "[\\x00-\\x7F]".to_string());
	map_rules.insert("blank".to_string(), "[\\t ]".to_string());
	map_rules.insert("cntrl".to_string(), "[\\x00-\\x1F\\x7F]".to_string());
	map_rules.insert("digit".to_string(), "[0-9]".to_string());
	map_rules.insert("graph".to_string(), "[!-~]".to_string());
	map_rules.insert("lower".to_string(), "[a-z]".to_string());
	map_rules.insert("print".to_string(), "[ -~]".to_string());
	map_rules.insert("punct".to_string(), "[!-/:-@[-`{-~]".to_string());
	map_rules.insert("space".to_string(), "[\\t\\n\\v\\f\\r ]".to_string());
	map_rules.insert("upper".to_string(), "[A-Z]".to_string());
	map_rules.insert("word".to_string(), "[0-9A-Za-z_]".to_string());
	map_rules.insert("xdigit".to_string(), "[0-9A-Fa-f]".to_string());

	map_rules
}

// s  : String
// *s : str (via Deref<Target=str>)
// &*s: &st
fn expand_definitions(s: &str, map: HashMap<String, String>) -> String {
	let re = Regex::new(r"(\{[:alpha:]{1,}\})").unwrap();
	let mut text = String::from(s);

	for cap in re.captures_iter(s) {
		let tmp = cap.at(1).unwrap_or("");
		let key = &tmp[1..tmp.len()-1];

		text = text.replace(tmp, &map[key]);
	}
	text
}

#[test]
fn test_expand_def(){
	let rules: HashMap<String, String> = build_rules("path");

	let formatted1 = expand_definitions("{digit}+ and {lower}.*", rules.clone());
	let formatted2 = expand_definitions("{word}.* or {alnum}", rules.clone());
	let formatted3 = expand_definitions("{ascii} and {blank}.*", rules.clone());

	assert_eq!(formatted1, "[0-9]+ and [a-z].*");
	assert_eq!(formatted2, "[0-9A-Za-z_].* or [0-9A-Za-z]");
    assert_eq!(formatted3, "[\\x00-\\x7F] and [\\t ].*");
}<|endoftext|>


<commit_before>use std::str;
use std::io::prelude::*;
use std::fs::File;
use std::str::from_utf8;

use nom::*;

use error::*;

named!(string_between_quotes, delimited!(char!('\"'), is_not!("\""), char!('\"')));
named!(get_cell, take_while!(is_not_cell_end));
named!(consume_useless_chars, take_while!(is_whitespace));

fn is_whitespace(c: u8) -> bool {
    c as char == ' ' || c as char == '\t'
}

fn is_not_cell_end(c: u8) -> bool {
    c as char != ',' && c as char != '\n'
}

fn get_column_value(input: &[u8], pos: Position) -> IResult<&[u8], &[u8], CsvError> {
    let (i, cell) = try_parse!(input,
        fix_error!(CsvError,
            preceded!(
            opt!(consume_useless_chars),
                alt!(
                    string_between_quotes
                  | get_cell
                )
            )
        )
    );

    if i.len() == 0 {
        IResult::Incomplete(Needed::Unknown)
    } else if is_not_cell_end(i[0]) {
        let p = Position { line: pos.line, column: pos.column + input.offset(i) };
        IResult::Error(Err::Code(ErrorKind::Custom(
            CsvError::InvalidCharacter(CharError::new(',', i[0] as char, &p))
        )))
    } else {
        IResult::Done(i, cell)
    }
}

fn get_string_column_value(input: &[u8], pos: Position) -> IResult<&[u8], String, CsvError> {
    map_res!(input,
        map_res!(
            dbg_dmp!(
                apply!(get_column_value, Position::new(pos.line, pos.column))
            ),
            from_utf8
        ),
        |d| {
            str::FromStr::from_str(d)
        }
    )
}

fn comma_then_column(input: &[u8], pos: Position) -> IResult<&[u8], String, CsvError> {
    preceded!(input,
        fix_error!(CsvError, char!(',')),
        apply!(get_string_column_value, Position::new(pos.line, pos.column))
    )
}

fn get_line_values<'a>(entry: &'a[u8],ret: &mut Vec<String>, line: usize) -> IResult<&'a[u8], &'a[u8], CsvError> {
    if entry.len() == 0 {
        IResult::Done(b"", b"")
    } else {
        let (i, col) = try_parse!(entry, apply!(get_string_column_value, Position::new(line, ret.len())));
        ret.push(col);

        match fix_error!(i, CsvError, terminated!(
            many0!(
                apply!(comma_then_column, Position::new(line, ret.len()))
            ),
            char!('\n')
        )) {
            IResult::Done(i, v)    => {
                ret.extend(v);
                IResult::Done(i, &entry[..entry.offset(i)])
            },
            IResult::Incomplete(i) => IResult::Incomplete(i),
            IResult::Error(e)      => IResult::Error(e)
        }
    }
}

fn get_lines_values(mut ret: Vec<Vec<String>>, entry: &[u8]) -> Result<Vec<Vec<String>>, CsvError> {
    let mut input = entry;
    let mut line  = 0;
    loop {
        let mut v: Vec<String> = Vec::new();
        match get_line_values(input, &mut v, line) {
            IResult::Error(Err::Code(ErrorKind::Custom(e))) => return Err(e),
            IResult::Error(_)                               => return Err(CsvError::GenericError),
            IResult::Incomplete(_)                          => {
                // did we reach the end of file?
                break
            }
            IResult::Done(i,_)                              => {
                input = i;
                line += 1;
                ret.push(v);
                if input.len() == 0 {
                    break;
                }
            },
        }
    }

    Ok(ret)
}

pub fn parse_csv_from_slice(entry: &[u8]) -> Result<Vec<Vec<String>>, CsvError> {
    get_lines_values(vec!(), entry)
}

pub fn parse_csv_from_file(filename: &str) -> Result<Vec<Vec<String>>, CsvError> {
    let mut f = File::open(filename).unwrap();
    let mut buffer = vec!();

    f.read_to_end(&mut buffer).unwrap();
    parse_csv_from_slice(&buffer)
}

pub fn parse_csv(entry: &str) -> Result<Vec<Vec<String>>, CsvError> {
    parse_csv_from_slice(entry.as_bytes())
}

#[test]
fn check_string_between_quotes() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";

    match string_between_quotes(f) {
        IResult::Done(in_, out) => {
            assert_eq!(out, b"nom");
            assert_eq!(in_, b",age\ncarles,30\nlaure,28\n");
        },
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
}

#[test]
fn check_get_cell() {
    let f = b"age\ncarles,30\n";
    let g = b"age2,carles,30\n";

    match get_cell(f) {
        IResult::Done(_, out) => assert_eq!(out, b"age"),
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
    match get_cell(g) {
        IResult::Done(_, out) => assert_eq!(out, b"age2"),
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
}

#[test]
fn check_get_line_values() {
    // no terminator, this is not a line
    //let mut cells = vec!();
    //get_line_values(&mut cells, b"\"nom\",,age", 0);
    //assert_eq!(cells, vec!("nom".to_owned(), "".to_owned(), "age".to_owned()));

    let mut cells = vec!();
    let res = get_line_values(b"\"nom\",,age\n", &mut cells, 0);
    println!("res: {:?}", res);
    assert_eq!(cells, vec!("nom".to_owned(), "".to_owned(), "age".to_owned()));

    let mut cells = vec!();
    get_line_values(b"\"nom\",age,\n", &mut cells, 0);
    assert_eq!(cells, vec!("nom".to_owned(), "age".to_owned(), "".to_owned()));

    let mut cells = vec!();
    get_line_values(b"\"nom\",age,,\"hoho\",,end\n", &mut cells, 0);
    assert_eq!(cells, vec!("nom".to_owned(), "age".to_owned(), "".to_owned(), "hoho".to_owned(), "".to_owned(), "end".to_owned()));

    let mut cells = vec!();
    let e = get_line_values(b"\"nom\" ,age,\"hoho\"", &mut cells, 0);
    assert_eq!(e,
        IResult::Error(Err::Code(ErrorKind::Custom(
            CsvError::InvalidCharacter(CharError::new(',', ' ', &Position::new(0, 5)))
        )))
    );
}

#[test]
fn check_get_lines_values() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";

    assert_eq!(get_lines_values(vec!(), f),
               Ok(vec!(
                       vec!("nom".to_owned(), "age".to_owned()),
                       vec!("carles".to_owned(), "30".to_owned()),
                       vec!("laure".to_owned(), "28".to_owned()))));
}

#[test]
fn check_parse_csv() {
    let f = "\"nom\",age\ncarles,30\nlaure,28\n";

    assert_eq!(parse_csv(f),
               Ok(vec!(
                       vec!("nom".to_owned(), "age".to_owned()),
                       vec!("carles".to_owned(), "30".to_owned()),
                       vec!("laure".to_owned(), "28".to_owned()))));
}
<commit_msg>Work in progress<commit_after>use std::str;
use std::io::prelude::*;
use std::fs::File;
use std::str::from_utf8;

use nom::*;

use error::*;

named!(string_between_quotes, delimited!(char!('\"'), is_not!("\""), char!('\"')));
named!(get_cell, take_while!(is_not_cell_end));
named!(consume_useless_chars, take_while!(is_whitespace));

fn is_whitespace(c: u8) -> bool {
    c as char == ' ' || c as char == '\t'
}

fn is_not_cell_end(c: u8) -> bool {
    c as char != ',' && c as char != '\n'
}

fn get_column_value(input: &[u8], pos: Position) -> IResult<&[u8], &[u8], CsvError> {
    let (i, cell) = try_parse!(input,
        fix_error!(CsvError,
            preceded!(
            opt!(consume_useless_chars),
                alt!(
                    string_between_quotes
                  | get_cell
                )
            )
        )
    );

    if i.len() == 0 {
        IResult::Incomplete(Needed::Unknown)
    } else if is_not_cell_end(i[0]) {
        let p = Position { line: pos.line, column: pos.column + input.offset(i) };
        IResult::Error(Err::Code(ErrorKind::Custom(
            CsvError::InvalidCharacter(CharError::new(',', i[0] as char, &p))
        )))
    } else {
        IResult::Done(i, cell)
    }
}

fn get_string_column_value(input: &[u8], pos: Position) -> IResult<&[u8], String, CsvError> {
    map_res!(input,
        map_res!(
            dbg_dmp!(
                apply!(get_column_value, Position::new(pos.line, pos.column))
            ),
            from_utf8
        ),
        |d| {
            str::FromStr::from_str(d)
        }
    )
}

fn comma_then_column(input: &[u8], pos: Position) -> IResult<&[u8], String, CsvError> {
    preceded!(input,
        fix_error!(CsvError, char!(',')),
        apply!(get_string_column_value, Position::new(pos.line, pos.column))
    )
}

fn get_line_values<'a>(entry: &'a[u8],ret: &mut Vec<String>, line: usize) -> IResult<&'a[u8], &'a[u8], CsvError> {
    if entry.len() == 0 {
        IResult::Done(b"", b"")
    } else {
        let (i, col) = try_parse!(entry, apply!(get_string_column_value, Position::new(line, ret.len())));
        ret.push(col);

        match fix_error!(i, CsvError, separated_list!(
            many0!(
                apply!(comma_then_column, Position::new(line, ret.len()))
            ),
            char!('\n')
        )) {
            IResult::Done(i, v)    => {
                let mut s = String::new();

                for c in v {
                    s.push(c);
                }
                ret.push(s);
                IResult::Done(i, &entry[..entry.offset(i)])
            },
            IResult::Incomplete(i) => IResult::Incomplete(i),
            IResult::Error(e)      => IResult::Error(e)
        }
    }
}

fn get_lines_values(mut ret: Vec<Vec<String>>, entry: &[u8]) -> Result<Vec<Vec<String>>, CsvError> {
    let mut input = entry;
    let mut line  = 0;
    loop {
        let mut v: Vec<String> = Vec::new();
        match get_line_values(input, &mut v, line) {
            IResult::Error(Err::Code(ErrorKind::Custom(e))) => return Err(e),
            IResult::Error(_)                               => return Err(CsvError::GenericError),
            IResult::Incomplete(_)                          => {
                // did we reach the end of file?
                break
            }
            IResult::Done(i,_)                              => {
                input = i;
                line += 1;
                ret.push(v);
                if input.len() == 0 {
                    break;
                }
            },
        }
    }

    Ok(ret)
}

pub fn parse_csv_from_slice(entry: &[u8]) -> Result<Vec<Vec<String>>, CsvError> {
    get_lines_values(vec!(), entry)
}

pub fn parse_csv_from_file(filename: &str) -> Result<Vec<Vec<String>>, CsvError> {
    let mut f = File::open(filename).unwrap();
    let mut buffer = vec!();

    f.read_to_end(&mut buffer).unwrap();
    parse_csv_from_slice(&buffer)
}

pub fn parse_csv(entry: &str) -> Result<Vec<Vec<String>>, CsvError> {
    parse_csv_from_slice(entry.as_bytes())
}

#[test]
fn check_string_between_quotes() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";

    match string_between_quotes(f) {
        IResult::Done(in_, out) => {
            assert_eq!(out, b"nom");
            assert_eq!(in_, b",age\ncarles,30\nlaure,28\n");
        },
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
}

#[test]
fn check_get_cell() {
    let f = b"age\ncarles,30\n";
    let g = b"age2,carles,30\n";

    match get_cell(f) {
        IResult::Done(_, out) => assert_eq!(out, b"age"),
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
    match get_cell(g) {
        IResult::Done(_, out) => assert_eq!(out, b"age2"),
        IResult::Incomplete(x) => panic!("incomplete: {:?}", x),
        IResult::Error(e) => panic!("error: {:?}", e),
    }
}

#[test]
fn check_get_line_values() {
    // no terminator, this is not a line
    //let mut cells = vec!();
    //get_line_values(&mut cells, b"\"nom\",,age", 0);
    //assert_eq!(cells, vec!("nom".to_owned(), "".to_owned(), "age".to_owned()));

    let mut cells = vec!();
    let res = get_line_values(b"\"nom\",,age\n", &mut cells, 0);
    println!("res: {:?}", res);
    assert_eq!(cells, vec!("nom".to_owned(), "".to_owned(), "age".to_owned()));

    let mut cells = vec!();
    get_line_values(b"\"nom\",age,\n", &mut cells, 0);
    assert_eq!(cells, vec!("nom".to_owned(), "age".to_owned(), "".to_owned()));

    let mut cells = vec!();
    get_line_values(b"\"nom\",age,,\"hoho\",,end\n", &mut cells, 0);
    assert_eq!(cells, vec!("nom".to_owned(), "age".to_owned(), "".to_owned(), "hoho".to_owned(), "".to_owned(), "end".to_owned()));

    let mut cells = vec!();
    let e = get_line_values(b"\"nom\" ,age,\"hoho\"", &mut cells, 0);
    assert_eq!(e,
        IResult::Error(Err::Code(ErrorKind::Custom(
            CsvError::InvalidCharacter(CharError::new(',', ' ', &Position::new(0, 5)))
        )))
    );
}

#[test]
fn check_get_lines_values() {
    let f = b"\"nom\",age\ncarles,30\nlaure,28\n";

    assert_eq!(get_lines_values(vec!(), f),
               Ok(vec!(
                       vec!("nom".to_owned(), "age".to_owned()),
                       vec!("carles".to_owned(), "30".to_owned()),
                       vec!("laure".to_owned(), "28".to_owned()))));
}

#[test]
fn check_parse_csv() {
    let f = "\"nom\",age\ncarles,30\nlaure,28\n";

    assert_eq!(parse_csv(f),
               Ok(vec!(
                       vec!("nom".to_owned(), "age".to_owned()),
                       vec!("carles".to_owned(), "30".to_owned()),
                       vec!("laure".to_owned(), "28".to_owned()))));
}
<|endoftext|>


<commit_before>use regex::Regex;

#[deriving(Show)]
pub enum Block<'s> {
    Header(Vec<Span<'s>>, uint),
    Break,
    Paragraph(Vec<Span<'s>>)
}

#[deriving(Show)]
pub enum Span<'s> {
    Text(&'s str),
    Emphasis(&'s str),
    Strong(&'s str),
    Code(&'s str),
    Link(&'s str, &'s str, &'s str),
    Image(&'s str, &'s str, &'s str)
}

// Block Patters
static SPLIT           : Regex = regex!(r"\n\n");
static ATX_HEADER      : Regex = regex!(r"(?P<level>#{1,6})\s(?P<text>.*)");
static SETEXT_HEADER_1 : Regex = regex!(r"(?P<text>.+)\n===+");
static SETEXT_HEADER_2 : Regex = regex!(r"(?P<text>.+)\n---+");
static BREAK           : Regex = regex!(r"  ");

// Span Patters
static SPANS : Regex = regex!(r"(!?\[.*\]\([^\(\)]*\))|(\*[^\*].+?\*)|(\*\*.+?\*\*)|(_[^_].+?_)|(__.+?__)|(`[^`].+?`)|(``.+?``)");
static LINK  : Regex = regex!(r"\[(?P<text>.*)\]\((?P<url>.*?)(?:\s(?P<title>.*?))?\)");
static EMPHASIS_UNDERSCORE  : Regex = regex!(r"^_(?P<text>[^_].+?)_");
static EMPHASIS_STAR  : Regex = regex!(r"^\*(?P<text>[^\*].+?)\*");

pub fn parse (md : &str) -> Vec<Block> {
    let mut split = SPLIT.split(md);
    let mut tokens = vec![];
    for block in split{
        match parse_block(block) {
            Some(e) => tokens.push(e),
            None => {},
        };
    }
    tokens
}

fn parse_spans(text : &str) -> Vec<Span>{
    let mut tokens = vec![];
    let mut current = 0;
    for (begin, end) in SPANS.find_iter(text) {
        tokens.push(Text(text.slice(current, begin)));
        tokens.push(parse_span(text.slice(begin, end)));
        current = end;
    }
    tokens.push(Text(text.slice(current, text.len())));
    tokens
}

#[test]
fn parse_link_test() {
    match parse_span("[an example](example.com \"Title\")"){
      Link("an example", "example.com", "Title") => {},
      _ => fail!()
    }
}

fn parse_span(text : &str) -> Span{
    if LINK.is_match(text){
        let caps = LINK.captures(text).unwrap();
        return Link(
            caps.name("text"),
            caps.name("url"),
            caps.name("title")
            );
    }else if EMPHASIS_UNDERSCORE.is_match(text){
        let caps = EMPHASIS_UNDERSCORE.captures(text).unwrap();
        return Emphasis(caps.name("text"));
    }else if EMPHASIS_STAR.is_match(text){
        let caps = EMPHASIS_STAR.captures(text).unwrap();
        return Emphasis(caps.name("text"));
    }
    return Text(text);
}

fn parse_block (text : &str) -> Option<Block>{
    if text.is_empty(){
        return None;
    }else if ATX_HEADER.is_match(text){
        let caps = ATX_HEADER.captures(text).unwrap();
        return Some(
            Header(
                parse_spans(caps.name("text")),
                caps.name("level").len()
                )
            );
    }else if SETEXT_HEADER_1.is_match(text){
        let caps = SETEXT_HEADER_1.captures(text).unwrap();
        return Some(
            Header(
                parse_spans(caps.name("text")),
                1
                )
            );
    }else if SETEXT_HEADER_2.is_match(text){
        let caps = SETEXT_HEADER_2.captures(text).unwrap();
        return Some(
            Header(
                parse_spans(caps.name("text")),
                2
                )
            );
    }else if BREAK.is_match(text){
        return Some(Break);
    }
    return Some(Paragraph(parse_spans(text)));
}

<commit_msg>fix quotes in link<commit_after>use regex::Regex;

#[deriving(Show)]
pub enum Block<'s> {
    Header(Vec<Span<'s>>, uint),
    Break,
    Paragraph(Vec<Span<'s>>)
}

#[deriving(Show)]
pub enum Span<'s> {
    Text(&'s str),
    Emphasis(&'s str),
    Strong(&'s str),
    Code(&'s str),
    Link(&'s str, &'s str, &'s str),
    Image(&'s str, &'s str, &'s str)
}

// Block Patters
static SPLIT           : Regex = regex!(r"\n\n");
static ATX_HEADER      : Regex = regex!(r"(?P<level>#{1,6})\s(?P<text>.*)");
static SETEXT_HEADER_1 : Regex = regex!(r"(?P<text>.+)\n===+");
static SETEXT_HEADER_2 : Regex = regex!(r"(?P<text>.+)\n---+");
static BREAK           : Regex = regex!(r"  ");

// Span Patters
static SPANS : Regex = regex!(r"(!?\[.*\]\([^\(\)]*\))|(\*[^\*].+?\*)|(\*\*.+?\*\*)|(_[^_].+?_)|(__.+?__)|(`[^`].+?`)|(``.+?``)");
static LINK  : Regex = regex!("\\[(?P<text>.*)\\]\\((?P<url>.*?)(?:\\s\"(?P<title>.*?)\")?\\)");
static EMPHASIS_UNDERSCORE  : Regex = regex!(r"^_(?P<text>[^_].+?)_");
static EMPHASIS_STAR  : Regex = regex!(r"^\*(?P<text>[^\*].+?)\*");

pub fn parse (md : &str) -> Vec<Block> {
    let mut split = SPLIT.split(md);
    let mut tokens = vec![];
    for block in split{
        match parse_block(block) {
            Some(e) => tokens.push(e),
            None => {},
        };
    }
    tokens
}

fn parse_spans(text : &str) -> Vec<Span>{
    let mut tokens = vec![];
    let mut current = 0;
    for (begin, end) in SPANS.find_iter(text) {
        tokens.push(Text(text.slice(current, begin)));
        tokens.push(parse_span(text.slice(begin, end)));
        current = end;
    }
    tokens.push(Text(text.slice(current, text.len())));
    tokens
}

#[test]
fn parse_link_test() {
    match parse_span("[an example](example.com \"Title\")"){
      Link("an example", "example.com", "Title") => {},
      _ => fail!()
    }
}

fn parse_span(text : &str) -> Span{
    if LINK.is_match(text){
        let caps = LINK.captures(text).unwrap();
        return Link(
            caps.name("text"),
            caps.name("url"),
            caps.name("title")
            );
    }else if EMPHASIS_UNDERSCORE.is_match(text){
        let caps = EMPHASIS_UNDERSCORE.captures(text).unwrap();
        return Emphasis(caps.name("text"));
    }else if EMPHASIS_STAR.is_match(text){
        let caps = EMPHASIS_STAR.captures(text).unwrap();
        return Emphasis(caps.name("text"));
    }
    return Text(text);
}

fn parse_block (text : &str) -> Option<Block>{
    if text.is_empty(){
        return None;
    }else if ATX_HEADER.is_match(text){
        let caps = ATX_HEADER.captures(text).unwrap();
        return Some(
            Header(
                parse_spans(caps.name("text")),
                caps.name("level").len()
                )
            );
    }else if SETEXT_HEADER_1.is_match(text){
        let caps = SETEXT_HEADER_1.captures(text).unwrap();
        return Some(
            Header(
                parse_spans(caps.name("text")),
                1
                )
            );
    }else if SETEXT_HEADER_2.is_match(text){
        let caps = SETEXT_HEADER_2.captures(text).unwrap();
        return Some(
            Header(
                parse_spans(caps.name("text")),
                2
                )
            );
    }else if BREAK.is_match(text){
        return Some(Break);
    }
    return Some(Paragraph(parse_spans(text)));
}

<|endoftext|>


<commit_before>use {DEFAULT_PALETTE, DotVoxData, Model, model, palette, Size, Voxel};
use nom::bytes::complete::{tag, take};
use nom::combinator::{flat_map, map_res};
use nom::multi::{count, many0};
use nom::number::complete::le_u32;
use nom::sequence::pair;
use nom::IResult;
use std::collections::HashMap;
use std::str;
use std::str::Utf8Error;

const MAGIC_NUMBER: &'static str = "VOX ";

#[derive(Debug, PartialEq)]
pub enum Chunk {
    Main(Vec<Chunk>),
    Size(Size),
    Voxels(Vec<Voxel>),
    Pack(Model),
    Palette(Vec<u32>),
    Material(Material),
    Unknown(String),
    Invalid(Vec<u8>),
}

/// A material used to render this model.
#[derive(Clone, Debug, PartialEq)]
pub struct Material {
    /// The Material's ID
    pub id: u32,
    /// Properties of the material, mapped by property name.
    pub properties: Dict,
}

/// General dictionary
pub type Dict = HashMap<String, String>;

pub fn to_str(i: &[u8]) -> Result<String, Utf8Error> {
    let res = str::from_utf8(i)?;
    Ok(res.to_owned())
}

pub fn parse_vox_file(i: &[u8]) -> IResult<&[u8], DotVoxData> {
    let (i, _) = tag(MAGIC_NUMBER)(i)?;
    let (i, version) = le_u32(i)?;
    let (i, main) = parse_chunk(i)?;
    Ok((i, map_chunk_to_data(version, main)))
}

fn map_chunk_to_data(version: u32, main: Chunk) -> DotVoxData {
    match main {
        Chunk::Main(children) => {
            let mut size_holder: Option<Size> = None;
            let mut models: Vec<Model> = vec![];
            let mut palette_holder: Vec<u32> = DEFAULT_PALETTE.to_vec();
            let mut materials: Vec<Material> = vec![];
            for chunk in children {
                match chunk {
                    Chunk::Size(size) => size_holder = Some(size),
                    Chunk::Voxels(voxels) => {
                        if let Some(size) = size_holder {
                            models.push(Model { size, voxels })
                        }
                    }
                    Chunk::Pack(model) => models.push(model),
                    Chunk::Palette(palette) => palette_holder = palette,
                    Chunk::Material(material) => materials.push(material),
                    _ => debug!("Unmapped chunk {:?}", chunk)
                }
            }

            DotVoxData {
                version,
                models,
                palette: palette_holder,
                materials,
            }
        }
        _ => DotVoxData {
            version,
            models: vec![],
            palette: vec![],
            materials: vec![],
        }
    }
}

fn parse_chunk(i: &[u8]) -> IResult<&[u8], Chunk> {
    let (i, id) = map_res(take(4usize), str::from_utf8)(i)?;
    let (i, (content_size, children_size)) = pair(le_u32, le_u32)(i)?;
    let (i, chunk_content) = take(content_size)(i)?;
    let (i, child_content) = take(children_size)(i)?;
    let chunk = build_chunk(id, chunk_content, children_size, child_content);
    Ok((i, chunk))
}

fn build_chunk(id: &str,
               chunk_content: &[u8],
               children_size: u32,
               child_content: &[u8]) -> Chunk {
    if children_size == 0 {
        match id {
            "SIZE" => build_size_chunk(chunk_content),
            "XYZI" => build_voxel_chunk(chunk_content),
            "PACK" => build_pack_chunk(chunk_content),
            "RGBA" => build_palette_chunk(chunk_content),
            "MATL" => build_material_chunk(chunk_content),
            _ => {
                debug!("Unknown childless chunk {:?}", id);
                Chunk::Unknown(id.to_owned())
            }
        }
    } else {
        let result: IResult<&[u8], Vec<Chunk>> = many0(parse_chunk)(child_content);
        let child_chunks = match result {
            Ok((_, result)) => result,
            result => {
                debug!("Failed to parse child chunks, due to {:?}", result);
                vec![]
            }
        };
        match id {
            "MAIN" => Chunk::Main(child_chunks),
            "PACK" => build_pack_chunk(chunk_content),
            _ => {
                debug!("Unknown chunk with children {:?}", id);
                Chunk::Unknown(id.to_owned())
            }
        }
    }
}

fn build_material_chunk(chunk_content: &[u8]) -> Chunk {
    if let Ok((_, material)) = parse_material(chunk_content) {
        return Chunk::Material(material);
    }
    Chunk::Invalid(chunk_content.to_vec())
}

fn build_palette_chunk(chunk_content: &[u8]) -> Chunk {
    if let Ok((_, palette)) = palette::extract_palette(chunk_content) {
        return Chunk::Palette(palette);
    }
    Chunk::Invalid(chunk_content.to_vec())
}

fn build_pack_chunk(chunk_content: &[u8]) -> Chunk {
    if let Ok((chunk_content, Chunk::Size(size))) = parse_chunk(chunk_content) {
        if let Ok((_, Chunk::Voxels(voxels))) = parse_chunk(chunk_content) {
            return Chunk::Pack(Model { size, voxels: voxels.to_vec() });
        }
    }
    Chunk::Invalid(chunk_content.to_vec())
}

fn build_size_chunk(chunk_content: &[u8]) -> Chunk {
    match model::parse_size(chunk_content) {
        Ok((_, size)) => Chunk::Size(size),
        _ => Chunk::Invalid(chunk_content.to_vec())
    }
}

fn build_voxel_chunk(chunk_content: &[u8]) -> Chunk {
    match model::parse_voxels(chunk_content) {
        Ok((_, voxels)) => Chunk::Voxels(voxels),
        _ => Chunk::Invalid(chunk_content.to_vec())
    }
}

pub fn parse_material(i: &[u8]) -> IResult<&[u8], Material> {
    let (i, (id, properties)) = pair(le_u32, parse_dict)(i)?;
    Ok((i, Material { id, properties }))
}

fn parse_dict(i: &[u8]) -> IResult<&[u8], Dict> {
    let (i, n) = le_u32(i)?;
    let (i, entries) = count(parse_dict_entry, n as usize)(i)?;
    Ok((i, build_dict_from_entries(entries)))
}

fn parse_dict_entry(i: &[u8]) -> IResult<&[u8], (String, String)> {
    pair(parse_string, parse_string)(i)
}

fn parse_string(i: &[u8]) -> IResult<&[u8], String> {
    let bytes = flat_map(le_u32, take);
    map_res(bytes, to_str)(i)
}

fn build_dict_from_entries(entries: Vec<(String, String)>) -> Dict {
    let mut map = HashMap::with_capacity(entries.len());
    for (key, value) in entries {
        map.insert(key, value);
    }
    map
}

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

    #[test]
    fn can_parse_size_chunk() {
        let bytes = include_bytes!("resources/valid_size.bytes").to_vec();
        let result = parse_chunk(&bytes);
        assert!(result.is_ok());
        let (_, size) = result.unwrap();
        assert_eq!(
            size,
            Chunk::Size(Size {
                x: 24,
                y: 24,
                z: 24,
            })
        );
    }

    #[test]
    fn can_parse_voxels_chunk() {
        let bytes = include_bytes!("resources/valid_voxels.bytes").to_vec();
        let result = parse_chunk(&bytes);
        assert!(result.is_ok());
        let (_, voxels) = result.unwrap();
        match voxels {
            Chunk::Voxels(voxels) => vec::are_eq(
                voxels,
                vec![Voxel { x: 0, y: 0, z: 0, i: 225 },
                     Voxel { x: 0, y: 1, z: 1, i: 215 },
                     Voxel { x: 1, y: 0, z: 1, i: 235 },
                     Voxel { x: 1, y: 1, z: 0, i: 5 },
                ],
            ),
            chunk => panic!("Expecting Voxel chunk, got {:?}", chunk)
        };
    }

    #[test]
    fn can_parse_palette_chunk() {
        let bytes = include_bytes!("resources/valid_palette.bytes").to_vec();
        let result = parse_chunk(&bytes);
        assert!(result.is_ok());
        let (_, palette) = result.unwrap();
        match palette {
            Chunk::Palette(palette) => vec::are_eq(palette, DEFAULT_PALETTE.to_vec()),
            chunk => panic!("Expecting Palette chunk, got {:?}", chunk)
        };
    }

    #[test]
    fn can_parse_a_material_chunk() {
        let bytes = include_bytes!("resources/valid_material.bytes").to_vec();
        let result = parse_material(&bytes);
        match result {
            Ok((_, material)) => {
                assert_eq!(material.id, 0);
                assert_eq!(material.properties.get("_type"), Some(&"_diffuse".to_owned()));
                assert_eq!(material.properties.get("_weight"), Some(&"1".to_owned()));
                assert_eq!(material.properties.get("_rough"), Some(&"0.1".to_owned()));
                assert_eq!(material.properties.get("_spec"), Some(&"0.5".to_owned()));
                assert_eq!(material.properties.get("_ior"), Some(&"0.3".to_owned()));
            }
            _ => panic!("Expected Done, got {:?}", result)
        }
    }
}
<commit_msg>Reduce allocation for material's dict parsing<commit_after>use {DEFAULT_PALETTE, DotVoxData, Model, model, palette, Size, Voxel};
use nom::bytes::complete::{tag, take};
use nom::combinator::{flat_map, map_res};
use nom::multi::{fold_many_m_n, many0};
use nom::number::complete::le_u32;
use nom::sequence::pair;
use nom::IResult;
use std::collections::HashMap;
use std::str;
use std::str::Utf8Error;

const MAGIC_NUMBER: &'static str = "VOX ";

#[derive(Debug, PartialEq)]
pub enum Chunk {
    Main(Vec<Chunk>),
    Size(Size),
    Voxels(Vec<Voxel>),
    Pack(Model),
    Palette(Vec<u32>),
    Material(Material),
    Unknown(String),
    Invalid(Vec<u8>),
}

/// A material used to render this model.
#[derive(Clone, Debug, PartialEq)]
pub struct Material {
    /// The Material's ID
    pub id: u32,
    /// Properties of the material, mapped by property name.
    pub properties: Dict,
}

/// General dictionary
pub type Dict = HashMap<String, String>;

pub fn to_str(i: &[u8]) -> Result<String, Utf8Error> {
    let res = str::from_utf8(i)?;
    Ok(res.to_owned())
}

pub fn parse_vox_file(i: &[u8]) -> IResult<&[u8], DotVoxData> {
    let (i, _) = tag(MAGIC_NUMBER)(i)?;
    let (i, version) = le_u32(i)?;
    let (i, main) = parse_chunk(i)?;
    Ok((i, map_chunk_to_data(version, main)))
}

fn map_chunk_to_data(version: u32, main: Chunk) -> DotVoxData {
    match main {
        Chunk::Main(children) => {
            let mut size_holder: Option<Size> = None;
            let mut models: Vec<Model> = vec![];
            let mut palette_holder: Vec<u32> = DEFAULT_PALETTE.to_vec();
            let mut materials: Vec<Material> = vec![];
            for chunk in children {
                match chunk {
                    Chunk::Size(size) => size_holder = Some(size),
                    Chunk::Voxels(voxels) => {
                        if let Some(size) = size_holder {
                            models.push(Model { size, voxels })
                        }
                    }
                    Chunk::Pack(model) => models.push(model),
                    Chunk::Palette(palette) => palette_holder = palette,
                    Chunk::Material(material) => materials.push(material),
                    _ => debug!("Unmapped chunk {:?}", chunk)
                }
            }

            DotVoxData {
                version,
                models,
                palette: palette_holder,
                materials,
            }
        }
        _ => DotVoxData {
            version,
            models: vec![],
            palette: vec![],
            materials: vec![],
        }
    }
}

fn parse_chunk(i: &[u8]) -> IResult<&[u8], Chunk> {
    let (i, id) = map_res(take(4usize), str::from_utf8)(i)?;
    let (i, (content_size, children_size)) = pair(le_u32, le_u32)(i)?;
    let (i, chunk_content) = take(content_size)(i)?;
    let (i, child_content) = take(children_size)(i)?;
    let chunk = build_chunk(id, chunk_content, children_size, child_content);
    Ok((i, chunk))
}

fn build_chunk(id: &str,
               chunk_content: &[u8],
               children_size: u32,
               child_content: &[u8]) -> Chunk {
    if children_size == 0 {
        match id {
            "SIZE" => build_size_chunk(chunk_content),
            "XYZI" => build_voxel_chunk(chunk_content),
            "PACK" => build_pack_chunk(chunk_content),
            "RGBA" => build_palette_chunk(chunk_content),
            "MATL" => build_material_chunk(chunk_content),
            _ => {
                debug!("Unknown childless chunk {:?}", id);
                Chunk::Unknown(id.to_owned())
            }
        }
    } else {
        let result: IResult<&[u8], Vec<Chunk>> = many0(parse_chunk)(child_content);
        let child_chunks = match result {
            Ok((_, result)) => result,
            result => {
                debug!("Failed to parse child chunks, due to {:?}", result);
                vec![]
            }
        };
        match id {
            "MAIN" => Chunk::Main(child_chunks),
            "PACK" => build_pack_chunk(chunk_content),
            _ => {
                debug!("Unknown chunk with children {:?}", id);
                Chunk::Unknown(id.to_owned())
            }
        }
    }
}

fn build_material_chunk(chunk_content: &[u8]) -> Chunk {
    if let Ok((_, material)) = parse_material(chunk_content) {
        return Chunk::Material(material);
    }
    Chunk::Invalid(chunk_content.to_vec())
}

fn build_palette_chunk(chunk_content: &[u8]) -> Chunk {
    if let Ok((_, palette)) = palette::extract_palette(chunk_content) {
        return Chunk::Palette(palette);
    }
    Chunk::Invalid(chunk_content.to_vec())
}

fn build_pack_chunk(chunk_content: &[u8]) -> Chunk {
    if let Ok((chunk_content, Chunk::Size(size))) = parse_chunk(chunk_content) {
        if let Ok((_, Chunk::Voxels(voxels))) = parse_chunk(chunk_content) {
            return Chunk::Pack(Model { size, voxels: voxels.to_vec() });
        }
    }
    Chunk::Invalid(chunk_content.to_vec())
}

fn build_size_chunk(chunk_content: &[u8]) -> Chunk {
    match model::parse_size(chunk_content) {
        Ok((_, size)) => Chunk::Size(size),
        _ => Chunk::Invalid(chunk_content.to_vec())
    }
}

fn build_voxel_chunk(chunk_content: &[u8]) -> Chunk {
    match model::parse_voxels(chunk_content) {
        Ok((_, voxels)) => Chunk::Voxels(voxels),
        _ => Chunk::Invalid(chunk_content.to_vec())
    }
}

pub fn parse_material(i: &[u8]) -> IResult<&[u8], Material> {
    let (i, (id, properties)) = pair(le_u32, parse_dict)(i)?;
    Ok((i, Material { id, properties }))
}

fn parse_dict(i: &[u8]) -> IResult<&[u8], Dict> {
    let (i, n) = le_u32(i)?;
    let init = move || Dict::with_capacity(n as usize);
    let fold = |mut map: Dict, (key, value)| {
        map.insert(key, value);
        map
    };
    fold_many_m_n(n as usize, n as usize, parse_dict_entry, init, fold)(i)
}

fn parse_dict_entry(i: &[u8]) -> IResult<&[u8], (String, String)> {
    pair(parse_string, parse_string)(i)
}

fn parse_string(i: &[u8]) -> IResult<&[u8], String> {
    let bytes = flat_map(le_u32, take);
    map_res(bytes, to_str)(i)
}

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

    #[test]
    fn can_parse_size_chunk() {
        let bytes = include_bytes!("resources/valid_size.bytes").to_vec();
        let result = parse_chunk(&bytes);
        assert!(result.is_ok());
        let (_, size) = result.unwrap();
        assert_eq!(
            size,
            Chunk::Size(Size {
                x: 24,
                y: 24,
                z: 24,
            })
        );
    }

    #[test]
    fn can_parse_voxels_chunk() {
        let bytes = include_bytes!("resources/valid_voxels.bytes").to_vec();
        let result = parse_chunk(&bytes);
        assert!(result.is_ok());
        let (_, voxels) = result.unwrap();
        match voxels {
            Chunk::Voxels(voxels) => vec::are_eq(
                voxels,
                vec![Voxel { x: 0, y: 0, z: 0, i: 225 },
                     Voxel { x: 0, y: 1, z: 1, i: 215 },
                     Voxel { x: 1, y: 0, z: 1, i: 235 },
                     Voxel { x: 1, y: 1, z: 0, i: 5 },
                ],
            ),
            chunk => panic!("Expecting Voxel chunk, got {:?}", chunk)
        };
    }

    #[test]
    fn can_parse_palette_chunk() {
        let bytes = include_bytes!("resources/valid_palette.bytes").to_vec();
        let result = parse_chunk(&bytes);
        assert!(result.is_ok());
        let (_, palette) = result.unwrap();
        match palette {
            Chunk::Palette(palette) => vec::are_eq(palette, DEFAULT_PALETTE.to_vec()),
            chunk => panic!("Expecting Palette chunk, got {:?}", chunk)
        };
    }

    #[test]
    fn can_parse_a_material_chunk() {
        let bytes = include_bytes!("resources/valid_material.bytes").to_vec();
        let result = parse_material(&bytes);
        match result {
            Ok((_, material)) => {
                assert_eq!(material.id, 0);
                assert_eq!(material.properties.get("_type"), Some(&"_diffuse".to_owned()));
                assert_eq!(material.properties.get("_weight"), Some(&"1".to_owned()));
                assert_eq!(material.properties.get("_rough"), Some(&"0.1".to_owned()));
                assert_eq!(material.properties.get("_spec"), Some(&"0.5".to_owned()));
                assert_eq!(material.properties.get("_ior"), Some(&"0.3".to_owned()));
            }
            _ => panic!("Expected Done, got {:?}", result)
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Write};
use std::ops::{Deref, DerefMut};

/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
#[cfg(target_os = "redox")]
pub struct RawTerminal<W: Write> {
    output: W,
}

#[cfg(target_os = "redox")]
impl<W: Write> Drop for RawTerminal<W> {
    fn drop(&mut self) {
        use control::TermWrite;
        self.csi(b"R").unwrap();
    }
}

#[cfg(not(target_os = "redox"))]
use termios::Termios;
/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
#[cfg(not(target_os = "redox"))]
pub struct RawTerminal<W: Write> {
    prev_ios: Termios,
    output: W,
}

#[cfg(not(target_os = "redox"))]
impl<W> RawTerminal<W>
where W: Write
{
    /// Enable mouse support.
    pub fn with_mouse(mut self) -> io::Result<MouseTerminal<W>> {
        try!(self.write(ENTER_MOUSE_SEQUENCE));
        Ok(MouseTerminal { term: self })
    }
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> Drop for RawTerminal<W> {
    fn drop(&mut self) {
        use termios::set_terminal_attr;
        set_terminal_attr(&mut self.prev_ios as *mut _);
    }
}

impl<W: Write> Deref for RawTerminal<W> {
    type Target = W;

    fn deref(&self) -> &W {
        &self.output
    }
}

impl<W: Write> DerefMut for RawTerminal<W> {
    fn deref_mut(&mut self) -> &mut W {
        &mut self.output
    }
}

impl<W: Write> Write for RawTerminal<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.output.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.output.flush()
    }
}

/// Types which can be converted into "raw mode".
pub trait IntoRawMode: Write + Sized {
    /// Switch to raw mode.
    ///
    /// Raw mode means that stdin won't be printed (it will instead have to be written manually by the
    /// program). Furthermore, the input isn't canonicalised or buffered (that is, you can read from
    /// stdin one byte of a time). The output is neither modified in any way.
    fn into_raw_mode(self) -> io::Result<RawTerminal<Self>>;
}

impl<W: Write> IntoRawMode for W {
    #[cfg(not(target_os = "redox"))]
    fn into_raw_mode(self) -> io::Result<RawTerminal<W>> {
        use termios::{cfmakeraw, get_terminal_attr, set_terminal_attr};

        let (mut ios, exit) = get_terminal_attr();
        let prev_ios = ios.clone();
        if exit != 0 {
            return Err(io::Error::new(io::ErrorKind::Other, "Unable to get Termios attribute."));
        }

        unsafe {
            cfmakeraw(&mut ios);
        }

        if set_terminal_attr(&mut ios as *mut _) != 0 {
            Err(io::Error::new(io::ErrorKind::Other, "Unable to set Termios attribute."))
        } else {
            let res = RawTerminal {
                prev_ios: prev_ios,
                output: self,
            };
            Ok(res)
        }
    }

    #[cfg(target_os = "redox")]
    fn into_raw_mode(mut self) -> io::Result<RawTerminal<W>> {
        use control::TermWrite;

        self.csi(b"r").map(|_| {
            let mut res = RawTerminal {
                output: self,
            };
            res
        })
    }
}

/// A sequence of escape codes to enable terminal mouse support.
const ENTER_MOUSE_SEQUENCE: &'static[u8] = b"\x1b[?1000h\x1b[?1002h\x1b[?1015h\x1b[?1006h";

/// A sequence of escape codes to disable terminal mouse support.
const EXIT_MOUSE_SEQUENCE: &'static[u8] = b"\x1b[?1006l\x1b[?1015l\x1b[?1002l\x1b[?1000l";

/// A `RawTerminal` with added mouse support.
///
/// To get such a terminal handle use `RawTerminal`'s
/// [`with_mouse()`](../termion/struct.RawTerminal.html#method.with_mouse) method.
#[cfg(not(target_os = "redox"))]
pub struct MouseTerminal<W: Write> {
    term: RawTerminal<W>,
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> Drop for MouseTerminal<W> {
    fn drop(&mut self) {
        self.term.write(EXIT_MOUSE_SEQUENCE).unwrap();
    }
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> Deref for MouseTerminal<W> {
    type Target = W;

    fn deref(&self) -> &W {
        self.term.deref()
    }
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> DerefMut for MouseTerminal<W> {
    fn deref_mut(&mut self) -> &mut W {
        self.term.deref_mut()
    }
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> Write for MouseTerminal<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.term.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.term.flush()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::{Write, stdout};

    #[test]
    fn test_into_raw_mode() {
        let mut out = stdout().into_raw_mode().unwrap();

        out.write(b"this is a test, muahhahahah").unwrap();
    }
}
<commit_msg>fixed formatting<commit_after>use std::io::{self, Write};
use std::ops::{Deref, DerefMut};

/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
#[cfg(target_os = "redox")]
pub struct RawTerminal<W: Write> {
    output: W,
}

#[cfg(target_os = "redox")]
impl<W: Write> Drop for RawTerminal<W> {
    fn drop(&mut self) {
        use control::TermWrite;
        self.csi(b"R").unwrap();
    }
}

#[cfg(not(target_os = "redox"))]
use termios::Termios;
/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
#[cfg(not(target_os = "redox"))]
pub struct RawTerminal<W: Write> {
    prev_ios: Termios,
    output: W,
}

#[cfg(not(target_os = "redox"))]
impl<W> RawTerminal<W>
    where W: Write
{
    /// Enable mouse support.
    pub fn with_mouse(mut self) -> io::Result<MouseTerminal<W>> {
        try!(self.write(ENTER_MOUSE_SEQUENCE));
        Ok(MouseTerminal { term: self })
    }
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> Drop for RawTerminal<W> {
    fn drop(&mut self) {
        use termios::set_terminal_attr;
        set_terminal_attr(&mut self.prev_ios as *mut _);
    }
}

impl<W: Write> Deref for RawTerminal<W> {
    type Target = W;

    fn deref(&self) -> &W {
        &self.output
    }
}

impl<W: Write> DerefMut for RawTerminal<W> {
    fn deref_mut(&mut self) -> &mut W {
        &mut self.output
    }
}

impl<W: Write> Write for RawTerminal<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.output.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.output.flush()
    }
}

/// Types which can be converted into "raw mode".
pub trait IntoRawMode: Write + Sized {
    /// Switch to raw mode.
    ///
    /// Raw mode means that stdin won't be printed (it will instead have to be written manually by
    /// the program). Furthermore, the input isn't canonicalised or buffered (that is, you can
    /// read from stdin one byte of a time). The output is neither modified in any way.
    fn into_raw_mode(self) -> io::Result<RawTerminal<Self>>;
}

impl<W: Write> IntoRawMode for W {
    #[cfg(not(target_os = "redox"))]
    fn into_raw_mode(self) -> io::Result<RawTerminal<W>> {
        use termios::{cfmakeraw, get_terminal_attr, set_terminal_attr};

        let (mut ios, exit) = get_terminal_attr();
        let prev_ios = ios.clone();
        if exit != 0 {
            return Err(io::Error::new(io::ErrorKind::Other, "Unable to get Termios attribute."));
        }

        unsafe {
            cfmakeraw(&mut ios);
        }

        if set_terminal_attr(&mut ios as *mut _) != 0 {
            Err(io::Error::new(io::ErrorKind::Other, "Unable to set Termios attribute."))
        } else {
            let res = RawTerminal {
                prev_ios: prev_ios,
                output: self,
            };
            Ok(res)
        }
    }

    #[cfg(target_os = "redox")]
    fn into_raw_mode(mut self) -> io::Result<RawTerminal<W>> {
        use control::TermWrite;

        self.csi(b"r").map(|_| {
            let mut res = RawTerminal { output: self };
            res
        })
    }
}

/// A sequence of escape codes to enable terminal mouse support.
const ENTER_MOUSE_SEQUENCE: &'static [u8] = b"\x1b[?1000h\x1b[?1002h\x1b[?1015h\x1b[?1006h";

/// A sequence of escape codes to disable terminal mouse support.
const EXIT_MOUSE_SEQUENCE: &'static [u8] = b"\x1b[?1006l\x1b[?1015l\x1b[?1002l\x1b[?1000l";

/// A `RawTerminal` with added mouse support.
///
/// To get such a terminal handle use `RawTerminal`'s
/// [`with_mouse()`](../termion/struct.RawTerminal.html#method.with_mouse) method.
#[cfg(not(target_os = "redox"))]
pub struct MouseTerminal<W: Write> {
    term: RawTerminal<W>,
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> Drop for MouseTerminal<W> {
    fn drop(&mut self) {
        self.term.write(EXIT_MOUSE_SEQUENCE).unwrap();
    }
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> Deref for MouseTerminal<W> {
    type Target = W;

    fn deref(&self) -> &W {
        self.term.deref()
    }
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> DerefMut for MouseTerminal<W> {
    fn deref_mut(&mut self) -> &mut W {
        self.term.deref_mut()
    }
}

#[cfg(not(target_os = "redox"))]
impl<W: Write> Write for MouseTerminal<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.term.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.term.flush()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::{Write, stdout};

    #[test]
    fn test_into_raw_mode() {
        let mut out = stdout().into_raw_mode().unwrap();

        out.write(b"this is a test, muahhahahah").unwrap();
    }
}
<|endoftext|>


<commit_before>///
/// Implements the force-directed graph layout algorithm as
/// proposed by Fruchterman and Reingold [1].
///
/// [1]: http://emr.cs.iit.edu/~reingold/force-directed.pdf
///

use super::{P2d, Vector};

// k_s == l
#[inline]
fn attractive_force<V>(p1: &V, p2: &V, k_s: f32) -> V
    where V: Vector<Scalar = f32>
{
    let force = p1.sub(p2);
    let length = force.length_squared().sqrt();
    let strength = length / k_s;
    return force.scale(strength);
}

// k_r == l^2
#[inline]
fn repulsive_force<V>(p1: &V, p2: &V, k_r: f32) -> V
    where V: Vector<Scalar = f32>
{
    let force = p1.sub(p2);
    let length_squared = force.length_squared();
    if length_squared > 0.0 {
        let strength = k_r / length_squared;
        return force.scale(strength);
    }
    return force;
}

pub trait ForceDirected<V> where V: Vector<Scalar = f32>
{
    fn reset_forces(&mut self);

    // adds result of `f` to force1 and substracts from force2
    fn update_force_each_node_pair<F: Fn(&V, &V) -> V>(&mut self, f: F);

    // adds result of `f` to force1 and substracts from force2
    fn update_force_each_edge<F: Fn(&V, &V) -> V>(&mut self, f: F);

    fn update_positions<F: FnMut(&V, &V) -> V>(&mut self, f: F);
}

fn iterate<V, FD>(fd: &mut FD, step: f32, k_r: f32, k_s: f32, min_pos: &V, max_pos: &V) -> f32
    where V: Vector<Scalar = f32>,
          FD: ForceDirected<V>
{

    // Reset all forces to zero.
    fd.reset_forces();

    // Calculate repulsive force between all pairs.
    fd.update_force_each_node_pair(|pos1, pos2| repulsive_force(pos1, pos2, k_r));

    // Calculate spring force between adjacent pairs (edges).
    fd.update_force_each_edge(|pos1, pos2| attractive_force(pos1, pos2, k_s).scale(-1.0));

    // update positions
    let mut sum_distance = 0.0;

    fd.update_positions(|position, force| {
        let mut new_pos = position.clone();

        let length = force.length_squared().sqrt();
        if length > 0.0 {
            new_pos.add_scaled(step / length, &force);

            // add up the moved distance. we move by step.
            sum_distance += step;
        }
        new_pos.clip_within(min_pos, max_pos)
    });

    return sum_distance;
}

pub fn layout<V, FD, F>(fd: &mut FD,
                        step_fn: F,
                        max_iter: usize,
                        converge_eps: f32,
                        k_r: f32,
                        k_s: f32,
                        min_pos: &V,
                        max_pos: &V)
    where V: Vector<Scalar = f32>,
          FD: ForceDirected<V>,
          F: Fn(usize) -> f32
{
    let mut iter: usize = 0;
    while iter < max_iter {
        let step = step_fn(iter);
        iter += 1;

        let dist_moved = iterate(fd, step, k_r, k_s, min_pos, max_pos);
        if dist_moved < converge_eps {
            break;
        }
    }
}

struct Layout<'a, 'b, V: 'a> {
    forces: Vec<V>,
    node_positions: &'a mut Vec<V>,
    node_neighbors: &'b [Vec<usize>],
}

impl<'a, 'b, V> Layout<'a, 'b, V> where
V:Vector<Scalar = f32> {

    fn new<'c, 'd>(node_positions: &'c mut Vec<V>,
                   node_neighbors: &'d [Vec<usize>])
                   -> Layout<'c, 'd, V> {
        let n = node_positions.len();
        assert!(node_neighbors.len() == n);
        Layout {
            forces: (0..n).map(|_| V::new()).collect(), // initialize forces
            node_positions: node_positions,
            node_neighbors: node_neighbors,
        }
    }
}

impl<'a, 'b, V> ForceDirected<V> for Layout<'a, 'b, V> where V:Vector<Scalar = f32> {
    fn reset_forces(&mut self) {
        for f in self.forces.iter_mut() {
            f.reset();
        }
    }

    fn update_force_each_node_pair<F: Fn(&V, &V) -> V>(&mut self, f: F) {
        let n = self.node_positions.len();
        assert!(n == self.forces.len());

        for i1 in 0..n - 1 {
            for i2 in i1 + 1..n {
                let force = f(&self.node_positions[i1], &self.node_positions[i2]);
                self.forces[i1].add_scaled(1.0, &force);
                self.forces[i2].add_scaled(-1.0, &force);
            }
        }
    }

    fn update_force_each_edge<F: Fn(&V, &V) -> V>(&mut self, f: F) {
        let n = self.node_positions.len();
        assert!(n == self.forces.len());

        for i1 in 0..n {
            for &i2 in self.node_neighbors[i1].iter() {
                let force = f(&self.node_positions[i1], &self.node_positions[i2]);
                self.forces[i1].add_scaled(1.0, &force);
                self.forces[i2].add_scaled(-1.0, &force);
            }
        }
    }

    fn update_positions<F: FnMut(&V, &V) -> V>(&mut self, mut f: F) {
        let n = self.node_positions.len();
        assert!(n == self.forces.len());

        for i in 0..n {
            let new_pos = f(&self.node_positions[i], &self.forces[i]);
            self.node_positions[i] = new_pos;
        }
    }
}

pub fn layout_typical_2d<'a, 'b>(l: Option<f32>,
                                 node_positions: &'a mut Vec<P2d>,
                                 node_neighbors: &'b [Vec<usize>]) {
    let n = node_positions.len();
    assert!(node_neighbors.len() == n);

    const MAX_ITER: usize = 300;
    const EPS: f32 = 0.01;

    let temp = 0.1f32;
    let dt = temp / (MAX_ITER as f32);
    let min_pos = P2d(0.0, 0.0);
    let max_pos = P2d(1.0, 1.0);
    let step_fn = |iter| temp - (iter as f32 * dt);

    // `l`: ideal length of spring
    let l: f32 = l.unwrap_or((1.0 / n as f32).sqrt());

    let k_r = l * l;
    let k_s = l;

    let mut lay = Layout::new(node_positions, node_neighbors);
    layout(&mut lay,
           step_fn,
           MAX_ITER,
           EPS,
           k_r,
           k_s,
           &min_pos,
           &max_pos);
}
<commit_msg>rustfmt<commit_after>///
/// Implements the force-directed graph layout algorithm as
/// proposed by Fruchterman and Reingold [1].
///
/// [1]: http://emr.cs.iit.edu/~reingold/force-directed.pdf
///

use super::{P2d, Vector};

// k_s == l
#[inline]
fn attractive_force<V>(p1: &V, p2: &V, k_s: f32) -> V
    where V: Vector<Scalar = f32>
{
    let force = p1.sub(p2);
    let length = force.length_squared().sqrt();
    let strength = length / k_s;
    return force.scale(strength);
}

// k_r == l^2
#[inline]
fn repulsive_force<V>(p1: &V, p2: &V, k_r: f32) -> V
    where V: Vector<Scalar = f32>
{
    let force = p1.sub(p2);
    let length_squared = force.length_squared();
    if length_squared > 0.0 {
        let strength = k_r / length_squared;
        return force.scale(strength);
    }
    return force;
}

pub trait ForceDirected<V> where V: Vector<Scalar = f32>
{
    fn reset_forces(&mut self);

    // adds result of `f` to force1 and substracts from force2
    fn update_force_each_node_pair<F: Fn(&V, &V) -> V>(&mut self, f: F);

    // adds result of `f` to force1 and substracts from force2
    fn update_force_each_edge<F: Fn(&V, &V) -> V>(&mut self, f: F);

    fn update_positions<F: FnMut(&V, &V) -> V>(&mut self, f: F);
}

fn iterate<V, FD>(fd: &mut FD, step: f32, k_r: f32, k_s: f32, min_pos: &V, max_pos: &V) -> f32
    where V: Vector<Scalar = f32>,
          FD: ForceDirected<V>
{

    // Reset all forces to zero.
    fd.reset_forces();

    // Calculate repulsive force between all pairs.
    fd.update_force_each_node_pair(|pos1, pos2| repulsive_force(pos1, pos2, k_r));

    // Calculate spring force between adjacent pairs (edges).
    fd.update_force_each_edge(|pos1, pos2| attractive_force(pos1, pos2, k_s).scale(-1.0));

    // update positions
    let mut sum_distance = 0.0;

    fd.update_positions(|position, force| {
        let mut new_pos = position.clone();

        let length = force.length_squared().sqrt();
        if length > 0.0 {
            new_pos.add_scaled(step / length, &force);

            // add up the moved distance. we move by step.
            sum_distance += step;
        }
        new_pos.clip_within(min_pos, max_pos)
    });

    return sum_distance;
}

pub fn layout<V, FD, F>(fd: &mut FD,
                        step_fn: F,
                        max_iter: usize,
                        converge_eps: f32,
                        k_r: f32,
                        k_s: f32,
                        min_pos: &V,
                        max_pos: &V)
    where V: Vector<Scalar = f32>,
          FD: ForceDirected<V>,
          F: Fn(usize) -> f32
{
    let mut iter: usize = 0;
    while iter < max_iter {
        let step = step_fn(iter);
        iter += 1;

        let dist_moved = iterate(fd, step, k_r, k_s, min_pos, max_pos);
        if dist_moved < converge_eps {
            break;
        }
    }
}

struct Layout<'a, 'b, V: 'a> {
    forces: Vec<V>,
    node_positions: &'a mut Vec<V>,
    node_neighbors: &'b [Vec<usize>],
}

impl<'a, 'b, V> Layout<'a, 'b, V> where V: Vector<Scalar = f32>
{
    fn new<'c, 'd>(node_positions: &'c mut Vec<V>,
                   node_neighbors: &'d [Vec<usize>])
                   -> Layout<'c, 'd, V> {
        let n = node_positions.len();
        assert!(node_neighbors.len() == n);
        Layout {
            forces: (0..n).map(|_| V::new()).collect(), // initialize forces
            node_positions: node_positions,
            node_neighbors: node_neighbors,
        }
    }
}

impl<'a, 'b, V> ForceDirected<V> for Layout<'a, 'b, V> where V: Vector<Scalar = f32>
{
    fn reset_forces(&mut self) {
        for f in self.forces.iter_mut() {
            f.reset();
        }
    }

    fn update_force_each_node_pair<F: Fn(&V, &V) -> V>(&mut self, f: F) {
        let n = self.node_positions.len();
        assert!(n == self.forces.len());

        for i1 in 0..n - 1 {
            for i2 in i1 + 1..n {
                let force = f(&self.node_positions[i1], &self.node_positions[i2]);
                self.forces[i1].add_scaled(1.0, &force);
                self.forces[i2].add_scaled(-1.0, &force);
            }
        }
    }

    fn update_force_each_edge<F: Fn(&V, &V) -> V>(&mut self, f: F) {
        let n = self.node_positions.len();
        assert!(n == self.forces.len());

        for i1 in 0..n {
            for &i2 in self.node_neighbors[i1].iter() {
                let force = f(&self.node_positions[i1], &self.node_positions[i2]);
                self.forces[i1].add_scaled(1.0, &force);
                self.forces[i2].add_scaled(-1.0, &force);
            }
        }
    }

    fn update_positions<F: FnMut(&V, &V) -> V>(&mut self, mut f: F) {
        let n = self.node_positions.len();
        assert!(n == self.forces.len());

        for i in 0..n {
            let new_pos = f(&self.node_positions[i], &self.forces[i]);
            self.node_positions[i] = new_pos;
        }
    }
}

pub fn layout_typical_2d<'a, 'b>(l: Option<f32>,
                                 node_positions: &'a mut Vec<P2d>,
                                 node_neighbors: &'b [Vec<usize>]) {
    let n = node_positions.len();
    assert!(node_neighbors.len() == n);

    const MAX_ITER: usize = 300;
    const EPS: f32 = 0.01;

    let temp = 0.1f32;
    let dt = temp / (MAX_ITER as f32);
    let min_pos = P2d(0.0, 0.0);
    let max_pos = P2d(1.0, 1.0);
    let step_fn = |iter| temp - (iter as f32 * dt);

    // `l`: ideal length of spring
    let l: f32 = l.unwrap_or((1.0 / n as f32).sqrt());

    let k_r = l * l;
    let k_s = l;

    let mut lay = Layout::new(node_positions, node_neighbors);
    layout(&mut lay,
           step_fn,
           MAX_ITER,
           EPS,
           k_r,
           k_s,
           &min_pos,
           &max_pos);
}
<|endoftext|>