<commit_before>#[macro_use]
extern crate log;

use std::collections::{BTreeMap, BTreeSet};

/// The version type alias used to uniquely reference migrations.
pub type Version = i64;

/// All migrations will implement this trait, and a migration trait specific to the chosen adapter.
/// This trait defines the metadata for tracking migration sequence and for human reference.
pub trait Migration {
    /// An ordered (but not necessarily sequential), unique identifier for this migration.
    /// Registered migrations will be applied in ascending order by version.
    fn version(&self) -> Version;

    /// A message describing the effects of this migration.
    fn description(&self) -> &'static str;
}

/// Efficiently implement the `Migration` trait for a given type.
///
/// ## Example
///
/// ```rust
/// # #[macro_use]
/// # extern crate schemamama;
/// struct MyMigration;
/// migration!(MyMigration, 100, "create some lovely database tables");
///
/// # fn main() {
/// use schemamama::Migration;
/// let m = MyMigration;
/// assert_eq!(m.version(), 100);
/// assert_eq!(m.description(), "create some lovely database tables");
/// # }
/// ```
#[macro_export]
macro_rules! migration {
    ($ty:ident, $version:expr, $description:expr) => {
        impl $crate::Migration for $ty {
            fn version(&self) -> $crate::Version { $version }
            fn description(&self) -> &'static str { $description }
        }
    }
}

/// Use this trait to connect the migrator to your chosen database technology.
pub trait Adapter {
    /// An alias to a specific trait that extends `Migration`. Typically, the aforementioned trait
    /// will declare functions that the adapter will use to migrate upwards and downwards.
    type MigrationType: Migration + ?Sized;

    /// An adapter-specific error type that can be returned from any of this trait's methods.
    type Error;

    /// Returns the latest migration version, or `None` if no migrations have been recorded.
    fn current_version(&self) -> Result<Option<Version>, Self::Error>;

    /// Returns a set of the versions of all of the currently applied migrations.
    fn migrated_versions(&self) -> Result<BTreeSet<Version>, Self::Error>;

    /// Applies the specified migration.
    fn apply_migration(&self, migration: &Self::MigrationType) -> Result<(), Self::Error>;

    /// Reverts the specified migration.
    fn revert_migration(&self, migration: &Self::MigrationType) -> Result<(), Self::Error>;
}

/// Maintains an ordered collection of migrations to utilize.
pub struct Migrator<T: Adapter> {
    adapter: T,
    migrations: BTreeMap<Version, Box<T::MigrationType>>
}

impl<T: Adapter> Migrator<T> {
    /// Create a migrator with a given adapter.
    pub fn new(adapter: T) -> Migrator<T> {
        Migrator { adapter: adapter, migrations: BTreeMap::new() }
    }

    /// Get a reference to the adapter.
    pub fn adapter(&self) -> &T {
        &self.adapter
    }

    /// Register a migration. If a migration with the same version is already registered, a warning
    /// is logged and the registration fails.
    pub fn register(&mut self, migration: Box<T::MigrationType>) {
        let version = migration.version();
        if self.version_registered(version) {
            warn!("Migration with version {:?} is already registered", version);
        } else {
            self.migrations.insert(version, migration);
        }
    }

    /// Returns true is a migration with the provided version has been registered.
    pub fn version_registered(&self, version: Version) -> bool {
        self.migrations.contains_key(&version)
    }

    /// Returns the set of all registered migration versions.
    pub fn registered_versions(&self) -> BTreeSet<Version> {
        self.migrations.keys().cloned().collect()
    }

    /// Returns the lowest version of the registered migrations, or `None` if no migrations have
    /// been registered.
    pub fn first_version(&self) -> Option<Version> {
        self.migrations.keys().next().map(|v| *v)
    }

    /// Returns the highest version of the registered migrations, or `None` if no migrations have
    /// been registered.
    pub fn last_version(&self) -> Option<Version> {
        self.migrations.keys().last().map(|v| *v)
    }

    /// Returns the latest migration version, or `None` if no migrations have been recorded.
    pub fn current_version(&self) -> Result<Option<Version>, T::Error> {
        self.adapter.current_version()
    }

    /// Returns a set of the versions of all of the currently applied migrations.
    pub fn migrated_versions(&self) -> Result<BTreeSet<Version>, T::Error> {
        self.adapter.migrated_versions()
    }

    /// Rollback to the specified version (exclusive), or rollback to the state before any
    /// registered migrations were applied if `None` is specified.
    pub fn down(&self, to: Option<Version>) -> Result<(), T::Error> {
        let from = try!(self.current_version());
        if from.is_none() { return Ok(()); }

        let migrated_versions = try!(self.migrated_versions());
        let targets = self.migrations.iter()
            // Rollback migrations from latest to oldest:
            .rev()
            // Rollback the current version, and all versions downwards until the specified version
            // (exclusive):
            .filter(|&(&v, _)| within_range(v, to, from))
            // Rollback only the migrations that are actually already migrated (in the case that
            // some intermediary migrations were never executed).
            .filter(|&(v, _)| migrated_versions.contains(v));

        for (version, migration) in targets {
            info!("Reverting migration {:?}: {}", version, migration.description());
            try!(self.adapter.revert_migration(migration));
        }

        Ok(())
    }

    /// Migrate to the specified version (inclusive).
    pub fn up(&self, to: Option<Version>) -> Result<(), T::Error> {
        let migrated_versions = try!(self.migrated_versions());
        let targets = self.migrations.iter()
            // Execute all versions upwards until the specified version (inclusive):
            .filter(|&(&v, _)| within_range(v, None, to))
            // Execute only the migrations that are actually not already migrated (in the case that
            // some intermediary migrations were previously executed).
            .filter(|&(v, _)| !migrated_versions.contains(v));

        for (version, migration) in targets {
            info!("Applying migration {:?}: {}", version, migration.description());
            try!(self.adapter.apply_migration(migration));
        }

        Ok(())
    }
}

// Tests whether a `Version` is within a range defined by the exclusive `low` and the inclusive
// `high` bounds.
fn within_range(version: Version, low: Option<Version>, high: Option<Version>) -> bool {
    match (low, high) {
        (None, None)            => true,
        (Some(low), Some(high)) => version > low && version <= high,
        (Some(low), None)       => version > low,
        (None, Some(high))      => version <= high
    }
}

#[test]
fn test_within_range() {
    // no lower or upper bound
    assert!(within_range(0, None, None));
    assert!(within_range(42, None, None));
    assert!(within_range(100000, None, None));

    // both lower and upper bounds
    assert!(!within_range(1, Some(2), Some(5)));
    assert!(!within_range(2, Some(2), Some(5)));
    assert!(within_range(3, Some(2), Some(5)));
    assert!(within_range(5, Some(2), Some(5)));
    assert!(!within_range(6, Some(2), Some(5)));

    // lower bound only
    assert!(!within_range(0, Some(5), None));
    assert!(!within_range(4, Some(5), None));
    assert!(!within_range(5, Some(5), None));
    assert!(within_range(6, Some(5), None));
    assert!(within_range(60, Some(5), None));

    // upper bound only
    assert!(within_range(0, None, Some(5)));
    assert!(within_range(5, None, Some(5)));
    assert!(!within_range(6, None, Some(5)));
}
<commit_msg>Code style normalization<commit_after>#[macro_use]
extern crate log;

use std::collections::{BTreeMap, BTreeSet};

/// The version type alias used to uniquely reference migrations.
pub type Version = i64;

/// All migrations will implement this trait, and a migration trait specific to the chosen adapter.
/// This trait defines the metadata for tracking migration sequence and for human reference.
pub trait Migration {
    /// An ordered (but not necessarily sequential), unique identifier for this migration.
    /// Registered migrations will be applied in ascending order by version.
    fn version(&self) -> Version;

    /// A message describing the effects of this migration.
    fn description(&self) -> &'static str;
}

/// Efficiently implement the `Migration` trait for a given type.
///
/// ## Example
///
/// ```rust
/// # #[macro_use]
/// # extern crate schemamama;
/// struct MyMigration;
/// migration!(MyMigration, 100, "create some lovely database tables");
///
/// # fn main() {
/// use schemamama::Migration;
/// let m = MyMigration;
/// assert_eq!(m.version(), 100);
/// assert_eq!(m.description(), "create some lovely database tables");
/// # }
/// ```
#[macro_export]
macro_rules! migration {
    ($ty:ident, $version:expr, $description:expr) => {
        impl $crate::Migration for $ty {
            fn version(&self) -> $crate::Version { $version }
            fn description(&self) -> &'static str { $description }
        }
    }
}

/// Use this trait to connect the migrator to your chosen database technology.
pub trait Adapter {
    /// An alias to a specific trait that extends `Migration`. Typically, the aforementioned trait
    /// will declare functions that the adapter will use to migrate upwards and downwards.
    type MigrationType: Migration + ?Sized;

    /// An adapter-specific error type that can be returned from any of this trait's methods.
    type Error;

    /// Returns the latest migration version, or `None` if no migrations have been recorded.
    fn current_version(&self) -> Result<Option<Version>, Self::Error>;

    /// Returns a set of the versions of all of the currently applied migrations.
    fn migrated_versions(&self) -> Result<BTreeSet<Version>, Self::Error>;

    /// Applies the specified migration.
    fn apply_migration(&self, migration: &Self::MigrationType) -> Result<(), Self::Error>;

    /// Reverts the specified migration.
    fn revert_migration(&self, migration: &Self::MigrationType) -> Result<(), Self::Error>;
}

/// Maintains an ordered collection of migrations to utilize.
pub struct Migrator<T: Adapter> {
    adapter: T,
    migrations: BTreeMap<Version, Box<T::MigrationType>>
}

impl<T: Adapter> Migrator<T> {
    /// Create a migrator with a given adapter.
    pub fn new(adapter: T) -> Migrator<T> {
        Migrator { adapter: adapter, migrations: BTreeMap::new() }
    }

    /// Get a reference to the adapter.
    pub fn adapter(&self) -> &T {
        &self.adapter
    }

