<commit_before>use std::time::Duration;
use plist::Plist;
use std::collections::BTreeMap;

use Stream;
use Result;
use Error;
use message_type;

/// A Client for usbmuxd.
pub struct Client {
    stream: Stream,
}

impl Client {
    /// Tries to create a new instance of the `Client`.
    pub fn new() -> Result<Self> {
        let mut stream = try!(Stream::connect());
        try!(stream.set_send_tymeout(Some(Duration::new(1, 0))));
        try!(stream.set_receive_timeout(Some(Duration::new(1, 0))));
        Ok(Client {
            stream: stream,
        })
    }

    /// Returns a list of connected devices.
    pub fn devices(&mut self) -> Result<Vec<Device>> {
        let mut plist = try!(self.request(Plist::Dictionary(message_type("ListDevices"))));
        let mut dict = try!(plist.as_dictionary_mut().ok_or(Error::UnexpectedFormat));
        match dict.remove("DeviceList") {
            Some(Plist::Array(array)) => {
                let results = array.into_iter().filter_map(|item| {
                    match item {
                        Plist::Dictionary(mut dict) => {
                            match dict.remove("Properties") {
                                Some(plist) => Device::from_plist(plist),
                                _ => None,
                            }
                        },
                        _ => None,
                    }
                }).collect();
                Ok(results)
            },
            _ => Err(Error::UnexpectedFormat),
        }
    }

    /// Sends a request and receives a response.
    pub fn request(&mut self, message: Plist) -> Result<Plist> {
        try!(self.stream.send(message));
        Ok(try!(self.stream.receive()))
    }
}

/// Represents a device.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Device {
    pub device_id: u32,
    pub product_id: u32,
    pub location_id: u32,
    pub serial_number: String,
}

impl Device {
    /// Creates an instance of `Device` from plist.
    pub fn from_plist(mut plist: Plist) -> Option<Device> {
        let mut dict = try_opt!(plist.as_dictionary_mut());
        Some(Device {
            device_id: try_opt!(dict.get("DeviceID").and_then(Plist::as_integer).map(|x| x as u32)),
            product_id: try_opt!(dict.get("ProductID").and_then(Plist::as_integer).map(|x| x as u32)),
            location_id: try_opt!(dict.get("LocationID").and_then(Plist::as_integer).map(|x| x as u32)),
            serial_number: try_opt!(dict.get("SerialNumber").and_then(Plist::as_string).map(|s| s.to_owned())),
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use expectest::prelude::*;
    use plist::Plist;
    use std::collections::BTreeMap;

    #[test]
    fn test_device_from_plist() {
        let mut map = BTreeMap::new();
        map.insert("ConnectionSpeed".to_owned(), Plist::Integer(480000000));
        map.insert("ConnectionType".to_owned(), Plist::String("USB".to_owned()));
        map.insert("DeviceID".to_owned(), Plist::Integer(3));
        map.insert("LocationID".to_owned(), Plist::Integer(336592896));
        map.insert("ProductID".to_owned(), Plist::Integer(4778));
        map.insert("SerialNumber".to_owned(),Plist::String("fffffffff".to_owned()));

        let device = Device {
            device_id: 3,
            product_id: 4778,
            location_id: 336592896,
            serial_number: "fffffffff".to_owned(),
        };

        expect!(Device::from_plist(Plist::Dictionary(map))).to(be_some().value(device));
    }
}<commit_msg>Update with plist crate.<commit_after>use std::time::Duration;
use plist::Plist;

use Stream;
use Result;
use Error;
use message_type;

/// A Client for usbmuxd.
pub struct Client {
    stream: Stream,
}

impl Client {
    /// Tries to create a new instance of the `Client`.
    pub fn new() -> Result<Self> {
        let mut stream = try!(Stream::connect());
        try!(stream.set_send_tymeout(Some(Duration::new(1, 0))));
        try!(stream.set_receive_timeout(Some(Duration::new(1, 0))));
        Ok(Client {
            stream: stream,
        })
    }

    /// Returns a list of connected devices.
    pub fn devices(&mut self) -> Result<Vec<Device>> {
        let mut plist = try!(self.request(Plist::Dictionary(message_type("ListDevices"))));
        let mut dict = try!(plist.as_dictionary_mut().ok_or(Error::UnexpectedFormat));
        match dict.remove("DeviceList") {
            Some(Plist::Array(array)) => {
                let results = array.into_iter().filter_map(|item| {
                    match item {
                        Plist::Dictionary(mut dict) => {
                            match dict.remove("Properties") {
                                Some(plist) => Device::from_plist(plist),
                                _ => None,
                            }
                        },
                        _ => None,
                    }
                }).collect();
                Ok(results)
            },
            _ => Err(Error::UnexpectedFormat),
        }
    }

    /// Sends a request and receives a response.
    pub fn request(&mut self, message: Plist) -> Result<Plist> {
        try!(self.stream.send(message));
        Ok(try!(self.stream.receive()))
    }
}

/// Represents a device.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Device {
    pub device_id: u32,
    pub product_id: u32,
    pub location_id: u32,
    pub serial_number: String,
}

impl Device {
    /// Creates an instance of `Device` from plist.
    pub fn from_plist(mut plist: Plist) -> Option<Device> {
        let mut dict = try_opt!(plist.as_dictionary_mut());
        Some(Device {
            device_id: try_opt!(dict.get("DeviceID").and_then(Plist::as_integer).map(|x| x as u32)),
            product_id: try_opt!(dict.get("ProductID").and_then(Plist::as_integer).map(|x| x as u32)),
            location_id: try_opt!(dict.get("LocationID").and_then(Plist::as_integer).map(|x| x as u32)),
            serial_number: try_opt!(dict.remove("SerialNumber").and_then(Plist::into_string)),
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use expectest::prelude::*;
    use plist::Plist;
    use std::collections::BTreeMap;

    #[test]
    fn test_device_from_plist() {
        let mut map = BTreeMap::new();
        map.insert("ConnectionSpeed".to_owned(), Plist::Integer(480000000));
        map.insert("ConnectionType".to_owned(), Plist::String("USB".to_owned()));
        map.insert("DeviceID".to_owned(), Plist::Integer(3));
        map.insert("LocationID".to_owned(), Plist::Integer(336592896));
        map.insert("ProductID".to_owned(), Plist::Integer(4778));
        map.insert("SerialNumber".to_owned(),Plist::String("fffffffff".to_owned()));

        let device = Device {
            device_id: 3,
            product_id: 4778,
            location_id: 336592896,
            serial_number: "fffffffff".to_owned(),
        };

        expect!(Device::from_plist(Plist::Dictionary(map))).to(be_some().value(device));
    }
}<|endoftext|>


<commit_before><commit_msg>Add IrcClient struct<commit_after>use user::IrcUser;
use std::net::ToSocketAddrs;

#[derive(Debug)]
pub struct IrcClient<A: ToSocketAddrs> {
    pub server: A,
    pub user: IrcUser
}

impl <A: ToSocketAddrs> IrcClient<A> {
    pub fn new(server: A, user: IrcUser) -> IrcClient<A> {
        IrcClient {
            server: server,
            user: user
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.
//! libc - Raw FFI bindings to platforms' system libraries
#![crate_name = "libc"]
#![crate_type = "rlib"]
#![cfg_attr(not(feature = "rustc-dep-of-std"), deny(warnings))]
#![allow(bad_style, overflowing_literals, improper_ctypes, unknown_lints)]
// Attributes needed when building as part of the standard library
#![cfg_attr(
    feature = "rustc-dep-of-std",
    feature(cfg_target_vendor, link_cfg, no_core)
)]
// Enable extra lints:
#![cfg_attr(feature = "extra_traits", deny(missing_debug_implementations))]
#![deny(missing_copy_implementations, safe_packed_borrows)]
#![no_std]
#![cfg_attr(feature = "rustc-dep-of-std", no_core)]

#[macro_use]
mod macros;

cfg_if! {
    if #[cfg(feature = "rustc-dep-of-std")] {
        extern crate rustc_std_workspace_core as core;
        #[allow(unused_imports)]
        use core::iter;
        #[allow(unused_imports)]
        use core::option;
    }
}

cfg_if! {
    if #[cfg(libc_priv_mod_use)] {
        #[cfg(libc_core_cvoid)]
        #[allow(unused_imports)]
        use core::ffi;
        #[allow(unused_imports)]
        use core::fmt;
        #[allow(unused_imports)]
        use core::hash;
        #[allow(unused_imports)]
        use core::num;
        #[allow(unused_imports)]
        use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::option::Option;
    } else {
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::fmt;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::hash;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::num;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::option::Option;
    }
}

cfg_if! {
    if #[cfg(windows)] {
        mod windows;
        pub use windows::*;
    } else if #[cfg(target_os = "redox")] {
        mod redox;
        pub use redox::*;
    } else if #[cfg(target_os = "cloudabi")] {
        mod cloudabi;
        pub use cloudabi::*;
    } else if #[cfg(target_os = "fuchsia")] {
        mod fuchsia;
        pub use fuchsia::*;
    } else if #[cfg(target_os = "switch")] {
        mod switch;
        pub use switch::*;
    } else if #[cfg(unix)] {
        mod unix;
        pub use unix::*;
    } else if #[cfg(target_env = "sgx")] {
        mod sgx;
        pub use sgx::*;
    }  else {
        // non-supported targets: empty...
    }
}
<commit_msg>Auto merge of #1290 - gnzlbg:doc_link, r=gnzlbg<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.
//! libc - Raw FFI bindings to platforms' system libraries
//!
//! [Documentation for other platforms][pd].
//!
//! [pd]: https://rust-lang.github.io/libc/#platform-specific-documentation
#![crate_name = "libc"]
#![crate_type = "rlib"]
#![cfg_attr(not(feature = "rustc-dep-of-std"), deny(warnings))]
#![allow(bad_style, overflowing_literals, improper_ctypes, unknown_lints)]
// Attributes needed when building as part of the standard library
#![cfg_attr(
    feature = "rustc-dep-of-std",
    feature(cfg_target_vendor, link_cfg, no_core)
)]
// Enable extra lints:
#![cfg_attr(feature = "extra_traits", deny(missing_debug_implementations))]
#![deny(missing_copy_implementations, safe_packed_borrows)]
#![no_std]
#![cfg_attr(feature = "rustc-dep-of-std", no_core)]

