<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! This module is the main module for the Ligature project.
//! It represents to common types and traits used by Ligature.

#![deny(missing_docs)]
//#![deny(missing_doc_example)] <-- for later, when I'm swole

#[macro_use]
extern crate lazy_static;

use regex::Regex;

/// A string that represents a Dataset by name.
/// Currently can only be ASCII text separated by /
#[derive(Debug)]
pub struct Dataset(String);

impl Dataset {
    /// Creates a new Dataset and returns a Result based on if it is valid or not.
    pub fn new(name: &str) -> Result<Dataset, LigatureError> {
        lazy_static! {
            static ref RE: Regex = Regex::new(r"^[a-zA-Z_]+(/[a-zA-Z0-9_]+)*$").unwrap();
        }

        if RE.is_match(name) {
            Ok(Dataset(name.to_string()))
        } else {
            Err(LigatureError(format!("Invalid Dataset name {}", name)))
        }
    }

    /// Returns the name of the given Dataset.
    pub fn name(&self) -> &str {
        &self.0
    }
}

/// A node that is only identified by a unique u64 id.
#[derive(Debug)]
pub struct BlankNode(u64);

/// An IRI is represented via https://www.ietf.org/rfc/rfc3987.txt
/// TODO add validator and tests
#[derive(Debug)]
pub struct IRI(String);

/// A unit struct used to represent the concept of a Default Graph in a quad store.
#[derive(Debug)]
pub struct DefaultGraph;

/// A wrapper type that represents a language tag.
#[derive(Debug)]
pub struct LangTag(String);

impl LangTag {
    /// Create a new LangTag from a &str and returns a Result based on if it is valid or not.
    pub fn new(tag: &str) -> Result<LangTag, LigatureError> {
        lazy_static! {
            static ref RE: Regex = Regex::new(r"^[a-zA-Z]+(\-[a-zA-Z0-9]+)*$").unwrap();
        }

        if RE.is_match(tag) {
            Ok(LangTag(tag.to_string()))
        } else {
            Err(LigatureError(format!("Invalid LangTag value {}", tag)))
        }
    }

    /// Returns the value of the LangTag.
    pub fn value(&self) -> &str {
        &self.0
    }
}

/// A struct containing text and a language tag that denotes what language the text is expressed in.
#[derive(Debug)]
pub struct LangLiteral {
    /// The String literal that is represented by this LangLiteral
    pub value: String,
    /// The LangTag that represents the language used to express the value.
    pub lang_tag: LangTag,
}

/// A struct containing a value represented as a String and the type of the value represented by an IRI.
/// TODO probably need a function that double checks a given UnknownLiteral is actually unknown
#[derive(Debug)]
pub struct UnknownLiteral {
    /// The value of this literal represented as a String.
    pub value: String,
    /// The IRI that represents this type.
    pub r#type: IRI,
}

/// An enum that represents all the currently supported literal types.
#[derive(Debug)]
pub enum Literal {
    /// A tagged LangLiteral used for an RDF literal
    LangLiteral(LangLiteral),
    /// A tagged String used for an RDF literal
    StringLiteral(String),
    /// A tagged bool used for an RDF literal
    BooleanLiteral(bool),
    /// A tagged i64 used for an RDF literal
    LongLiteral(i64),
    /// A tagged f64 used for an RDF literal
    DoubleLiteral(f64),
    /// A tagged UnknownLiteral used for an RDF literal
    UnknownLiteral(UnknownLiteral),
}

/// A set of enums used to express range queries when it makes sense for that type (ie no support for BooleanLiteralRange or UnknownLiteralRange since they don't make sense).
#[derive(Debug)]
pub enum Range {
    /// Represents a range of LangLiterals
    /// Note: LangTag needs to match for any comparison to take place.
    LangLiteralRange {
        /// The starting LangLiteral (inclusive)
        start: LangLiteral,
        /// The end LangLiteral (exclusive)
        end: LangLiteral,
    },
    /// Represents a String range using basic String comparisons.
    StringLiteralRange {
        /// The starting String (inclusive)
        start: String,
        /// The end String (exclusive)
        end: String,
    },
    /// Represents a String range using basic i64 comparisons.
    LongLiteralRange {
        /// The starting i64 (inclusive)
        start: i64,
        /// The end i64 (exclusive)
        end: i64,
    },
    /// Represents a String range using basic f64 comparisons.
    DoubleLiteralRange {
        /// The starting f64 (inclusive)
        start: f64,
        /// The end f64 (exclusive)
        end: f64,
    },
}

/// The set of valid types that can be used as a Subject.
#[derive(Debug)]
pub enum Subject {
    /// A tagged IRI used as a Subject.
    IRI(IRI),
    /// A tagged BlankNode used as a Subject.
    BlankNode(BlankNode),
    /// A tagged DefaultGraph used as a Subject.
    DefaultGraph(DefaultGraph),
}

/// The set of valid types that can be used as a Predicate.
#[derive(Debug)]
pub enum Predicate {
    /// A tagged IRI used as a Predicate.
    IRI(IRI),
}

/// The set of valid types that can be used as an Object.
#[derive(Debug)]
pub enum Object {
    /// A tagged Subject used as an Object.
    Subject(Subject),
    /// A tagged Literal used as an Object.
    Literal(Literal),
}

/// The set of valid types that can be used as a Graph name.
#[derive(Debug)]
pub enum Graph {
    /// A tagged IRI used as a Graph.
    IRI(IRI),
    /// A tagged BlankNode used as a Graph.
    BlankNode(BlankNode),
    /// A tagged DefaultGraph used as a Graph.
    DefaultGraph(DefaultGraph),
}

/// A Statement is a grouping of Subject, Predicate, and Object.
#[derive(Debug)]
pub struct Statement {
    /// The Subject of a Statement
    pub subject: Subject,
    /// The Predicate of a Statement
    pub predicate: Predicate,
    /// The Object of a Statement
    pub object: Object,
}

/// A PersistedStatement is a Statement along with a Dataset and Graph that that Statement belongs to.
#[derive(Debug)]
pub struct PersistedStatement {
    /// The Dataset this Statement is persisted in
    pub dataset: Dataset,
    /// The Statement that is persisted
    pub statement: Statement,
    /// The Graph this Statement is persisted in
    pub graph: Graph,
}

//val a: IRI = IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type").getOrElse(???)

/// A general struct for representing errors involving Ligature.
/// TODO should probably be an enum with a bunch of specific cases
#[derive(Debug)]
pub struct LigatureError(String);

/// A trait that all Ligature implementations implement.
pub trait Ligature {
    /// Returns all Datasets in a Ligature instance.
    fn all_datasets(&self) -> Box<dyn Iterator<Item = Dataset>>;

    /// Returns all Datasets in a Ligature instance that start with the given prefix.
    fn match_datasets(&self, prefix: &str) -> Box<dyn Iterator<Item = Dataset>>;

    /// Returns all Datasets in a Ligature instance that are in a given range (inclusive, exclusive].
    fn match_datasets_range(&self, start: &str, end: &str)
        -> Box<dyn Iterator<Item = Dataset>>;

    /// Creates a dataset with the given name.
    /// TODO should probably return its own error type { InvalidDataset, DatasetExists, CouldNotCreateDataset }
    fn create_dataset(&self, dataset: Dataset) -> Result<(), LigatureError>;

    /// Deletes a dataset with the given name.
    /// TODO should probably return its own error type { InvalidDataset, CouldNotDeleteDataset }
    fn delete_dataset(&self, dataset: Dataset) -> Result<(), LigatureError>;

    /// Initiazes a QueryTx
    /// TODO should probably return its own error type CouldNotInitializeQueryTx
    fn query(&self, dataset: Dataset) -> Result<Box<dyn QueryTx>, LigatureError>;

    /// Initiazes a WriteTx
    /// TODO should probably return its own error type CouldNotInitializeWriteTx
    fn write(&self, dataset: Dataset) -> Result<Box<dyn WriteTx>, LigatureError>;
}

/// Represents a QueryTx within the context of a Ligature instance and a single Dataset
pub trait QueryTx {
    /// Returns all Statements in this Dataset as PersistedStatements.
    /// TODO should probably return a Result
    fn all_statements(&self) -> Box<dyn Iterator<Item = PersistedStatement>>;

    /// Retuns all Statements that match the given criteria.
    /// If a parameter is None then it matches all, so passing all Nones is the same as calling all_statements.
    /// TODO should return a Result
    fn match_statements(
        &self,
        subject: Option<Subject>,
        predicate: Option<Predicate>,
        object: Option<Object>,
        graph: Option<Graph>,
    ) -> Box<dyn Iterator<Item = PersistedStatement>>;

    /// Retuns all Statements that match the given criteria.
    /// If a parameter is None then it matches all.
    /// TODO should return a Result
    fn match_statements_range(
        &self,
        subject: Option<Subject>,
        predicate: Option<Predicate>,
        graph: Option<Graph>,
        range: Range,
    ) -> Box<dyn Iterator<Item = PersistedStatement>>;
}

/// Represents a WriteTx within the context of a Ligature instance and a single Dataset
pub trait WriteTx {
    /// Creates a new, unique BlankNode within this Dataset.
    /// Note: BlankNodes are shared across named graphs in a given Dataset.
    fn new_blank_node(&self) -> Result<BlankNode, LigatureError>;

    /// Adds a given Statement to this Dataset.
    /// If the Statement already exists nothing happens.
    /// Note: Potentally could trigger a ValidationError
    fn add_statement(
        &self,
        statement: Statement,
        graph: Graph,
    ) -> Result<PersistedStatement, LigatureError>;