    /// Register a migration. If a migration with the same version is already registered, a warning
    /// is logged and the registration fails.
    pub fn register(&mut self, migration: Box<T::MigrationType>) {
        let version = migration.version();
        if self.version_registered(version) {
            warn!("Migration with version {:?} is already registered", version);
        } else {
            self.migrations.insert(version, migration);
        }
    }

    /// Returns true is a migration with the provided version has been registered.
    pub fn version_registered(&self, version: Version) -> bool {
        self.migrations.contains_key(&version)
    }

    /// Returns the set of all registered migration versions.
    pub fn registered_versions(&self) -> BTreeSet<Version> {
        self.migrations.keys().cloned().collect()
    }

    /// Returns the lowest version of the registered migrations, or `None` if no migrations have
    /// been registered.
    pub fn first_version(&self) -> Option<Version> {
        self.migrations.keys().next().map(|v| *v)
    }

    /// Returns the highest version of the registered migrations, or `None` if no migrations have
    /// been registered.
    pub fn last_version(&self) -> Option<Version> {
        self.migrations.keys().last().map(|v| *v)
    }

    /// Returns the latest migration version, or `None` if no migrations have been recorded.
    pub fn current_version(&self) -> Result<Option<Version>, T::Error> {
        self.adapter.current_version()
    }

    /// Returns a set of the versions of all of the currently applied migrations.
    pub fn migrated_versions(&self) -> Result<BTreeSet<Version>, T::Error> {
        self.adapter.migrated_versions()
    }

    /// Rollback to the specified version (exclusive), or rollback to the state before any
    /// registered migrations were applied if `None` is specified.
    pub fn down(&self, to: Option<Version>) -> Result<(), T::Error> {
        let from = try!(self.current_version());
        if from.is_none() {
            return Ok(());
        }

        let migrated_versions = try!(self.migrated_versions());
        let targets = self.migrations.iter()
            // Rollback migrations from latest to oldest:
            .rev()
            // Rollback the current version, and all versions downwards until the specified version
            // (exclusive):
            .filter(|&(&v, _)| within_range(v, to, from))
            // Rollback only the migrations that are actually already migrated (in the case that
            // some intermediary migrations were never executed).
            .filter(|&(v, _)| migrated_versions.contains(v));

        for (version, migration) in targets {
            info!("Reverting migration {:?}: {}", version, migration.description());
            try!(self.adapter.revert_migration(migration));
        }

        Ok(())
    }

    /// Migrate to the specified version (inclusive).
    pub fn up(&self, to: Option<Version>) -> Result<(), T::Error> {
        let migrated_versions = try!(self.migrated_versions());
        let targets = self.migrations.iter()
            // Execute all versions upwards until the specified version (inclusive):
            .filter(|&(&v, _)| within_range(v, None, to))
            // Execute only the migrations that are actually not already migrated (in the case that
            // some intermediary migrations were previously executed).
            .filter(|&(v, _)| !migrated_versions.contains(v));

        for (version, migration) in targets {
            info!("Applying migration {:?}: {}", version, migration.description());
            try!(self.adapter.apply_migration(migration));
        }

        Ok(())
    }
}

// Tests whether a `Version` is within a range defined by the exclusive `low` and the inclusive
// `high` bounds.
fn within_range(version: Version, low: Option<Version>, high: Option<Version>) -> bool {
    match (low, high) {
        (None, None) => true,
        (Some(low), None) => version > low,
        (None, Some(high)) => version <= high,
        (Some(low), Some(high)) => version > low && version <= high,
    }
}

#[test]
fn test_within_range() {
    // no lower or upper bound
    assert!(within_range(0, None, None));
    assert!(within_range(42, None, None));
    assert!(within_range(100000, None, None));

    // both lower and upper bounds
    assert!(!within_range(1, Some(2), Some(5)));
    assert!(!within_range(2, Some(2), Some(5)));
    assert!(within_range(3, Some(2), Some(5)));
    assert!(within_range(5, Some(2), Some(5)));
    assert!(!within_range(6, Some(2), Some(5)));

    // lower bound only
    assert!(!within_range(0, Some(5), None));
    assert!(!within_range(4, Some(5), None));
    assert!(!within_range(5, Some(5), None));
    assert!(within_range(6, Some(5), None));
    assert!(within_range(60, Some(5), None));

    // upper bound only
    assert!(within_range(0, None, Some(5)));
    assert!(within_range(5, None, Some(5)));
    assert!(!within_range(6, None, Some(5)));
}
<|endoftext|>


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

extern crate num;

pub mod create;
pub use create::*;

pub mod set;
pub use set::*;

pub mod mul;
pub use mul::*;

pub mod sdiv;
pub use sdiv::*;

pub mod misc;
pub use misc::*;

pub mod transform;
pub use transform::*;
<commit_msg>updated to lastest rust nightly<commit_after>#![no_std]

extern crate num;

pub mod create;
pub use create::*;

pub mod set;
pub use set::*;

pub mod mul;
pub use mul::*;

pub mod sdiv;
pub use sdiv::*;

pub mod misc;
pub use misc::*;

pub mod transform;
pub use transform::*;
<|endoftext|>


<commit_before>use impl_prelude::*;

/// A solution to the singular value decomposition.
///
/// A singular value decomposition solution includes singular values
/// and, optionally, the left and right singular vectors, stored as a
/// mtrix.
pub struct SVDSolution<T: LinxalImplScalar> {
    /// Singular values of the matrix.
    ///
    /// Singular values, which are guaranteed to be non-negative
    /// reals, are returned in descending order.
    pub values: Array<T::RealPart, Ix1>,

    /// The matrix `U` of left singular vectors.
    pub left_vectors: Option<Array<T, Ix2>>,

    /// The matrix V^t of singular vectors.
    ///
    /// The transpose of V is stored, not V itself.
    pub right_vectors: Option<Array<T, Ix2>>,
}

impl<T: LinxalImplScalar> SVDSolution<T> {
    // Return true if the full complement of vectors is available to
    // fully reconstruct the original matrix.
    pub fn is_reconstructable(&self) -> bool {
        self.left_vectors.is_some() && self.right_vectors.is_some()
    }

    /// Reconstruct the original matrix if both left and right
    /// singular vectors are present.
    pub fn reconstruct(&self) -> Option<Array<T, Ix2>> {
        match (&self.left_vectors, &self.right_vectors)  {
            (&Some(ref u), &Some(ref vt)) => {
                let mut d: Array<T, Ix2> = Array::zeros((self.values.len(), self.values.len()));
                d.diag_mut().zip_mut_with(&self.values, |dx, vx| {
                    *dx = T::from_real(*vx)
                });

                Some(u.dot(&d.dot(vt)))
            },
            _ => None
        }
    }
}

/// An error resulting from a `SVD::compute*` method.
#[derive(Debug)]
pub enum SVDError {
    Unconverged,
    IllegalParameter(i32),
    BadLayout,
}
<commit_msg>SVDError enum documentation<commit_after>use impl_prelude::*;

/// A solution to the singular value decomposition.
///
/// A singular value decomposition solution includes singular values
/// and, optionally, the left and right singular vectors, stored as a
/// mtrix.
pub struct SVDSolution<T: LinxalImplScalar> {
    /// Singular values of the matrix.
    ///
    /// Singular values, which are guaranteed to be non-negative
    /// reals, are returned in descending order.
    pub values: Array<T::RealPart, Ix1>,

    /// The matrix `U` of left singular vectors.
    pub left_vectors: Option<Array<T, Ix2>>,

    /// The matrix V^t of singular vectors.
    ///
    /// The transpose of V is stored, not V itself.
    pub right_vectors: Option<Array<T, Ix2>>,
}

impl<T: LinxalImplScalar> SVDSolution<T> {
    // Return true if the full complement of vectors is available to
    // fully reconstruct the original matrix.
    pub fn is_reconstructable(&self) -> bool {
        self.left_vectors.is_some() && self.right_vectors.is_some()
    }

    /// Reconstruct the original matrix if both left and right
    /// singular vectors are present.
    pub fn reconstruct(&self) -> Option<Array<T, Ix2>> {
        match (&self.left_vectors, &self.right_vectors)  {
            (&Some(ref u), &Some(ref vt)) => {
                let mut d: Array<T, Ix2> = Array::zeros((u.dim().1, vt.dim().0));
                d.diag_mut().zip_mut_with(&self.values, |dx, vx| {
                    *dx = T::from_real(*vx)
                });

                Some(u.dot(&d.dot(vt)))
            },
            _ => None
        }
    }
}

/// An error resulting from a `SVD::compute*` method.
#[derive(Debug)]
pub enum SVDError {
    /// The decomposition algorithm failed to converge
    Unconverged,

    // Internal error from underlying LAPACK call
    IllegalParameter(i32),

    /// The input matrix does not follow C- or F- layout.
    BadLayout,
}
<|endoftext|>


<commit_before>//! Utilities for logging messages from the library.

use once_cell::sync::Lazy;

#[macro_export]
macro_rules! rsvg_log {
    (
        $($arg:tt)+
    ) => {
        if $crate::log::log_enabled() {
            println!("{}", format_args!($($arg)+));
        }
    };
}

pub fn log_enabled() -> bool {
    static ENABLED: Lazy<bool> = Lazy::new(|| ::std::env::var_os("RSVG_LOG").is_some());

    *ENABLED
}
<commit_msg>New CairoContextState struct to capture the state of a passed-in Cairo context<commit_after>//! Utilities for logging messages from the library.

use once_cell::sync::Lazy;

#[macro_export]
macro_rules! rsvg_log {
    (
        $($arg:tt)+
    ) => {
        if $crate::log::log_enabled() {
            println!("{}", format_args!($($arg)+));
        }
    };
}

pub fn log_enabled() -> bool {
    static ENABLED: Lazy<bool> = Lazy::new(|| ::std::env::var_os("RSVG_LOG").is_some());

    *ENABLED
}

/// Captures the basic state of a [`cairo::Context`] for logging purposes.
///
/// A librsvg "transaction" like rendering a
/// [`crate::api::SvgHandle`], which takes a Cairo context, depends on the state of the
/// context as it was passed in by the caller.  For example, librsvg may decide to
/// operate differently depending on the context's target surface type, or its current
/// transformation matrix.  This struct captures that sort of information.
#[derive(Copy, Clone, Debug, PartialEq)]
struct CairoContextState {
    surface_type: cairo::SurfaceType,
}