#[macro_use]
mod macros;

cfg_if! {
    if #[cfg(feature = "rustc-dep-of-std")] {
        extern crate rustc_std_workspace_core as core;
        #[allow(unused_imports)]
        use core::iter;
        #[allow(unused_imports)]
        use core::option;
    }
}

cfg_if! {
    if #[cfg(libc_priv_mod_use)] {
        #[cfg(libc_core_cvoid)]
        #[allow(unused_imports)]
        use core::ffi;
        #[allow(unused_imports)]
        use core::fmt;
        #[allow(unused_imports)]
        use core::hash;
        #[allow(unused_imports)]
        use core::num;
        #[allow(unused_imports)]
        use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        use core::option::Option;
    } else {
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::fmt;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::hash;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::num;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::mem;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::clone::Clone;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::marker::Copy;
        #[doc(hidden)]
        #[allow(unused_imports)]
        pub use core::option::Option;
    }
}

cfg_if! {
    if #[cfg(windows)] {
        mod windows;
        pub use windows::*;
    } else if #[cfg(target_os = "redox")] {
        mod redox;
        pub use redox::*;
    } else if #[cfg(target_os = "cloudabi")] {
        mod cloudabi;
        pub use cloudabi::*;
    } else if #[cfg(target_os = "fuchsia")] {
        mod fuchsia;
        pub use fuchsia::*;
    } else if #[cfg(target_os = "switch")] {
        mod switch;
        pub use switch::*;
    } else if #[cfg(unix)] {
        mod unix;
        pub use unix::*;
    } else if #[cfg(target_env = "sgx")] {
        mod sgx;
        pub use sgx::*;
    }  else {
        // non-supported targets: empty...
    }
}
<|endoftext|>


<commit_before>use std::io::BufRead;

pub fn read_line() -> String {
    let stdin = std::io::stdin();
    let stdin = stdin.lock();
    let mut lines = stdin.lines();
    lines.next().unwrap().unwrap()
}
<commit_msg>a generic read function for all FromStr types<commit_after>use std::io::{BufRead, Read};
use std::str::{FromStr, from_utf8};
use std::fmt::Debug;

pub fn read_line() -> String {
    let stdin = std::io::stdin();
    let stdin = stdin.lock();
    let mut lines = stdin.lines();
    lines.next().unwrap().unwrap()
}

pub fn read<T: FromStr>() -> T
    where <T as FromStr>::Err: Debug
{
    let stdin = std::io::stdin();
    let stdin = stdin.lock();
    let v: Vec<u8> = stdin.bytes()
        .map(|c| c.unwrap())
        .take_while(|c| b" \n\r\t".contains(&c))
        .collect();
    FromStr::from_str(from_utf8(&v).unwrap()).unwrap()
}
<|endoftext|>


<commit_before>pub mod xml_export {

    use std::fs::File;
    use std::io::prelude::*;
    use std::error::Error;

    pub enum QuestionType {
        SingleChoice,
        MultipleChoice,
        Essay,
        TrueFalse,
        Matching,
        ShortAnswer,
        NumericalResponse,
        UndefinedQuestion,
    }
    pub struct Answer {
        pub title: String,
        pub points: i32,
    }
    pub struct Question {
        pub question_type: QuestionType,
        pub title: String,
        pub answers: Vec<Answer>,
    }

    pub fn questions_to_moodle(questions: &mut Vec<Question>) {
        let mut xml_string = String::new();
        xml_string += "<?xml version=\"1.0\"?>";
        xml_string += "<quiz>";

        for question in questions {
            let question_type_id = determine_type(&question.question_type);
            let new_question = format!("<question type=\"{}\">", question_type_id);
            xml_string += &new_question;

            xml_string += "<questiontext format=\"html\">";

            xml_string += "<text>";
            xml_string += &question.title;
            xml_string += "</text></questiontext>";

            for answer in &question.answers {
                xml_string += "<answer fraction=\"0\">";
                xml_string += "<text>";
                let answer_text = &answer.title;
                xml_string += &answer_text;
                xml_string += "</text>";
                xml_string += "</answer>";
            }

            xml_string += "</question>";
        }
        xml_string += "</quiz>";
        print_to_file(&xml_string);
    }

    fn print_to_file(xml_string: &String) {
        let mut file = match File::create("test.xml") {
            Err(why) => panic!("Ging net: {}", why.description()),
            Ok(file) => file,
        };

        match file.write_all(xml_string.as_bytes()) {
            Err(why) => {
                panic!("Ging auch net: {}", why.description());
            }
            Ok(_) => println!("Gesaved!"),
        }
    }

    fn determine_type(question_type: &QuestionType) -> String {
        match question_type {
            &QuestionType::SingleChoice => "multichoice".to_string(),
            &QuestionType::MultipleChoice => "multichoice".to_string(),
            &QuestionType::Essay => "essay".to_string(),
            &QuestionType::TrueFalse => "truefalse".to_string(),
            &QuestionType::Matching => "match".to_string(),
            &QuestionType::ShortAnswer => "shortanswer".to_string(),
            &QuestionType::NumericalResponse => "numerical".to_string(),
            &QuestionType::UndefinedQuestion => "description".to_string(),
        }
    }
}
<commit_msg>Bugfixed, questions are now accepted by moodle import<commit_after>pub mod xml_export {

    use std::fs::File;
    use std::io::prelude::*;
    use std::error::Error;

    pub enum QuestionType {
        SingleChoice,
        MultipleChoice,
        Essay,
        TrueFalse,
        Matching,
        ShortAnswer,
        NumericalResponse,
        UndefinedQuestion,
    }
    pub struct Answer {
        pub title: String,
        pub points: i32,
    }
    pub struct Question {
        pub question_type: QuestionType,
        pub title: String,
        pub answers: Vec<Answer>,
    }

    pub fn questions_to_moodle(questions: &mut Vec<Question>) {
        let mut xml_string = String::new();
        xml_string += "<?xml version=\"1.0\"?>";
        xml_string += "<quiz>";

        for question in questions {
            let question_type_id = determine_type(&question.question_type);
            let new_question = format!("<question type=\"{}\">", question_type_id);
            xml_string += &new_question;

            xml_string += "<name><text>";
            xml_string += &question.title;
            xml_string += "</text></name>";
            xml_string += "<questiontext format=\"html\">";
            xml_string += "<text>";
            xml_string += &question.title;
            xml_string += "</text></questiontext>";

            for answer in &question.answers {
                xml_string += "<answer fraction=\"0\">";
                xml_string += "<text>";
                let answer_text = &answer.title;
                xml_string += &answer_text;
                xml_string += "</text>";
                xml_string += "</answer>";
            }

            xml_string += "</question>";
        }
        xml_string += "</quiz>";
        print_to_file(&xml_string);
    }

    fn print_to_file(xml_string: &String) {
        let mut file = match File::create("test.xml") {
            Err(why) => panic!("Ging net: {}", why.description()),
            Ok(file) => file,
        };

        match file.write_all(xml_string.as_bytes()) {
            Err(why) => {
                panic!("Ging auch net: {}", why.description());
            }
            Ok(_) => println!("Gesaved!"),
        }
    }

    fn determine_type(question_type: &QuestionType) -> String {
        match question_type {
            &QuestionType::SingleChoice => "multichoice".to_string(),
            &QuestionType::MultipleChoice => "multichoice".to_string(),
            &QuestionType::Essay => "essay".to_string(),
            &QuestionType::TrueFalse => "truefalse".to_string(),
            &QuestionType::Matching => "match".to_string(),
            &QuestionType::ShortAnswer => "shortanswer".to_string(),
            &QuestionType::NumericalResponse => "numerical".to_string(),
            &QuestionType::UndefinedQuestion => "description".to_string(),
        }
    }
}
<|endoftext|>


<commit_before>extern crate nalgebra;
use nalgebra::DMat;

pub struct SmithWaterman{
    sequence1: String,
    sequence2: String
}

#[test]
fn it_works() {
}
<commit_msg>Create matrix with loops<commit_after>#![feature(str_char)]
extern crate nalgebra;

use nalgebra::DMat;
use std::fmt::{Debug, Formatter, Result};

pub struct SmithWaterman{
    sequence1: String,
    sequence2: String,
    matrix:  DMat<isize>,
    matched: isize,
    missed: isize,
}

impl SmithWaterman{
    pub fn new(sequence1: String, sequence2: String) -> SmithWaterman {
        SmithWaterman{matrix: nalgebra::DMat::new_zeros(sequence1.len()+1, sequence2.len()+1),
            sequence1: sequence1, sequence2: sequence2, matched: 2, missed: -1}
    }

    fn penalty(&self, value: isize, penalty_value: isize) -> isize{
        match value.checked_add(penalty_value){
            Some(i) =>{
                if i<0 { 0 }else { i }
            },
            _ => {0}
        }
    }