    /// Removes a given Statement from this Dataset.
    /// If the Statement doesn't exist nothing happens.
    /// Note: Potentally could trigger a ValidationError.
    fn remove_statement(
        &self,
        statement: Statement,
        graph: Graph,
    ) -> Result<Statement, LigatureError>;

    /// Cancels this transaction so that none of the changes made so far will be stored.
    /// This also closes this transaction so no other methods can be called.
    fn cancel(&self) -> Result<(), LigatureError>;

    /// Commits this transaction.
    /// This also closes this transaction so no other methods can be called.
    fn commit(&self) -> Result<(), LigatureError>;
}
<commit_msg>removing PersistedStatement + moving graph field to Statement<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! This module is the main module for the Ligature project.
//! It represents to common types and traits used by Ligature.

#![deny(missing_docs)]
//#![deny(missing_doc_example)] <-- for later, when I'm swole

#[macro_use] extern crate lazy_static;

use regex::Regex;

/// A string that represents a Dataset by name.
/// Currently can only be ASCII text separated by /
#[derive(Debug, PartialEq)]
pub struct Dataset(String);

impl Dataset {
    /// Creates a new Dataset and returns a Result based on if it is valid or not.
    pub fn new(name: &str) -> Result<Dataset, LigatureError> {
        lazy_static! {
            static ref RE: Regex = Regex::new(r"^[a-zA-Z_]+(/[a-zA-Z0-9_]+)*$").unwrap();
        }

        if RE.is_match(name) {
            Ok(Dataset(name.to_string()))
        } else {
            Err(LigatureError(format!("Invalid Dataset name {}", name)))
        }
    }

    /// Returns the name of the given Dataset.
    pub fn name(&self) -> &str {
        &self.0
    }
}

/// A node that is only identified by a unique u64 id.
#[derive(Debug)]
pub struct BlankNode(u64);

/// An IRI is represented via https://www.ietf.org/rfc/rfc3987.txt
/// TODO add validator and tests
#[derive(Debug)]
pub struct IRI(String);

/// A unit struct used to represent the concept of a Default Graph in a quad store.
#[derive(Debug)]
pub struct DefaultGraph;

/// A wrapper type that represents a language tag.
#[derive(Debug)]
pub struct LangTag(String);

impl LangTag {
    /// Create a new LangTag from a &str and returns a Result based on if it is valid or not.
    pub fn new(tag: &str) -> Result<LangTag, LigatureError> {
        lazy_static! {
            static ref RE: Regex = Regex::new(r"^[a-zA-Z]+(\-[a-zA-Z0-9]+)*$").unwrap();
        }

        if RE.is_match(tag) {
            Ok(LangTag(tag.to_string()))
        } else {
            Err(LigatureError(format!("Invalid LangTag value {}", tag)))
        }
    }

    /// Returns the value of the LangTag.
    pub fn value(&self) -> &str {
        &self.0
    }
}

/// A struct containing text and a language tag that denotes what language the text is expressed in.
#[derive(Debug)]
pub struct LangLiteral {
    /// The String literal that is represented by this LangLiteral
    pub value: String,
    /// The LangTag that represents the language used to express the value.
    pub lang_tag: LangTag,
}

/// A struct containing a value represented as a String and the type of the value represented by an IRI.
/// TODO probably need a function that double checks a given UnknownLiteral is actually unknown
#[derive(Debug)]
pub struct UnknownLiteral {
    /// The value of this literal represented as a String.
    pub value: String,
    /// The IRI that represents this type.
    pub r#type: IRI,
}

/// An enum that represents all the currently supported literal types.
#[derive(Debug)]
pub enum Literal {
    /// A tagged LangLiteral used for an RDF literal
    LangLiteral(LangLiteral),
    /// A tagged String used for an RDF literal
    StringLiteral(String),
    /// A tagged bool used for an RDF literal
    BooleanLiteral(bool),
    /// A tagged i64 used for an RDF literal
    LongLiteral(i64),
    /// A tagged f64 used for an RDF literal
    DoubleLiteral(f64),
    /// A tagged UnknownLiteral used for an RDF literal
    UnknownLiteral(UnknownLiteral),
}

/// A set of enums used to express range queries when it makes sense for that type (ie no support for BooleanLiteralRange or UnknownLiteralRange since they don't make sense).
#[derive(Debug)]
pub enum Range {
    /// Represents a range of LangLiterals
    /// Note: LangTag needs to match for any comparison to take place.
    LangLiteralRange {
        /// The starting LangLiteral (inclusive)
        start: LangLiteral,
        /// The end LangLiteral (exclusive)
        end: LangLiteral,
    },
    /// Represents a String range using basic String comparisons.
    StringLiteralRange {
        /// The starting String (inclusive)
        start: String,
        /// The end String (exclusive)
        end: String,
    },
    /// Represents a String range using basic i64 comparisons.
    LongLiteralRange {
        /// The starting i64 (inclusive)
        start: i64,
        /// The end i64 (exclusive)
        end: i64,
    },
    /// Represents a String range using basic f64 comparisons.
    DoubleLiteralRange {
        /// The starting f64 (inclusive)
        start: f64,
        /// The end f64 (exclusive)
        end: f64,
    },
}

/// The set of valid types that can be used as a Subject.
#[derive(Debug)]
pub enum Subject {
    /// A tagged IRI used as a Subject.
    IRI(IRI),
    /// A tagged BlankNode used as a Subject.
    BlankNode(BlankNode),
    /// A tagged DefaultGraph used as a Subject.
    DefaultGraph(DefaultGraph),
}

/// The set of valid types that can be used as a Predicate.
#[derive(Debug)]
pub enum Predicate {
    /// A tagged IRI used as a Predicate.
    IRI(IRI),
}

/// The set of valid types that can be used as an Object.
#[derive(Debug)]
pub enum Object {
    /// A tagged Subject used as an Object.
    Subject(Subject),
    /// A tagged Literal used as an Object.
    Literal(Literal),
}

/// The set of valid types that can be used as a Graph name.
#[derive(Debug)]
pub enum Graph {
    /// A tagged IRI used as a Graph.
    IRI(IRI),
    /// A tagged BlankNode used as a Graph.
    BlankNode(BlankNode),
    /// A tagged DefaultGraph used as a Graph.
    DefaultGraph(DefaultGraph),
}

/// A Statement is a grouping of Subject, Predicate, and Object.
#[derive(Debug)]
pub struct Statement {
    /// The Subject of a Statement
    pub subject: Subject,
    /// The Predicate of a Statement
    pub predicate: Predicate,
    /// The Object of a Statement
    pub object: Object,
    /// The Graph this Statement in
    pub graph: Graph,
}

//val a: IRI = IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type").getOrElse(???)

/// A general struct for representing errors involving Ligature.
/// TODO should probably be an enum with a bunch of specific cases
#[derive(Debug)]
pub struct LigatureError(String);

/// A trait that all Ligature implementations implement.
pub trait Ligature {
    /// Returns all Datasets in a Ligature instance.
    fn all_datasets(&self) -> Box<dyn Iterator<Item = Dataset>>;

    /// Returns all Datasets in a Ligature instance that start with the given prefix.
    fn match_datasets(&self, prefix: &str) -> Box<dyn Iterator<Item = Dataset>>;

    /// Returns all Datasets in a Ligature instance that are in a given range (inclusive, exclusive].
    fn match_datasets_range(&self, start: &str, end: &str)
        -> Box<dyn Iterator<Item = Dataset>>;

    /// Creates a dataset with the given name.
    /// TODO should probably return its own error type { InvalidDataset, DatasetExists, CouldNotCreateDataset }
    fn create_dataset(&self, dataset: Dataset) -> Result<(), LigatureError>;

    /// Deletes a dataset with the given name.
    /// TODO should probably return its own error type { InvalidDataset, CouldNotDeleteDataset }
    fn delete_dataset(&self, dataset: Dataset) -> Result<(), LigatureError>;

    /// Initiazes a QueryTx
    /// TODO should probably return its own error type CouldNotInitializeQueryTx
    fn query(&self, dataset: Dataset) -> Result<Box<dyn QueryTx>, LigatureError>;

    /// Initiazes a WriteTx
    /// TODO should probably return its own error type CouldNotInitializeWriteTx
    fn write(&self, dataset: Dataset) -> Result<Box<dyn WriteTx>, LigatureError>;
}

/// Represents a QueryTx within the context of a Ligature instance and a single Dataset
pub trait QueryTx {
    /// Returns all Statements in this Dataset as Statements.
    /// TODO should probably return a Result
    fn all_statements(&self) -> Box<dyn Iterator<Item = Statement>>;

    /// Retuns all Statements that match the given criteria.
    /// If a parameter is None then it matches all, so passing all Nones is the same as calling all_statements.
    /// TODO should return a Result
    fn match_statements(
        &self,
        subject: Option<Subject>,
        predicate: Option<Predicate>,
        object: Option<Object>,
        graph: Option<Graph>,
    ) -> Box<dyn Iterator<Item = Statement>>;

    /// Retuns all Statements that match the given criteria.
    /// If a parameter is None then it matches all.
    /// TODO should return a Result
    fn match_statements_range(
        &self,
        subject: Option<Subject>,
        predicate: Option<Predicate>,
        graph: Option<Graph>,
        range: Range,
    ) -> Box<dyn Iterator<Item = Statement>>;
}

/// Represents a WriteTx within the context of a Ligature instance and a single Dataset
pub trait WriteTx {
    /// Creates a new, unique BlankNode within this Dataset.
    /// Note: BlankNodes are shared across named graphs in a given Dataset.
    fn new_blank_node(&self) -> Result<BlankNode, LigatureError>;