impl CairoContextState {
    fn new(cr: &cairo::Context) -> Self {
        let surface_type = cr.target().type_();

        Self { surface_type }
    }
}

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

    #[test]
    fn captures_cr_surface_type() {
        let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, 10, 10).unwrap();
        let cr = cairo::Context::new(&surface).unwrap();
        let state = CairoContextState::new(&cr);

        assert_eq!(
            CairoContextState {
                surface_type: cairo::SurfaceType::Image,
            },
            state,
        );

        let surface = cairo::RecordingSurface::create(cairo::Content::ColorAlpha, None).unwrap();
        let cr = cairo::Context::new(&surface).unwrap();
        let state = CairoContextState::new(&cr);

        assert_eq!(
            CairoContextState {
                surface_type: cairo::SurfaceType::Recording,
            },
            state,
        );
    }
}
<|endoftext|>


<commit_before>use super::*;

/// Represents a macro invocation. The Path indicates which macro
/// is being invoked, and the vector of token-trees contains the source
/// of the macro invocation.
///
/// NB: the additional ident for a `macro_rules`-style macro is actually
/// stored in the enclosing item. Oog.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Mac {
    pub path: Path,
    pub tts: Vec<TokenTree>,
}

/// When the main rust parser encounters a syntax-extension invocation, it
/// parses the arguments to the invocation as a token-tree. This is a very
/// loose structure, such that all sorts of different AST-fragments can
/// be passed to syntax extensions using a uniform type.
///
/// If the syntax extension is an MBE macro, it will attempt to match its
/// LHS token tree against the provided token tree, and if it finds a
/// match, will transcribe the RHS token tree, splicing in any captured
/// `macro_parser::matched_nonterminals` into the `SubstNt`s it finds.
///
/// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
/// Nothing special happens to misnamed or misplaced `SubstNt`s.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum TokenTree {
    /// A single token
    Token(Token),
    /// A delimited sequence of token trees
    Delimited(Delimited),
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Delimited {
    /// The type of delimiter
    pub delim: DelimToken,
    /// The delimited sequence of token trees
    pub tts: Vec<TokenTree>,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Token {
    // Expression-operator symbols.
    Eq,
    Lt,
    Le,
    EqEq,
    Ne,
    Ge,
    Gt,
    AndAnd,
    OrOr,
    Not,
    Tilde,
    BinOp(BinOpToken),
    BinOpEq(BinOpToken),

    // Structural symbols
    At,
    Dot,
    DotDot,
    DotDotDot,
    Comma,
    Semi,
    Colon,
    ModSep,
    RArrow,
    LArrow,
    FatArrow,
    Pound,
    Dollar,
    Question,

    // Literals
    Literal(Lit),

    // Name components
    Ident(Ident),
    Underscore,
    Lifetime(Ident),

    DocComment(String),
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum BinOpToken {
    Plus,
    Minus,
    Star,
    Slash,
    Percent,
    Caret,
    And,
    Or,
    Shl,
    Shr,
}

/// A delimiter token
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum DelimToken {
    /// A round parenthesis: `(` or `)`
    Paren,
    /// A square bracket: `[` or `]`
    Bracket,
    /// A curly brace: `{` or `}`
    Brace,
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use Lifetime;
    use generics::parsing::lifetime;
    use ident::parsing::ident;
    use lit::parsing::lit;
    use space::{block_comment, whitespace};

    named!(pub mac -> Mac, do_parse!(
        name: ident >>
        punct!("!") >>
        body: delimited >>
        (Mac {
            path: name.into(),
            tts: vec![TokenTree::Delimited(body)],
        })
    ));

    named!(pub delimited -> Delimited, alt!(
        delimited!(
            punct!("("),
            many0!(token_tree),
            punct!(")")
        ) => { |tts| Delimited { delim: DelimToken::Paren, tts: tts } }
        |
        delimited!(
            punct!("["),
            many0!(token_tree),
            punct!("]")
        ) => { |tts| Delimited { delim: DelimToken::Bracket, tts: tts } }
        |
        delimited!(
            punct!("{"),
            many0!(token_tree),
            punct!("}")
        ) => { |tts| Delimited { delim: DelimToken::Brace, tts: tts } }
    ));

    named!(token_tree -> TokenTree, alt!(
        map!(token, TokenTree::Token)
        |
        map!(delimited, TokenTree::Delimited)
    ));

    named!(token -> Token, alt!(
        keyword!("_") => { |_| Token::Underscore }
        |
        punct!("&&") => { |_| Token::AndAnd } // must be before bin_op
        |
        punct!("||") => { |_| Token::OrOr } // must be before bin_op
        |
        map!(bin_op_eq, Token::BinOpEq)
        |
        map!(bin_op, Token::BinOp)
        |
        map!(lit, Token::Literal)
        |
        map!(ident, Token::Ident)
        |
        map!(lifetime, |lt: Lifetime| Token::Lifetime(lt.ident))
        |
        map!(doc_comment, Token::DocComment)
        |
        punct!("<=") => { |_| Token::Le }
        |
        punct!("==") => { |_| Token::EqEq }
        |
        punct!("!=") => { |_| Token::Ne }
        |
        punct!(">=") => { |_| Token::Ge }
        |
        punct!("::") => { |_| Token::ModSep }
        |
        punct!("->") => { |_| Token::RArrow }
        |
        punct!("<-") => { |_| Token::LArrow }
        |
        punct!("=>") => { |_| Token::FatArrow }
        |
        punct!("...") => { |_| Token::DotDotDot }
        |
        punct!("..") => { |_| Token::DotDot }
        |
        punct!(".") => { |_| Token::Dot }
        |
        punct!("=") => { |_| Token::Eq }
        |
        punct!("<") => { |_| Token::Lt }
        |
        punct!(">") => { |_| Token::Gt }
        |
        punct!("!") => { |_| Token::Not }
        |
        punct!("~") => { |_| Token::Tilde }
        |
        punct!("@") => { |_| Token::At }
        |
        punct!(",") => { |_| Token::Comma }
        |
        punct!(";") => { |_| Token::Semi }
        |
        punct!(":") => { |_| Token::Colon }
        |
        punct!("#") => { |_| Token::Pound }
        |
        punct!("$") => { |_| Token::Dollar }
        |
        punct!("?") => { |_| Token::Question }
    ));

    named!(bin_op -> BinOpToken, alt!(
        punct!("+") => { |_| BinOpToken::Plus }
        |
        punct!("-") => { |_| BinOpToken::Minus }
        |
        punct!("*") => { |_| BinOpToken::Star }
        |
        punct!("/") => { |_| BinOpToken::Slash }
        |
        punct!("%") => { |_| BinOpToken::Percent }
        |
        punct!("^") => { |_| BinOpToken::Caret }
        |
        punct!("&") => { |_| BinOpToken::And }
        |
        punct!("|") => { |_| BinOpToken::Or }
        |
        punct!("<<") => { |_| BinOpToken::Shl }
        |
        punct!(">>") => { |_| BinOpToken::Shr }
    ));

    named!(bin_op_eq -> BinOpToken, alt!(
        punct!("+=") => { |_| BinOpToken::Plus }
        |
        punct!("-=") => { |_| BinOpToken::Minus }
        |
        punct!("*=") => { |_| BinOpToken::Star }
        |
        punct!("/=") => { |_| BinOpToken::Slash }
        |
        punct!("%=") => { |_| BinOpToken::Percent }
        |
        punct!("^=") => { |_| BinOpToken::Caret }
        |
        punct!("&=") => { |_| BinOpToken::And }
        |
        punct!("|=") => { |_| BinOpToken::Or }
        |
        punct!("<<=") => { |_| BinOpToken::Shl }
        |
        punct!(">>=") => { |_| BinOpToken::Shr }
    ));

    named!(doc_comment -> String, alt!(
        do_parse!(
            punct!("//!") >>
            content: take_until!("\n") >>
            (format!("//!{}", content))
        )
        |
        do_parse!(
            option!(whitespace) >>
            peek!(tag!("/*!")) >>
            com: block_comment >>
            (com.to_owned())
        )
        |
        do_parse!(
            punct!("///") >>
            not!(peek!(tag!("/"))) >>
            content: take_until!("\n") >>
            (format!("///{}", content))
        )
        |
        do_parse!(
            option!(whitespace) >>
            peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
            com: block_comment >>
            (com.to_owned())
        )
    ));
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Mac {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.path.to_tokens(tokens);
            tokens.append("!");
            for tt in &self.tts {
                tt.to_tokens(tokens);
            }
        }
    }

    impl ToTokens for TokenTree {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                TokenTree::Token(ref token) => token.to_tokens(tokens),
                TokenTree::Delimited(ref delimited) => delimited.to_tokens(tokens),
            }
        }
    }

    impl DelimToken {
        fn open(&self) -> &'static str {
            match *self {
                DelimToken::Paren => "(",
                DelimToken::Bracket => "[",
                DelimToken::Brace => "{",
            }
        }

        fn close(&self) -> &'static str {
            match *self {
                DelimToken::Paren => ")",
                DelimToken::Bracket => "]",
                DelimToken::Brace => "}",
            }
        }
    }

    impl ToTokens for Delimited {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(self.delim.open());
            for tt in &self.tts {
                tt.to_tokens(tokens);
            }
            tokens.append(self.delim.close());
        }
    }

    impl ToTokens for Token {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                Token::Eq => tokens.append("="),
                Token::Lt => tokens.append("<"),
                Token::Le => tokens.append("<="),
                Token::EqEq => tokens.append("=="),
                Token::Ne => tokens.append("!="),
                Token::Ge => tokens.append(">="),
                Token::Gt => tokens.append(">"),
                Token::AndAnd => tokens.append("&&"),
                Token::OrOr => tokens.append("||"),
                Token::Not => tokens.append("!"),
                Token::Tilde => tokens.append("~"),
                Token::BinOp(binop) => tokens.append(binop.op()),
                Token::BinOpEq(binop) => tokens.append(binop.assign_op()),
                Token::At => tokens.append("@"),
                Token::Dot => tokens.append("."),
                Token::DotDot => tokens.append(".."),
                Token::DotDotDot => tokens.append("..."),
                Token::Comma => tokens.append(","),
                Token::Semi => tokens.append(";"),
                Token::Colon => tokens.append(":"),
                Token::ModSep => tokens.append("::"),
                Token::RArrow => tokens.append("->"),
                Token::LArrow => tokens.append("<-"),
                Token::FatArrow => tokens.append("=>"),
                Token::Pound => tokens.append("#"),
                Token::Dollar => tokens.append("$"),
                Token::Question => tokens.append("?"),
                Token::Literal(ref lit) => lit.to_tokens(tokens),
                Token::Ident(ref ident) => ident.to_tokens(tokens),
                Token::Underscore => tokens.append("_"),
                Token::Lifetime(ref ident) => ident.to_tokens(tokens),
                Token::DocComment(ref com) => {
                    tokens.append(&format!("{}\n", com));
                }
            }
        }
    }

    impl BinOpToken {
        fn op(&self) -> &'static str {
            match *self {
                BinOpToken::Plus => "+",
                BinOpToken::Minus => "-",
                BinOpToken::Star => "*",
                BinOpToken::Slash => "/",
                BinOpToken::Percent => "%",
                BinOpToken::Caret => "^",
                BinOpToken::And => "&",
                BinOpToken::Or => "|",
                BinOpToken::Shl => "<<",
                BinOpToken::Shr => ">>",
            }
        }

        fn assign_op(&self) -> &'static str {
            match *self {
                BinOpToken::Plus => "+=",
                BinOpToken::Minus => "-=",
                BinOpToken::Star => "*=",
                BinOpToken::Slash => "/=",
                BinOpToken::Percent => "%=",
                BinOpToken::Caret => "^=",
                BinOpToken::And => "&=",
                BinOpToken::Or => "|=",
                BinOpToken::Shl => "<<=",
                BinOpToken::Shr => ">>=",
            }
        }
    }

    impl ToTokens for BinOpToken {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(self.op());
        }
    }
}
<commit_msg>Update order of macro token parsing<commit_after>use super::*;