    pub fn score(&mut self){
        let mut max_point = (0,0);
        let mut max = 0;
        for row in (1..self.sequence1.len()+1){
            for col in (1..self.sequence2.len()+1){
                let left = self.penalty(self.matrix[(row, col-1)], self.missed);
                let top = self.penalty(self.matrix[(row-1, col)], self.missed);
                let diagonal = self.matrix[(row-1, col-1)];
                let diagonal_match = if self.sequence2.char_at(col-1) == self.sequence1.char_at(row-1){
                    self.penalty(diagonal, self.matched)
                }else{
                    self.penalty(diagonal, self.missed)
                };
                let n = std::cmp::max(left, std::cmp::max(top, diagonal_match));
                if n>=max{
                    max =n;
                    max_point = (row,col);
                }
                self.matrix[(row, col)] = n;
            }
        }
    }
}
impl Debug for SmithWaterman {
    fn fmt(&self, form:&mut Formatter) -> Result {
        //nrows already has an extra over the sequence counts for the row of zeros
        for row in 0..self.matrix.nrows()+1 {
            for col in 0..self.matrix.ncols()+1 {
                let _ = if col==0 && row>1{
                    write!(form, "{:>5}", self.sequence1.char_at(row-2).to_string())
                } else if row==0 && col>1{
                    write!(form, "{:>5}", self.sequence2.char_at(col-2).to_string())
                } else if row>=1 && col>=1{
                    write!(form, "{:>5}", self.matrix[(row-1,col-1)])
                }else{
                    write!(form, "{:>5}", "-")
                };
            }
            let _ = write!(form, "\n");
        }
        write!(form, "\n")
    }
}

#[test]
fn its_debugging() {
    let mut smitty = SmithWaterman::new("atgcatgcatgc".to_string(), "atgggcatg".to_string());
    smitty.score();
    println!("{:?}", smitty);

    let mut smitty = SmithWaterman::new( "atgggcatg".to_string(),"atgcatgcatgc".to_string());
    smitty.score();
    println!("{:?}", smitty);
}
<|endoftext|>


<commit_before>//! Promises in Rust.
//! See the `Promise` struct for more details.

#![warn(missing_docs)]

use std::thread;
use std::sync::mpsc::channel;
use std::time::Duration;
use std::thread::JoinHandle;
use std::marker::{Send};
use std::sync::mpsc::{Sender, Receiver, TryRecvError};

/// A promise is a way of doing work in the background. The promises in
/// this library have the same featureset as those in Ecmascript 5.
///
/// # Promises
/// Promises (sometimes known as "futures") are objects that represent
/// asynchronous tasks being run in the background, or results which
/// will exist in the future.
/// A promise will be in state of running, fulfilled, or done. In order to
/// use the results of a fulfilled promise, one attaches another promise
/// to it (i.e. via `then`). Like their Javascript counterparts, promises can
/// return an error (of type `E`).
///
/// # Panics
/// If the function being executed by a promise panics, it does so silently.
/// The panic will not resurface in the thread which created the promise,
/// and promises waiting on its result will never be called. In addition,
/// the `all` and `race` proimse methods will _ignore_ "dead" promises. They
/// will remove promises from their lists, and if there aren't any left
/// they will silently exit without doing anything.
///
/// Unfortunately, panics must be ignored for two reasons:
/// * Panic messages don't have a concrete type yet in Rust. If they did,
/// promiess would be able to inspect their predecessors' errors.
/// * Although a `Receiver` can correctly handle its paired `Sender` being
/// dropped, such as during a panic, for reasons stated above the "message"
/// of the panic is not relayed.
///
/// Finally, Ecmascript promises themselves do have the ability to return
/// and error type, represented as a `Result<T, E>` here. Thus, one should
/// use `try!` and other error handling rather than calls to `unwrap()`.
pub struct Promise<T: Send, E: Send> {
    receiver: Receiver<Result<T, E>>
}

impl<T: Send + 'static, E: Send + 'static> Promise<T, E> {

    /// Chains a function to be called after this promise resolves.
    pub fn then<T2, E2>(self, callback: fn(f: T) -> Result<T2, E2>,
                              errback:  fn(e: E) -> Result<T2, E2>)
                        -> Promise<T2, E2>
    where T2: Send + 'static, E2: Send + 'static {
        let recv = self.receiver;
        let (tx, rx) = channel();

        let thread = thread::spawn(move || {
            Promise::promise_then(tx, recv, callback, errback);
        });
        recv.recv();
        return Promise { receiver: rx };
    }

    /// Chains a function to be called after this promise resolves,
    /// using a `Result` type.
    pub fn then_result<T2, E2>(self,
                               callback: fn(Result<T, E>) -> Result<T2, E2>)
                               -> Promise<T2, E2>
    where T2: Send + 'static, E2: Send + 'static {
        let recv = self.receiver;
        let recv2 = self.receiver;
        let (tx, rx) = channel();

        let thread = thread::spawn(move || {
            Promise::promise_then_result(tx, callback);
        });
        return Promise { receiver: rx };
    }

    /// Creates a new promsie
    pub fn new<F>(func: F) -> Promise<T, E>
    where F: Send + 'static + FnOnce() -> Result<T, E> {
        let (tx, rx) = channel();

        let thread = thread::spawn(move || {
            Promise::promise_new(tx, func);
        });

        return Promise { receiver: rx };
    }

    /// Applies a promise to the first of some promises to become fulfilled.
    pub fn race<T2, E2>(promises: Vec<Promise<T, E>>,
                        func: fn(res: Result<T, E>) -> Result<T2, E2>)
                        -> Promise<T2, E2>
    where T2: Send + 'static, E2: Send + 'static {
        let mut recs = promises.into_iter().map(|p| p.receiver).collect();
        let (tx, rx) = channel::<Result<T2, E2>>();

        thread::spawn(move || {
            Promise::promise_race(tx, recs, func);
        });
        return Promise { receiver: rx };
    }

    /// Calls a function with the result of all of the promises, or the error
    /// of the first promise to error.
    pub fn all<T2, E2>(promises: Vec<Promise<T, E>>,
                       func: fn(res: Result<Vec<T>, E>) -> Result<T2, E2>)
                       -> Promise<Vec<T>, E>
    where T2: Send + 'static, E2: Send + 'static {
        let receivers: Vec<Receiver<Result<T, E>>> =
            promises.into_iter().map(|p| p.receiver).collect();
        let (tx, rx) = channel();

        thread::spawn(move || {
            Promise::promise_all(receivers, tx);
        });

        return Promise { receiver: rx };
    }

    /// Creates a promise that resolves to a value
    pub fn resolve(val: T) -> Promise<T, E> {
        Promise::from_result(Ok(val))
    }

    /// Creates a promise that resolves to an error.
    pub fn reject(val: E) -> Promise<T, E> {
        Promise::from_result(Err(val))
    }

    /// Creates a new promise that will resolve to the result value.
    pub fn from_result(result: Result<T, E>) -> Promise<T, E> {
        let (tx, rx) = channel();
        tx.send(result).unwrap();

        Promise { receiver: rx }
    }

    // Implementation Functions

    fn promise_new(tx: Sender<Result<T, E>>,
                   func: Box<FnOnce() -> Result<T, E>>) {
        let result = func();
        tx.send(result).unwrap_or(());
    }

    fn promise_then<T2, E2>(tx: Sender<Result<T2, E2>>,
                            rx: Receiver<Result<T, E>>,
                            callback: fn(T) -> Result<T2, E2>,
                            errback: fn(E) -> Result<T2, E2>)
    where T2: Send + 'static, E2: Send + 'static {
        if let Ok(message) = rx.recv() {
            match message {
                Ok(val) => tx.send(callback(val)).unwrap_or(()),
                Err(err) => tx.send(errback(err)).unwrap_or(())
            };
        }
    }

    fn promise_then_result<T2, E2>(tx: Sender<Result<T2, E2>>,
                                   rx: Receiver<Result<T, E>>,
                                 callback: fn(Result<T, E>) -> Result<T2, E2>)
    where T2: Send + 'static, E2: Send + 'static {

        if let Ok(result) = rx.recv() {
            tx.send(callback(result)).unwrap_or(());
        }
    }

    // Static methods

    fn promise_race<T2, E2>(tx: Sender<Result<T2, E2>>,
                            recs: Vec<Receiver<Result<T, E>>>,
                            func: fn(Result<T, E>) -> Result<T2, E2>)
    where T2: Send + 'static, E2: Send + 'static {
        'outer: loop {
            for i in 0..recs.len() {
                match recs[i].try_recv() {
                    Ok(val) => {
                        let new_val = func(val);
                        let _ = tx.send(new_val).unwrap_or(());
                        return;
                    }
                    Err(err) => {
                        if err == TryRecvError::Disconnected {
                            recs.remove(i);
                        }
                    }
                }
            }
        }
    }

    fn promise_all(receivers: Vec<Receiver<Result<T, E>>>,
                          tx: Sender<Result<Vec<T>, E>>) {
        let mut values: Vec<T> = Vec::with_capacity(receivers.len());
        let mut mut_receivers = receivers;
        'outer: loop {
            for rec in receivers {
                match rec.try_recv() {
                    Ok(val) => {
                        match val {
                            Ok(t) => values.push(t),
                            Err(e) => {
                                let _ = tx.send(Err(e)).unwrap_or(());
                                return;
                            }
                        }
                    }
                    Err(err) => {
                        // Remove dead promises?
                    }
                }
            }
        }
    }
}
<commit_msg>Rename internal functions to impl_*<commit_after>//! Promises in Rust.
//! See the `Promise` struct for more details.

#![warn(missing_docs)]

use std::thread;
use std::sync::mpsc::channel;
use std::time::Duration;
use std::thread::JoinHandle;
use std::marker::{Send};
use std::sync::mpsc::{Sender, Receiver, TryRecvError};