    /// Adds a given Statement to this Dataset.
    /// If the Statement already exists nothing happens.
    /// Note: Potentally could trigger a ValidationError
    fn add_statement(
        &self,
        statement: Statement,
        graph: Graph,
    ) -> Result<Statement, LigatureError>;

    /// Removes a given Statement from this Dataset.
    /// If the Statement doesn't exist nothing happens.
    /// Note: Potentally could trigger a ValidationError.
    fn remove_statement(
        &self,
        statement: Statement,
        graph: Graph,
    ) -> Result<Statement, LigatureError>;

    /// Cancels this transaction so that none of the changes made so far will be stored.
    /// This also closes this transaction so no other methods can be called.
    fn cancel(&self) -> Result<(), LigatureError>;

    /// Commits this transaction.
    /// This also closes this transaction so no other methods can be called.
    fn commit(&self) -> Result<(), LigatureError>;
}
<|endoftext|>


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

extern crate libc;

/// returns true if this is a tty
#[cfg(unix)]
pub fn is() -> bool {
  let r = unsafe { libc::isatty(libc::STDOUT_FILENO) };
  r != 0
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is() -> bool {
    extern crate kernel32;
    extern crate winapi;
    use winapi::{self, HANDLE, INVALID_HANDLE_VALUE};
    use std::ptr;
    let handle: HANDLE = unsafe {
        let name = b"CONOUT$\0";
        let handle: HANDLE = unsafe {
            kernel32::CreateFileA(
                name.as_ptr() as *const i8,
                winapi::GENERIC_READ | winapi::GENERIC_WRITE,
                winapi::FILE_SHARE_WRITE,
                ptr::null_mut(),
                winapi::OPEN_EXISTING,
                0,
                ptr::null_mut(),
            )
        };
        println!("handle {:?}", handle);
        if handle == INVALID_HANDLE_VALUE {
            println!("handle was invalid");
            return false;
        }
        let mut out = 0;
        kernel32::GetConsoleMode(handle, &mut out) != 0

    }
}

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

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

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

extern crate libc;

/// returns true if this is a tty
#[cfg(unix)]
pub fn is() -> bool {
  let r = unsafe { libc::isatty(libc::STDOUT_FILENO) };
  r != 0
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is() -> bool {
    extern crate kernel32;
    extern crate winapi;
    use winapi::{self, HANDLE, INVALID_HANDLE_VALUE};
    use std::ptr;
    let handle: HANDLE = unsafe {
        kernel32::CreateFileA(
            b"CONOUT$\0".as_ptr() as *const i8,
            winapi::GENERIC_READ | winapi::GENERIC_WRITE,
            winapi::FILE_SHARE_WRITE,
            ptr::null_mut(),
            winapi::OPEN_EXISTING,
            0,
            ptr::null_mut(),
            )
    };
    if handle == INVALID_HANDLE_VALUE {
        println!("handle was invalid");
    }
    let mut out = 0;
    kernel32::GetConsoleMode(handle, &mut out) != 0
}

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

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

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


<commit_before>//! # TLS Parser
//!
//! A TLS parser, implemented with the [nom](https://github.com/Geal/nom)
//! parser combinator framework.
//!
//! The goal of this parser is to implement TLS messages analysis, for example
//! to use rules from a network IDS, for ex during the TLS handshake.
//!
//! It implements structures and parsing functions for records and messages, but
//! need additional code to handle fragmentation, or to fully inspect messages.
//! Parsing some TLS messages requires to know the previously selected parameters.
//! See [the rusticata TLS parser](https://github.com/rusticata/rusticata/blob/master/src/tls.rs)
//! for a full example.
//!
//! The code is available on [Github](https://github.com/rusticata/tls-parser)
//! and is part of the [Rusticata](https://github.com/rusticata) project.
//!
//! # Implementation notes
//!
//! When parsing messages, if a field is an integer corresponding to an enum of known values,
//! it is not parsed as an enum type, but as an integer. While this complicates accesses,
//! it allows to read invalid values and continue parsing (for an IDS, it's better to read
//! values than to get a generic parse error).

#[macro_use]
extern crate enum_primitive;

#[macro_use]
extern crate nom;

extern crate phf;

#[macro_use]
extern crate rusticata_macros;

pub use tls_alert::*;
/// TLS alerts
#[macro_use]
pub mod tls_alert;
pub use tls_ciphers::*;
/// TLS ciphersuites definitions and parameters
pub mod tls_ciphers;
pub use tls_dh::*;
/// Diffie-Hellman parameters
pub mod tls_dh;
pub use tls_ec::*;
/// Elliptic curves
pub mod tls_ec;
pub use tls_extensions::*;
/// TLS extensions
#[macro_use]
pub mod tls_extensions;
pub use tls_sign_hash::*;
/// TLS signature schemes
pub mod tls_sign_hash;
pub use tls_states::*;
/// TLS state machine
pub mod tls_states;
pub use tls::*;
/// TLS parser structures and functions
pub mod tls;

mod tls_debug;
<commit_msg>QA: prevent unsafe code, unstable features etc.<commit_after>//! # TLS Parser
//!
//! A TLS parser, implemented with the [nom](https://github.com/Geal/nom)
//! parser combinator framework.
//!
//! The goal of this parser is to implement TLS messages analysis, for example
//! to use rules from a network IDS, for ex during the TLS handshake.
//!
//! It implements structures and parsing functions for records and messages, but
//! need additional code to handle fragmentation, or to fully inspect messages.
//! Parsing some TLS messages requires to know the previously selected parameters.
//! See [the rusticata TLS parser](https://github.com/rusticata/rusticata/blob/master/src/tls.rs)
//! for a full example.
//!
//! The code is available on [Github](https://github.com/rusticata/tls-parser)
//! and is part of the [Rusticata](https://github.com/rusticata) project.
//!
//! # Implementation notes
//!
//! When parsing messages, if a field is an integer corresponding to an enum of known values,
//! it is not parsed as an enum type, but as an integer. While this complicates accesses,
//! it allows to read invalid values and continue parsing (for an IDS, it's better to read
//! values than to get a generic parse error).

#![deny(/*missing_docs,*/unsafe_code,
        unstable_features,
        unused_import_braces, unused_qualifications)]

#[macro_use]
extern crate enum_primitive;

#[macro_use]
extern crate nom;

extern crate phf;

#[macro_use]
extern crate rusticata_macros;

pub use tls_alert::*;
/// TLS alerts
#[macro_use]
pub mod tls_alert;
pub use tls_ciphers::*;
/// TLS ciphersuites definitions and parameters
pub mod tls_ciphers;
pub use tls_dh::*;
/// Diffie-Hellman parameters
pub mod tls_dh;
pub use tls_ec::*;
/// Elliptic curves
pub mod tls_ec;
pub use tls_extensions::*;
/// TLS extensions
#[macro_use]
pub mod tls_extensions;
pub use tls_sign_hash::*;
/// TLS signature schemes
pub mod tls_sign_hash;
pub use tls_states::*;
/// TLS state machine
pub mod tls_states;
pub use tls::*;
/// TLS parser structures and functions
pub mod tls;

mod tls_debug;
<|endoftext|>


<commit_before>#![feature(slice_splits, test)]
extern crate itertools;
extern crate rand;

use itertools::partition;

#[derive(Debug, Clone)]
struct LazySort<T> {
    greater: Vec<T>,
    less: Option<Box<LazySort<T>>>,
}

impl<T: Ord> LazySort<T> {
    fn split_greater(&mut self) -> Option<T> {
        match self.greater.len() {
            0 => None,
            1 => self.greater.pop(),
            _ => {
                let split_idx = {
                    let (pivot, rest) = self.greater.split_last_mut().unwrap();
                    partition(rest, |el| el > pivot)
                };
                let pivot_idx = self.greater.len() - 1;
                self.greater.swap(pivot_idx, split_idx);
                let mut less = Box::new(LazySort {
                    greater: self.greater.split_off(split_idx + 1),
                    less: None,
                });
                if let next @ Some(_) = less.next() {
                    self.less = Some(less);
                    next
                } else {
                    self.greater.pop()
                }
            }
        }
    }
}

impl<T: Ord> Iterator for LazySort<T> {
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        let next = if let Some(ref mut less) = self.less {
            less.next()
        } else {
            return self.split_greater();
        };
        if next.is_some() {
            next
        } else {
            self.less = None;
            self.greater.pop()
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        match self.less {
            None => (self.greater.len(), Some(self.greater.len())),
            Some(ref less) => {
                let (lower, upper) = less.size_hint();
                (lower + self.greater.len(),
                 upper.map(|upper| upper + self.greater.len()))
            }
        }
    }

}

trait LazySortIterator: Iterator
    where Self: Sized
{
    fn lazy_sort(self) -> LazySort<Self::Item> {
        LazySort {
            greater: self.collect(),
            less: None,
        }
    }
}

impl<T> LazySortIterator for T where T: Iterator { }

#[test]
fn test_sort() {
    let mut v = vec![2, 4, 2, 5, 8, 4, 3, 4, 6];
    let v2: Vec<_> = v.iter().cloned().lazy_sort().collect();
    v.sort();
    assert_eq!(v, v2);
}

#[test]
fn test_empty() {
    let v: Vec<u64> = vec![];
    let v2: Vec<_> = v.iter().cloned().lazy_sort().collect();
    assert_eq!(v, v2);
}