/// Represents a macro invocation. The Path indicates which macro
/// is being invoked, and the vector of token-trees contains the source
/// of the macro invocation.
///
/// NB: the additional ident for a `macro_rules`-style macro is actually
/// stored in the enclosing item. Oog.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Mac {
    pub path: Path,
    pub tts: Vec<TokenTree>,
}

/// When the main rust parser encounters a syntax-extension invocation, it
/// parses the arguments to the invocation as a token-tree. This is a very
/// loose structure, such that all sorts of different AST-fragments can
/// be passed to syntax extensions using a uniform type.
///
/// If the syntax extension is an MBE macro, it will attempt to match its
/// LHS token tree against the provided token tree, and if it finds a
/// match, will transcribe the RHS token tree, splicing in any captured
/// `macro_parser::matched_nonterminals` into the `SubstNt`s it finds.
///
/// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
/// Nothing special happens to misnamed or misplaced `SubstNt`s.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum TokenTree {
    /// A single token
    Token(Token),
    /// A delimited sequence of token trees
    Delimited(Delimited),
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Delimited {
    /// The type of delimiter
    pub delim: DelimToken,
    /// The delimited sequence of token trees
    pub tts: Vec<TokenTree>,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Token {
    // Expression-operator symbols.
    Eq,
    Lt,
    Le,
    EqEq,
    Ne,
    Ge,
    Gt,
    AndAnd,
    OrOr,
    Not,
    Tilde,
    BinOp(BinOpToken),
    BinOpEq(BinOpToken),

    // Structural symbols
    At,
    Dot,
    DotDot,
    DotDotDot,
    Comma,
    Semi,
    Colon,
    ModSep,
    RArrow,
    LArrow,
    FatArrow,
    Pound,
    Dollar,
    Question,

    // Literals
    Literal(Lit),

    // Name components
    Ident(Ident),
    Underscore,
    Lifetime(Ident),

    DocComment(String),
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum BinOpToken {
    Plus,
    Minus,
    Star,
    Slash,
    Percent,
    Caret,
    And,
    Or,
    Shl,
    Shr,
}

/// A delimiter token
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum DelimToken {
    /// A round parenthesis: `(` or `)`
    Paren,
    /// A square bracket: `[` or `]`
    Bracket,
    /// A curly brace: `{` or `}`
    Brace,
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use Lifetime;
    use generics::parsing::lifetime;
    use ident::parsing::ident;
    use lit::parsing::lit;
    use space::{block_comment, whitespace};

    named!(pub mac -> Mac, do_parse!(
        name: ident >>
        punct!("!") >>
        body: delimited >>
        (Mac {
            path: name.into(),
            tts: vec![TokenTree::Delimited(body)],
        })
    ));

    named!(pub delimited -> Delimited, alt!(
        delimited!(
            punct!("("),
            many0!(token_tree),
            punct!(")")
        ) => { |tts| Delimited { delim: DelimToken::Paren, tts: tts } }
        |
        delimited!(
            punct!("["),
            many0!(token_tree),
            punct!("]")
        ) => { |tts| Delimited { delim: DelimToken::Bracket, tts: tts } }
        |
        delimited!(
            punct!("{"),
            many0!(token_tree),
            punct!("}")
        ) => { |tts| Delimited { delim: DelimToken::Brace, tts: tts } }
    ));

    named!(token_tree -> TokenTree, alt!(
        map!(token, TokenTree::Token)
        |
        map!(delimited, TokenTree::Delimited)
    ));

    named!(token -> Token, alt!(
        keyword!("_") => { |_| Token::Underscore }
        |
        punct!("&&") => { |_| Token::AndAnd } // must be before BinOp
        |
        punct!("||") => { |_| Token::OrOr } // must be before BinOp
        |
        punct!("->") => { |_| Token::RArrow } // must be before BinOp
        |
        punct!("<-") => { |_| Token::LArrow } // must be before Lt
        |
        punct!("=>") => { |_| Token::FatArrow } // must be before Eq
        |
        punct!("...") => { |_| Token::DotDotDot } // must be before DotDot
        |
        punct!("..") => { |_| Token::DotDot } // must be before Dot
        |
        punct!(".") => { |_| Token::Dot }
        |
        map!(bin_op_eq, Token::BinOpEq)
        |
        map!(bin_op, Token::BinOp)
        |
        map!(lit, Token::Literal)
        |
        map!(ident, Token::Ident)
        |
        map!(lifetime, |lt: Lifetime| Token::Lifetime(lt.ident))
        |
        map!(doc_comment, Token::DocComment)
        |
        punct!("<=") => { |_| Token::Le }
        |
        punct!("==") => { |_| Token::EqEq }
        |
        punct!("!=") => { |_| Token::Ne }
        |
        punct!(">=") => { |_| Token::Ge }
        |
        punct!("::") => { |_| Token::ModSep }
        |
        punct!("=") => { |_| Token::Eq }
        |
        punct!("<") => { |_| Token::Lt }
        |
        punct!(">") => { |_| Token::Gt }
        |
        punct!("!") => { |_| Token::Not }
        |
        punct!("~") => { |_| Token::Tilde }
        |
        punct!("@") => { |_| Token::At }
        |
        punct!(",") => { |_| Token::Comma }
        |
        punct!(";") => { |_| Token::Semi }
        |
        punct!(":") => { |_| Token::Colon }
        |
        punct!("#") => { |_| Token::Pound }
        |
        punct!("$") => { |_| Token::Dollar }
        |
        punct!("?") => { |_| Token::Question }
    ));

    named!(bin_op -> BinOpToken, alt!(
        punct!("+") => { |_| BinOpToken::Plus }
        |
        punct!("-") => { |_| BinOpToken::Minus }
        |
        punct!("*") => { |_| BinOpToken::Star }
        |
        punct!("/") => { |_| BinOpToken::Slash }
        |
        punct!("%") => { |_| BinOpToken::Percent }
        |
        punct!("^") => { |_| BinOpToken::Caret }
        |
        punct!("&") => { |_| BinOpToken::And }
        |
        punct!("|") => { |_| BinOpToken::Or }
        |
        punct!("<<") => { |_| BinOpToken::Shl }
        |
        punct!(">>") => { |_| BinOpToken::Shr }
    ));

    named!(bin_op_eq -> BinOpToken, alt!(
        punct!("+=") => { |_| BinOpToken::Plus }
        |
        punct!("-=") => { |_| BinOpToken::Minus }
        |
        punct!("*=") => { |_| BinOpToken::Star }
        |
        punct!("/=") => { |_| BinOpToken::Slash }
        |
        punct!("%=") => { |_| BinOpToken::Percent }
        |
        punct!("^=") => { |_| BinOpToken::Caret }
        |
        punct!("&=") => { |_| BinOpToken::And }
        |
        punct!("|=") => { |_| BinOpToken::Or }
        |
        punct!("<<=") => { |_| BinOpToken::Shl }
        |
        punct!(">>=") => { |_| BinOpToken::Shr }
    ));

    named!(doc_comment -> String, alt!(
        do_parse!(
            punct!("//!") >>
            content: take_until!("\n") >>
            (format!("//!{}", content))
        )
        |
        do_parse!(
            option!(whitespace) >>
            peek!(tag!("/*!")) >>
            com: block_comment >>
            (com.to_owned())
        )
        |
        do_parse!(
            punct!("///") >>
            not!(peek!(tag!("/"))) >>
            content: take_until!("\n") >>
            (format!("///{}", content))
        )
        |
        do_parse!(
            option!(whitespace) >>
            peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
            com: block_comment >>
            (com.to_owned())
        )
    ));
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Mac {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.path.to_tokens(tokens);
            tokens.append("!");
            for tt in &self.tts {
                tt.to_tokens(tokens);
            }
        }
    }

    impl ToTokens for TokenTree {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                TokenTree::Token(ref token) => token.to_tokens(tokens),
                TokenTree::Delimited(ref delimited) => delimited.to_tokens(tokens),
            }
        }
    }

    impl DelimToken {
        fn open(&self) -> &'static str {
            match *self {
                DelimToken::Paren => "(",
                DelimToken::Bracket => "[",
                DelimToken::Brace => "{",
            }
        }

        fn close(&self) -> &'static str {
            match *self {
                DelimToken::Paren => ")",
                DelimToken::Bracket => "]",
                DelimToken::Brace => "}",
            }
        }
    }

    impl ToTokens for Delimited {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(self.delim.open());
            for tt in &self.tts {
                tt.to_tokens(tokens);
            }
            tokens.append(self.delim.close());
        }
    }

    impl ToTokens for Token {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                Token::Eq => tokens.append("="),
                Token::Lt => tokens.append("<"),
                Token::Le => tokens.append("<="),
                Token::EqEq => tokens.append("=="),
                Token::Ne => tokens.append("!="),
                Token::Ge => tokens.append(">="),
                Token::Gt => tokens.append(">"),
                Token::AndAnd => tokens.append("&&"),
                Token::OrOr => tokens.append("||"),
                Token::Not => tokens.append("!"),
                Token::Tilde => tokens.append("~"),
                Token::BinOp(binop) => tokens.append(binop.op()),
                Token::BinOpEq(binop) => tokens.append(binop.assign_op()),
                Token::At => tokens.append("@"),
                Token::Dot => tokens.append("."),
                Token::DotDot => tokens.append(".."),
                Token::DotDotDot => tokens.append("..."),
                Token::Comma => tokens.append(","),
                Token::Semi => tokens.append(";"),
                Token::Colon => tokens.append(":"),
                Token::ModSep => tokens.append("::"),
                Token::RArrow => tokens.append("->"),
                Token::LArrow => tokens.append("<-"),
                Token::FatArrow => tokens.append("=>"),
                Token::Pound => tokens.append("#"),
                Token::Dollar => tokens.append("$"),
                Token::Question => tokens.append("?"),
                Token::Literal(ref lit) => lit.to_tokens(tokens),
                Token::Ident(ref ident) => ident.to_tokens(tokens),
                Token::Underscore => tokens.append("_"),
                Token::Lifetime(ref ident) => ident.to_tokens(tokens),
                Token::DocComment(ref com) => {
                    tokens.append(&format!("{}\n", com));
                }
            }
        }
    }

    impl BinOpToken {
        fn op(&self) -> &'static str {
            match *self {
                BinOpToken::Plus => "+",
                BinOpToken::Minus => "-",
                BinOpToken::Star => "*",
                BinOpToken::Slash => "/",
                BinOpToken::Percent => "%",
                BinOpToken::Caret => "^",
                BinOpToken::And => "&",
                BinOpToken::Or => "|",
                BinOpToken::Shl => "<<",
                BinOpToken::Shr => ">>",
            }
        }

        fn assign_op(&self) -> &'static str {
            match *self {
                BinOpToken::Plus => "+=",
                BinOpToken::Minus => "-=",
                BinOpToken::Star => "*=",
                BinOpToken::Slash => "/=",
                BinOpToken::Percent => "%=",
                BinOpToken::Caret => "^=",
                BinOpToken::And => "&=",
                BinOpToken::Or => "|=",
                BinOpToken::Shl => "<<=",
                BinOpToken::Shr => ">>=",
            }
        }
    }

    impl ToTokens for BinOpToken {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(self.op());
        }
    }
}
<|endoftext|>