/// A promise is a way of doing work in the background. The promises in
/// this library have the same featureset as those in Ecmascript 5.
///
/// # Promises
/// Promises (sometimes known as "futures") are objects that represent
/// asynchronous tasks being run in the background, or results which
/// will exist in the future.
/// A promise will be in state of running, fulfilled, or done. In order to
/// use the results of a fulfilled promise, one attaches another promise
/// to it (i.e. via `then`). Like their Javascript counterparts, promises can
/// return an error (of type `E`).
///
/// # Panics
/// If the function being executed by a promise panics, it does so silently.
/// The panic will not resurface in the thread which created the promise,
/// and promises waiting on its result will never be called. In addition,
/// the `all` and `race` proimse methods will _ignore_ "dead" promises. They
/// will remove promises from their lists, and if there aren't any left
/// they will silently exit without doing anything.
///
/// Unfortunately, panics must be ignored for two reasons:
/// * Panic messages don't have a concrete type yet in Rust. If they did,
/// promiess would be able to inspect their predecessors' errors.
/// * Although a `Receiver` can correctly handle its paired `Sender` being
/// dropped, such as during a panic, for reasons stated above the "message"
/// of the panic is not relayed.
///
/// Finally, Ecmascript promises themselves do have the ability to return
/// and error type, represented as a `Result<T, E>` here. Thus, one should
/// use `try!` and other error handling rather than calls to `unwrap()`.
pub struct Promise<T: Send, E: Send> {
    receiver: Receiver<Result<T, E>>
}

impl<T: Send + 'static, E: Send + 'static> Promise<T, E> {

    /// Chains a function to be called after this promise resolves.
    pub fn then<T2, E2>(self, callback: fn(t: T) -> Result<T2, E2>,
                              errback:  fn(e: E) -> Result<T2, E2>)
                        -> Promise<T2, E2>
    where T2: Send + 'static, E2: Send + 'static {
        let recv = self.receiver;
        let (tx, rx) = channel();

        let thread = thread::spawn(move || {
            Promise::impl_then(tx, recv, callback, errback);
        });
        return Promise { receiver: rx };
    }

    /// Chains a function to be called after this promise resolves,
    /// using a `Result` type.
    pub fn then_result<T2, E2>(self,
                               callback: fn(r: Result<T, E>) -> Result<T2, E2>)
                               -> Promise<T2, E2>
    where T2: Send + 'static, E2: Send + 'static {
        let recv = self.receiver;
        let (tx, rx) = channel();

        let thread = thread::spawn(move || {
            Promise::impl_then_result(tx, callback);
        });
        return Promise { receiver: rx };
    }

    /// Creates a new promsie, which will eventually resolve to one of the
    /// values of the `Result<T, E>` type.
    pub fn new<F>(func: F) -> Promise<T, E>
    where F: Send + 'static + FnOnce() -> Result<T, E> {
        let (tx, rx) = channel();

        let thread = thread::spawn(move || {
            Promise::impl_new(tx, func);
        });

        return Promise { receiver: rx };
    }

    /// Applies a promise to the first of some promises to become fulfilled.
    pub fn race(promises: Vec<Promise<T, E>>) -> Promise<T, E> {
        let recs = promises.into_iter().map(|p| p.receiver).collect();
        let (tx, rx) = channel();

        thread::spawn(move || {
            Promise::impl_race(tx, recs);
        });

        Promise { receiver: rx }
    }

    /// Calls a function with the result of all of the promises, or the error
    /// of the first promise to error.
    pub fn all(promises: Vec<Promise<T, E>>) -> Promise<Vec<T>, E> {
        let receivers: Vec<Receiver<Result<T, E>>> =
            promises.into_iter().map(|p| p.receiver).collect();
        let (tx, rx) = channel();

        thread::spawn(move || {
            Promise::impl_all(tx, receivers);
        });

        return Promise { receiver: rx };
    }

    /// Creates a promise that resolves to a value
    pub fn resolve(val: T) -> Promise<T, E> {
        Promise::from_result(Ok(val))
    }

    /// Creates a promise that resolves to an error.
    pub fn reject(val: E) -> Promise<T, E> {
        Promise::from_result(Err(val))
    }

    /// Creates a new promise that will resolve to the result value.
    pub fn from_result(result: Result<T, E>) -> Promise<T, E> {
        let (tx, rx) = channel();
        tx.send(result).unwrap();

        Promise { receiver: rx }
    }

    // Implementation Functions

    fn impl_new(tx: Sender<Result<T, E>>,
                func: Box<FnOnce() -> Result<T, E>>) {
        let result = func();
        tx.send(result).unwrap_or(());
    }

    fn impl_then<T2, E2>(tx: Sender<Result<T2, E2>>,
                            rx: Receiver<Result<T, E>>,
                            callback: fn(T) -> Result<T2, E2>,
                            errback: fn(E) -> Result<T2, E2>)
    where T2: Send + 'static, E2: Send + 'static {
        if let Ok(message) = rx.recv() {
            match message {
                Ok(val) => tx.send(callback(val)).unwrap_or(()),
                Err(err) => tx.send(errback(err)).unwrap_or(())
            };
        }
    }

    fn impl_then_result<T2, E2>(tx: Sender<Result<T2, E2>>,
                                rx: Receiver<Result<T, E>>,
                                callback: fn(Result<T, E>) -> Result<T2, E2>)
    where T2: Send + 'static, E2: Send + 'static {

        if let Ok(result) = rx.recv() {
            tx.send(callback(result)).unwrap_or(());
        }
    }

    // Static methods

    fn impl_race<T2, E2>(tx: Sender<Result<T, E>>,
                         recs: Vec<Receiver<Result<T, E>>>) {
        'outer: loop {
            // Don't get stuck in an infinite loop
            if recs.len() == 0 { return; }
            for i in 0..recs.len() {
                match recs[i].try_recv() {
                    Ok(val) => {
                        tx.send(val).unwrap_or(());
                        return;
                    }
                    Err(err) => {
                        if err == TryRecvError::Disconnected {
                            recs.remove(i);
                        }
                    }
                }
            }
        }
    }

    fn impl_all<T2, E2>(tx: Sender<Result<Vec<T>, E>>,
                        recs: Vec<Receiver<Result<T, E>>>) {
        let mut values: Vec<T> = Vec::with_capacity(recs.len());
        let mut mut_receivers = recs;
        'outer: loop {
            for i in 0..mut_receivers.len() {
                match mut_receivers[i].try_recv() {
                    Ok(val) => {
                        match val {
                            Ok(t) => values.push(t),
                            Err(_) => {
                                tx.send(val).unwrap_or(());
                                return;
                            }
                        }
                        mut_receivers.remove(i);
                    }
                    Err(err) => {
                        if err == TryRecvError::Disconnected {
                            mut_receivers.remove(i);
                        }
                    }
                }
            }
            // Check if we are finished waiting for promises
            // This can also happen if all promises panic
            if mut_receivers.len() == 0 {
                let result = Ok(values);
                tx.send(result).unwrap_or(());
                return; // Break from outer loop
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(catch_panic, fnbox)]
#[macro_use]
extern crate lazy_static;
mod util;
pub mod reporter;
mod world_state;
pub mod example_group;
mod example_group_and_block;

use std::string::ToString;
use std::thread::JoinHandle;
use std::sync::{Arc, Mutex};

use util::{await_handles, any_is_err};
use example_group_and_block::ExampleGroupAndBlock;

#[derive(Debug)]
struct World {
    state: Arc<Mutex<world_state::WorldState>>,
    example_groups: Vec<ExampleGroupAndBlock>,
}

fn with_world<F, T>(blk: F) -> T where F: FnOnce(&mut World) -> T {
    let c = WORLD.clone();
    let mut guard = c.lock().unwrap();
    blk(&mut guard)
}

fn consuming_world<F, T>(blk: F) -> T where F: FnOnce(World) -> T {
    let guard = WORLD.clone();
    let mut world_current = guard.lock().unwrap();
    let mut world = World::new();
    std::mem::swap(&mut world, &mut world_current);
    blk(world)

}

impl World {
    fn new() -> World {
        World {
            state: Arc::new(Mutex::new(world_state::WorldState {
                failed: false,
                reporter: reporter::Reporter,
            })),
            example_groups: Vec::new(),
        }
    }

    fn describe<F>(&mut self, description: &str, example_group_definition_block: F) where F: Fn(&mut example_group::ExampleGroup) + Send + 'static {
        self.example_groups.push(
            ExampleGroupAndBlock {
                group: example_group::ExampleGroup {
                    description: description.to_string(),
                    examples: Vec::new(),
                },
                block: Box::new(example_group_definition_block)
            }
        );
    }

    fn run(self) -> world_state::WorldState {
        let join_handles: Vec<_> = World::create_example_group_join_handles(self.state.clone(), self.example_groups);
        let results = await_handles(join_handles);
        let failed = any_is_err(results);

        let state_guard = self.state.clone();
        let mut state = state_guard.lock().unwrap();
        state.failed = failed;

        world_state::WorldState {
            failed: state.failed,
            reporter: reporter::Reporter

        }
    }

    fn create_example_group_join_handles(state: Arc<Mutex<world_state::WorldState>>, example_groups: Vec<ExampleGroupAndBlock>) -> Vec<JoinHandle<Result<(), ()>>> {
        example_groups.into_iter().map(|egab| {
            egab.spawn(&state)
        }).collect()
    }

}

lazy_static! {
    static ref WORLD: Arc<Mutex<World>> = Arc::new(Mutex::new(World::new()));
}

pub fn describe<F>(description: &str, example_group_definition_block: F) where F: Fn(&mut example_group::ExampleGroup) + Send + 'static {
    with_world(|world| {
        world.describe(description, example_group_definition_block);
    });
}

pub fn descriptor_main() {
    let state = consuming_world(|world| world.run());
    println!("{}", state.failed);
}
<commit_msg>Fixups<commit_after>#![feature(catch_panic, fnbox)]
#[macro_use]
extern crate lazy_static;
mod util;
pub mod reporter;
mod world_state;
pub mod example_group;
mod example_group_and_block;

use std::string::ToString;
use std::thread::JoinHandle;
use std::sync::{Arc, Mutex};

use util::{await_handles, any_is_err};
use example_group_and_block::ExampleGroupAndBlock;

#[derive(Debug)]
struct World {
    state: Arc<Mutex<world_state::WorldState>>,
    example_groups: Vec<ExampleGroupAndBlock>,
}