#[test]
fn test_size_hint() {
    let v = vec![2, 4, 2, 5, 8, 4, 3, 4, 6];
    let mut sort_iter = v.iter().cloned().lazy_sort();
    for i in 0..v.len() {
        let (lower, upper) = sort_iter.size_hint();
        assert_eq!(v.len() - i, lower);
        assert_eq!(Some(v.len() - i), upper);
        sort_iter.next();
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use self::test::Bencher;
    use rand::{thread_rng, Rng};
    use super::LazySortIterator;

    #[bench]
    fn bench_lazy(b: &mut Bencher) {
        let mut rng = thread_rng();
        let v: Vec<u32> = rng.gen_iter().take(50_000).collect();
        b.iter(|| v.iter().cloned().lazy_sort().take(1000).collect::<Vec<_>>());
    }

    #[bench]
    fn bench_eager(b: &mut Bencher) {
        let mut rng = thread_rng();
        let v: Vec<u32> = rng.gen_iter().take(50_000).collect();
        b.iter(|| {
            let mut v = v.clone();
            v.sort();
            v.iter().cloned().take(1000).collect::<Vec<_>>();
        });
    }
}
<commit_msg>Conditionally set feature(test)<commit_after>#![feature(slice_splits)]
#![cfg_attr(test, feature(test))]
extern crate itertools;
extern crate rand;

use itertools::partition;

#[derive(Debug, Clone)]
struct LazySort<T> {
    greater: Vec<T>,
    less: Option<Box<LazySort<T>>>,
}

impl<T: Ord> LazySort<T> {
    fn split_greater(&mut self) -> Option<T> {
        match self.greater.len() {
            0 => None,
            1 => self.greater.pop(),
            _ => {
                let split_idx = {
                    let (pivot, rest) = self.greater.split_last_mut().unwrap();
                    partition(rest, |el| el > pivot)
                };
                let pivot_idx = self.greater.len() - 1;
                self.greater.swap(pivot_idx, split_idx);
                let mut less = Box::new(LazySort {
                    greater: self.greater.split_off(split_idx + 1),
                    less: None,
                });
                if let next @ Some(_) = less.next() {
                    self.less = Some(less);
                    next
                } else {
                    self.greater.pop()
                }
            }
        }
    }
}

impl<T: Ord> Iterator for LazySort<T> {
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        let next = if let Some(ref mut less) = self.less {
            less.next()
        } else {
            return self.split_greater();
        };
        if next.is_some() {
            next
        } else {
            self.less = None;
            self.greater.pop()
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        match self.less {
            None => (self.greater.len(), Some(self.greater.len())),
            Some(ref less) => {
                let (lower, upper) = less.size_hint();
                (lower + self.greater.len(),
                 upper.map(|upper| upper + self.greater.len()))
            }
        }
    }

}

trait LazySortIterator: Iterator
    where Self: Sized
{
    fn lazy_sort(self) -> LazySort<Self::Item> {
        LazySort {
            greater: self.collect(),
            less: None,
        }
    }
}

impl<T> LazySortIterator for T where T: Iterator { }

#[test]
fn test_sort() {
    let mut v = vec![2, 4, 2, 5, 8, 4, 3, 4, 6];
    let v2: Vec<_> = v.iter().cloned().lazy_sort().collect();
    v.sort();
    assert_eq!(v, v2);
}

#[test]
fn test_empty() {
    let v: Vec<u64> = vec![];
    let v2: Vec<_> = v.iter().cloned().lazy_sort().collect();
    assert_eq!(v, v2);
}

#[test]
fn test_size_hint() {
    let v = vec![2, 4, 2, 5, 8, 4, 3, 4, 6];
    let mut sort_iter = v.iter().cloned().lazy_sort();
    for i in 0..v.len() {
        let (lower, upper) = sort_iter.size_hint();
        assert_eq!(v.len() - i, lower);
        assert_eq!(Some(v.len() - i), upper);
        sort_iter.next();
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use self::test::Bencher;
    use rand::{thread_rng, Rng};
    use super::LazySortIterator;

    #[bench]
    fn bench_lazy(b: &mut Bencher) {
        let mut rng = thread_rng();
        let v: Vec<u32> = rng.gen_iter().take(50_000).collect();
        b.iter(|| v.iter().cloned().lazy_sort().take(1000).collect::<Vec<_>>());
    }

    #[bench]
    fn bench_eager(b: &mut Bencher) {
        let mut rng = thread_rng();
        let v: Vec<u32> = rng.gen_iter().take(50_000).collect();
        b.iter(|| {
            let mut v = v.clone();
            v.sort();
            v.iter().cloned().take(1000).collect::<Vec<_>>();
        });
    }
}
<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

#![feature(asm)]
#![feature(drain)]
#![feature(link_llvm_intrinsics)]

//! This is an implementation of the `RCImmixCons` garbage collector.
//!
//! A conservative reference counting garbage collector with the immix heap
//! partition schema. For details please refer to:
//!
//! - S. M. S. Blackburn and K. K. S. McKinley. Immix: a mark-region garbage
//!   collector with space efficiency, fast collection, and mutator performance.
//!   ACM SIGPLAN Notices, 43(6):22, May 2008.
//! - R. Shahriyar, S. M. Blackburn, and D. Frampton. Down for the count?  Getting
//!   reference counting back in the ring. ACM SIGPLAN Notices, 47(11):73, Jan.
//!   2013.
//! - R. Shahriyar, S. M. Blackburn, and K. S. McKinley. Fast conservative garbage
//!   collection. In Proceedings of the 2014 ACM International Conference on
//!   Object Oriented Programming Systems Languages & Applications - OOPSLA ’14,
//!   pages 121-139, New York, New York, USA, Oct. 2014. ACM Press.
//! - R. Shahriyar, S. M. Blackburn, X. Yang, and K. S. McKinley. Taking off the
//!   gloves with reference counting Immix. ACM SIGPLAN Notices, 48(10):93-110,
//!   Nov. 2013.
//!
//! To use this garbage collector your objects must be structs derived from
//! `GCObject`. Allocation and collection is done using `RCImmixCons`.

extern crate libc;
extern crate bit_set;
extern crate vec_map;

use std::ptr;

pub use self::gc_object::{GCHeader, GCRTTI, GCObject, GCObjectRef};

mod macros;
mod constants;
mod gc_object;
mod spaces;
mod stack;

/// The `RCImmixCons` garbage collector.
///
/// The `allocate()` function will return a pointer to a `GCObject`. Please
/// see the documentation of `GCHeader`, `GCRTTI` and `GCObject` for details.
///
/// Always call `write_barrier()` on an object before modifying its members.
pub struct RCImmixCons {
    /// The different spaces of this garbage collector.
    spaces: spaces::Spaces,
}

impl RCImmixCons {
    /// Create a new `RCImmixCons`.
    pub fn new() -> RCImmixCons {
        RCImmixCons {
            spaces: spaces::Spaces::new(),
        }
    }

    /// Allocate a new object described by the `rtti` or returns `None`.
    ///
    /// This may trigger a garbage collection if the allocation was not
    /// succussful. If there is still no memory to fullfill the allocation
    /// request return `None`.
    pub fn allocate(&mut self, rtti: *const GCRTTI) -> Option<GCObjectRef> {
        self.spaces.allocate(rtti)
            .or_else(|| { self.collect(true, true);
                          self.spaces.allocate(rtti) })
    }

    /// Trigger a garbage collection.
    ///
    /// This will always run the referece counting collector. If `evacuation`
    /// is set the collectors will try to evacuate. If `cycle_collect` is set
    /// the immix tracing collector will be used.
    #[allow(unused_variables)]
    pub fn collect(&mut self, evacuation: bool, cycle_collect: bool) {
        // Calling this function befor **ANYTHING** is important to save the
        // callee save registers on the stack.
        let registers = stack::Stack::get_registers();
        self.spaces.collect(evacuation, cycle_collect)
    }

    /// Set an address to an object reference as static root.
    ///
    /// Use this to mark global/static variables as roots. This is needed, if
    /// the pointer to a garbage collected object does not reside on the stack
    /// or in any register.
    pub fn set_static_root(&mut self, address: *const GCObjectRef) {
        self.spaces.set_static_root(address);
    }

    /// A write barrier for the given `object`.
    ///
    /// Call this function before modifying the members of this object!
    pub fn write_barrier(&mut self, object: GCObjectRef) {
        if self.spaces.write_barrier(object) {
            self.collect(false, false);
        }
    }
}

#[no_mangle]
#[doc(hidden)]
pub extern fn rcx_create() -> *mut RCImmixCons {
    Box::into_raw(Box::new(RCImmixCons::new()))
}

#[no_mangle]
#[doc(hidden)]
pub extern fn rcx_allocate(this: *mut RCImmixCons, rtti: *const GCRTTI)
    -> GCObjectRef {
    unsafe { (*this).allocate(rtti).unwrap_or(ptr::null_mut()) }
}

#[no_mangle]
#[doc(hidden)]
pub extern fn rcx_collect(this: *mut RCImmixCons, evacuation: bool, cycle_collect: bool) {
    unsafe { (*this).collect(evacuation, cycle_collect) };
}

#[no_mangle]
#[doc(hidden)]
pub extern fn rcx_set_static_root(this: *mut RCImmixCons, address: *const GCObjectRef) {
    unsafe { (*this).set_static_root(address) };
}

#[no_mangle]
#[doc(hidden)]
pub extern fn rcx_write_barrier(this: *mut RCImmixCons, object: GCObjectRef) {
    unsafe { (*this).write_barrier(object) };
}

#[no_mangle]
#[doc(hidden)]
pub extern fn rcx_destroy(this: *mut RCImmixCons) {
    let _to_be_dropped = unsafe{ Box::from_raw(this) };
}
<commit_msg>Remove obsolete feature `drain`<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

#![feature(asm)]
#![feature(link_llvm_intrinsics)]

//! This is an implementation of the `RCImmixCons` garbage collector.
//!
//! A conservative reference counting garbage collector with the immix heap
//! partition schema. For details please refer to:
//!
//! - S. M. S. Blackburn and K. K. S. McKinley. Immix: a mark-region garbage
//!   collector with space efficiency, fast collection, and mutator performance.
//!   ACM SIGPLAN Notices, 43(6):22, May 2008.
//! - R. Shahriyar, S. M. Blackburn, and D. Frampton. Down for the count?  Getting
//!   reference counting back in the ring. ACM SIGPLAN Notices, 47(11):73, Jan.
//!   2013.
//! - R. Shahriyar, S. M. Blackburn, and K. S. McKinley. Fast conservative garbage
//!   collection. In Proceedings of the 2014 ACM International Conference on
//!   Object Oriented Programming Systems Languages & Applications - OOPSLA ’14,
//!   pages 121-139, New York, New York, USA, Oct. 2014. ACM Press.
//! - R. Shahriyar, S. M. Blackburn, X. Yang, and K. S. McKinley. Taking off the
//!   gloves with reference counting Immix. ACM SIGPLAN Notices, 48(10):93-110,
//!   Nov. 2013.
//!
//! To use this garbage collector your objects must be structs derived from
//! `GCObject`. Allocation and collection is done using `RCImmixCons`.

extern crate libc;
extern crate bit_set;
extern crate vec_map;

use std::ptr;

pub use self::gc_object::{GCHeader, GCRTTI, GCObject, GCObjectRef};

mod macros;
mod constants;
mod gc_object;
mod spaces;
mod stack;

/// The `RCImmixCons` garbage collector.
///
/// The `allocate()` function will return a pointer to a `GCObject`. Please
/// see the documentation of `GCHeader`, `GCRTTI` and `GCObject` for details.
///
/// Always call `write_barrier()` on an object before modifying its members.
pub struct RCImmixCons {
    /// The different spaces of this garbage collector.
    spaces: spaces::Spaces,
}

impl RCImmixCons {
    /// Create a new `RCImmixCons`.
    pub fn new() -> RCImmixCons {
        RCImmixCons {
            spaces: spaces::Spaces::new(),
        }
    }

    /// Allocate a new object described by the `rtti` or returns `None`.
    ///
    /// This may trigger a garbage collection if the allocation was not
    /// succussful. If there is still no memory to fullfill the allocation
    /// request return `None`.
    pub fn allocate(&mut self, rtti: *const GCRTTI) -> Option<GCObjectRef> {
        self.spaces.allocate(rtti)
            .or_else(|| { self.collect(true, true);
                          self.spaces.allocate(rtti) })
    }

    /// Trigger a garbage collection.
    ///
    /// This will always run the referece counting collector. If `evacuation`
    /// is set the collectors will try to evacuate. If `cycle_collect` is set
    /// the immix tracing collector will be used.
    #[allow(unused_variables)]
    pub fn collect(&mut self, evacuation: bool, cycle_collect: bool) {
        // Calling this function befor **ANYTHING** is important to save the
        // callee save registers on the stack.
        let registers = stack::Stack::get_registers();
        self.spaces.collect(evacuation, cycle_collect)
    }

    /// Set an address to an object reference as static root.
    ///
    /// Use this to mark global/static variables as roots. This is needed, if
    /// the pointer to a garbage collected object does not reside on the stack
    /// or in any register.
    pub fn set_static_root(&mut self, address: *const GCObjectRef) {
        self.spaces.set_static_root(address);
    }

    /// A write barrier for the given `object`.
    ///
    /// Call this function before modifying the members of this object!
    pub fn write_barrier(&mut self, object: GCObjectRef) {
        if self.spaces.write_barrier(object) {
            self.collect(false, false);
        }
    }
}

#[no_mangle]
#[doc(hidden)]
pub extern fn rcx_create() -> *mut RCImmixCons {
    Box::into_raw(Box::new(RCImmixCons::new()))
}

#[no_mangle]
#[doc(hidden)]
pub extern fn rcx_allocate(this: *mut RCImmixCons, rtti: *const GCRTTI)
    -> GCObjectRef {
    unsafe { (*this).allocate(rtti).unwrap_or(ptr::null_mut()) }
}

#[no_mangle]
#[doc(hidden)]
pub extern fn rcx_collect(this: *mut RCImmixCons, evacuation: bool, cycle_collect: bool) {
    unsafe { (*this).collect(evacuation, cycle_collect) };
}

#[no_mangle]
#[doc(hidden)]
pub extern fn rcx_set_static_root(this: *mut RCImmixCons, address: *const GCObjectRef) {
    unsafe { (*this).set_static_root(address) };
}

#[no_mangle]
#[doc(hidden)]
pub extern fn rcx_write_barrier(this: *mut RCImmixCons, object: GCObjectRef) {
    unsafe { (*this).write_barrier(object) };
}

#[no_mangle]
#[doc(hidden)]
pub extern fn rcx_destroy(this: *mut RCImmixCons) {
    let _to_be_dropped = unsafe{ Box::from_raw(this) };
}
<|endoftext|>


<commit_before>//! A Rust implementation of the [XXHash] algorithm.
//!
//! [XXHash]: https://github.com/Cyan4973/xxHash
//!
//! ### With a fixed seed
//!
//! ```rust
//! use std::hash::BuildHasherDefault;
//! use std::collections::HashMap;
//! use twox_hash::XxHash;
//!
//! let mut hash: HashMap<_, _, BuildHasherDefault<XxHash>> = Default::default();
//! hash.insert(42, "the answer");
//! assert_eq!(hash.get(&42), Some(&"the answer"));
//! ```
//!
//! ### With a random seed
//!
//! ```rust
//! use std::collections::HashMap;
//! use twox_hash::RandomXxHashBuilder;
//!
//! let mut hash: HashMap<_, _, RandomXxHashBuilder> = Default::default();
//! hash.insert(42, "the answer");
//! assert_eq!(hash.get(&42), Some(&"the answer"));
//! ```

#![no_std]

#[cfg(test)]
extern crate std;

#[cfg(feature = "std")]
extern crate rand;

#[cfg(feature="serialize")]
extern crate serde;
#[cfg(feature="serialize")]
use serde::{Serialize, Deserialize};

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

mod number_streams;
mod thirty_two;

#[cfg(feature = "digest")]
mod digest_support;

pub use thirty_two::XxHash as XxHash32;
#[cfg(feature = "std")]
pub use thirty_two::RandomXxHashBuilder as RandomXxHashBuilder32;

use core::hash::Hasher;
use number_streams::NumberStreams;

const CHUNK_SIZE: usize = 32;

const PRIME_1: u64 = 11400714785074694791;
const PRIME_2: u64 = 14029467366897019727;
const PRIME_3: u64 = 1609587929392839161;
const PRIME_4: u64 = 9650029242287828579;
const PRIME_5: u64 = 2870177450012600261;

#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
#[derive(Copy,Clone,PartialEq)]
struct XxCore {
    v1: u64,
    v2: u64,
    v3: u64,
    v4: u64,
}

/// Calculates the 64-bit hash.
#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
#[derive(PartialEq, Debug,Copy,Clone)]
pub struct XxHash {
    total_len: u64,
    seed: u64,
    core: XxCore,
    buffer: [u8; CHUNK_SIZE],
    buffer_usage: usize,
}

impl XxCore {
    fn with_seed(seed: u64) -> XxCore {
        XxCore {
            v1: seed.wrapping_add(PRIME_1).wrapping_add(PRIME_2),
            v2: seed.wrapping_add(PRIME_2),
            v3: seed,
            v4: seed.wrapping_sub(PRIME_1),
        }
    }

    #[inline(always)]
    fn ingest_chunks<I>(&mut self, values: I)
        where I: Iterator<Item=u64>
    {
        #[inline(always)]
        fn ingest_one_number(mut current_value: u64, mut value: u64) -> u64 {
            value = value.wrapping_mul(PRIME_2);
            current_value = current_value.wrapping_add(value);
            current_value = current_value.rotate_left(31);
            current_value.wrapping_mul(PRIME_1)
        };

        // By drawing these out, we can avoid going back and forth to
        // memory. It only really helps for large files, when we need
        // to iterate multiple times here.

        let mut v1 = self.v1;
        let mut v2 = self.v2;
        let mut v3 = self.v3;
        let mut v4 = self.v4;

        let mut values = values.peekable();

        while values.peek().is_some() {
            v1 = ingest_one_number(v1, values.next().unwrap());
            v2 = ingest_one_number(v2, values.next().unwrap());
            v3 = ingest_one_number(v3, values.next().unwrap());
            v4 = ingest_one_number(v4, values.next().unwrap());
        }

        self.v1 = v1;
        self.v2 = v2;
        self.v3 = v3;
        self.v4 = v4;
    }

    #[inline(always)]
    fn finish(&self) -> u64 {
        // The original code pulls out local vars for v[1234]
        // here. Performance tests did not show that to be effective
        // here, presumably because this method is not called in a
        // tight loop.

        let mut hash;

        hash =                   self.v1.rotate_left( 1);
        hash = hash.wrapping_add(self.v2.rotate_left( 7));
        hash = hash.wrapping_add(self.v3.rotate_left(12));
        hash = hash.wrapping_add(self.v4.rotate_left(18));

        #[inline(always)]
        fn mix_one(mut hash: u64, mut value: u64) -> u64 {
            value = value.wrapping_mul(PRIME_2);
            value = value.rotate_left(31);
            value = value.wrapping_mul(PRIME_1);
            hash ^= value;
            hash = hash.wrapping_mul(PRIME_1);
            hash.wrapping_add(PRIME_4)
        }

        hash = mix_one(hash, self.v1);
        hash = mix_one(hash, self.v2);
        hash = mix_one(hash, self.v3);
        hash = mix_one(hash, self.v4);

        hash
    }
}

impl core::fmt::Debug for XxCore {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
        write!(
            f, "XxCore {{ {:016x} {:016x} {:016x} {:016x} }}",
            self.v1, self.v2, self.v3, self.v4
        )
    }
}

impl XxHash {
    /// Constructs the hash with an initial seed
    pub fn with_seed(seed: u64) -> XxHash {
        XxHash {
            total_len: 0,
            seed: seed,
            core: XxCore::with_seed(seed),
            buffer: unsafe { ::core::mem::uninitialized() },
            buffer_usage: 0,
        }
    }
}

impl Default for XxHash {
    fn default() -> XxHash {
        XxHash::with_seed(0)
    }
}

impl Hasher for XxHash {
    fn write(&mut self, bytes: &[u8]) {
        let mut bytes = bytes;

        self.total_len += bytes.len() as u64;

        // Even with new data, we still don't have a full buffer. Wait
        // until we have a full buffer.
        if self.buffer_usage + bytes.len() < self.buffer.len() {
            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                core::ptr::copy_nonoverlapping(bytes.as_ptr(), tail, bytes.len());
            }
            self.buffer_usage += bytes.len();
            return;
        }

        // Some data left from previous update. Fill the buffer and
        // consume it first.
        if self.buffer_usage > 0 {
            let bytes_to_use = self.buffer.len() - self.buffer_usage;
            let (to_use, leftover) = bytes.split_at(bytes_to_use);

            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                core::ptr::copy_nonoverlapping(to_use.as_ptr(), tail, bytes_to_use);
            }

            let (iter, _) = self.buffer.u64_stream();

            self.core.ingest_chunks(iter);

            bytes = leftover;
            self.buffer_usage = 0;
        }

        // Consume the input data in large chunks
        let (iter, bytes) = bytes.u64_stream_with_stride(4);
        self.core.ingest_chunks(iter);

        // Save any leftover data for the next call
        if bytes.len() > 0 {
            unsafe {
                core::ptr::copy_nonoverlapping(bytes.as_ptr(), self.buffer.as_mut_ptr(), bytes.len());
            }
            self.buffer_usage = bytes.len();
        }
    }

    fn finish(&self) -> u64 {
        let mut hash;

        // We have processed at least one full chunk
        if self.total_len >= CHUNK_SIZE as u64 {
            hash = self.core.finish();
        } else {
            hash = self.seed.wrapping_add(PRIME_5);
        }

        hash = hash.wrapping_add(self.total_len);

        let buffered = &self.buffer[..self.buffer_usage];
        let (buffered_u64s, buffered) = buffered.u64_stream();

        for mut k1 in buffered_u64s {
            k1 = k1.wrapping_mul(PRIME_2);
            k1 = k1.rotate_left(31);
            k1 = k1.wrapping_mul(PRIME_1);
            hash ^= k1;
            hash = hash.rotate_left(27);
            hash = hash.wrapping_mul(PRIME_1);
            hash = hash.wrapping_add(PRIME_4);
        }

        let (buffered_u32s, buffered) = buffered.u32_stream();

        for k1 in buffered_u32s {
            let k1 = (k1 as u64).wrapping_mul(PRIME_1);
            hash ^= k1;
            hash = hash.rotate_left(23);
            hash = hash.wrapping_mul(PRIME_2);
            hash = hash.wrapping_add(PRIME_3);
        }

        for buffered_u8 in buffered {
            let k1 = (*buffered_u8 as u64).wrapping_mul(PRIME_5);
            hash ^= k1;
            hash = hash.rotate_left(11);
            hash = hash.wrapping_mul(PRIME_1);
        }

        // The final intermixing
        hash ^= hash >> 33;
        hash = hash.wrapping_mul(PRIME_2);
        hash ^= hash >> 29;
        hash = hash.wrapping_mul(PRIME_3);
        hash ^= hash >> 32;

        hash
    }
}