<commit_before>extern crate kv_cab;

use kv_cab::{ KV, Value };

macro_rules! test_setup {
    ( $p:ident, $i:ident ) => {
        let _ = std::fs::remove_file($p);
        let mut $i = KV::<String, Value>::new($p);
    }
}

macro_rules! test_teardown {
    ( $p:ident ) => {
        use std::{thread, time};

        thread::sleep(time::Duration::from_secs(1));
        let _ = std::fs::remove_file($p);
    }
}

#[test]
fn test_create() {
    let test_cab_path ="./test_create.cab";

    let _ = std::fs::remove_file(test_cab_path);
    let _ = KV::<String, Value>::new(test_cab_path);

    test_teardown!(test_cab_path);
}

#[test]
fn test_insert_string() {
    let test_cab_path = "./text_insert_string.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.insert("key".to_string(), Value::String("value".to_string()));
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_insert_int() {
    let test_cab_path = "./test_insert_int.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.insert("key".to_string(), Value::Int(0i32));
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_insert_float() {
    let test_cab_path = "./test_insert_float.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.insert("key".to_string(), Value::Float(0f32));
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_string() {
    let test_cab_path = "./test_get_string.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::String("value".to_string()));
        assert_eq!(res, Ok(true));
    }

    {
        assert_eq!(test_store.get("key".to_string()), Some(Value::String("value".to_string())));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_int() {
    let test_cab_path = "./test_get_int.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::Int(0i32));
        assert_eq!(res, Ok(true));
    }

    {
        assert_eq!(test_store.get("key".to_string()), Some(Value::Int(0i32)));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_float() {
    let test_cab_path = "./test_get_float.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::Float(0f32));
        assert_eq!(res, Ok(true));
    }

    {
        assert_eq!(test_store.get("key".to_string()), Some(Value::Float(0f32)));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_none() {
    let test_cab_path = "./test_get_none.cab";
    test_setup!(test_cab_path, test_store);

    assert_eq!(test_store.get("none".to_string()), None);

    test_teardown!(test_cab_path);
}

#[test]
fn test_remove() {
    let test_cab_path = "./test_remove.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::String("value".to_string()));
        assert_eq!(res, Ok(true));
    }

    {
        let res = test_store.remove("key".to_string());
        assert_eq!(res, Ok(true));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_remove_none() {
    let test_cab_path = "./test_remove_none.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.remove("key".to_string());
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_keys() {
    let test_cab_path = "./test_keys.cab";
    test_setup!(test_cab_path, test_store);

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    let _ = test_store.insert("key2".to_string(), Value::String("value2".to_string()));

    assert!(test_store.keys().len() == 2);
    let _ = test_store.remove("key".to_string());
    assert!(test_store.keys().len() == 1);
    let _ = test_store.remove("key2".to_string());
    assert!(test_store.keys().len() == 0);

    test_teardown!(test_cab_path);
}

#[test]
fn test_kv_all() {
    let test_cab_path = "./test_kv_all.cab";
    test_setup!(test_cab_path, test_store);

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    test_store.get("key".to_string());
    let _ = test_store.remove("key".to_string());

    test_teardown!(test_cab_path);
}

#[test]
fn test_multi_instance() {
    let test_cab_path = "./test_multi_instance.cab";
    {
        let mut test_store = KV::<String, Value>::new(test_cab_path);
        let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    }
    {
        let mut test_store = KV::<String, Value>::new(test_cab_path);
        assert!(test_store.get("key".to_string()) == Some(Value::String("value".to_string())));
        let _ = test_store.remove("key".to_string());
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_multithread_instance() {
    const TEST_CAB_PATH: &'static str = "./test_multithread_instance.cab";

    let t_1 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    });

    let t_2 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        std::thread::sleep(std::time::Duration::new(1u64, 0u32));
        let _ = test_store.get("key".to_string()).unwrap();
        let _ = test_store.remove("key".to_string());
    });

    assert!(t_2.join().is_ok());
    assert!(t_1.join().is_ok());

    test_teardown!(TEST_CAB_PATH);
}

#[test]
fn test_multithread_instance_insert() {
    const TEST_CAB_PATH: &'static str = "./test_multithread_instance_insert.cab";

    let t_1 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        for i in 0..1000 {
            let _ = test_store.insert(format!("{}", i), Value::Int(i));
        }
    });

    let t_2 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        for i in 1000..2000 {
            let _ = test_store.insert(format!("{}", i), Value::Int(i));
        }
    });

    assert!(t_2.join().is_ok());
    assert!(t_1.join().is_ok());

    test_teardown!(TEST_CAB_PATH);
}

#[test]
fn test_multithread_instance_read_between() {
    const TEST_CAB_PATH: &'static str = "./test_multithread_instance_read_between.cab";

    let t_1 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    });

    let t_2 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        std::thread::sleep(std::time::Duration::new(1u64, 0u32));
        assert!(test_store.get("key".to_string()).unwrap() == Value::String("value".to_string()));
        let _ = test_store.remove("key".to_string());
    });

    assert!(t_2.join().is_ok());
    assert!(t_1.join().is_ok());

    test_teardown!(TEST_CAB_PATH);
}
<commit_msg>Added asserts where they were missing in tests<commit_after>extern crate kv_cab;

use kv_cab::{ KV, Value };

macro_rules! test_setup {
    ( $p:ident, $i:ident ) => {
        let _ = std::fs::remove_file($p);
        let mut $i = KV::<String, Value>::new($p);
    }
}

macro_rules! test_teardown {
    ( $p:ident ) => {
        use std::{thread, time};

        thread::sleep(time::Duration::from_secs(1));
        let _ = std::fs::remove_file($p);
    }
}

#[test]
fn test_create() {
    let test_cab_path ="./test_create.cab";

    let _ = std::fs::remove_file(test_cab_path);
    let _ = KV::<String, Value>::new(test_cab_path);

    test_teardown!(test_cab_path);
}