impl World {
    fn new() -> World {
        World {
            state: Arc::new(Mutex::new(world_state::WorldState {
                failed: false,
                reporter: reporter::Reporter,
            })),
            example_groups: Vec::new(),
        }
    }

    fn describe<F>(&mut self, description: &str, example_group_definition_block: F) where F: Fn(&mut example_group::ExampleGroup) + Send + 'static {
        self.example_groups.push(
            ExampleGroupAndBlock {
                group: example_group::ExampleGroup {
                    description: description.to_string(),
                    examples: Vec::new(),
                },
                block: Box::new(example_group_definition_block)
            }
        );
    }

    fn run(self) -> world_state::WorldState {
        let join_handles: Vec<_> = World::create_example_group_join_handles(self.state.clone(), self.example_groups);
        let results = await_handles(join_handles);
        let failed = any_is_err(results);

        let state_guard = self.state.clone();
        let mut state = state_guard.lock().unwrap();
        state.failed = failed;

        world_state::WorldState {
            failed: state.failed,
            reporter: reporter::Reporter

        }
    }

    fn create_example_group_join_handles(state: Arc<Mutex<world_state::WorldState>>, example_groups: Vec<ExampleGroupAndBlock>) -> Vec<JoinHandle<Result<(), ()>>> {
        example_groups.into_iter().map(|egab| {
            egab.spawn(&state)
        }).collect()
    }

}

lazy_static! {
    static ref WORLD: Arc<Mutex<World>> = Arc::new(Mutex::new(World::new()));
}

fn with_world<F, T>(blk: F) -> T where F: FnOnce(&mut World) -> T {
    let c = WORLD.clone();
    let mut guard = c.lock().unwrap();
    blk(&mut guard)
}

fn consuming_world<F, T>(blk: F) -> T where F: FnOnce(World) -> T {
    let guard = WORLD.clone();
    let mut world_current = guard.lock().unwrap();
    let mut world = World::new();
    std::mem::swap(&mut world, &mut world_current);
    blk(world)
}

pub fn describe<F>(description: &str, example_group_definition_block: F) where F: Fn(&mut example_group::ExampleGroup) + Send + 'static {
    with_world(|world| {
        world.describe(description, example_group_definition_block);
    });
}

pub fn descriptor_main() {
    let state = consuming_world(|world| world.run());
    println!("{}", state.failed);
}
<|endoftext|>


<commit_before>/// Calculate the crc64 checksum of the given data, starting with the given crc.
///
/// Implements the CRC64 used by Redis, which is the variant with "Jones" coefficients and init value of 0.
///
/// Specification of this CRC64 variant follows:
///
/// ```text
/// Name: crc-64-jones
/// Width: 64 bites
/// Poly: 0xad93d23594c935a9
/// Reflected In: True
/// Xor_In: 0xffffffffffffffff
/// Reflected_Out: True
/// Xor_Out: 0x0
/// Check("123456789"): 0xe9c6d914c4b8d9ca
/// ```
///
/// Example:
///
/// ```rust
/// crc64::crc64(0, "123456789".as_bytes());
/// ```

use std::io;
use std::io::Write;
use std::mem;
use crc_table::CRC64_TAB;
mod crc_table;

fn crc_reflect(data: u64, len: usize) -> u64 {
    let mut data = data;
    let mut ret = data & 0x01;

    let mut i = 1;
    while i < len {
        data >>= 1;
        ret = (ret << 1) | (data & 0x01);
        i+=1;
    }

    ret
}

fn crc64_trivial(crc: u64, in_data: &[u8]) -> u64 {
    let mut crc = crc;
    let len = in_data.len();

    let poly : u64 = 0xad93d23594c935a9;

    let mut bit : bool;

    let mut offset = 0;

    while offset < len {
        let c = in_data[offset];
        let mut i = 0x01;
        while i & 0xff != 0x0 {
            bit = crc & 0x8000000000000000 != 0x0;
            if c & i != 0x0 {
                bit = !bit;
            }
            crc <<= 1;
            if bit {
                crc ^= poly;
            }
            i <<= 1;
        }
        crc &= 0xffffffffffffffff;
        offset+=1;
    }
    crc = crc & 0xffffffffffffffff;

    return crc_reflect(crc, 64) ^ 0x0000000000000000;
}

pub fn crc64_init() -> Vec<Vec<u64>> {
    let mut crc : u64;

    let mut table : Vec<Vec<u64>> = Vec::with_capacity(8);

    for _ in 0..8 {
        table.push(Vec::with_capacity(256));
    };

    for n in 0..256 {
        table[0].push(crc64_trivial(0, &vec![n as u8]));
        table[1].push(0);
        table[2].push(0);
        table[3].push(0);
        table[4].push(0);
        table[5].push(0);
        table[6].push(0);
        table[7].push(0);
    }

    for n in 0..256 {
        crc = table[0][n];
        for k in 1..8 {
            let idx  = (crc as usize) & 0xff;
            crc = table[0][idx] ^ (crc >> 8);
            table[k][n] = crc;
        }
    };

    table
}

// transmute slice of 8 u8 values to one u64 (drop the length)
macro_rules! slice_to_long {
    ($curVec:expr) => {
        {
            unsafe {
                let (tmp, _) : (*const u64, usize) = mem::transmute(&$curVec);
                *tmp
            }
        }
    }
}

pub fn crc64(crc: u64, data: &[u8]) -> u64 {
    let mut crc = crc;
    let mut len = data.len();
    let mut offset = 0usize;

    while len >= 8 {
        crc ^= slice_to_long!(data[offset..(offset+8)]);
        crc = CRC64_TAB[7][(crc & 0xff) as usize] ^
              CRC64_TAB[6][((crc >> 8) & 0xff) as usize] ^
              CRC64_TAB[5][((crc >> 16) & 0xff) as usize] ^
              CRC64_TAB[4][((crc >> 24) & 0xff) as usize] ^
              CRC64_TAB[3][((crc >> 32) & 0xff) as usize] ^
              CRC64_TAB[2][((crc >> 40) & 0xff) as usize] ^
              CRC64_TAB[1][((crc >> 48) & 0xff) as usize] ^
              CRC64_TAB[0][(crc >> 56) as usize];

        offset += 8;
        len -= 8;
    }

    while len > 0 {
        crc = CRC64_TAB[0][((crc ^ data[offset] as u64) & 0xff) as usize] ^ (crc >> 8);
        offset += 1;
        len -= 1;
    }

    crc
}

pub struct Crc64 {
    crc64: u64,
}

impl Crc64 {
    pub fn new() -> Crc64 {
        Crc64 { crc64: 0 }
    }
    pub fn get(&self) -> u64 {
        self.crc64
    }
}