#[cfg(feature = "std")]
mod std_support;

#[cfg(feature = "std")]
pub use std_support::sixty_four::RandomXxHashBuilder;

#[cfg(test)]
mod test {
    use std::prelude::v1::*;

    use std::hash::{Hasher, BuildHasherDefault};
    use std::collections::HashMap;
    use super::{XxHash, RandomXxHashBuilder};

    #[test]
    fn ingesting_byte_by_byte_is_equivalent_to_large_chunks() {
        let bytes: Vec<_> = (0..32).map(|_| 0).collect();

        let mut byte_by_byte = XxHash::with_seed(0);
        for byte in bytes.chunks(1) {
            byte_by_byte.write(byte);
        }

        let mut one_chunk = XxHash::with_seed(0);
        one_chunk.write(&bytes);

        assert_eq!(byte_by_byte.core, one_chunk.core);
    }

    #[test]
    fn hash_of_nothing_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0xef46db3751d8e999);
    }

    #[test]
    fn hash_of_single_byte_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(&[42]);
        assert_eq!(hasher.finish(), 0x0a9edecebeb03ae4);
    }

    #[test]
    fn hash_of_multiple_bytes_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(b"Hello, world!\0");
        assert_eq!(hasher.finish(), 0x7b06c531ea43e89f);
    }

    #[test]
    fn hash_of_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::with_seed(0);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x6ac1e58032166597);
    }

    #[test]
    fn hash_with_different_seed_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0xae0543311b702d91);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0x4b6a04fcdf7a4672);
    }

    #[test]
    fn hash_with_different_seed_and_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::with_seed(0xae0543311b702d91);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x567e355e0682e1f1);
    }

    #[test]
    fn can_be_used_in_a_hashmap_with_a_default_seed() {
        let mut hash: HashMap<_, _, BuildHasherDefault<XxHash>> = Default::default();
        hash.insert(42, "the answer");
        assert_eq!(hash.get(&42), Some(&"the answer"));
    }

    #[test]
    fn can_be_used_in_a_hashmap_with_a_random_seed() {
        let mut hash: HashMap<_, _, RandomXxHashBuilder> = Default::default();
        hash.insert(42, "the answer");
        assert_eq!(hash.get(&42), Some(&"the answer"));
    }

    #[cfg(feature="serialize")]
    #[test]
    fn test_serialization() {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(b"Hello, world!\0");
        hasher.finish();

        let serialized = serde_json::to_string(&hasher).unwrap();
        let unserialized: XxHash = serde_json::from_str(&serialized).unwrap();
        assert_eq!(hasher, unserialized);
    }
}
<commit_msg>Ensure hasher is serializable across versions<commit_after>//! A Rust implementation of the [XXHash] algorithm.
//!
//! [XXHash]: https://github.com/Cyan4973/xxHash
//!
//! ### With a fixed seed
//!
//! ```rust
//! use std::hash::BuildHasherDefault;
//! use std::collections::HashMap;
//! use twox_hash::XxHash;
//!
//! let mut hash: HashMap<_, _, BuildHasherDefault<XxHash>> = Default::default();
//! hash.insert(42, "the answer");
//! assert_eq!(hash.get(&42), Some(&"the answer"));
//! ```
//!
//! ### With a random seed
//!
//! ```rust
//! use std::collections::HashMap;
//! use twox_hash::RandomXxHashBuilder;
//!
//! let mut hash: HashMap<_, _, RandomXxHashBuilder> = Default::default();
//! hash.insert(42, "the answer");
//! assert_eq!(hash.get(&42), Some(&"the answer"));
//! ```