#[test]
fn test_insert_string() {
    let test_cab_path = "./text_insert_string.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.insert("key".to_string(), Value::String("value".to_string()));
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_insert_int() {
    let test_cab_path = "./test_insert_int.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.insert("key".to_string(), Value::Int(0i32));
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_insert_float() {
    let test_cab_path = "./test_insert_float.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.insert("key".to_string(), Value::Float(0f32));
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_string() {
    let test_cab_path = "./test_get_string.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::String("value".to_string()));
        assert_eq!(res, Ok(true));
    }

    {
        assert_eq!(test_store.get("key".to_string()), Some(Value::String("value".to_string())));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_int() {
    let test_cab_path = "./test_get_int.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::Int(0i32));
        assert_eq!(res, Ok(true));
    }

    {
        assert_eq!(test_store.get("key".to_string()), Some(Value::Int(0i32)));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_float() {
    let test_cab_path = "./test_get_float.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::Float(0f32));
        assert_eq!(res, Ok(true));
    }

    {
        assert_eq!(test_store.get("key".to_string()), Some(Value::Float(0f32)));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_get_none() {
    let test_cab_path = "./test_get_none.cab";
    test_setup!(test_cab_path, test_store);

    assert_eq!(test_store.get("none".to_string()), None);

    test_teardown!(test_cab_path);
}

#[test]
fn test_remove() {
    let test_cab_path = "./test_remove.cab";
    test_setup!(test_cab_path, test_store);

    {
        let res = test_store.insert("key".to_string(), Value::String("value".to_string()));
        assert_eq!(res, Ok(true));
    }

    {
        let res = test_store.remove("key".to_string());
        assert_eq!(res, Ok(true));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_remove_none() {
    let test_cab_path = "./test_remove_none.cab";
    test_setup!(test_cab_path, test_store);

    let res = test_store.remove("key".to_string());
    assert_eq!(res, Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_keys() {
    let test_cab_path = "./test_keys.cab";
    test_setup!(test_cab_path, test_store);

    assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    assert!(test_store.insert("key2".to_string(), Value::String("value2".to_string())) == Ok(true));

    assert!(test_store.keys().len() == 2);
    assert!(test_store.remove("key".to_string()) == Ok(true));
    assert!(test_store.keys().len() == 1);
    assert!(test_store.remove("key2".to_string()) == Ok(true));
    assert!(test_store.keys().len() == 0);

    test_teardown!(test_cab_path);
}

#[test]
fn test_kv_all() {
    let test_cab_path = "./test_kv_all.cab";
    test_setup!(test_cab_path, test_store);

    assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    assert!(test_store.get("key".to_string()).is_some());
    assert!(test_store.remove("key".to_string()) == Ok(true));

    test_teardown!(test_cab_path);
}

#[test]
fn test_multi_instance() {
    let test_cab_path = "./test_multi_instance.cab";
    {
        let mut test_store = KV::<String, Value>::new(test_cab_path);
        assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    }
    {
        let mut test_store = KV::<String, Value>::new(test_cab_path);
        assert!(test_store.get("key".to_string()) == Some(Value::String("value".to_string())));
        assert!(test_store.remove("key".to_string()) == Ok(true));
    }

    test_teardown!(test_cab_path);
}

#[test]
fn test_multithread_instance() {
    const TEST_CAB_PATH: &'static str = "./test_multithread_instance.cab";

    let t_1 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    });

    let t_2 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        std::thread::sleep(std::time::Duration::new(1u64, 0u32));
        assert!(test_store.get("key".to_string()).is_some());
        assert!(test_store.remove("key".to_string()) == Ok(true));
    });

    assert!(t_2.join().is_ok());
    assert!(t_1.join().is_ok());

    test_teardown!(TEST_CAB_PATH);
}

#[test]
fn test_multithread_instance_insert() {
    const TEST_CAB_PATH: &'static str = "./test_multithread_instance_insert.cab";

    let t_1 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        for i in 0..1000 {
            assert!(test_store.insert(format!("{}", i), Value::Int(i)) == Ok(true));
        }
    });

    let t_2 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        for i in 1000..2000 {
            assert!(test_store.insert(format!("{}", i), Value::Int(i)) == Ok(true));
        }
    });

    assert!(t_2.join().is_ok());
    assert!(t_1.join().is_ok());

    test_teardown!(TEST_CAB_PATH);
}

#[test]
fn test_multithread_instance_read_between() {
    const TEST_CAB_PATH: &'static str = "./test_multithread_instance_read_between.cab";

    let t_1 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        assert!(test_store.insert("key".to_string(), Value::String("value".to_string())) == Ok(true));
    });

    let t_2 = thread::spawn(|| {
        let mut test_store = KV::<String, Value>::new(TEST_CAB_PATH);
        std::thread::sleep(std::time::Duration::new(1u64, 0u32));
        assert!(test_store.get("key".to_string()).unwrap() == Value::String("value".to_string()));
        assert!(test_store.remove("key".to_string()) == Ok(true));
    });

    assert!(t_2.join().is_ok());
    assert!(t_1.join().is_ok());

    test_teardown!(TEST_CAB_PATH);
}
<|endoftext|>


<commit_before>/* The Wizards' Wallet
 * Written in 2014 by
 *   Andrew Poelstra <apoelstra@wpsoftware.net>
 *
 * To the extent possible under law, the author(s) have dedicated all
 * copyright and related and neighboring rights to this software to
 * the public domain worldwide. This software is distributed without
 * any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication
 * along with this software.
 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
 */

//! # The Wizards' Wallet
//!
//! The Wizards' Wallet is a SPV Bitcoin Wallet designed for ease of prototyping
//! and a willingness to experiment with user interfaces, and exposing potentially
//! dangerous or experimental ideas built on top of the Bitcoin protocol.
//!
//! It is also written entirely in Rust to illustrate the benefits of strong type
//! safety, including ownership and lifetime, for financial and/or cryptographic
//! software.
//!

#![crate_name = "wizards-wallet-test"]

#![comment = "The Wizards' Wallet Test Root"]
#![license = "CC0"]

// Experimental features we need
#![feature(macro_rules)]
#![feature(phase)]
#![feature(globs)]

// Coding conventions
#![deny(non_uppercase_pattern_statics)]
#![deny(uppercase_variables)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case_functions)]
#![deny(unused_mut)]
#![warn(missing_doc)]

extern crate rand;
extern crate time;

#[phase(plugin,link)] extern crate bitcoin;

mod bitcoind;
mod constants;
mod user_data;

<commit_msg>Remove `test-root.rs` since it hasn't been used since Cargo<commit_after><|endoftext|>


<commit_before>#[macro_use]
mod common;

extern crate time;
extern crate filetime;

use filetime::FileTime;
use common::util::*;

static UTIL_NAME: &'static str = "touch";

fn get_file_times(at: &AtPath, path: &str) -> (FileTime, FileTime) {
    let m = at.metadata(path);
    (FileTime::from_last_access_time(&m),
     FileTime::from_last_modification_time(&m))
}

fn set_file_times(at: &AtPath, path: &str, atime: FileTime, mtime: FileTime) {
    filetime::set_file_times(&at.plus_as_string(path), atime, mtime).unwrap()
}

// Adjusts for local timezone
fn str_to_filetime(format: &str, s: &str) -> FileTime {
    let mut tm = time::strptime(s, format).unwrap();
    tm.tm_utcoff = time::now().tm_utcoff;
    let ts = tm.to_timespec();
    FileTime::from_seconds_since_1970(ts.sec as u64, ts.nsec as u32)
}

#[test]
fn test_touch_default() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_default_file";

    let result = ucmd.arg(file).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));
}

#[test]
fn test_touch_no_create_file_absent() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_no_create_file_absent";

    let result = ucmd.arg("-c").arg(file).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(!at.file_exists(file));
}

#[test]
fn test_touch_no_create_file_exists() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_no_create_file_exists";

    at.touch(file);
    assert!(at.file_exists(file));

    let result = ucmd.arg("-c").arg(file).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));
}