impl Write for Crc64 {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.crc64 = crc64(self.crc64, buf);
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

#[test]
fn test_crc64_works() {
    assert_eq!(0xe9c6d914c4b8d9ca, crc64(0, "123456789".as_bytes()))
}

#[test]
fn test_crc64_write() {
    let step1 = "12345".as_bytes();
    let step2 = "6789".as_bytes();
    let value1 = 17326901458626182669;
    let value2 = 16845390139448941002;
    assert_eq!(value1, crc64(0, &step1));
    assert_eq!(value2, crc64(value1, &step2));

    let mut crc = Crc64::new();
    assert_eq!(crc.write(&step1).unwrap(), step1.len());
    assert_eq!(value1, crc.get());
    assert_eq!(crc.write(&step2).unwrap(), step2.len());
    assert_eq!(value2, crc.get());
}
<commit_msg>docs: Proper module documentation<commit_after>//! Calculate the crc64 checksum of the given data, starting with the given crc.
//!
//! Implements the CRC64 used by Redis, which is the variant with "Jones" coefficients and init value of 0.
//!
//! Specification of this CRC64 variant follows:
//!
//! ```text
//! Name: crc-64-jones
//! Width: 64 bites
//! Poly: 0xad93d23594c935a9
//! Reflected In: True
//! Xor_In: 0xffffffffffffffff
//! Reflected_Out: True
//! Xor_Out: 0x0
//! Check("123456789"): 0xe9c6d914c4b8d9ca
//! ```
//!
//! Example:
//!
//! ```rust
//! let cksum = crc64::crc64(0, "123456789".as_bytes());
//! assert_eq!(16845390139448941002, cksum);
//! ```

use std::io;
use std::io::Write;
use std::mem;
use crc_table::CRC64_TAB;
mod crc_table;

fn crc_reflect(data: u64, len: usize) -> u64 {
    let mut data = data;
    let mut ret = data & 0x01;

    let mut i = 1;
    while i < len {
        data >>= 1;
        ret = (ret << 1) | (data & 0x01);
        i+=1;
    }

    ret
}

fn crc64_trivial(crc: u64, in_data: &[u8]) -> u64 {
    let mut crc = crc;
    let len = in_data.len();

    let poly : u64 = 0xad93d23594c935a9;

    let mut bit : bool;

    let mut offset = 0;

    while offset < len {
        let c = in_data[offset];
        let mut i = 0x01;
        while i & 0xff != 0x0 {
            bit = crc & 0x8000000000000000 != 0x0;
            if c & i != 0x0 {
                bit = !bit;
            }
            crc <<= 1;
            if bit {
                crc ^= poly;
            }
            i <<= 1;
        }
        crc &= 0xffffffffffffffff;
        offset+=1;
    }
    crc = crc & 0xffffffffffffffff;

    return crc_reflect(crc, 64) ^ 0x0000000000000000;
}

pub fn crc64_init() -> Vec<Vec<u64>> {
    let mut crc : u64;

    let mut table : Vec<Vec<u64>> = Vec::with_capacity(8);

    for _ in 0..8 {
        table.push(Vec::with_capacity(256));
    };

    for n in 0..256 {
        table[0].push(crc64_trivial(0, &vec![n as u8]));
        table[1].push(0);
        table[2].push(0);
        table[3].push(0);
        table[4].push(0);
        table[5].push(0);
        table[6].push(0);
        table[7].push(0);
    }

    for n in 0..256 {
        crc = table[0][n];
        for k in 1..8 {
            let idx  = (crc as usize) & 0xff;
            crc = table[0][idx] ^ (crc >> 8);
            table[k][n] = crc;
        }
    };

    table
}

// transmute slice of 8 u8 values to one u64 (drop the length)
macro_rules! slice_to_long {
    ($curVec:expr) => {
        {
            unsafe {
                let (tmp, _) : (*const u64, usize) = mem::transmute(&$curVec);
                *tmp
            }
        }
    }
}

pub fn crc64(crc: u64, data: &[u8]) -> u64 {
    let mut crc = crc;
    let mut len = data.len();
    let mut offset = 0usize;

    while len >= 8 {
        crc ^= slice_to_long!(data[offset..(offset+8)]);
        crc = CRC64_TAB[7][(crc & 0xff) as usize] ^
              CRC64_TAB[6][((crc >> 8) & 0xff) as usize] ^
              CRC64_TAB[5][((crc >> 16) & 0xff) as usize] ^
              CRC64_TAB[4][((crc >> 24) & 0xff) as usize] ^
              CRC64_TAB[3][((crc >> 32) & 0xff) as usize] ^
              CRC64_TAB[2][((crc >> 40) & 0xff) as usize] ^
              CRC64_TAB[1][((crc >> 48) & 0xff) as usize] ^
              CRC64_TAB[0][(crc >> 56) as usize];

        offset += 8;
        len -= 8;
    }

    while len > 0 {
        crc = CRC64_TAB[0][((crc ^ data[offset] as u64) & 0xff) as usize] ^ (crc >> 8);
        offset += 1;
        len -= 1;
    }

    crc
}

pub struct Crc64 {
    crc64: u64,
}

impl Crc64 {
    pub fn new() -> Crc64 {
        Crc64 { crc64: 0 }
    }
    pub fn get(&self) -> u64 {
        self.crc64
    }
}

impl Write for Crc64 {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.crc64 = crc64(self.crc64, buf);
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

#[test]
fn test_crc64_works() {
    assert_eq!(0xe9c6d914c4b8d9ca, crc64(0, "123456789".as_bytes()))
}

#[test]
fn test_crc64_write() {
    let step1 = "12345".as_bytes();
    let step2 = "6789".as_bytes();
    let value1 = 17326901458626182669;
    let value2 = 16845390139448941002;
    assert_eq!(value1, crc64(0, &step1));
    assert_eq!(value2, crc64(value1, &step2));

    let mut crc = Crc64::new();
    assert_eq!(crc.write(&step1).unwrap(), step1.len());
    assert_eq!(value1, crc.get());
    assert_eq!(crc.write(&step2).unwrap(), step2.len());
    assert_eq!(value2, crc.get());
}
<|endoftext|>


<commit_before>#![feature(asm)]
#![feature(no_std)]
#![no_std]

#[test]
fn it_works() {
}
<commit_msg>Add skeletal kernel source<commit_after>#![crate_name = "sos_kernel"]
#![crate_type = "staticlib"]
#![feature(asm)]
#![feature(no_std, lang_items)]
#![no_std]

/// Kernel main loop
#[no_mangle]
pub extern fn kernel_main() {}

/// Required for Rust stack unwinding
#[lang = "eh_personality"]
extern fn eh_personality() {
    // TODO: add support for stack unwinding
}

#[lang = "panic_fmt"]
extern fn panic_fmt() -> ! {
    // TODO: actually format panics (waiting for robust VGA support)
    loop{}
}
<|endoftext|>


<commit_before>extern crate libc;

pub mod instruction;
pub mod constants;
mod ffi;
pub mod capstone;

pub use instruction::*;
pub use constants::*;

pub use capstone::Capstone;

/// An opaque reference to a capstone engine.
///
/// bindgen by default used this type name everywhere, so it is easier to leave it with a confusing
/// name.
///
/// It should not be exported, rust's new visibility rules make tackling this not immediately
/// obvious
#[allow(non_camel_case_types)]
type csh = libc::c_ulong;

#[cfg(test)]
mod test {
    use super::*;
    static CODE: &'static [u8] = b"\x55\x48\x8b\x05\xb8\x13\x00\x00";

    #[test]
    fn test_x86_simple() {
        match capstone::Capstone::new(constants::CsArch::ARCH_X86, constants::CsMode::MODE_64) {
            Some(cs) => {
                if let Some(insns) = cs.disasm(CODE, 0x1000, 0) {
                    assert_eq!(insns.len(), 2);
                    let is: Vec<_> = insns.iter().collect();
                    assert_eq!(is[0].mnemonic().unwrap(), "push");
                    assert_eq!(is[1].mnemonic().unwrap(), "mov");

                    assert_eq!(is[0].address, 0x1000);
                    assert_eq!(is[1].address, 0x1001);
                } else {
                    assert!(false, "Couldn't disasm instructions")
                }

                let reg_id = 1;
                match cs.reg_name(reg_id) {
                    Some(reg_name) => assert_eq!(reg_name, "ah"),
                    None => assert!(false, "Couldn't get register name"),
                }

                let insn_id = 1;
                match cs.insn_name(insn_id) {
                    Some(insn_name) => assert_eq!(insn_name, "aaa"),
                    None => assert!(false, "Couldn't get instruction name"),
                }
            }
            None => {
                assert!(false, "Couldn't create a cs engine");
            }
        }
    }
}
<commit_msg>Update tests for new format<commit_after>extern crate libc;

pub mod instruction;
pub mod constants;
mod ffi;
pub mod capstone;

pub use instruction::*;
pub use constants::*;

pub use capstone::Capstone;

/// An opaque reference to a capstone engine.
///
/// bindgen by default used this type name everywhere, so it is easier to leave it with a confusing
/// name.
///
/// It should not be exported, rust's new visibility rules make tackling this not immediately
/// obvious
#[allow(non_camel_case_types)]
type csh = libc::c_ulong;

#[cfg(test)]
mod test {
    use super::*;
    static CODE: &'static [u8] = b"\x55\x48\x8b\x05\xb8\x13\x00\x00";

    #[test]
    fn test_x86_simple() {
        match capstone::Capstone::new(constants::CsArch::ARCH_X86, constants::CsMode::MODE_64) {
            Ok(cs) => {
                match cs.disasm(CODE, 0x1000, 0) {
                    Ok(insns) => {
                        assert_eq!(insns.len(), 2);
                        let is: Vec<_> = insns.iter().collect();
                        assert_eq!(is[0].mnemonic().unwrap(), "push");
                        assert_eq!(is[1].mnemonic().unwrap(), "mov");

                        assert_eq!(is[0].address, 0x1000);
                        assert_eq!(is[1].address, 0x1001);
                    },
                    Err(err) => {
                        assert!(false, format!("Couldn't disasm instructions: {}", err.to_string()))
                    }
                }
                let reg_id = 1;
                match cs.reg_name(reg_id) {
                    Ok(reg_name) => assert_eq!(reg_name, "ah"),
                    Err(err) => assert!(false, format!("Couldn't get register name: {}", err.to_string())),
                }

                let insn_id = 1;
                match cs.insn_name(insn_id) {
                    Ok(insn_name) => assert_eq!(insn_name, "aaa"),
                    Err(err) => assert!(false, format!("Couldn't get instruction name: {}", err.to_string())),
                }
            }
            Err(e) => {
                assert!(false, format!("Couldn't create a cs engine: {}", e.to_string()));
            }
        }
    }
}
<|endoftext|>


<commit_before>// (c) 2015 Joost Yervante Damad <joost@damad.be>

// loosely based on https://github.com/cgaebel/sexp
// latest version can be found at https://github.com/andete/rust_sexp

use std::fmt;
use std::str::FromStr;
use std::f64;

use std::fs::File;
use std::io::prelude::*;

pub enum Atom {
  S(String),
  Q(String),
  I(i64),
  F(f64),
}

impl Atom {
    pub fn f(&self) -> Result<f64,String> {
        match *self {
            Atom::F(f) => Ok(f),
            Atom::I(i) => Ok(i as f64),
            ref x => Err(format!("not a float: {}", x))
        }
    }
    pub fn i(&self) -> Result<i64,String> {
        match *self {
            Atom::I(i) => Ok(i),
            ref x => Err(format!("not an int: {}", x))
        }
    }
    pub fn string(&self) -> Result<String,String> {
        match *self {
            Atom::S(ref s) => Ok(s.clone()),
            Atom::Q(ref s) => Ok(s.clone()),
            ref x => Err(format!("not a string: {}", x))
        }
    }
    pub fn as_string(&self) -> Result<String,String> {
        match *self {
            Atom::S(ref s) => Ok(s.clone()),
            Atom::Q(ref s) => Ok(s.clone()),
            Atom::F(ref s) => Ok(format!("{}", s)),
            Atom::I(ref s) => Ok(format!("{}", s)),
        }
    }
}

pub enum Sexp {
  Atom(Atom),
  Empty,
  List(Vec<Sexp>),
}

impl Sexp {
    pub fn atom(&self) -> Result<&Atom,String> {
        match *self {
            Sexp::Atom(ref f) => Ok(f),
            ref x => Err(format!("not an atom: {}", x))
        }
    }
    pub fn list(&self) -> Result<&Vec<Sexp>,String> {
        match *self {
            Sexp::List(ref v) => Ok(v),
            ref x => Err(format!("not a list: {}", x))
        }
    }
}

pub struct ParseError {
    msg: &'static str,
    line: usize,
    lpos: usize,
}

pub enum Error {
    ParseError(ParseError),
    IOError(std::io::Error),
}

pub type ERes<T> = Result<T, Error>;

fn err_parse<T>(msg: &'static str, state: &ParseState) -> ERes<T> {
    Err(Error::ParseError(ParseError { msg: msg, line: state.line, lpos: state.lpos}))
}

fn err_io<T>(err: std::io::Error) -> ERes<T> {
    Err(Error::IOError(err))
}

struct ParseState {
    pos: usize,
    line: usize,
    lpos: usize,
    vec: Vec<char>,
    len: usize,
}

impl ParseState {
    fn peek(&self) -> ERes<char> {
        if self.pos >= self.len {
            return err_parse("end of document reached", self)
        }
        Ok(self.vec[self.pos])
    }
    fn peek_option(&self) -> Option<char> {
        if self.pos >= self.len {
            return None
        }
        Some(self.vec[self.pos])
    }
    fn next(&mut self) -> ERes<()> {
        if self.pos >= self.len {
            return err_parse("end of document reached", self)
        }
        let c = self.vec[self.pos];
        self.pos += 1;
        match c {
            '\r' | '\n' => {
                self.lpos = 0;
                self.line += 1;
            }
            _ => {
                self.lpos += 1;
            }
        }
        Ok(())
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::ParseError(ref p) =>
                write!(f, "Parse Error {}:{}: {}", p.line, p.lpos, p.msg),
            Error::IOError(ref i) =>
                write!(f, "{}", i)
        }
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::ParseError(ref p) =>
                write!(f, "Parse Error {}:{}: {}", p.line, p.lpos, p.msg),
            Error::IOError(ref i) =>
                write!(f, "{}", i)
        }
    }
}