#![no_std]

#[cfg(test)]
extern crate std;

#[cfg(feature = "std")]
extern crate rand;

#[cfg(feature="serialize")]
extern crate serde;
#[cfg(feature="serialize")]
use serde::{Serialize, Deserialize};

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

mod number_streams;
mod thirty_two;

#[cfg(feature = "digest")]
mod digest_support;

pub use thirty_two::XxHash as XxHash32;
#[cfg(feature = "std")]
pub use thirty_two::RandomXxHashBuilder as RandomXxHashBuilder32;

use core::hash::Hasher;
use number_streams::NumberStreams;

const CHUNK_SIZE: usize = 32;

const PRIME_1: u64 = 11400714785074694791;
const PRIME_2: u64 = 14029467366897019727;
const PRIME_3: u64 = 1609587929392839161;
const PRIME_4: u64 = 9650029242287828579;
const PRIME_5: u64 = 2870177450012600261;

#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
#[derive(Copy,Clone,PartialEq)]
struct XxCore {
    v1: u64,
    v2: u64,
    v3: u64,
    v4: u64,
}

/// Calculates the 64-bit hash.
#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
#[derive(PartialEq, Debug,Copy,Clone)]
pub struct XxHash {
    total_len: u64,
    seed: u64,
    core: XxCore,
    buffer: [u8; CHUNK_SIZE],
    buffer_usage: usize,
}

impl XxCore {
    fn with_seed(seed: u64) -> XxCore {
        XxCore {
            v1: seed.wrapping_add(PRIME_1).wrapping_add(PRIME_2),
            v2: seed.wrapping_add(PRIME_2),
            v3: seed,
            v4: seed.wrapping_sub(PRIME_1),
        }
    }