#[test]
fn test_touch_set_mdhm_time() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_mdhm_time";

    let result = ucmd.args(&["-t", "01011234", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
}

#[test]
fn test_touch_set_mdhms_time() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_mdhms_time";

    let result = ucmd.args(&["-t", "01011234.56", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M.%S", "201501010000.00");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45296);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45296);
}

#[test]
fn test_touch_set_ymdhm_time() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_ymdhm_time";

    let result = ucmd.args(&["-t", "1501011234", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%y%m%d%H%M", "1501010000");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
}

#[test]
fn test_touch_set_ymdhms_time() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_ymdhms_time";

    let result = ucmd.args(&["-t", "1501011234.56", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%y%m%d%H%M.%S", "1501010000.00");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45296);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45296);
}

#[test]
fn test_touch_set_cymdhm_time() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_cymdhm_time";

    let result = ucmd.args(&["-t", "201501011234", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
}

#[test]
fn test_touch_set_cymdhms_time() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_cymdhms_time";

    let result = ucmd.args(&["-t", "201501011234.56", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M.%S", "201501010000.00");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45296);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45296);
}

#[test]
fn test_touch_set_only_atime() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_only_atime";

    let result = ucmd.args(&["-t", "201501011234", "-a", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
    let (atime, mtime) = get_file_times(&at, file);
    assert!(atime != mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
}

#[test]
fn test_touch_set_only_mtime() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_only_mtime";

    let result = ucmd.args(&["-t", "201501011234", "-m", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
    let (atime, mtime) = get_file_times(&at, file);
    assert!(atime != mtime);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
}

#[test]
fn test_touch_set_both() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_both";

    let result = ucmd.args(&["-t", "201501011234", "-a", "-m", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
}

#[test]
fn test_touch_reference() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file_a = "test_touch_reference_a";
    let file_b = "test_touch_reference_b";
    let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");

    at.touch(file_a);
    set_file_times(&at, file_a, start_of_year, start_of_year);
    assert!(at.file_exists(file_a));

    let result = ucmd.args(&["-r", file_a, file_b]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file_b));

    let (atime, mtime) = get_file_times(&at, file_b);
    assert_eq!(atime, mtime);
    assert_eq!(atime, start_of_year);
    assert_eq!(mtime, start_of_year);
}

#[test]
fn test_touch_set_date() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_date";

    let result = ucmd.args(&["-d", "Thu Jan 01 12:34:00 2015", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501011234");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime, start_of_year);
    assert_eq!(mtime, start_of_year);
}
<commit_msg>tests/touch: fix tests<commit_after>#[macro_use]
mod common;

extern crate time;
extern crate filetime;

use filetime::FileTime;
use common::util::*;

static UTIL_NAME: &'static str = "touch";

fn get_file_times(at: &AtPath, path: &str) -> (FileTime, FileTime) {
    let m = at.metadata(path);
    (FileTime::from_last_access_time(&m),
     FileTime::from_last_modification_time(&m))
}

fn set_file_times(at: &AtPath, path: &str, atime: FileTime, mtime: FileTime) {
    filetime::set_file_times(&at.plus_as_string(path), atime, mtime).unwrap()
}

// Adjusts for local timezone
fn str_to_filetime(format: &str, s: &str) -> FileTime {
    let mut tm = time::strptime(s, format).unwrap();
    tm.tm_utcoff = time::now().tm_utcoff;
    let ts = tm.to_timespec();
    FileTime::from_seconds_since_1970(ts.sec as u64, ts.nsec as u32)
}

#[test]
fn test_touch_default() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_default_file";

    let result = ucmd.arg(file).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));
}

#[test]
fn test_touch_no_create_file_absent() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_no_create_file_absent";

    let result = ucmd.arg("-c").arg(file).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(!at.file_exists(file));
}

#[test]
fn test_touch_no_create_file_exists() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_no_create_file_exists";

    at.touch(file);
    assert!(at.file_exists(file));

    let result = ucmd.arg("-c").arg(file).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));
}

#[test]
fn test_touch_set_mdhm_time() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_mdhm_time";

    let result = ucmd.args(&["-t", "01011234", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M", &format!("{}01010000", 1900+time::now().tm_year));
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
}

#[test]
fn test_touch_set_mdhms_time() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_mdhms_time";

    let result = ucmd.args(&["-t", "01011234.56", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M.%S", &format!("{}01010000.00", 1900+time::now().tm_year));
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45296);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45296);
}

#[test]
fn test_touch_set_ymdhm_time() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_ymdhm_time";

    let result = ucmd.args(&["-t", "1501011234", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%y%m%d%H%M", "1501010000");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
}

#[test]
fn test_touch_set_ymdhms_time() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_ymdhms_time";

    let result = ucmd.args(&["-t", "1501011234.56", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%y%m%d%H%M.%S", "1501010000.00");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45296);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45296);
}

#[test]
fn test_touch_set_cymdhm_time() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_cymdhm_time";

    let result = ucmd.args(&["-t", "201501011234", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
}

#[test]
fn test_touch_set_cymdhms_time() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_cymdhms_time";

    let result = ucmd.args(&["-t", "201501011234.56", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M.%S", "201501010000.00");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45296);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45296);
}

#[test]
fn test_touch_set_only_atime() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_only_atime";

    let result = ucmd.args(&["-t", "201501011234", "-a", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
    let (atime, mtime) = get_file_times(&at, file);
    assert!(atime != mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
}

#[test]
fn test_touch_set_only_mtime() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_only_mtime";

    let result = ucmd.args(&["-t", "201501011234", "-m", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
    let (atime, mtime) = get_file_times(&at, file);
    assert!(atime != mtime);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
}

#[test]
fn test_touch_set_both() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_both";

    let result = ucmd.args(&["-t", "201501011234", "-a", "-m", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
    assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(),
               45240);
}

#[test]
fn test_touch_reference() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file_a = "test_touch_reference_a";
    let file_b = "test_touch_reference_b";
    let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");

    at.touch(file_a);
    set_file_times(&at, file_a, start_of_year, start_of_year);
    assert!(at.file_exists(file_a));

    let result = ucmd.args(&["-r", file_a, file_b]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file_b));

    let (atime, mtime) = get_file_times(&at, file_b);
    assert_eq!(atime, mtime);
    assert_eq!(atime, start_of_year);
    assert_eq!(mtime, start_of_year);
}

#[test]
fn test_touch_set_date() {
    let (at, mut ucmd) = testing(UTIL_NAME);
    let file = "test_touch_set_date";

    let result = ucmd.args(&["-d", "Thu Jan 01 12:34:00 2015", file]).run();
    assert_empty_stderr!(result);
    assert!(result.success);

    assert!(at.file_exists(file));

    let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501011234");
    let (atime, mtime) = get_file_times(&at, file);
    assert_eq!(atime, mtime);
    assert_eq!(atime, start_of_year);
    assert_eq!(mtime, start_of_year);
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;
use std::ops::Index;
use std::ops::IndexMut;

#[derive(Copy, Clone)]
pub enum MemSection {
    Vram,
    RomBank0,
}

pub struct AddressSpace {
    data: [u8; 0x10000],
}

pub const IOREG_P1:     u16 = 0xFF00;
pub const IOREG_SB:     u16 = 0xFF01;
pub const IOREG_DIV:    u16 = 0xFF04;
pub const IOREG_TIMA:   u16 = 0xFF05;
pub const IOREG_TMA:    u16 = 0xFF06;
pub const IOREG_TAC:    u16 = 0xFF07;
pub const IOREG_IF:     u16 = 0xFF0F;
pub const IOREG_LCDC:   u16 = 0xFF40;
pub const IOREG_STAT:   u16 = 0xFF41;
pub const IOREG_SCY:    u16 = 0xFF42;
pub const IOREG_SCX:    u16 = 0xFF43;
pub const IOREG_LY:     u16 = 0xFF44;
pub const IOREG_LYC:    u16 = 0xFF45;
pub const IOREG_BGP:    u16 = 0xFF47;
pub const IOREG_OBP0:   u16 = 0xFF48;
pub const IOREG_OBP1:   u16 = 0xFF49;
pub const IOREG_WY:     u16 = 0xFF4A;
pub const IOREG_WX:     u16 = 0xFF4B;
pub const IOREG_IE:     u16 = 0xFFFF;

impl AddressSpace {

    pub fn new() -> AddressSpace {
        AddressSpace { data: [0; 0x10000] }
    }

    pub fn read(&self, addr: u16) -> u8 {
        self.data[addr as usize]
    }

    pub fn read_u16(&self, addr: u16) -> u16 {
        let lo = self.read(addr) as u16;
        let hi = (self.read(addr + 1) as u16) << 8;
        lo | hi
    }

    pub fn read_slice(&self, addr: u16, bytes: u16) -> &[u8] {
        &self.data[addr as usize .. (addr + bytes) as usize]
    }

    pub fn write(&mut self, addr: u16, data: u8) {
        let mut addr = addr;
        let mut data = data;
        let rw = match addr {
            // ROM Banks, read only
            0x0000...0x7FFF => false,
            // Switchable RAM bank
            // TODO: Make RAM switchable
            0xA000...0xBFFF => true,
            // Internal RAM echo
            0xE000...0xFDFF => {
                addr -= 0x2000;
                true
            },
            // I/O registers
            IOREG_DIV => {
                data = 0;
                true
            },
            IOREG_LY => {
                data = 0;
                true
            },
            // No special write rules
            _ => true,
        };
        if rw {
            self.data[addr as usize] = data;
        }
    }

    pub fn write_u16(&mut self, addr: u16, data: u16) {
        let lo = (data & 0xFF) as u8;
        let hi = ((data & 0xFF00) >> 8) as u8;
        self.write(addr, lo);
        self.write(addr + 1, hi);
    }

    pub fn load_bios(&mut self, bios: &mut File) -> ::std::io::Result<()> {
        try!(bios.read(&mut self.data[0x000..0x100]));
        Ok(())
    }

    pub fn load_rom(&mut self, rom: &mut File) -> ::std::io::Result<()> {
        // Read in header first
        try!(rom.seek(SeekFrom::Start(0x100)));
        try!(rom.read(&mut self.data[0x100..0x150]));
        // Then read in remaining cart data
        try!(rom.read(&mut self.data[0x0150..0x8000]));
        Ok(())
    }

}

impl Index<u16> for AddressSpace {
    type Output = u8;

    fn index(&self, idx: u16) -> &u8 {
        &self.data[idx as usize]
    }
}

impl IndexMut<u16> for AddressSpace {
    fn index_mut(&mut self, idx: u16) -> &mut u8 {
        &mut self.data[idx as usize]
    }
}

#[derive(Copy, Clone)]
pub enum RegFlag {
    Zero,
    Subtract,
    HalfCarry,
    Carry,
}

#[derive(Copy, Clone)]
pub enum Register {
    A,
    B,
    C,
    D,
    E,
    F,
    H,
    L,
    AF,
    BC,
    DE,
    HL,
    SP,
    PC,
    Flag,
}

pub struct RegData {
    a: u8,
    b: u8,
    c: u8,
    d: u8,
    e: u8,
    f: u8,
    h: u8,
    l: u8,
    sp: u16,
    pc: u16,
    flag: u8,
}

impl RegData {

    pub fn new() -> RegData {
        RegData {
            a: 0,
            b: 0,
            c: 0,
            d: 0,
            e: 0,
            f: 0,
            h: 0,
            l: 0,
            sp: 0xFFFE,
            pc: 0x100,
            flag: 0,
        }
    }

    pub fn read(&self, reg: Register) -> u8 {
        match reg {
            Register::A => self.a,
            Register::B => self.b,
            Register::C => self.c,
            Register::D => self.d,
            Register::E => self.e,
            Register::F => self.f,
            Register::H => self.h,
            Register::L => self.l,
            Register::Flag => self.flag,
            _ => panic!("Register not available for 8-bit read"),
        }
    }

    pub fn read_u16(&self, reg: Register) -> u16 {
        match reg {
            Register::AF => (self.a as u16) << 8 | self.f as u16,
            Register::BC => (self.b as u16) << 8 | self.c as u16,
            Register::DE => (self.d as u16) << 8 | self.e as u16,
            Register::HL => (self.h as u16) << 8 | self.l as u16,
            Register::SP => self.sp,
            Register::PC => self.pc,
            _ => panic!("Register not available for 16-bit read"),
        }
    }

    pub fn write(&mut self, reg: Register, data: u8) {
        match reg {
            Register::A => self.a = data,
            Register::B => self.b = data,
            Register::C => self.c = data,
            Register::D => self.d = data,
            Register::E => self.e = data,
            Register::F => self.f = data,
            Register::H => self.h = data,
            Register::L => self.l = data,
            _ => panic!("Register not available for 8-bit write"),
        }
    }

    pub fn write_u16(&mut self, reg: Register, data: u16) {
        let (hi, lo) = (((data & 0xFF00) >> 8) as u8, (data & 0xFF) as u8);
        match reg {
            Register::AF => {
                self.a = hi;
                self.f = lo;
            },
            Register::BC => {
                self.b = hi;
                self.c = lo;
            },
            Register::DE => {
                self.d = hi;
                self.c = lo;
            },
            Register::HL => {
                self.h = hi;
                self.l = lo;
            },
            Register::SP => self.sp = data,
            Register::PC => self.pc = data,
            _ => panic!("Register not available for 16-bit write"),
        }
    }

    pub fn copy(&mut self, dst: Register, src: Register) {
        let data = self.read(src);
        self.write(dst, data);
    }

    pub fn copy_u16(&mut self, dst: Register, src: Register) {
        let data = self.read_u16(src);
        self.write_u16(dst, data);
    }

    pub fn set_flag(&mut self, flag: RegFlag, on: bool) {
        let bit = match flag {
            RegFlag::Zero => 0x80,
            RegFlag::Subtract => 0x40,
            RegFlag::HalfCarry => 0x20,
            RegFlag::Carry => 0x10,
        };
        if (on) {
            self.flag |= bit;
        } else {
            self.flag &= bit ^ 0xFF;
        }
    }

    pub fn get_flag(&self, flag: RegFlag) -> bool {
        let bit = match flag {
            RegFlag::Zero => 0x80,
            RegFlag::Subtract => 0x40,
            RegFlag::HalfCarry => 0x20,
            RegFlag::Carry => 0x10,
        };
        self.flag & bit != 0
    }

    pub fn advance_pc(&mut self) -> u16 {
        let pc = self.pc;
        self.pc += 1;
        pc
    }

    pub fn set_pc(&mut self, addr: u16) -> u16 {
        let pc = self.pc;
        self.pc = addr;
        pc
    }

    pub fn add_pc(&mut self, n: i8) -> u16 {
        let pc = self.pc;
        self.pc = ((self.pc as i32) + (n as i32)) as u16;
        pc
    }

    pub fn get_pc(&self) -> u16 {
        self.pc
    }

}
<commit_msg>Correct possible typo in register write function<commit_after>use std::fs::File;
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;
use std::ops::Index;
use std::ops::IndexMut;

#[derive(Copy, Clone)]
pub enum MemSection {
    Vram,
    RomBank0,
}

pub struct AddressSpace {
    data: [u8; 0x10000],
}

pub const IOREG_P1:     u16 = 0xFF00;
pub const IOREG_SB:     u16 = 0xFF01;
pub const IOREG_DIV:    u16 = 0xFF04;
pub const IOREG_TIMA:   u16 = 0xFF05;
pub const IOREG_TMA:    u16 = 0xFF06;
pub const IOREG_TAC:    u16 = 0xFF07;
pub const IOREG_IF:     u16 = 0xFF0F;
pub const IOREG_LCDC:   u16 = 0xFF40;
pub const IOREG_STAT:   u16 = 0xFF41;
pub const IOREG_SCY:    u16 = 0xFF42;
pub const IOREG_SCX:    u16 = 0xFF43;
pub const IOREG_LY:     u16 = 0xFF44;
pub const IOREG_LYC:    u16 = 0xFF45;
pub const IOREG_BGP:    u16 = 0xFF47;
pub const IOREG_OBP0:   u16 = 0xFF48;
pub const IOREG_OBP1:   u16 = 0xFF49;
pub const IOREG_WY:     u16 = 0xFF4A;
pub const IOREG_WX:     u16 = 0xFF4B;
pub const IOREG_IE:     u16 = 0xFFFF;

impl AddressSpace {

    pub fn new() -> AddressSpace {
        AddressSpace { data: [0; 0x10000] }
    }

    pub fn read(&self, addr: u16) -> u8 {
        self.data[addr as usize]
    }

    pub fn read_u16(&self, addr: u16) -> u16 {
        let lo = self.read(addr) as u16;
        let hi = (self.read(addr + 1) as u16) << 8;
        lo | hi
    }

    pub fn read_slice(&self, addr: u16, bytes: u16) -> &[u8] {
        &self.data[addr as usize .. (addr + bytes) as usize]
    }

    pub fn write(&mut self, addr: u16, data: u8) {
        let mut addr = addr;
        let mut data = data;
        let rw = match addr {
            // ROM Banks, read only
            0x0000...0x7FFF => false,
            // Switchable RAM bank
            // TODO: Make RAM switchable
            0xA000...0xBFFF => true,
            // Internal RAM echo
            0xE000...0xFDFF => {
                addr -= 0x2000;
                true
            },
            // I/O registers
            IOREG_DIV => {
                data = 0;
                true
            },
            IOREG_LY => {
                data = 0;
                true
            },
            // No special write rules
            _ => true,
        };
        if rw {
            self.data[addr as usize] = data;
        }
    }

    pub fn write_u16(&mut self, addr: u16, data: u16) {
        let lo = (data & 0xFF) as u8;
        let hi = ((data & 0xFF00) >> 8) as u8;
        self.write(addr, lo);
        self.write(addr + 1, hi);
    }

    pub fn load_bios(&mut self, bios: &mut File) -> ::std::io::Result<()> {
        try!(bios.read(&mut self.data[0x000..0x100]));
        Ok(())
    }

    pub fn load_rom(&mut self, rom: &mut File) -> ::std::io::Result<()> {
        // Read in header first
        try!(rom.seek(SeekFrom::Start(0x100)));
        try!(rom.read(&mut self.data[0x100..0x150]));
        // Then read in remaining cart data
        try!(rom.read(&mut self.data[0x0150..0x8000]));
        Ok(())
    }

}

impl Index<u16> for AddressSpace {
    type Output = u8;

    fn index(&self, idx: u16) -> &u8 {
        &self.data[idx as usize]
    }
}

impl IndexMut<u16> for AddressSpace {
    fn index_mut(&mut self, idx: u16) -> &mut u8 {
        &mut self.data[idx as usize]
    }
}

#[derive(Copy, Clone)]
pub enum RegFlag {
    Zero,
    Subtract,
    HalfCarry,
    Carry,
}

#[derive(Copy, Clone)]
pub enum Register {
    A,
    B,
    C,
    D,
    E,
    F,
    H,
    L,
    AF,
    BC,
    DE,
    HL,
    SP,
    PC,
    Flag,
}

pub struct RegData {
    a: u8,
    b: u8,
    c: u8,
    d: u8,
    e: u8,
    f: u8,
    h: u8,
    l: u8,
    sp: u16,
    pc: u16,
    flag: u8,
}

impl RegData {

    pub fn new() -> RegData {
        RegData {
            a: 0,
            b: 0,
            c: 0,
            d: 0,
            e: 0,
            f: 0,
            h: 0,
            l: 0,
            sp: 0xFFFE,
            pc: 0x100,
            flag: 0,
        }
    }

    pub fn read(&self, reg: Register) -> u8 {
        match reg {
            Register::A => self.a,
            Register::B => self.b,
            Register::C => self.c,
            Register::D => self.d,
            Register::E => self.e,
            Register::F => self.f,
            Register::H => self.h,
            Register::L => self.l,
            Register::Flag => self.flag,
            _ => panic!("Register not available for 8-bit read"),
        }
    }

    pub fn read_u16(&self, reg: Register) -> u16 {
        match reg {
            Register::AF => (self.a as u16) << 8 | self.f as u16,
            Register::BC => (self.b as u16) << 8 | self.c as u16,
            Register::DE => (self.d as u16) << 8 | self.e as u16,
            Register::HL => (self.h as u16) << 8 | self.l as u16,
            Register::SP => self.sp,
            Register::PC => self.pc,
            _ => panic!("Register not available for 16-bit read"),
        }
    }

    pub fn write(&mut self, reg: Register, data: u8) {
        match reg {
            Register::A => self.a = data,
            Register::B => self.b = data,
            Register::C => self.c = data,
            Register::D => self.d = data,
            Register::E => self.e = data,
            Register::F => self.f = data,
            Register::H => self.h = data,
            Register::L => self.l = data,
            _ => panic!("Register not available for 8-bit write"),
        }
    }

    pub fn write_u16(&mut self, reg: Register, data: u16) {
        let (hi, lo) = (((data & 0xFF00) >> 8) as u8, (data & 0xFF) as u8);
        match reg {
            Register::AF => {
                self.a = hi;
                self.f = lo;
            },
            Register::BC => {
                self.b = hi;
                self.c = lo;
            },
            Register::DE => {
                self.d = hi;
                self.e = lo;
            },
            Register::HL => {
                self.h = hi;
                self.l = lo;
            },
            Register::SP => self.sp = data,
            Register::PC => self.pc = data,
            _ => panic!("Register not available for 16-bit write"),
        }
    }

    pub fn copy(&mut self, dst: Register, src: Register) {
        let data = self.read(src);
        self.write(dst, data);
    }

    pub fn copy_u16(&mut self, dst: Register, src: Register) {
        let data = self.read_u16(src);
        self.write_u16(dst, data);
    }

    pub fn set_flag(&mut self, flag: RegFlag, on: bool) {
        let bit = match flag {
            RegFlag::Zero => 0x80,
            RegFlag::Subtract => 0x40,
            RegFlag::HalfCarry => 0x20,
            RegFlag::Carry => 0x10,
        };
        if (on) {
            self.flag |= bit;
        } else {
            self.flag &= bit ^ 0xFF;
        }
    }

    pub fn get_flag(&self, flag: RegFlag) -> bool {
        let bit = match flag {
            RegFlag::Zero => 0x80,
            RegFlag::Subtract => 0x40,
            RegFlag::HalfCarry => 0x20,
            RegFlag::Carry => 0x10,
        };
        self.flag & bit != 0
    }

    pub fn advance_pc(&mut self) -> u16 {
        let pc = self.pc;
        self.pc += 1;
        pc
    }

    pub fn set_pc(&mut self, addr: u16) -> u16 {
        let pc = self.pc;
        self.pc = addr;
        pc
    }

    pub fn add_pc(&mut self, n: i8) -> u16 {
        let pc = self.pc;
        self.pc = ((self.pc as i32) + (n as i32)) as u16;
        pc
    }

    pub fn get_pc(&self) -> u16 {
        self.pc
    }

}
<|endoftext|>