impl fmt::Display for Atom {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
        Atom::S(ref s) => write!(f, "{}", s),
        Atom::Q(ref s) => write!(f, "\"{}\"", s),
        Atom::I(i)     => write!(f, "{}", i),
        Atom::F(d)     => {
            let z = d.floor();
            if d - z < f64::EPSILON {
                write!(f, "{}.0", z)
            } else {
                write!(f, "{}", d)
            }
        }
    }
  }
}

impl fmt::Display for Sexp {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
      Sexp::Atom(ref a) => write!(f, "{}", a),
      Sexp::List(ref xs) => {
        try!(write!(f, "("));
        for (i, x) in xs.iter().enumerate() {
          let s = if i == 0 { "" } else { " " };
          try!(write!(f, "{}{}", s, x));
        }
        write!(f, ")")
      },
      Sexp::Empty => write!(f, ""),
    }
  }
}

fn parse_list(state: &mut ParseState) -> ERes<Sexp> {
    //println!("list");
    try!(state.next()); // skip (
    let mut l: Vec<Sexp> = Vec::new();
    loop {
        match try!(state.peek()) {
            ')' => {
                try!(state.next());
                break;
            }
            _ => {
                l.push(try!(parse_sexp(state)));
            }
        }
    }
    //println!("Found list");
    Ok(Sexp::List(l))
}

fn parse_quoted_string(state: &mut ParseState) -> ERes<Atom> {
    //println!("qstring");
    try!(state.next()); // skip "
    let mut s = String::new();
    loop {
        match try!(state.peek()) {
            '"' => {
                try!(state.next());
                break
            }
            x @ '\r' | x @ '\n' => {
                s.push(x);
                try!(state.next());
                }
            x => {
                s.push(x);
                try!(state.next());
            }
        }
    }
    //println!("Found quoted string {}", s);
    Ok(Atom::Q(s))
}

fn parse_string(state: &mut ParseState) -> ERes<Atom> {
    //println!("string");
    let mut s = String::new();
    loop {
        match state.peek_option() {
            Some(x) => {
                match x {
                    ' ' | '\t' | '\r' | '\n' | ')' => break,
                    '"' => return err_parse("unexpected \" in string", state),
                    x => s.push(x),
                }
            }
            None => {
                break;
            }
        }
        try!(state.next())
    }
    //println!("Found string {}", s);
    Ok(Atom::S(s))
}

fn parse_number(state: &mut ParseState) -> ERes<Atom> {
    //println!("number");
    let mut s = String::new();
    loop {
        match state.peek_option() {
            Some(x) => {
                match x {
                    ' ' | '\r' | '\n' | '\t' | ')' => {
                        break
                    },
                    '0' ... '9' | '.' | '-' => {
                        s.push(state.vec[state.pos])
                    },
                    _ => {
                        return err_parse("unexpected char in number", state)
                    },
                }
            }
            None => {
                break
            }
        }
        try!(state.next())
    }
    //println!("Found number {}", s);
    let s2: &str = &s[..];
    if s.contains('.') {
        Ok(Atom::F(f64::from_str(s2).unwrap()))
    } else {
        Ok(Atom::I(i64::from_str(s2).unwrap()))
    }
}

fn parse_atom(state: &mut ParseState) -> ERes<Sexp> {
    //println!("atom");
    let a = match try!(state.peek()) {
        '"' => {
            try!(parse_quoted_string(state))
        }
        '0' ... '9' | '.' | '-' => {
            try!(parse_number(state))
        }
        _ => {
            try!(parse_string(state))
        }
    };
    Ok(Sexp::Atom(a))
}

fn parse_sexp(state: &mut ParseState) -> ERes<Sexp> {
    loop {
        match try!(state.peek()) {
            '(' => {
                return parse_list(state)
            }
            ' ' | '\t' | '\r' | '\n' => {
                try!(state.next());
            }
            ')' => {
                return err_parse("unmatched )", state)
            }
            _ => {
                return parse_atom(state)
            }
        }
    }
}

fn parse(data: &str) -> ERes<Sexp> {
    if data.len() == 0 {
        Ok(Sexp::Empty)
    } else {
        let vec: Vec<char> = data.chars().collect();
        let len = vec.len();
        let state = &mut ParseState { pos: 0, line: 1, lpos: 0, vec: vec, len: len };
        parse_sexp(state)
    }
}

fn read_file(name: &str) -> Result<String, std::io::Error> {
    let mut f = try!(File::open(name));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_str(s: &str) -> ERes<Sexp> {
    parse(s)
}

pub fn parse_file(name: &str) -> ERes<Sexp> {
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => err_io(x),
    });
    parse(&s[..])
}

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

    #[allow(dead_code)]
    fn check_parse(s: &str) {
        let e = parse_str(s).unwrap();
        let t = format!("{}", e);
        assert_eq!(s, t);
    }

    #[allow(dead_code)]
    fn parse_fail(s: &str) {
        parse_str(s).unwrap();
    }

    #[test]
    fn test_empty() { check_parse("") }

    #[test]
    fn test_minimal() { check_parse("()") }

    #[test]
    fn test_string() { check_parse("hello") }

    #[test]
    fn test_qstring() { check_parse("\"hello\"") }

    #[test]
    fn test_number() { check_parse("1.3") }

    #[test]
    fn test_float_vs_int() { check_parse("2.0") }

    #[test]
    fn test_double() { check_parse("(())") }

    #[test]
    fn test_br_string() { check_parse("(world)") }

    #[test]
    fn test_br_qstring() { check_parse("(\"world\")") }

    #[test]
    fn test_br_int() { check_parse("(42)") }

    #[test]
    fn test_br_float() { check_parse("(12.7)") }

    #[test]
    fn test_br_qbrstring() { check_parse("(\"(()\")") }

    #[test]
    #[should_panic(expected="Parse Error 1:1: end of document reached")]
    fn test_invalid1() { parse_fail("(") }

    #[test]
    #[should_panic(expected="Parse Error 1:0: unmatched )")]
    fn test_invalid2() { parse_fail(")") }

    #[test]
    #[should_panic(expected="Parse Error 1:6: end of document reached")]
    fn test_invalid3() { parse_fail("\"hello") }

    #[test]
    fn test_complex() { check_parse("(module SWITCH_3W_SIDE_MMP221-R (layer F.Cu) (descr \"\") (pad 1 thru_hole rect (size 1.2 1.2) (at -2.5 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 2 thru_hole rect (size 1.2 1.2) (at 0.0 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 3 thru_hole rect (size 1.2 1.2) (at 2.5 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 5 thru_hole rect (size 1.2 1.2) (at 0.0 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 6 thru_hole rect (size 1.2 1.2) (at -2.5 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 4 thru_hole rect (size 1.2 1.2) (at 2.5 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (fp_line (start -4.5 -1.75) (end 4.5 -1.75) (layer F.SilkS) (width 0.127)) (fp_line (start 4.5 -1.75) (end 4.5 1.75) (layer F.SilkS) (width 0.127)) (fp_line (start 4.5 1.75) (end -4.5 1.75) (layer F.SilkS) (width 0.127)) (fp_line (start -4.5 1.75) (end -4.5 -1.75) (layer F.SilkS) (width 0.127)))") }
}
<commit_msg>fix email<commit_after>// (c) 2015 Joost Yervante Damad <joost@productize.be>

// loosely based on https://github.com/cgaebel/sexp
// latest version can be found at https://github.com/andete/rust_sexp

use std::fmt;
use std::str::FromStr;
use std::f64;

use std::fs::File;
use std::io::prelude::*;

pub enum Atom {
  S(String),
  Q(String),
  I(i64),
  F(f64),
}

impl Atom {
    pub fn f(&self) -> Result<f64,String> {
        match *self {
            Atom::F(f) => Ok(f),
            Atom::I(i) => Ok(i as f64),
            ref x => Err(format!("not a float: {}", x))
        }
    }
    pub fn i(&self) -> Result<i64,String> {
        match *self {
            Atom::I(i) => Ok(i),
            ref x => Err(format!("not an int: {}", x))
        }
    }
    pub fn string(&self) -> Result<String,String> {
        match *self {
            Atom::S(ref s) => Ok(s.clone()),
            Atom::Q(ref s) => Ok(s.clone()),
            ref x => Err(format!("not a string: {}", x))
        }
    }
    pub fn as_string(&self) -> Result<String,String> {
        match *self {
            Atom::S(ref s) => Ok(s.clone()),
            Atom::Q(ref s) => Ok(s.clone()),
            Atom::F(ref s) => Ok(format!("{}", s)),
            Atom::I(ref s) => Ok(format!("{}", s)),
        }
    }
}