    #[inline(always)]
    fn ingest_chunks<I>(&mut self, values: I)
        where I: Iterator<Item=u64>
    {
        #[inline(always)]
        fn ingest_one_number(mut current_value: u64, mut value: u64) -> u64 {
            value = value.wrapping_mul(PRIME_2);
            current_value = current_value.wrapping_add(value);
            current_value = current_value.rotate_left(31);
            current_value.wrapping_mul(PRIME_1)
        };

        // By drawing these out, we can avoid going back and forth to
        // memory. It only really helps for large files, when we need
        // to iterate multiple times here.

        let mut v1 = self.v1;
        let mut v2 = self.v2;
        let mut v3 = self.v3;
        let mut v4 = self.v4;

        let mut values = values.peekable();

        while values.peek().is_some() {
            v1 = ingest_one_number(v1, values.next().unwrap());
            v2 = ingest_one_number(v2, values.next().unwrap());
            v3 = ingest_one_number(v3, values.next().unwrap());
            v4 = ingest_one_number(v4, values.next().unwrap());
        }

        self.v1 = v1;
        self.v2 = v2;
        self.v3 = v3;
        self.v4 = v4;
    }

    #[inline(always)]
    fn finish(&self) -> u64 {
        // The original code pulls out local vars for v[1234]
        // here. Performance tests did not show that to be effective
        // here, presumably because this method is not called in a
        // tight loop.

        let mut hash;

        hash =                   self.v1.rotate_left( 1);
        hash = hash.wrapping_add(self.v2.rotate_left( 7));
        hash = hash.wrapping_add(self.v3.rotate_left(12));
        hash = hash.wrapping_add(self.v4.rotate_left(18));

        #[inline(always)]
        fn mix_one(mut hash: u64, mut value: u64) -> u64 {
            value = value.wrapping_mul(PRIME_2);
            value = value.rotate_left(31);
            value = value.wrapping_mul(PRIME_1);
            hash ^= value;
            hash = hash.wrapping_mul(PRIME_1);
            hash.wrapping_add(PRIME_4)
        }

        hash = mix_one(hash, self.v1);
        hash = mix_one(hash, self.v2);
        hash = mix_one(hash, self.v3);
        hash = mix_one(hash, self.v4);

        hash
    }
}

impl core::fmt::Debug for XxCore {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
        write!(
            f, "XxCore {{ {:016x} {:016x} {:016x} {:016x} }}",
            self.v1, self.v2, self.v3, self.v4
        )
    }
}

impl XxHash {
    /// Constructs the hash with an initial seed
    pub fn with_seed(seed: u64) -> XxHash {
        XxHash {
            total_len: 0,
            seed: seed,
            core: XxCore::with_seed(seed),
            buffer: [0; CHUNK_SIZE],
            buffer_usage: 0,
        }
    }
}

impl Default for XxHash {
    fn default() -> XxHash {
        XxHash::with_seed(0)
    }
}

impl Hasher for XxHash {
    fn write(&mut self, bytes: &[u8]) {
        let mut bytes = bytes;

        self.total_len += bytes.len() as u64;

        // Even with new data, we still don't have a full buffer. Wait
        // until we have a full buffer.
        if self.buffer_usage + bytes.len() < self.buffer.len() {
            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                core::ptr::copy_nonoverlapping(bytes.as_ptr(), tail, bytes.len());
            }
            self.buffer_usage += bytes.len();
            return;
        }

        // Some data left from previous update. Fill the buffer and
        // consume it first.
        if self.buffer_usage > 0 {
            let bytes_to_use = self.buffer.len() - self.buffer_usage;
            let (to_use, leftover) = bytes.split_at(bytes_to_use);

            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                core::ptr::copy_nonoverlapping(to_use.as_ptr(), tail, bytes_to_use);
            }

            let (iter, _) = self.buffer.u64_stream();

            self.core.ingest_chunks(iter);

            bytes = leftover;
            self.buffer_usage = 0;
        }

        // Consume the input data in large chunks
        let (iter, bytes) = bytes.u64_stream_with_stride(4);
        self.core.ingest_chunks(iter);

        // Save any leftover data for the next call
        if bytes.len() > 0 {
            unsafe {
                core::ptr::copy_nonoverlapping(bytes.as_ptr(), self.buffer.as_mut_ptr(), bytes.len());
            }
            self.buffer_usage = bytes.len();
        }
    }

    fn finish(&self) -> u64 {
        let mut hash;

        // We have processed at least one full chunk
        if self.total_len >= CHUNK_SIZE as u64 {
            hash = self.core.finish();
        } else {
            hash = self.seed.wrapping_add(PRIME_5);
        }

        hash = hash.wrapping_add(self.total_len);

        let buffered = &self.buffer[..self.buffer_usage];
        let (buffered_u64s, buffered) = buffered.u64_stream();

        for mut k1 in buffered_u64s {
            k1 = k1.wrapping_mul(PRIME_2);
            k1 = k1.rotate_left(31);
            k1 = k1.wrapping_mul(PRIME_1);
            hash ^= k1;
            hash = hash.rotate_left(27);
            hash = hash.wrapping_mul(PRIME_1);
            hash = hash.wrapping_add(PRIME_4);
        }

        let (buffered_u32s, buffered) = buffered.u32_stream();

        for k1 in buffered_u32s {
            let k1 = (k1 as u64).wrapping_mul(PRIME_1);
            hash ^= k1;
            hash = hash.rotate_left(23);
            hash = hash.wrapping_mul(PRIME_2);
            hash = hash.wrapping_add(PRIME_3);
        }

        for buffered_u8 in buffered {
            let k1 = (*buffered_u8 as u64).wrapping_mul(PRIME_5);
            hash ^= k1;
            hash = hash.rotate_left(11);
            hash = hash.wrapping_mul(PRIME_1);
        }

        // The final intermixing
        hash ^= hash >> 33;
        hash = hash.wrapping_mul(PRIME_2);
        hash ^= hash >> 29;
        hash = hash.wrapping_mul(PRIME_3);
        hash ^= hash >> 32;

        hash
    }
}

#[cfg(feature = "std")]
mod std_support;

#[cfg(feature = "std")]
pub use std_support::sixty_four::RandomXxHashBuilder;

#[cfg(test)]
mod test {
    use std::prelude::v1::*;

    use std::hash::{Hasher, BuildHasherDefault};
    use std::collections::HashMap;
    use super::{XxHash, RandomXxHashBuilder};

    #[test]
    fn ingesting_byte_by_byte_is_equivalent_to_large_chunks() {
        let bytes: Vec<_> = (0..32).map(|_| 0).collect();

        let mut byte_by_byte = XxHash::with_seed(0);
        for byte in bytes.chunks(1) {
            byte_by_byte.write(byte);
        }

        let mut one_chunk = XxHash::with_seed(0);
        one_chunk.write(&bytes);

        assert_eq!(byte_by_byte.core, one_chunk.core);
    }

    #[test]
    fn hash_of_nothing_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0xef46db3751d8e999);
    }

    #[test]
    fn hash_of_single_byte_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(&[42]);
        assert_eq!(hasher.finish(), 0x0a9edecebeb03ae4);
    }

    #[test]
    fn hash_of_multiple_bytes_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(b"Hello, world!\0");
        assert_eq!(hasher.finish(), 0x7b06c531ea43e89f);
    }

    #[test]
    fn hash_of_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::with_seed(0);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x6ac1e58032166597);
    }

    #[test]
    fn hash_with_different_seed_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0xae0543311b702d91);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0x4b6a04fcdf7a4672);
    }

    #[test]
    fn hash_with_different_seed_and_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::with_seed(0xae0543311b702d91);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x567e355e0682e1f1);
    }

    #[test]
    fn can_be_used_in_a_hashmap_with_a_default_seed() {
        let mut hash: HashMap<_, _, BuildHasherDefault<XxHash>> = Default::default();
        hash.insert(42, "the answer");
        assert_eq!(hash.get(&42), Some(&"the answer"));
    }

    #[test]
    fn can_be_used_in_a_hashmap_with_a_random_seed() {
        let mut hash: HashMap<_, _, RandomXxHashBuilder> = Default::default();
        hash.insert(42, "the answer");
        assert_eq!(hash.get(&42), Some(&"the answer"));
    }

    #[cfg(feature="serialize")]
    type TestResult<T = ()> = Result<T, Box<dyn std::error::Error>>;

    #[cfg(feature="serialize")]
    #[test]
    fn test_serialization_cycle() -> TestResult {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(b"Hello, world!\0");
        hasher.finish();

        let serialized = serde_json::to_string(&hasher)?;
        let unserialized: XxHash = serde_json::from_str(&serialized)?;
        assert_eq!(hasher, unserialized);
        Ok(())
    }

    #[cfg(feature="serialize")]
    #[test]
    fn test_serialization_stability() -> TestResult {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(b"Hello, world!\0");
        hasher.finish();

        let serialized = r#"{
            "total_len": 14,
            "seed": 0,
            "core": {
              "v1": 6983438078262162902,
              "v2": 14029467366897019727,
              "v3": 0,
              "v4": 7046029288634856825
            },
            "buffer": [
              72,  101, 108, 108, 111, 44, 32, 119,
              111, 114, 108, 100, 33,  0,  0,  0,
              0,   0,   0,   0,   0,   0,  0,  0,
              0,   0,   0,   0,   0,   0,  0,  0
            ],
            "buffer_usage": 14
        }"#;

        let unserialized: XxHash = serde_json::from_str(serialized).unwrap();
        assert_eq!(hasher, unserialized);
        Ok(())
    }
}
<|endoftext|>


<commit_before>extern crate regex;
#[macro_use]
extern crate lazy_static;

pub mod lexer;
pub mod parser;

#[cfg(test)]
mod tests {
    use parser;
    #[test]
    fn addition() {
        let input = String::from("1 + 2");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (1+2) as f64);
    }
    #[test]
    fn subtraction() {
        let input = String::from("18 - 4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (18-4) as f64);
    }
    #[test]
    fn multiplication() {
        let input = String::from("3 * 6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (3*6) as f64);
    }
    #[test]
    fn divide() {
        let input = String::from("15 / 3");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (15/3) as f64);
    }
    #[test]
    fn end() {
        let input = String::from("");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
    }
    #[test]
    fn ignore_whitespace() {
        let input = String::from("   12        -  8   ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (12-8) as f64);
        let input = String::from("142        -9   ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (142-9) as f64);
        let input = String::from("72+  15");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (72+15) as f64);
        let input = String::from(" 12*  4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (12*4) as f64);
        let input = String::from(" 50/10");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (50.0/10.0) as f64);
    }
    #[test]
    fn long_add_expressions() {
        let input = String::from("2 -4 +6 -1 -1- 0 +8");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2-4+6-1-1-0+8) as f64);
        let input = String::from("1 -1   + 2   - 2   +  4 - 4 +    6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (1-1+2-2+4-4+6) as f64);
    }
    #[test]
    fn long_mult_expressions() {
        let input = String::from("2 *4 *6 *1 *1* 0 *8");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2*4*6*1*1*0*8) as f64);
        let input = String::from("1 *1   * 2   * 2   *  4 * 4 *    6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (1*1*2*2*4*4*6) as f64);
    }
    #[test]
    fn long_mixed() {
        let input = String::from(" 2*3 - 4*5 + 6/3 ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0*3.0-4.0*5.0+6.0/3.0) as f64);
        let input = String::from("2*3*4/8 -   5/2*4 +  6 + 0/3   ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0*3.0*4.0/8.0-5.0/2.0*4.0+6.0+0.0/3.0) as f64);
    }
    #[test]
    fn floating() {
        let input = String::from("10/4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (10.0/4.0) as f64);
        let input = String::from("5/3");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (5.0/3.0) as f64);
        let input = String::from("3 + 8/5 -1 -2*5");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (3.0+8.0/5.0-1.0-2.0*5.0) as f64);
    }
    #[test]
    fn bad_tokens() {
        let input = String::from("  6 + c");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
        let input = String::from("  7 & 2");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
        let input = String::from("  %");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
    }
    #[test]
    fn syntax_error() {
        let input = String::from(" 5 + + 6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
        let input = String::from(" 5 * / 6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
    }
    #[test]
    fn divide_zero() {
        let input = String::from("5/0");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap().is_infinite());
        let input = String::from(" 2 - 1 + 14/0 + 7");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap().is_infinite());
    }
    #[test]
    fn unused_parens() {
        let input = String::from(" (2) ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2) as f64);
    }
    #[test]
    fn enclosing_parens() {
        let input = String::from("(5 + 2*3 - 1 + 7 * 8)");
        let mut my_parser = parser::Parser::new(input);
        let r = my_parser.parse().unwrap();
        let result = (5.0+2.0*3.0-1.0+7.0*8.0) as f64;
        assert!(r == result, "{}\t{}", r, result);
        let input = String::from("(67 + 2 * 3 - 67 + 2/1 - 7)");
        let mut my_parser = parser::Parser::new(input);
        let r = my_parser.parse().unwrap();
        let result = (67.0+2.0*3.0-67.0+2.0/1.0-7.0) as f64;
        assert!(r == result, "{}\t{}", r, result);
    }
    #[test]
    fn sub_expressions() {
        let input = String::from("(2) + (17*2-30) * (5)+2 - (8/2)*4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == ((2.0)+(17.0*2.0-30.0)*(5.0)+2.0-(8.0/2.0)*4.0) as f64);
        let input = String::from("(5*7/5) + (23) - 5 * (98-4)/(6*7-42)");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == ((5.0*7.0/5.0)+(23.0)-5.0*(98.0-4.0)/(6.0*7.0-42.0)) as f64);
    }
    #[test]
    fn nested_parens() {
        let input = String::from("(((((5)))))");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == ((((((5)))))) as f64);
        let input = String::from("(( ((2)) + 4))*((5))");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (((((2.0))+4.0))*((5.0))) as f64);
    }
    #[test]
    fn unbalanced_parens() {
        let input = String::from("2 + (5 * 2");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0+(5.0*2.0)) as f64);
        let input = String::from("(((((4))))");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (4.0) as f64);
        let input = String::from("((2)) * ((3");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0*3.0) as f64);
        let input = String::from("((9)) * ((1)");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (9.0*1.0) as f64);
    }
}
<commit_msg>Make sure division is f64<commit_after>extern crate regex;
#[macro_use]
extern crate lazy_static;

pub mod lexer;
pub mod parser;

#[cfg(test)]
mod tests {
    use parser;
    #[test]
    fn addition() {
        let input = String::from("1 + 2");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (1+2) as f64);
    }
    #[test]
    fn subtraction() {
        let input = String::from("18 - 4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (18-4) as f64);
    }
    #[test]
    fn multiplication() {
        let input = String::from("3 * 6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (3*6) as f64);
    }
    #[test]
    fn divide() {
        let input = String::from("15 / 3");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (15.0/3.0) as f64);
    }
    #[test]
    fn end() {
        let input = String::from("");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
    }
    #[test]
    fn ignore_whitespace() {
        let input = String::from("   12        -  8   ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (12-8) as f64);
        let input = String::from("142        -9   ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (142-9) as f64);
        let input = String::from("72+  15");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (72+15) as f64);
        let input = String::from(" 12*  4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (12*4) as f64);
        let input = String::from(" 50/10");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (50.0/10.0) as f64);
    }
    #[test]
    fn long_add_expressions() {
        let input = String::from("2 -4 +6 -1 -1- 0 +8");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2-4+6-1-1-0+8) as f64);
        let input = String::from("1 -1   + 2   - 2   +  4 - 4 +    6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (1-1+2-2+4-4+6) as f64);
    }
    #[test]
    fn long_mult_expressions() {
        let input = String::from("2 *4 *6 *1 *1* 0 *8");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2*4*6*1*1*0*8) as f64);
        let input = String::from("1 *1   * 2   * 2   *  4 * 4 *    6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (1*1*2*2*4*4*6) as f64);
    }
    #[test]
    fn long_mixed() {
        let input = String::from(" 2*3 - 4*5 + 6/3 ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0*3.0-4.0*5.0+6.0/3.0) as f64);
        let input = String::from("2*3*4/8 -   5/2*4 +  6 + 0/3   ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0*3.0*4.0/8.0-5.0/2.0*4.0+6.0+0.0/3.0) as f64);
    }
    #[test]
    fn floating() {
        let input = String::from("10/4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (10.0/4.0) as f64);
        let input = String::from("5/3");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (5.0/3.0) as f64);
        let input = String::from("3 + 8/5 -1 -2*5");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (3.0+8.0/5.0-1.0-2.0*5.0) as f64);
    }
    #[test]
    fn bad_tokens() {
        let input = String::from("  6 + c");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
        let input = String::from("  7 & 2");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
        let input = String::from("  %");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
    }
    #[test]
    fn syntax_error() {
        let input = String::from(" 5 + + 6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
        let input = String::from(" 5 * / 6");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().is_err());
    }
    #[test]
    fn divide_zero() {
        let input = String::from("5/0");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap().is_infinite());
        let input = String::from(" 2 - 1 + 14/0 + 7");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap().is_infinite());
    }
    #[test]
    fn unused_parens() {
        let input = String::from(" (2) ");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2) as f64);
    }
    #[test]
    fn enclosing_parens() {
        let input = String::from("(5 + 2*3 - 1 + 7 * 8)");
        let mut my_parser = parser::Parser::new(input);
        let r = my_parser.parse().unwrap();
        let result = (5.0+2.0*3.0-1.0+7.0*8.0) as f64;
        assert!(r == result, "{}\t{}", r, result);
        let input = String::from("(67 + 2 * 3 - 67 + 2/1 - 7)");
        let mut my_parser = parser::Parser::new(input);
        let r = my_parser.parse().unwrap();
        let result = (67.0+2.0*3.0-67.0+2.0/1.0-7.0) as f64;
        assert!(r == result, "{}\t{}", r, result);
    }
    #[test]
    fn sub_expressions() {
        let input = String::from("(2) + (17*2-30) * (5)+2 - (8/2)*4");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == ((2.0)+(17.0*2.0-30.0)*(5.0)+2.0-(8.0/2.0)*4.0) as f64);
        let input = String::from("(5*7/5) + (23) - 5 * (98-4)/(6*7-42)");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == ((5.0*7.0/5.0)+(23.0)-5.0*(98.0-4.0)/(6.0*7.0-42.0)) as f64);
    }
    #[test]
    fn nested_parens() {
        let input = String::from("(((((5)))))");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == ((((((5)))))) as f64);
        let input = String::from("(( ((2)) + 4))*((5))");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (((((2.0))+4.0))*((5.0))) as f64);
    }
    #[test]
    fn unbalanced_parens() {
        let input = String::from("2 + (5 * 2");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0+(5.0*2.0)) as f64);
        let input = String::from("(((((4))))");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (4.0) as f64);
        let input = String::from("((2)) * ((3");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (2.0*3.0) as f64);
        let input = String::from("((9)) * ((1)");
        let mut my_parser = parser::Parser::new(input);
        assert!(my_parser.parse().unwrap() == (9.0*1.0) as f64);
    }
}
<|endoftext|>