pub enum Sexp {
  Atom(Atom),
  Empty,
  List(Vec<Sexp>),
}

impl Sexp {
    pub fn atom(&self) -> Result<&Atom,String> {
        match *self {
            Sexp::Atom(ref f) => Ok(f),
            ref x => Err(format!("not an atom: {}", x))
        }
    }
    pub fn list(&self) -> Result<&Vec<Sexp>,String> {
        match *self {
            Sexp::List(ref v) => Ok(v),
            ref x => Err(format!("not a list: {}", x))
        }
    }
}

pub struct ParseError {
    msg: &'static str,
    line: usize,
    lpos: usize,
}

pub enum Error {
    ParseError(ParseError),
    IOError(std::io::Error),
}

pub type ERes<T> = Result<T, Error>;

fn err_parse<T>(msg: &'static str, state: &ParseState) -> ERes<T> {
    Err(Error::ParseError(ParseError { msg: msg, line: state.line, lpos: state.lpos}))
}

fn err_io<T>(err: std::io::Error) -> ERes<T> {
    Err(Error::IOError(err))
}

struct ParseState {
    pos: usize,
    line: usize,
    lpos: usize,
    vec: Vec<char>,
    len: usize,
}

impl ParseState {
    fn peek(&self) -> ERes<char> {
        if self.pos >= self.len {
            return err_parse("end of document reached", self)
        }
        Ok(self.vec[self.pos])
    }
    fn peek_option(&self) -> Option<char> {
        if self.pos >= self.len {
            return None
        }
        Some(self.vec[self.pos])
    }
    fn next(&mut self) -> ERes<()> {
        if self.pos >= self.len {
            return err_parse("end of document reached", self)
        }
        let c = self.vec[self.pos];
        self.pos += 1;
        match c {
            '\r' | '\n' => {
                self.lpos = 0;
                self.line += 1;
            }
            _ => {
                self.lpos += 1;
            }
        }
        Ok(())
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::ParseError(ref p) =>
                write!(f, "Parse Error {}:{}: {}", p.line, p.lpos, p.msg),
            Error::IOError(ref i) =>
                write!(f, "{}", i)
        }
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::ParseError(ref p) =>
                write!(f, "Parse Error {}:{}: {}", p.line, p.lpos, p.msg),
            Error::IOError(ref i) =>
                write!(f, "{}", i)
        }
    }
}

impl fmt::Display for Atom {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
        Atom::S(ref s) => write!(f, "{}", s),
        Atom::Q(ref s) => write!(f, "\"{}\"", s),
        Atom::I(i)     => write!(f, "{}", i),
        Atom::F(d)     => {
            let z = d.floor();
            if d - z < f64::EPSILON {
                write!(f, "{}.0", z)
            } else {
                write!(f, "{}", d)
            }
        }
    }
  }
}

impl fmt::Display for Sexp {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
      Sexp::Atom(ref a) => write!(f, "{}", a),
      Sexp::List(ref xs) => {
        try!(write!(f, "("));
        for (i, x) in xs.iter().enumerate() {
          let s = if i == 0 { "" } else { " " };
          try!(write!(f, "{}{}", s, x));
        }
        write!(f, ")")
      },
      Sexp::Empty => write!(f, ""),
    }
  }
}

fn parse_list(state: &mut ParseState) -> ERes<Sexp> {
    //println!("list");
    try!(state.next()); // skip (
    let mut l: Vec<Sexp> = Vec::new();
    loop {
        match try!(state.peek()) {
            ')' => {
                try!(state.next());
                break;
            }
            _ => {
                l.push(try!(parse_sexp(state)));
            }
        }
    }
    //println!("Found list");
    Ok(Sexp::List(l))
}

fn parse_quoted_string(state: &mut ParseState) -> ERes<Atom> {
    //println!("qstring");
    try!(state.next()); // skip "
    let mut s = String::new();
    loop {
        match try!(state.peek()) {
            '"' => {
                try!(state.next());
                break
            }
            x @ '\r' | x @ '\n' => {
                s.push(x);
                try!(state.next());
                }
            x => {
                s.push(x);
                try!(state.next());
            }
        }
    }
    //println!("Found quoted string {}", s);
    Ok(Atom::Q(s))
}

fn parse_string(state: &mut ParseState) -> ERes<Atom> {
    //println!("string");
    let mut s = String::new();
    loop {
        match state.peek_option() {
            Some(x) => {
                match x {
                    ' ' | '\t' | '\r' | '\n' | ')' => break,
                    '"' => return err_parse("unexpected \" in string", state),
                    x => s.push(x),
                }
            }
            None => {
                break;
            }
        }
        try!(state.next())
    }
    //println!("Found string {}", s);
    Ok(Atom::S(s))
}

fn parse_number(state: &mut ParseState) -> ERes<Atom> {
    //println!("number");
    let mut s = String::new();
    loop {
        match state.peek_option() {
            Some(x) => {
                match x {
                    ' ' | '\r' | '\n' | '\t' | ')' => {
                        break
                    },
                    '0' ... '9' | '.' | '-' => {
                        s.push(state.vec[state.pos])
                    },
                    _ => {
                        return err_parse("unexpected char in number", state)
                    },
                }
            }
            None => {
                break
            }
        }
        try!(state.next())
    }
    //println!("Found number {}", s);
    let s2: &str = &s[..];
    if s.contains('.') {
        Ok(Atom::F(f64::from_str(s2).unwrap()))
    } else {
        Ok(Atom::I(i64::from_str(s2).unwrap()))
    }
}

fn parse_atom(state: &mut ParseState) -> ERes<Sexp> {
    //println!("atom");
    let a = match try!(state.peek()) {
        '"' => {
            try!(parse_quoted_string(state))
        }
        '0' ... '9' | '.' | '-' => {
            try!(parse_number(state))
        }
        _ => {
            try!(parse_string(state))
        }
    };
    Ok(Sexp::Atom(a))
}

fn parse_sexp(state: &mut ParseState) -> ERes<Sexp> {
    loop {
        match try!(state.peek()) {
            '(' => {
                return parse_list(state)
            }
            ' ' | '\t' | '\r' | '\n' => {
                try!(state.next());
            }
            ')' => {
                return err_parse("unmatched )", state)
            }
            _ => {
                return parse_atom(state)
            }
        }
    }
}

fn parse(data: &str) -> ERes<Sexp> {
    if data.len() == 0 {
        Ok(Sexp::Empty)
    } else {
        let vec: Vec<char> = data.chars().collect();
        let len = vec.len();
        let state = &mut ParseState { pos: 0, line: 1, lpos: 0, vec: vec, len: len };
        parse_sexp(state)
    }
}

fn read_file(name: &str) -> Result<String, std::io::Error> {
    let mut f = try!(File::open(name));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_str(s: &str) -> ERes<Sexp> {
    parse(s)
}

pub fn parse_file(name: &str) -> ERes<Sexp> {
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => err_io(x),
    });
    parse(&s[..])
}

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

    #[allow(dead_code)]
    fn check_parse(s: &str) {
        let e = parse_str(s).unwrap();
        let t = format!("{}", e);
        assert_eq!(s, t);
    }

    #[allow(dead_code)]
    fn parse_fail(s: &str) {
        parse_str(s).unwrap();
    }

    #[test]
    fn test_empty() { check_parse("") }

    #[test]
    fn test_minimal() { check_parse("()") }

    #[test]
    fn test_string() { check_parse("hello") }

    #[test]
    fn test_qstring() { check_parse("\"hello\"") }

    #[test]
    fn test_number() { check_parse("1.3") }

    #[test]
    fn test_float_vs_int() { check_parse("2.0") }

    #[test]
    fn test_double() { check_parse("(())") }

    #[test]
    fn test_br_string() { check_parse("(world)") }

    #[test]
    fn test_br_qstring() { check_parse("(\"world\")") }

    #[test]
    fn test_br_int() { check_parse("(42)") }

    #[test]
    fn test_br_float() { check_parse("(12.7)") }

    #[test]
    fn test_br_qbrstring() { check_parse("(\"(()\")") }

    #[test]
    #[should_panic(expected="Parse Error 1:1: end of document reached")]
    fn test_invalid1() { parse_fail("(") }

    #[test]
    #[should_panic(expected="Parse Error 1:0: unmatched )")]
    fn test_invalid2() { parse_fail(")") }

    #[test]
    #[should_panic(expected="Parse Error 1:6: end of document reached")]
    fn test_invalid3() { parse_fail("\"hello") }

    #[test]
    fn test_complex() { check_parse("(module SWITCH_3W_SIDE_MMP221-R (layer F.Cu) (descr \"\") (pad 1 thru_hole rect (size 1.2 1.2) (at -2.5 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 2 thru_hole rect (size 1.2 1.2) (at 0.0 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 3 thru_hole rect (size 1.2 1.2) (at 2.5 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 5 thru_hole rect (size 1.2 1.2) (at 0.0 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 6 thru_hole rect (size 1.2 1.2) (at -2.5 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 4 thru_hole rect (size 1.2 1.2) (at 2.5 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (fp_line (start -4.5 -1.75) (end 4.5 -1.75) (layer F.SilkS) (width 0.127)) (fp_line (start 4.5 -1.75) (end 4.5 1.75) (layer F.SilkS) (width 0.127)) (fp_line (start 4.5 1.75) (end -4.5 1.75) (layer F.SilkS) (width 0.127)) (fp_line (start -4.5 1.75) (end -4.5 -1.75) (layer F.SilkS) (width 0.127)))") }
}
<|endoftext|>