<commit_before>// Half Sleep -- Mutation Testing for Rust
// Written in 2015 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/>.
//

#![feature(custom_derive, plugin, plugin_registrar, rustc_private)]

extern crate aster;
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use syntax::ext::base::{Annotatable, MultiModifier};
use syntax::parse::token;
use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;
use syntax::fold::Folder;
use syntax::ptr::P;

mod locator;
mod mutator;
mod test_duper;
mod util;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(
        token::intern("mutation_test"),
        MultiModifier(Box::new(expand_mutation_test)));

    reg.register_syntax_extension(
        token::intern("mutate"),
        MultiModifier(Box::new(expand_mutate)));
}

/// check whether an annotation is on a function or function-like object
fn annotation_is_fn(item: &Annotatable) -> bool {
    match *item {
        Annotatable::Item(ref i) => {
            match i.node {
                ast::Item_::ItemMod(_) | ast::Item_::ItemFn(_, _, _, _, _) => true,
                _ => false
            }
        },
        Annotatable::TraitItem(ref i) => {
            match i.node {
                ast::TraitItem_::MethodTraitItem(_, _) => true,
                _ => false
            }
        },
        Annotatable::ImplItem(ref i) => {
            match i.node {
                ast::ImplItem_::MethodImplItem(_, _) => true,
                _ => false
            }
        }
    }
}

/// This is an annotation on functions; we do not use the syntax extender
/// to handle these, rather we do our own AST walk when parsing #[mutation_test]
/// on the module. So all this does is emit warnings for.
pub fn expand_mutate(cx: &mut ExtCtxt, decorator_span: Span,
                     _meta: &ast::MetaItem, item: Annotatable)
                    -> Annotatable {
    if !annotation_is_fn(&item) {
        cx.span_warn(decorator_span, "#[mutate] has no effect except functions and methods");
    }
    item
}

/// This annotation should only be applied to modules
pub fn expand_mutation_test(cx: &mut ExtCtxt, decorator_span: Span,
                            _meta: &ast::MetaItem, item: Annotatable)
                           -> Annotatable {

    // Ensure that we are actually looking at a module
    let this_mod = match item {
        Annotatable::Item(ref ast_item) => {
            if let ast::ItemMod(ref this_mod) = ast_item.node {
                Some(this_mod.clone())
            } else {
                None
            }
        },
        _ => None
    };
    // Is there a less awkward way to do this?
    if this_mod.is_none() {
        if annotation_is_fn(&item) {
            cx.span_warn(decorator_span, concat!("#[mutation_test] can only be applied to modules; to ",
                                                 "mark a function for mutation use #[mutate]"));
        } else {
            cx.span_warn(decorator_span, "#[mutation_test] can only be applied to modules");
        }
        return item;
    };

    // At this point we know we are looking at a module
    // Run through the module duplicating and marring annotated functions
    let item = item.expect_item();
    let mut loc = locator::Locator::new();
    let item = loc.fold_item_simple((*item).clone());

    // Add new unit tests...
    let mut test_duper = test_duper::TestDuper::new(&loc);
    // ...and replace the module in the AST
    Annotatable::Item(P(test_duper.fold_item_simple(item)))
}

<commit_msg>updatelib.rs code to latest rust code<commit_after>// Half Sleep -- Mutation Testing for Rust
// Written in 2015 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/>.
//

#![allow(custom_derive, plugin, plugin_registrar, rustc_private)]

extern crate aster;
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use syntax::ext::base::{Annotatable, MultiModifier};
use syntax::parse::token;
use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;
use syntax::fold::Folder;
use syntax::ptr::P;

mod locator;
mod mutator;
mod test_duper;
mod util;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(
        token::intern("mutation_test"),
        MultiModifier(Box::new(expand_mutation_test)));

    reg.register_syntax_extension(
        token::intern("mutate"),
        MultiModifier(Box::new(expand_mutate)));
}

/// check whether an annotation is on a function or function-like object
fn annotation_is_fn(item: &Annotatable) -> bool {
    match *item {
        Annotatable::Item(ref i) => {
            match i.node {
                ast::Item_::ItemMod(_) | ast::Item_::ItemFn(_, _, _, _, _) => true,
                _ => false
            }
        },
        Annotatable::TraitItem(ref i) => {
            match i.node {
                ast::TraitItem_::MethodTraitItem(_, _) => true,
                _ => false
            }
        },
        Annotatable::ImplItem(ref i) => {
            match i.node {
                ast::ImplItem_::MethodImplItem(_, _) => true,
                _ => false
            }
        }
    }
}

/// This is an annotation on functions; we do not use the syntax extender
/// to handle these, rather we do our own AST walk when parsing #[mutation_test]
/// on the module. So all this does is emit warnings for.
pub fn expand_mutate(cx: &mut ExtCtxt, decorator_span: Span,
                     _meta: &ast::MetaItem, item: Annotatable)
                    -> Annotatable {
    if !annotation_is_fn(&item) {
        cx.span_warn(decorator_span, "#[mutate] has no effect except functions and methods");
    }
    item
}

/// This annotation should only be applied to modules
pub fn expand_mutation_test(cx: &mut ExtCtxt, decorator_span: Span,
                            _meta: &ast::MetaItem, item: Annotatable)
                           -> Annotatable {

    // Ensure that we are actually looking at a module
    let this_mod = match item {
        Annotatable::Item(ref ast_item) => {
            if let ast::ItemMod(ref this_mod) = ast_item.node {
                Some(this_mod.clone())
            } else {
                None
            }
        },
        _ => None
    };
    // Is there a less awkward way to do this?
    if this_mod.is_none() {
        if annotation_is_fn(&item) {
            cx.span_warn(decorator_span, concat!("#[mutation_test] can only be applied to modules; to ",
                                                 "mark a function for mutation use #[mutate]"));
        } else {
            cx.span_warn(decorator_span, "#[mutation_test] can only be applied to modules");
        }
        return item;
    };

    // At this point we know we are looking at a module
    // Run through the module duplicating and marring annotated functions
    let item = item.expect_item();
    let mut loc = locator::Locator::new();
    let item = loc.fold_item_simple((*item).clone());

    // Add new unit tests...
    let mut test_duper = test_duper::TestDuper::new(&loc);
    // ...and replace the module in the AST
    Annotatable::Item(P(test_duper.fold_item_simple(item)))
}

<|endoftext|>


<commit_before>//#![deny(warnings)]
#![feature(try_from)]
#![feature(conservative_impl_trait)]
#![feature(splice)]
#[macro_use]
extern crate cfg_if;
extern crate r2d2;
extern crate url;
extern crate bigdecimal;
extern crate dao;
#[macro_use]
extern crate rustorm_codegen;
extern crate chrono;
extern crate uuid;

cfg_if! {if #[cfg(feature = "with-postgres")]{
    extern crate r2d2_postgres;
    extern crate postgres;
    #[macro_use]
    extern crate postgres_shared;
    mod pg;
}}
cfg_if! {if #[cfg(feature = "with-sqlite")]{
    extern crate r2d2_sqlite3;
    extern crate sqlite as sqlite3;
    mod sq;
}}

mod pool;
mod platform;
mod error;
mod database;
mod entity;
mod table;
mod column;
mod foreign;
mod types;

pub use pool::Pool;
pub use database::Database;
pub use dao::Dao;
pub use dao::Value;
pub use dao::Rows;
pub use error::DbError;
pub use dao::{ToDao,FromDao};
pub use table::Table;
pub use column::Column;
pub use dao::TableName;
pub use dao::ToTableName;
pub use dao::ColumnName;
pub use dao::ToColumnNames;

#[cfg(test)]
mod test {
    use super::*;
    use dao::{FromDao, ToDao};

    #[test]
    fn derive_fromdao_and_todao() {
        #[derive(Debug, PartialEq, FromDao, ToDao)]
        struct User {
            id: i32,
            username: String,
            active: Option<bool>,
        }

        let user = User {
            id: 1,
            username: "ivanceras".into(),
            active: Some(true),
        };
        println!("user: {:#?}", user);
        let dao = user.to_dao();
        let mut expected_dao = Dao::new();
        expected_dao.insert("id", 1);
        expected_dao.insert("username", "ivanceras".to_string());
        expected_dao.insert("active", true);

        assert_eq!(expected_dao, dao);

        println!("dao: {:#?}", dao);
        let from_dao = User::from_dao(&dao);
        println!("from_dao: {:#?}", from_dao);
        assert_eq!(from_dao, user);
    }
}
<commit_msg>expose foreign<commit_after>//#![deny(warnings)]
#![feature(try_from)]
#![feature(conservative_impl_trait)]
#![feature(splice)]
#[macro_use]
extern crate cfg_if;
extern crate r2d2;
extern crate url;
extern crate bigdecimal;
extern crate dao;
#[macro_use]
extern crate rustorm_codegen;
extern crate chrono;
extern crate uuid;

cfg_if! {if #[cfg(feature = "with-postgres")]{
    extern crate r2d2_postgres;
    extern crate postgres;
    #[macro_use]
    extern crate postgres_shared;
    mod pg;
}}
cfg_if! {if #[cfg(feature = "with-sqlite")]{
    extern crate r2d2_sqlite3;
    extern crate sqlite as sqlite3;
    mod sq;
}}

mod pool;
mod platform;
mod error;
mod database;
mod entity;
mod table;
mod column;
pub mod foreign;
mod types;

pub use pool::Pool;
pub use database::Database;
pub use dao::Dao;
pub use dao::Value;
pub use dao::Rows;
pub use error::DbError;
pub use dao::{ToDao,FromDao};
pub use table::Table;
pub use column::Column;
pub use dao::TableName;
pub use dao::ToTableName;
pub use dao::ColumnName;
pub use dao::ToColumnNames;

#[cfg(test)]
mod test {
    use super::*;
    use dao::{FromDao, ToDao};

    #[test]
    fn derive_fromdao_and_todao() {
        #[derive(Debug, PartialEq, FromDao, ToDao)]
        struct User {
            id: i32,
            username: String,
            active: Option<bool>,
        }

        let user = User {
            id: 1,
            username: "ivanceras".into(),
            active: Some(true),
        };
        println!("user: {:#?}", user);
        let dao = user.to_dao();
        let mut expected_dao = Dao::new();
        expected_dao.insert("id", 1);
        expected_dao.insert("username", "ivanceras".to_string());
        expected_dao.insert("active", true);

        assert_eq!(expected_dao, dao);

        println!("dao: {:#?}", dao);
        let from_dao = User::from_dao(&dao);
        println!("from_dao: {:#?}", from_dao);
        assert_eq!(from_dao, user);
    }
}
<|endoftext|>


<commit_before>//! An implementation of [FLAC](https://xiph.org/flac), free lossless audio
//! codec, written in Rust.

#[macro_use]
extern crate nom;

#[macro_use]
mod utility;
pub mod metadata;
pub mod frame;
pub mod subframe;
pub mod stream;

pub use frame::{frame_parser, Frame};
pub use subframe::{subframe_parser, SubFrame};
<commit_msg>Re-export Metadata<commit_after>//! An implementation of [FLAC](https://xiph.org/flac), free lossless audio
//! codec, written in Rust.

#[macro_use]
extern crate nom;

#[macro_use]
mod utility;
pub mod metadata;
pub mod frame;
pub mod subframe;
pub mod stream;

pub use metadata::Metadata;
pub use frame::{frame_parser, Frame};
pub use subframe::{subframe_parser, SubFrame};
<|endoftext|>


<commit_before>type Stack<T> = Vec<T>;

pub struct Interpreter<T> {
    data_stack: Stack<T>,
}

impl<T> Interpreter<T> {

    fn new() -> Interpreter<T> {
        Interpreter {
            data_stack: Stack::new(),
        }
    }

    fn push(&mut self, value: T) {
        self.data_stack.push(value)
    }

    fn pop(&mut self) -> Option<T> {
        self.data_stack.pop()
    }
}

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

    #[test]
    fn pops_nothing() {
        let mut interpreter = Interpreter::<i32>::new();
        assert_eq!(None, interpreter.pop())
    }

    #[test]
    fn pops_as_pushed() {
        let mut interpreter = Interpreter::<i32>::new();
        interpreter.push(42);
        assert_eq!(Some(42), interpreter.pop())
    }
}
<commit_msg>Test push/pop sequence<commit_after>type Stack<T> = Vec<T>;

pub struct Interpreter<T> {
    data_stack: Stack<T>,
}

impl<T> Interpreter<T> {

    fn new() -> Interpreter<T> {
        Interpreter {
            data_stack: Stack::new(),
        }
    }

    fn push(&mut self, value: T) {
        self.data_stack.push(value)
    }

    fn pop(&mut self) -> Option<T> {
        self.data_stack.pop()
    }
}

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

    #[test]
    fn pops_nothing() {
        let mut interpreter = Interpreter::<i32>::new();
        assert_eq!(None, interpreter.pop())
    }

    #[test]
    fn pops_as_pushed() {
        let mut interpreter = Interpreter::<i32>::new();
        interpreter.push(42);
        assert_eq!(Some(42), interpreter.pop());
        assert_eq!(None, interpreter.pop())
    }

    #[test]
    fn pops_in_reverse_order() {
        let mut interpreter = Interpreter::<i32>::new();
        interpreter.push(42);
        interpreter.push(51);
        assert_eq!(Some(51), interpreter.pop());
        assert_eq!(Some(42), interpreter.pop());
        assert_eq!(None, interpreter.pop())
    }
}
<|endoftext|>


<commit_before>extern crate arrayvec;

use self::arrayvec::ArrayVec;

/// A token in noise message patterns.
#[allow(missing_docs)]
#[derive(Copy, Clone)]
pub enum Token {
    E,
    S,
    EE,
    ES,
    SE,
    SS,
    PSK,
}

use self::Token::*;

/// Noise handshake pattern.
#[derive(Clone)]
pub struct HandshakePattern {
    pre_i: ArrayVec<[Token; 4]>,
    pre_r: ArrayVec<[Token; 4]>,
    msg_patterns: ArrayVec<[ArrayVec<[Token; 8]>; 8]>,
    name: &'static str,
}

impl HandshakePattern {
    /// Get initiator pre-messages.
    pub fn get_pre_i(&self) -> &[Token] {
        &self.pre_i
    }

    /// Get responder pre-messages.
    pub fn get_pre_r(&self) -> &[Token] {
        &self.pre_r
    }

    /// Get message patterns.
    pub fn get_message_pattern(&self, i: usize) -> &[Token] {
        &self.msg_patterns[i]
    }

    /// Get number of message patterns.
    pub fn get_message_patterns_len(&self) -> usize {
        self.msg_patterns.len()
    }

    /// Get pattern name.
    pub fn get_name(&self) -> &str {
        self.name
    }
}

macro_rules! vec {
    () => {
        ArrayVec::new()
    };
    ( $( $x:expr ),* ) => {
        {
            let mut temp_vec = ArrayVec::new();
            $(
                temp_vec.push($x);
            )*
            temp_vec
        }
    };
}

/// The `Noise_N` pattern.
pub fn noise_n() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES]],
        name: "N",
    }
}

/// The `Noise_K` pattern.
pub fn noise_k() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![S],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES, SS]],
        name: "K",
    }
}

/// The `Noise_X` pattern.
pub fn noise_x() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES, S, SS]],
        name: "X",
    }
}

/// The `Noise_NN` pattern.
pub fn noise_nn() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![],
        msg_patterns: vec![vec![E], vec![E, EE]],
        name: "NN",
    }
}

/// The `Noise_NK` pattern.
pub fn noise_nk() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES], vec![E, EE]],
        name: "NK",
    }
}

/// The `Noise_NX` pattern.
pub fn noise_nx() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![],
        msg_patterns: vec![vec![E], vec![E, EE, S, ES]],
        name: "NX",
    }
}

/// The `Noise_XN` pattern.
pub fn noise_xn() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![],
        msg_patterns: vec![vec![E], vec![E, EE], vec![S, SE]],
        name: "XN",
    }
}

/// The `Noise_XK` pattern.
pub fn noise_xk() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES], vec![E, EE], vec![S, SE]],
        name: "XK",
    }
}

/// The `Noise_XX` pattern.
pub fn noise_xx() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![],
        msg_patterns: vec![vec![E], vec![E, EE, S, ES], vec![S, SE]],
        name: "XX",
    }
}

/// The `Noise_KN` pattern.
pub fn noise_kn() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![S],
        pre_r: vec![],
        msg_patterns: vec![vec![E], vec![E, EE, SE]],
        name: "KN",
    }
}

/// The `Noise_KK` pattern.
pub fn noise_kk() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![S],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES, SS], vec![E, EE, SE]],
        name: "KK",
    }
}

/// The `Noise_KX` pattern.
pub fn noise_kx() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![S],
        pre_r: vec![],
        msg_patterns: vec![vec![E], vec![E, EE, SE, S, ES]],
        name: "KX",
    }
}

/// The `Noise_IN` pattern.
pub fn noise_in() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![],
        msg_patterns: vec![vec![E, S], vec![E, EE, SE]],
        name: "IN",
    }
}

/// The `Noise_IK` pattern.
pub fn noise_ik() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES, S, SS], vec![E, EE, SE]],
        name: "IK",
    }
}

/// The `Noise_IX` pattern.
pub fn noise_ix() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![],
        msg_patterns: vec![vec![E, S], vec![E, EE, SE, S, ES]],
        name: "IX",
    }
}

/// The `Noise_XXfallback` pattern.
///
/// Something that is used in noise pipes.
pub fn noise_xx_fallback() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![E],
        msg_patterns: vec![vec![E, EE, S, SE], vec![S, ES]],
        name: "XXfallback",
    }
}
<commit_msg>Extend HandshakePattern<commit_after>extern crate arrayvec;

use self::arrayvec::ArrayVec;

/// A token in noise message patterns.
#[allow(missing_docs)]
#[derive(Copy, Clone)]
pub enum Token {
    E,
    S,
    EE,
    ES,
    SE,
    SS,
    PSK,
}

use self::Token::*;

/// Noise handshake pattern.
#[derive(Clone)]
pub struct HandshakePattern {
    pre_i: ArrayVec<[Token; 4]>,
    pre_r: ArrayVec<[Token; 4]>,
    msg_patterns: ArrayVec<[ArrayVec<[Token; 8]>; 8]>,
    name: &'static str,
}

impl HandshakePattern {
    /// Construct a new HandshakePattern from pre-message patterns, message patterns and name.
    ///
    /// # Pattern validity
    ///
    /// It is the caller's responlity to ensure that the pattern is *valid*.
    ///
    /// # Panics
    ///
    /// If any of the patterns are too long (longer than 8 tokens).
    ///
    /// Or if the number of patterns are too large (larger than 8).
    pub fn new<'a>(
        pre_i: &[Token],
        pre_r: &[Token],
        msg_patterns: &[&[Token]],
        name: &'static str,
    ) -> Self {
        HandshakePattern {
            pre_i: pre_i.into_iter().cloned().collect(),
            pre_r: pre_r.into_iter().cloned().collect(),
            msg_patterns: msg_patterns
                .into_iter()
                .map(|p| p.into_iter().cloned().collect())
                .collect(),
            name,
        }
    }

    /// Get initiator pre-messages.
    pub fn get_pre_i(&self) -> &[Token] {
        &self.pre_i
    }

    /// Get responder pre-messages.
    pub fn get_pre_r(&self) -> &[Token] {
        &self.pre_r
    }

    /// Get message patterns.
    pub fn get_message_pattern(&self, i: usize) -> &[Token] {
        &self.msg_patterns[i]
    }

    /// Get number of message patterns.
    pub fn get_message_patterns_len(&self) -> usize {
        self.msg_patterns.len()
    }

    /// Get pattern name.
    pub fn get_name(&self) -> &str {
        self.name
    }

    /// Whether there are any psk tokens in this pattern.
    pub fn has_psk(&self) -> bool {
        self.msg_patterns.iter().any(|m| {
            m.iter().any(|m| match m {
                Token::PSK => true,
                _ => false,
            })
        })
    }
}

macro_rules! vec {
    () => {
        ArrayVec::new()
    };
    ( $( $x:expr ),* ) => {
        {
            let mut temp_vec = ArrayVec::new();
            $(
                temp_vec.push($x);
            )*
            temp_vec
        }
    };
}

/// The `Noise_N` pattern.
pub fn noise_n() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES]],
        name: "N",
    }
}

/// The `Noise_K` pattern.
pub fn noise_k() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![S],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES, SS]],
        name: "K",
    }
}

/// The `Noise_X` pattern.
pub fn noise_x() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES, S, SS]],
        name: "X",
    }
}

/// The `Noise_NN` pattern.
pub fn noise_nn() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![],
        msg_patterns: vec![vec![E], vec![E, EE]],
        name: "NN",
    }
}

/// The `Noise_NK` pattern.
pub fn noise_nk() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES], vec![E, EE]],
        name: "NK",
    }
}

/// The `Noise_NX` pattern.
pub fn noise_nx() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![],
        msg_patterns: vec![vec![E], vec![E, EE, S, ES]],
        name: "NX",
    }
}

/// The `Noise_XN` pattern.
pub fn noise_xn() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![],
        msg_patterns: vec![vec![E], vec![E, EE], vec![S, SE]],
        name: "XN",
    }
}

/// The `Noise_XK` pattern.
pub fn noise_xk() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES], vec![E, EE], vec![S, SE]],
        name: "XK",
    }
}

/// The `Noise_XX` pattern.
pub fn noise_xx() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![],
        msg_patterns: vec![vec![E], vec![E, EE, S, ES], vec![S, SE]],
        name: "XX",
    }
}

/// The `Noise_KN` pattern.
pub fn noise_kn() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![S],
        pre_r: vec![],
        msg_patterns: vec![vec![E], vec![E, EE, SE]],
        name: "KN",
    }
}

/// The `Noise_KK` pattern.
pub fn noise_kk() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![S],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES, SS], vec![E, EE, SE]],
        name: "KK",
    }
}

/// The `Noise_KX` pattern.
pub fn noise_kx() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![S],
        pre_r: vec![],
        msg_patterns: vec![vec![E], vec![E, EE, SE, S, ES]],
        name: "KX",
    }
}

/// The `Noise_IN` pattern.
pub fn noise_in() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![],
        msg_patterns: vec![vec![E, S], vec![E, EE, SE]],
        name: "IN",
    }
}

/// The `Noise_IK` pattern.
pub fn noise_ik() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![S],
        msg_patterns: vec![vec![E, ES, S, SS], vec![E, EE, SE]],
        name: "IK",
    }
}

/// The `Noise_IX` pattern.
pub fn noise_ix() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![],
        msg_patterns: vec![vec![E, S], vec![E, EE, SE, S, ES]],
        name: "IX",
    }
}

/// The `Noise_XXfallback` pattern.
///
/// Something that is used in noise pipes.
pub fn noise_xx_fallback() -> HandshakePattern {
    HandshakePattern {
        pre_i: vec![],
        pre_r: vec![E],
        msg_patterns: vec![vec![E, EE, S, SE], vec![S, ES]],
        name: "XXfallback",
    }
}
<|endoftext|>


<commit_before>#![feature(convert)]

extern crate openssl;

use openssl::crypto::hash::{hash, Type};

pub enum HashTypes {
    SHA1,
    SHA2256,
    SHA2512,
    SHA3,
    Blake2b,
    Blake2s
}

impl HashTypes {
    pub fn to_u8(&self) -> u8 {
        match *self {
            HashTypes::SHA1 => 0x11,
            HashTypes::SHA2256 => 0x12,
            HashTypes::SHA2512 => 0x13,
            HashTypes::SHA3 => 0x14,
            HashTypes::Blake2b => 0x40,
            HashTypes::Blake2s => 0x41,
        }
    }
}

pub fn multihash(wanthash: HashTypes, input: Vec<u8>) -> Result<Vec<u8>, String> {
    let ssl_hash: Option<Type> = match wanthash {
        HashTypes::SHA1 => Some(Type::SHA1),
        HashTypes::SHA2256 => Some(Type::SHA256),
        HashTypes::SHA2512 => Some(Type::SHA512),
        _ => None,
    };
    match ssl_hash {
        Some(openssl_type) => {
            let mut temphash = hash(openssl_type, input.as_slice());
            let length = temphash.len() as u8;
            temphash.insert(0, length);
            temphash.insert(0, wanthash.to_u8()); // Add the hashtype to the hash.
            Ok(temphash)
        }
        None => Err("Sorry, we don't support that hash algorithm yet.".to_string()),
    }
}

#[cfg(test)]
mod test {
    use super::{HashTypes, multihash};
    use openssl::crypto::hash::{hash, Type};

    #[test]
    fn test1() {
        let example = b"Hello World";
        let mut result = hash(Type::SHA256, example);
        let length = result.len() as u8;
        result.insert(0, 0x12);
        result.insert(1, length);

        assert_eq!(multihash(HashTypes::SHA2256, example.to_vec()).unwrap(), result);
    }
}
<commit_msg>License in lib.rs<commit_after>// Copyright [yyyy] [name of copyright owner]

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//    http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![feature(convert)]

extern crate openssl;

use openssl::crypto::hash::{hash, Type};

pub enum HashTypes {
    SHA1,
    SHA2256,
    SHA2512,
    SHA3,
    Blake2b,
    Blake2s
}

impl HashTypes {
    pub fn to_u8(&self) -> u8 {
        match *self {
            HashTypes::SHA1 => 0x11,
            HashTypes::SHA2256 => 0x12,
            HashTypes::SHA2512 => 0x13,
            HashTypes::SHA3 => 0x14,
            HashTypes::Blake2b => 0x40,
            HashTypes::Blake2s => 0x41,
        }
    }
}

pub fn multihash(wanthash: HashTypes, input: Vec<u8>) -> Result<Vec<u8>, String> {
    let ssl_hash: Option<Type> = match wanthash {
        HashTypes::SHA1 => Some(Type::SHA1),
        HashTypes::SHA2256 => Some(Type::SHA256),
        HashTypes::SHA2512 => Some(Type::SHA512),
        _ => None,
    };
    match ssl_hash {
        Some(openssl_type) => {
            let mut temphash = hash(openssl_type, input.as_slice());
            let length = temphash.len() as u8;
            temphash.insert(0, length);
            temphash.insert(0, wanthash.to_u8()); // Add the hashtype to the hash.
            Ok(temphash)
        }
        None => Err("Sorry, we don't support that hash algorithm yet.".to_string()),
    }
}

#[cfg(test)]
mod test {
    use super::{HashTypes, multihash};
    use openssl::crypto::hash::{hash, Type};

    #[test]
    fn test1() {
        let example = b"Hello World";
        let mut result = hash(Type::SHA256, example);
        let length = result.len() as u8;
        result.insert(0, 0x12);
        result.insert(1, length);

        assert_eq!(multihash(HashTypes::SHA2256, example.to_vec()).unwrap(), result);
    }
}
<|endoftext|>


<commit_before>#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/7853871?s=128", html_favicon_url = "https://avatars0.githubusercontent.com/u/7853871?s=256", html_root_url = "http://ironframework.io/core/iron")]
#![deny(missing_docs)]
#![deny(warnings)]
#![allow(unstable)]

#![feature(unboxed_closures, slicing_syntax)]

//! The main crate for the Iron library.
//!
//! Iron is a high level web framework built in and for Rust.
//!
//! Iron provides a robust and efficient framework
//! for creating and plugging in middleware.
//!
//! Obligatory Hello World:
//!
//! ```ignore
//! fn hello_world(req: &mut Request) -> IronResult<Response> {
//!   Response::new().set(Status(status::Ok)).set(Body("Hello World!"))
//! }
//!
//! Iron::new(hello_world).listen(Ipv4Addr(127, 0, 0, 1), 3000);
//! ```

// Stdlib dependencies
#[macro_use] extern crate log;
#[cfg(test)] extern crate test;

// Third party packages
extern crate hyper;
extern crate "typemap" as tmap;
extern crate plugin;
extern crate "modifier" as modfier;
extern crate error;
extern crate url;

// Request + Response
pub use request::{Request, Url};
pub use response::Response;

// Middleware system
pub use middleware::{BeforeMiddleware, AfterMiddleware, AroundMiddleware,
                     Handler, Chain, ChainBuilder};

// Server
pub use iron::Iron;

// Extensions
pub use typemap::TypeMap;

// Headers
pub use hyper::header::common as headers;
pub use hyper::header::Headers;

// Expose `Pluggable` as `Plugin` so users can do `use iron::Plugin`.
pub use plugin::Pluggable as Plugin;

// Expose modifiers.
pub use modifier::Set;

// Errors
pub use error::Error;

// Mime types
pub use hyper::mime;

// Return type of many methods

/// The type of Errors inside and when using Iron.
pub type IronError = Box<Error>;

/// The Result alias used throughout Iron and in clients of Iron.
pub type IronResult<T> = Result<T, IronError>;

/// A module meant to be glob imported when using Iron, for instance:
///
/// ```{ignore}
/// #![feature(globs)]
/// use iron::prelude::*;
/// ```
///
/// This module contains several important traits that provide many
/// of the convenience methods in Iron, as well as `Request`, `Response`
/// `IronResult`, `IronError` and `Iron`.
pub mod prelude {
    pub use {Set, Plugin, Chain, Request, Response,
             IronResult, IronError, Iron};
}

/// Re-exports from the TypeMap crate.
pub mod typemap {
    pub use tmap::{TypeMap, Key};
}

/// Re-exports from the Modifier crate.
pub mod modifier;

/// Status Codes
pub mod status {
    pub use hyper::status::StatusCode as Status;
    pub use hyper::status::StatusCode::*;
}

/// HTTP Methods
pub mod method {
    pub use hyper::method::Method;
    pub use hyper::method::Method::*;
}

// Publicized to show the documentation
pub mod middleware;

// Response utilities
pub mod response;

// Request and Response Modifiers
pub mod modifiers;

// Internal modules
mod request;
mod iron;

<commit_msg>(feat) Use a better setup for deny(warnings).<commit_after>#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/7853871?s=128", html_favicon_url = "https://avatars0.githubusercontent.com/u/7853871?s=256", html_root_url = "http://ironframework.io/core/iron")]

#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]

#![allow(unstable)]

#![feature(unboxed_closures, slicing_syntax)]

//! The main crate for the Iron library.
//!
//! Iron is a high level web framework built in and for Rust.
//!
//! Iron provides a robust and efficient framework
//! for creating and plugging in middleware.
//!
//! Obligatory Hello World:
//!
//! ```ignore
//! fn hello_world(req: &mut Request) -> IronResult<Response> {
//!   Response::new().set(Status(status::Ok)).set(Body("Hello World!"))
//! }
//!
//! Iron::new(hello_world).listen(Ipv4Addr(127, 0, 0, 1), 3000);
//! ```

// Stdlib dependencies
#[macro_use] extern crate log;
#[cfg(test)] extern crate test;

// Third party packages
extern crate hyper;
extern crate "typemap" as tmap;
extern crate plugin;
extern crate "modifier" as modfier;
extern crate error;
extern crate url;

// Request + Response
pub use request::{Request, Url};
pub use response::Response;

// Middleware system
pub use middleware::{BeforeMiddleware, AfterMiddleware, AroundMiddleware,
                     Handler, Chain, ChainBuilder};

// Server
pub use iron::Iron;

// Extensions
pub use typemap::TypeMap;

// Headers
pub use hyper::header::common as headers;
pub use hyper::header::Headers;

// Expose `Pluggable` as `Plugin` so users can do `use iron::Plugin`.
pub use plugin::Pluggable as Plugin;

// Expose modifiers.
pub use modifier::Set;

// Errors
pub use error::Error;

// Mime types
pub use hyper::mime;

// Return type of many methods

/// The type of Errors inside and when using Iron.
pub type IronError = Box<Error>;

/// The Result alias used throughout Iron and in clients of Iron.
pub type IronResult<T> = Result<T, IronError>;

/// A module meant to be glob imported when using Iron, for instance:
///
/// ```{ignore}
/// #![feature(globs)]
/// use iron::prelude::*;
/// ```
///
/// This module contains several important traits that provide many
/// of the convenience methods in Iron, as well as `Request`, `Response`
/// `IronResult`, `IronError` and `Iron`.
pub mod prelude {
    pub use {Set, Plugin, Chain, Request, Response,
             IronResult, IronError, Iron};
}

/// Re-exports from the TypeMap crate.
pub mod typemap {
    pub use tmap::{TypeMap, Key};
}

/// Re-exports from the Modifier crate.
pub mod modifier;

/// Status Codes
pub mod status {
    pub use hyper::status::StatusCode as Status;
    pub use hyper::status::StatusCode::*;
}

/// HTTP Methods
pub mod method {
    pub use hyper::method::Method;
    pub use hyper::method::Method::*;
}

// Publicized to show the documentation
pub mod middleware;

// Response utilities
pub mod response;

// Request and Response Modifiers
pub mod modifiers;

// Internal modules
mod request;
mod iron;

<|endoftext|>


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

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

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

    // while let Some(foo) = st.next() {
    //     println!("{:?}", foo);
    // }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            let name_end = i;

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

            let value_beginning = self.offset;
            i = value_beginning;

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

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

                self.skip_leading_whitespace();

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

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

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

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

            let c = bytes[i];

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

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

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

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

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

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

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

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

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

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

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

    // while let Some(foo) = st.next() {
    //     println!("{:?}", foo);
    // }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            let name_end = i;

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

            let value_beginning = self.offset;
            i = value_beginning;

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

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

                self.skip_leading_whitespace();

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

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

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

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

            let c = bytes[i];

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

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

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

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

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

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

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

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

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


<commit_before>#![crate_name = "macaroons"]
#![crate_type = "lib"]

#![feature(core)]
#![feature(collections)]

use std::slice::bytes;

pub mod caveat;
pub use caveat::{Caveat, Predicate};
pub use sodiumoxide::crypto::auth::hmacsha256::{Key, Tag, TAGBYTES};

extern crate sodiumoxide;
use sodiumoxide::crypto::auth::hmacsha256::authenticate;

extern crate "rustc-serialize" as serialize;
use serialize::base64::{self, FromBase64, ToBase64};

// Macaroons personalize the HMAC key using this string
// "macaroons-key-generator" padded to 32-bytes with zeroes
const KEY_GENERATOR: &'static [u8; 32] = b"macaroons-key-generator\0\0\0\0\0\0\0\0\0";

const PACKET_PREFIX_LENGTH: usize = 4;
const MAX_PACKET_LENGTH:    usize = 65535;

pub struct Token {
  pub location:   Vec<u8>,
  pub identifier: Vec<u8>,
  pub caveats:    Vec<Caveat>,
  pub tag:        Tag
}

struct Packet {
  pub field: Vec<u8>,
  pub value: Vec<u8>
}

impl Token {
  pub fn new(key: Vec<u8>, identifier: Vec<u8>, location: Vec<u8>) -> Token {
    let Tag(personalized_key) = authenticate(&key, &Key(*KEY_GENERATOR));
    let tag = authenticate(&identifier, &Key(personalized_key));

    Token {
      location:   location,
      identifier: identifier,
      caveats:    Vec::new(),
      tag:        tag
    }
  }

  pub fn deserialize(macaroon: Vec<u8>) -> Result<Token, &'static str> {
    let mut location:   Option<Vec<u8>> = None;
    let mut identifier: Option<Vec<u8>> = None;
    let mut caveats:    Vec<Caveat>     = Vec::new();
    let mut tag:        Option<Tag>     = None;

    let token_data = match macaroon.as_slice().from_base64() {
      Ok(bytes) => bytes,
      _         => return Err("couldn't parse base64")
    };

    let mut index: usize = 0;

    while index < token_data.len() {
      let (packet, taken) = Token::depacketize(&token_data, index);
      index += taken;

      match packet.field.as_slice() {
        b"location"   => { location = Some(packet.value) },
        b"identifier" => { identifier = Some(packet.value) },
        b"cid"        => { caveats.push(Caveat::new(Predicate(packet.value))) },
        b"signature"  => {
          if packet.value.len() != TAGBYTES {
            return Err("invalid signature length")
          }

          let mut signature_bytes = [0u8; TAGBYTES];
          bytes::copy_memory(&mut signature_bytes, &packet.value[..TAGBYTES]);

          tag = Some(Tag(signature_bytes))
        },
        _ => { return Err("unrecognized packet type"); }
      }
    }

    if location   == None { return Err("no 'location' found"); }
    if identifier == None { return Err("no 'identifier' found"); }
    if tag        == None { return Err("no 'signature' found"); }

    let token = Token {
      location:   location.unwrap(),
      identifier: identifier.unwrap(),
      caveats:    caveats,
      tag:        tag.unwrap()
    };

    Ok(token)
  }

  fn depacketize(data: &Vec<u8>, index: usize) -> (Packet, usize) {
    let length_str = std::str::from_utf8(&data[index .. index + PACKET_PREFIX_LENGTH]).unwrap();
    let packet_length: usize = std::num::from_str_radix(length_str, 16).unwrap();

    let mut packet_bytes = data[index + PACKET_PREFIX_LENGTH .. index + packet_length].to_vec();

    let pos = packet_bytes.iter().position(|&byte| byte == b' ').unwrap();
    let mut value = packet_bytes.split_off(pos);
    value.remove(0);
    value.pop();

    let packet = Packet { field: packet_bytes, value: value };
    (packet, packet_length)
  }

  pub fn add_caveat(&self, caveat: Caveat) -> Token {
    let Tag(key_bytes) = self.tag;
    let Predicate(predicate_bytes) = caveat.predicate.clone();
    let tag = authenticate(&predicate_bytes, &Key(key_bytes));

    let mut new_caveats = self.caveats.to_vec();
    new_caveats.push(caveat);

    Token {
      identifier: self.identifier.clone(),
      location:   self.location.clone(),
      caveats:    new_caveats,
      tag:        tag
    }
  }

  pub fn serialize(&self) -> Vec<u8> {
    // TODO: estimate capacity and use Vec::with_capacity
    let mut result: Vec<u8> = Vec::new();

    Token::packetize(&mut result, "location",   &self.location);
    Token::packetize(&mut result, "identifier", &self.identifier);

    for caveat in self.caveats.iter() {
      let Predicate(predicate_bytes) = caveat.predicate.clone();
      Token::packetize(&mut result, "cid", &predicate_bytes);
    }

    let Tag(signature_bytes) = self.tag;
    let mut signature_vec = Vec::new();
    signature_vec.push_all(&signature_bytes);

    Token::packetize(&mut result, "signature", &signature_vec);

    result.to_base64(base64::URL_SAFE).into_bytes()
  }

  fn packetize(result: &mut Vec<u8>, field: &str, value: &Vec<u8>) {
    let field_bytes: Vec<u8> = String::from_str(field).into_bytes();
    let packet_length = PACKET_PREFIX_LENGTH + field_bytes.len() + value.len() + 2;

    if packet_length > MAX_PACKET_LENGTH {
      panic!("packet too large to serialize");
    }

    let mut pkt_line = format!("{:04x}{} ", packet_length, field).into_bytes();
    result.append(&mut pkt_line);
    result.append(&mut value.clone());
    result.push('\n' as u8);
  }
}
<commit_msg>Return Err on depacketizing failures<commit_after>#![crate_name = "macaroons"]
#![crate_type = "lib"]

#![feature(core)]
#![feature(collections)]

use std::slice::bytes;

pub mod caveat;
pub use caveat::{Caveat, Predicate};
pub use sodiumoxide::crypto::auth::hmacsha256::{Key, Tag, TAGBYTES};

extern crate sodiumoxide;
use sodiumoxide::crypto::auth::hmacsha256::authenticate;

extern crate "rustc-serialize" as serialize;
use serialize::base64::{self, FromBase64, ToBase64};

// Macaroons personalize the HMAC key using this string
// "macaroons-key-generator" padded to 32-bytes with zeroes
const KEY_GENERATOR: &'static [u8; 32] = b"macaroons-key-generator\0\0\0\0\0\0\0\0\0";

const PACKET_PREFIX_LENGTH: usize = 4;
const MAX_PACKET_LENGTH:    usize = 65535;

pub struct Token {
  pub location:   Vec<u8>,
  pub identifier: Vec<u8>,
  pub caveats:    Vec<Caveat>,
  pub tag:        Tag
}

struct Packet {
  pub field: Vec<u8>,
  pub value: Vec<u8>
}

impl Token {
  pub fn new(key: Vec<u8>, identifier: Vec<u8>, location: Vec<u8>) -> Token {
    let Tag(personalized_key) = authenticate(&key, &Key(*KEY_GENERATOR));
    let tag = authenticate(&identifier, &Key(personalized_key));

    Token {
      location:   location,
      identifier: identifier,
      caveats:    Vec::new(),
      tag:        tag
    }
  }

  pub fn deserialize(macaroon: Vec<u8>) -> Result<Token, &'static str> {
    let mut location:   Option<Vec<u8>> = None;
    let mut identifier: Option<Vec<u8>> = None;
    let mut caveats:    Vec<Caveat>     = Vec::new();
    let mut tag:        Option<Tag>     = None;

    let token_data = match macaroon.as_slice().from_base64() {
      Ok(bytes) => bytes,
      _         => return Err("couldn't parse base64")
    };

    let mut index: usize = 0;

    while index < token_data.len() {
      let (packet, taken) = match Token::depacketize(&token_data, index) {
        Ok((p, t))  => (p, t),
        Err(reason) => return Err(reason)
      };

      index += taken;

      match packet.field.as_slice() {
        b"location"   => { location = Some(packet.value) },
        b"identifier" => { identifier = Some(packet.value) },
        b"cid"        => { caveats.push(Caveat::new(Predicate(packet.value))) },
        b"signature"  => {
          if packet.value.len() != TAGBYTES {
            return Err("invalid signature length")
          }

          let mut signature_bytes = [0u8; TAGBYTES];
          bytes::copy_memory(&mut signature_bytes, &packet.value[..TAGBYTES]);

          tag = Some(Tag(signature_bytes))
        },
        _ => { return Err("unrecognized packet type"); }
      }
    }

    if location   == None { return Err("no 'location' found"); }
    if identifier == None { return Err("no 'identifier' found"); }
    if tag        == None { return Err("no 'signature' found"); }

    let token = Token {
      location:   location.unwrap(),
      identifier: identifier.unwrap(),
      caveats:    caveats,
      tag:        tag.unwrap()
    };

    Ok(token)
  }

  fn depacketize(data: &Vec<u8>, index: usize) -> Result<(Packet, usize), &'static str> {
    // TODO: parse this length without involving any UTF-8 conversions
    let length_str = match std::str::from_utf8(&data[index .. index + PACKET_PREFIX_LENGTH]) {
      Ok(string) => string,
      _          => return Err("couldn't stringify packet length")
    };

    let packet_length: usize = match std::num::from_str_radix(length_str, 16) {
      Ok(length) => length,
      _          => return Err("couldn't parse packet length")
    };

    let mut packet_bytes = data[index + PACKET_PREFIX_LENGTH .. index + packet_length].to_vec();

    let pos = match packet_bytes.iter().position(|&byte| byte == b' ') {
      Some(i) => i,
      None    => return Err("malformed packet")
    };

    let mut value = packet_bytes.split_off(pos);
    value.remove(0);
    value.pop();

    let packet = Packet { field: packet_bytes, value: value };
    Ok((packet, packet_length))
  }

  pub fn add_caveat(&self, caveat: Caveat) -> Token {
    let Tag(key_bytes) = self.tag;
    let Predicate(predicate_bytes) = caveat.predicate.clone();
    let tag = authenticate(&predicate_bytes, &Key(key_bytes));

    let mut new_caveats = self.caveats.to_vec();
    new_caveats.push(caveat);

    Token {
      identifier: self.identifier.clone(),
      location:   self.location.clone(),
      caveats:    new_caveats,
      tag:        tag
    }
  }

  pub fn serialize(&self) -> Vec<u8> {
    // TODO: estimate capacity and use Vec::with_capacity
    let mut result: Vec<u8> = Vec::new();

    Token::packetize(&mut result, "location",   &self.location);
    Token::packetize(&mut result, "identifier", &self.identifier);

    for caveat in self.caveats.iter() {
      let Predicate(predicate_bytes) = caveat.predicate.clone();
      Token::packetize(&mut result, "cid", &predicate_bytes);
    }

    let Tag(signature_bytes) = self.tag;
    let mut signature_vec = Vec::new();
    signature_vec.push_all(&signature_bytes);

    Token::packetize(&mut result, "signature", &signature_vec);

    result.to_base64(base64::URL_SAFE).into_bytes()
  }

  fn packetize(result: &mut Vec<u8>, field: &str, value: &Vec<u8>) {
    let field_bytes: Vec<u8> = String::from_str(field).into_bytes();
    let packet_length = PACKET_PREFIX_LENGTH + field_bytes.len() + value.len() + 2;

    if packet_length > MAX_PACKET_LENGTH {
      panic!("packet too large to serialize");
    }

    let mut pkt_line = format!("{:04x}{} ", packet_length, field).into_bytes();
    result.append(&mut pkt_line);
    result.append(&mut value.clone());
    result.push('\n' as u8);
  }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate rustc_serialize;
extern crate url;
extern crate regex;

use regex::{Captures, Regex};
use rustc_serialize::json;

use hyper::Client;
use hyper::server::{Handler, Server, Request, Response};
use std::collections::HashMap;
use std::io::Read;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::channel;
use std::thread;

fn params<R: Read>(read: &mut R) -> HashMap<String, String> {
    let mut buffer = String::new();
    read.read_to_string(&mut buffer).unwrap();
    let mut params = HashMap::new();
    for (k, v) in url::form_urlencoded::parse(buffer.as_bytes()) {
        params.insert(k, v);
    }
    params
}

pub enum Resp {
    // say reponds in channel
    Say(String),
    // reply responds to caller of command
    Reply(String),
}

pub trait Responder {
    fn respond(&self, response: Resp) -> ();
}

pub struct DefaultResponder {
    response_url: String,
}

// todo: attachments
#[derive(Debug, RustcEncodable)]
pub struct ResponseBody {
    pub text: String,
    pub response_type: Option<String>,
}

impl Responder for DefaultResponder {
    fn respond(&self, response: Resp) {
        let body = match response {
            Resp::Say(text) => {
                ResponseBody {
                    text: text,
                    response_type: Some("in_channel".to_owned()),
                }
            }
            Resp::Reply(text) => {
                ResponseBody {
                    text: text,
                    response_type: None,
                }
            }
        };
        let client = Client::new();
        let _ = client.post(&self.response_url[..])
                      .body(json::encode(&body).unwrap().as_bytes())
                      .send();
    }
}

pub struct DiscardResponder;

impl Responder for DiscardResponder {
    fn respond(&self, resp: Resp) {

    }
}

/// A Handle handles matched commands
pub trait Handle: Sync + Send {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Resp>;
}

impl<F> Handle for F
    where F: Fn(&Command, &Option<Captures>, Box<Responder>) -> Option<Resp>,
          F: Send + Sync
{
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Resp> {
        self(cmd, caps, responder)
    }
}

pub struct TokenValidator<H: Handle + 'static> {
    handler: H,
    token: String,
}

impl<H: Handle + 'static> Handle for TokenValidator<H> {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Resp> {
        if cmd.token == self.token {
            self.handler.handle(cmd, caps, responder)
        } else {
            None
        }
    }
}

/// A matcher matches commands
pub trait Matcher: Send + Sync {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool);
}

impl<F> Matcher for F
    where F: Fn(&Command) -> (Option<Captures>, bool),
          F: Send + Sync
{
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        self(cmd)
    }
}

/// A direct command matcher
///
pub struct MatchCommand(String);

impl Matcher for MatchCommand {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        (None, cmd.command == self.0)
    }
}

/// A regex pattern matcher
///
pub struct MatchRegex(Regex);

impl Matcher for MatchRegex {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        if self.0.is_match(cmd.command.as_ref()) {
            (self.0.captures(cmd.command.as_ref()), true)
        } else {
            (None, false)
        }
    }
}

/// A binding between a command handler and which commands its handles
pub struct Route {
    handler: Box<Handle>,
    matcher: Box<Matcher>,
}

///
/// A command de-multiplexor
///
#[derive(Default)]
pub struct Mux {
    routes: Vec<Box<Route>>,
}

impl Mux {
    pub fn command<C, T, H>(&mut self, cmd: C, token: T, handler: H)
        where C: Into<String>,
              T: Into<String>,
              H: Handle + 'static
    {
        self.matching(MatchCommand(cmd.into()),
                      TokenValidator {
                          handler: handler,
                          token: token.into(),
                      })
    }

    pub fn matching<M, H>(&mut self, matcher: M, handler: H)
        where M: Matcher + 'static,
              H: Handle + 'static
    {
        let route = Route {
            handler: Box::new(handler),
            matcher: Box::new(matcher),
        };
        self.route(route)
    }

    ///
    pub fn route(&mut self, route: Route) {
        self.routes.push(Box::new(route));
    }

    pub fn handler<'a>(&self, cmd: &'a Command) -> Option<(Option<Captures<'a>>, &Box<Handle>)> {
        for r in self.routes.iter() {
            if let (captures, true) = r.matcher.matches(cmd) {
                return Some((captures, &r.handler));
            }
        }
        None
    }
}

pub struct Listener {
    pub mux: Mux,
}

#[derive(Default)]
pub struct Command {
    token: String,
    team_id: String,
    team_domain: String,
    channel_id: String,
    channel_name: String,
    user_id: String,
    user_name: String,
    command: String,
    text: String,
    response_url: String,
}

impl Command {
    pub fn from_params(params: HashMap<String, String>) -> Option<Command> {
        if let (Some(token),
                Some(team_id),
                Some(team_domain),
                Some(channel_id),
                Some(channel_name),
                Some(user_id),
                Some(user_name),
                Some(command),
                Some(text),
                Some(response_url)) = (params.get("token"),
                                       params.get("team_id"),
                                       params.get("team_domain"),
                                       params.get("channel_id"),
                                       params.get("channel_name"),
                                       params.get("user_id"),
                                       params.get("user_name"),
                                       params.get("command"),
                                       params.get("text"),
                                       params.get("response_url")) {
            Some(Command {
                token: token.clone(),
                team_id: team_id.clone(),
                team_domain: team_domain.clone(),
                channel_id: channel_id.clone(),
                channel_name: channel_name.clone(),
                user_id: user_id.clone(),
                user_name: user_name.clone(),
                command: command.clone(),
                text: text.clone(),
                response_url: response_url.clone(),
            })
        } else {
            None
        }
    }
}

impl Handler for Listener {
    // https://api.slack.com/slash-commands
    fn handle(&self, req: Request, res: Response) {
        let (_, _, _, _, _, mut body) = req.deconstruct();
        // parse params
        let params = params(&mut body);
        // parse cmd
        let cmd = Command::from_params(params).unwrap();
        // set up responder
        let responder = DefaultResponder { response_url: cmd.response_url.clone() };
        // handle cmd
        if let &Some((ref captures, handler)) = &self.mux.handler(&cmd) {
            handler.handle(&cmd, &captures, Box::new(responder));
        }
        res.send(b"ok");
        ()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::regex::{Regex,Captures};

    #[test]
    fn matches_commands() {
        let cmd = Command { command: "/test".to_owned(), ..Default::default() };
        let (caps, matched) = MatchCommand("/test".to_owned()).matches(&cmd);
        assert!(matched)
    }

    #[test]
    fn matches_regexes() {
        let cmd = Command { command: "/test".to_owned(), ..Default::default() };
        let (caps, matched) = MatchRegex(Regex::new("(test)").unwrap()).matches(&cmd);
        assert!(matched)
    }
}
<commit_msg>fix rustc warnings<commit_after>extern crate hyper;
extern crate rustc_serialize;
extern crate url;
extern crate regex;

use regex::{Captures, Regex};
use rustc_serialize::json;

use hyper::Client;
use hyper::server::{Handler, Request, Response};
use std::collections::HashMap;
use std::io::Read;

fn params<R: Read>(read: &mut R) -> HashMap<String, String> {
    let mut buffer = String::new();
    read.read_to_string(&mut buffer).unwrap();
    let mut params = HashMap::new();
    for (k, v) in url::form_urlencoded::parse(buffer.as_bytes()) {
        params.insert(k, v);
    }
    params
}

pub enum Resp {
    // say reponds in channel
    Say(String),
    // reply responds to caller of command
    Reply(String),
}

pub trait Responder {
    fn respond(&self, response: Resp) -> ();
}

pub struct DefaultResponder {
    response_url: String,
}

// todo: attachments
#[derive(Debug, RustcEncodable)]
pub struct ResponseBody {
    pub text: String,
    pub response_type: Option<String>,
}

impl Responder for DefaultResponder {
    fn respond(&self, response: Resp) {
        let body = match response {
            Resp::Say(text) => {
                ResponseBody {
                    text: text,
                    response_type: Some("in_channel".to_owned()),
                }
            }
            Resp::Reply(text) => {
                ResponseBody {
                    text: text,
                    response_type: None,
                }
            }
        };
        let client = Client::new();
        let _ = client.post(&self.response_url[..])
                      .body(json::encode(&body).unwrap().as_bytes())
                      .send();
    }
}

pub struct DiscardResponder;

impl Responder for DiscardResponder {
    fn respond(&self, _: Resp) {

    }
}

/// A Handle handles matched commands
pub trait Handle: Sync + Send {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Resp>;
}

impl<F> Handle for F
    where F: Fn(&Command, &Option<Captures>, Box<Responder>) -> Option<Resp>,
          F: Send + Sync
{
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Resp> {
        self(cmd, caps, responder)
    }
}

pub struct TokenValidator<H: Handle + 'static> {
    handler: H,
    token: String,
}

impl<H: Handle + 'static> Handle for TokenValidator<H> {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Resp> {
        if cmd.token == self.token {
            self.handler.handle(cmd, caps, responder)
        } else {
            None
        }
    }
}

/// A matcher matches commands
pub trait Matcher: Send + Sync {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool);
}

impl<F> Matcher for F
    where F: Fn(&Command) -> (Option<Captures>, bool),
          F: Send + Sync
{
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        self(cmd)
    }
}

/// A direct command matcher
///
pub struct MatchCommand(String);

impl Matcher for MatchCommand {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        (None, cmd.command == self.0)
    }
}

/// A regex pattern matcher
///
pub struct MatchRegex(Regex);

impl Matcher for MatchRegex {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        if self.0.is_match(cmd.command.as_ref()) {
            (self.0.captures(cmd.command.as_ref()), true)
        } else {
            (None, false)
        }
    }
}

/// A binding between a command handler and which commands its handles
pub struct Route {
    handler: Box<Handle>,
    matcher: Box<Matcher>,
}

///
/// A command de-multiplexor
///
#[derive(Default)]
pub struct Mux {
    routes: Vec<Box<Route>>,
}

impl Mux {
    pub fn command<C, T, H>(&mut self, cmd: C, token: T, handler: H)
        where C: Into<String>,
              T: Into<String>,
              H: Handle + 'static
    {
        self.matching(MatchCommand(cmd.into()),
                      TokenValidator {
                          handler: handler,
                          token: token.into(),
                      })
    }

    pub fn matching<M, H>(&mut self, matcher: M, handler: H)
        where M: Matcher + 'static,
              H: Handle + 'static
    {
        let route = Route {
            handler: Box::new(handler),
            matcher: Box::new(matcher),
        };
        self.route(route)
    }

    ///
    pub fn route(&mut self, route: Route) {
        self.routes.push(Box::new(route));
    }

    pub fn handler<'a>(&self, cmd: &'a Command) -> Option<(Option<Captures<'a>>, &Box<Handle>)> {
        for r in self.routes.iter() {
            if let (captures, true) = r.matcher.matches(cmd) {
                return Some((captures, &r.handler));
            }
        }
        None
    }
}

pub struct Listener {
    pub mux: Mux,
}

#[derive(Default)]
pub struct Command {
    pub token: String,
    pub team_id: String,
    pub team_domain: String,
    pub channel_id: String,
    pub channel_name: String,
    pub user_id: String,
    pub user_name: String,
    pub command: String,
    pub text: String,
    pub response_url: String,
}

impl Command {
    pub fn from_params(params: HashMap<String, String>) -> Option<Command> {
        if let (Some(token),
                Some(team_id),
                Some(team_domain),
                Some(channel_id),
                Some(channel_name),
                Some(user_id),
                Some(user_name),
                Some(command),
                Some(text),
                Some(response_url)) = (params.get("token"),
                                       params.get("team_id"),
                                       params.get("team_domain"),
                                       params.get("channel_id"),
                                       params.get("channel_name"),
                                       params.get("user_id"),
                                       params.get("user_name"),
                                       params.get("command"),
                                       params.get("text"),
                                       params.get("response_url")) {
            Some(Command {
                token: token.clone(),
                team_id: team_id.clone(),
                team_domain: team_domain.clone(),
                channel_id: channel_id.clone(),
                channel_name: channel_name.clone(),
                user_id: user_id.clone(),
                user_name: user_name.clone(),
                command: command.clone(),
                text: text.clone(),
                response_url: response_url.clone(),
            })
        } else {
            None
        }
    }
}

impl Handler for Listener {
    // https://api.slack.com/slash-commands
    fn handle(&self, req: Request, res: Response) {
        let (_, _, _, _, _, mut body) = req.deconstruct();
        // parse params
        let params = params(&mut body);
        // parse cmd
        if let Some(cmd) = Command::from_params(params) {
            // set up responder
            let responder = DefaultResponder { response_url: cmd.response_url.clone() };
            // handle cmd
            if let &Some((ref captures, handler)) = &self.mux.handler(&cmd) {
                handler.handle(&cmd, &captures, Box::new(responder));
            }
        }
        let _ = res.send(b"ok");
        ()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::regex::{Regex,Captures};

    #[test]
    fn matches_commands() {
        let cmd = Command { command: "/test".to_owned(), ..Default::default() };
        let (caps, matched) = MatchCommand("/test".to_owned()).matches(&cmd);
        assert!(matched)
    }

    #[test]
    fn matches_regexes() {
        let cmd = Command { command: "/test".to_owned(), ..Default::default() };
        let (caps, matched) = MatchRegex(Regex::new("(test)").unwrap()).matches(&cmd);
        assert!(matched)
    }
}
<|endoftext|>


<commit_before>//! Useful stuff for working with a bunch of hexagons
//!
//! # Example
//!
//! ```
//! use hex_math::{distance, Point};
//!
//! let point: Point = Point::new(1, 2, 5);
//! let other: Point = Point::new(3, 4, 5);
//! let dist: i32 = distance(&point, &other);
//!
//! assert_eq!(4, dist);
//! ```
//!
//! ```
//! use std::collections::HashSet;
//!
//! use hex_math::{Point, range};
//!
//! let point: Point = Point::new(1, 2, 5);
//! let other: Point = Point::new(3, 4, 5);
//! let set: HashSet<Point> = range(&point, 4);
//!
//! assert!(set.contains(&other));
//! ```

mod travel;
mod distance;
mod line;
mod range;
mod rotate;
mod ring;

mod enums;
mod structs;
mod traits;

pub use travel::travel;
pub use distance::{distance, distance_2d};
pub use line::{line, line_through, ray, ray_through};
pub use range::{range, range_2d, flood, flood_2d};
pub use rotate::rotate_2d;
pub use ring::{ring, ring_2d};

pub use enums::Direction;
pub use structs::{FloatPoint, PixelPoint, Point, Prism};
pub use traits::{HasValues, HasWalls, IsPointMap};

<commit_msg>Issue #33: Remove doc test from main<commit_after>//! Useful stuff for working with a bunch of hexagons

mod travel;
mod distance;
mod line;
mod range;
mod rotate;
mod ring;

mod enums;
mod structs;
mod traits;

pub use travel::travel;
pub use distance::{distance, distance_2d};
pub use line::{line, line_through, ray, ray_through};
pub use range::{range, range_2d, flood, flood_2d};
pub use rotate::rotate_2d;
pub use ring::{ring, ring_2d};

pub use enums::Direction;
pub use structs::{FloatPoint, PixelPoint, Point, Prism};
pub use traits::{HasValues, HasWalls, IsPointMap};

<|endoftext|>


<commit_before>#![crate_name = "XBTVEd"]
#![crate_type = "dylib"]
#![feature(libc, convert, collections, unboxed_closures)]

extern crate libc;

use std::ffi::{CStr, CString};
use std::mem;

pub mod action;
pub mod parse;
pub mod schedule;
pub mod program;
pub mod tags;
pub mod blocks;
pub mod gui;

pub use gui::XBTVEd;
use action::*;

#[no_mangle]
pub extern fn create_app() -> *const XBTVEd {
    let app = Box::new(XBTVEd::new());
    unsafe {
        mem::transmute(app)
    }
}

#[no_mangle]
pub extern fn undo(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).current_buffer_mut().undo()
    }
}

#[no_mangle]
pub extern fn redo(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).current_buffer_mut().redo()
    }
}

#[no_mangle]
pub extern fn buffers_len(xbtved: *const XBTVEd) -> u32 {
    unsafe {
        let res = (*xbtved).buffers_len();
        res as u32
    }
}

#[no_mangle]
pub extern fn new_buffer(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).add_buffer();
    }
}

#[no_mangle]
pub extern fn prev_buffer(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).prev_buffer();
    }
}

#[no_mangle]
pub extern fn next_buffer(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).next_buffer();
    }
}

#[no_mangle]
pub extern fn get_buffer_name(xbtved: *const XBTVEd) -> *const i8 {
    unsafe {
        match CString::new((*xbtved).current_buffer().get_name()) {
            Ok(x) => x.as_ptr(),
            Err(_) => CString::new("SCREWED UP!").unwrap().as_ptr()
        }
    }
}

fn ptr_to_string(name: *const libc::c_char) -> String {
    unsafe {
        match String::from_utf8(CStr::from_ptr(name).to_bytes().to_vec()) {
            Ok(x) => x,
            Err(f) => panic!(f)
        }
    }
}

#[no_mangle]
pub extern fn set_buffer_name(xbtved: *mut XBTVEd, name: *const libc::c_char) {
    unsafe {
        let new_name = ptr_to_string(name);
        let name_change = SetName::new((*xbtved).current_buffer(), &new_name);
        if let Err(f) = (*xbtved).current_buffer_mut().apply(name_change) {
            panic!(f)
        }
    }
}

#[no_mangle]
pub extern fn add_program(xbtved: *mut XBTVEd,
                          source: *const libc::c_char,
                          loc: *const libc::c_char) -> *const i8 {
    unsafe {
        let location = ptr_to_string(loc);
        let source = match ptr_to_string(source).as_str() {
            "local" => program::Source::Pathname(location),
            "network" => program::Source::URL(location),
            x => return CString::new(format!("{} is invalid source", x)).unwrap().as_ptr()
        };

        let prog = program::Program::new(source, tags::Tags::new(),
                                         vec!(program::Instruction::Play(0, 0)));
        let add_prog = AddProgram::new(&prog);

        match (*xbtved).current_buffer_mut().apply(add_prog) {
            Err(f) => CString::new(f).unwrap().as_ptr(),
            Ok(_) => CString::new("Ok").unwrap().as_ptr()
        }
    }
}
<commit_msg>working on the C interface; added a destructor since the struct was allocated on the heap<commit_after>#![crate_name = "XBTVEd"]
#![crate_type = "dylib"]
#![feature(alloc, libc, convert, collections, unboxed_closures)]

extern crate libc;

use std::ffi::{CStr, CString};
use std::mem;

pub mod action;
pub mod parse;
pub mod schedule;
pub mod program;
pub mod tags;
pub mod blocks;
pub mod gui;

pub use gui::XBTVEd;
use action::*;

#[no_mangle]
pub extern fn create_app() -> *const XBTVEd {
    let app = Box::new(XBTVEd::new());
    unsafe {
        mem::transmute(app)
    }
}

#[no_mangle]
pub extern fn destroy_app(xbtved: *mut XBTVEd) {
    unsafe {
        drop(Box::from_raw(xbtved));
    }
}

#[no_mangle]
pub extern fn undo(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).current_buffer_mut().undo()
    }
}

#[no_mangle]
pub extern fn redo(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).current_buffer_mut().redo()
    }
}

#[no_mangle]
pub extern fn buffers_len(xbtved: *const XBTVEd) -> u32 {
    unsafe {
        let res = (*xbtved).buffers_len();
        res as u32
    }
}

#[no_mangle]
pub extern fn new_buffer(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).add_buffer();
    }
}

#[no_mangle]
pub extern fn prev_buffer(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).prev_buffer();
    }
}

#[no_mangle]
pub extern fn next_buffer(xbtved: *mut XBTVEd) {
    unsafe {
        (*xbtved).next_buffer();
    }
}

#[no_mangle]
pub extern fn get_buffer_name(xbtved: *const XBTVEd) -> *const i8 {
    unsafe {
        match CString::new((*xbtved).current_buffer().get_name()) {
            Ok(x) => x.as_ptr(),
            Err(_) => CString::new("SCREWED UP!").unwrap().as_ptr()
        }
    }
}

fn ptr_to_string(name: *const libc::c_char) -> String {
    unsafe {
        match String::from_utf8(CStr::from_ptr(name).to_bytes().to_vec()) {
            Ok(x) => x,
            Err(f) => panic!(f)
        }
    }
}

#[no_mangle]
pub extern fn set_buffer_name(xbtved: *mut XBTVEd, name: *const libc::c_char) {
    unsafe {
        let new_name = ptr_to_string(name);
        let name_change = SetName::new((*xbtved).current_buffer(), &new_name);
        if let Err(f) = (*xbtved).current_buffer_mut().apply(name_change) {
            panic!(f)
        }
    }
}

#[no_mangle]
pub extern fn add_program(xbtved: *mut XBTVEd,
                          source: *const libc::c_char,
                          loc: *const libc::c_char) -> *const i8 {
    unsafe {
        let location = ptr_to_string(loc);
        let source = match ptr_to_string(source).as_str() {
            "local" => program::Source::Pathname(location),
            "network" => program::Source::URL(location),
            x => return CString::new(format!("{} is invalid source", x)).unwrap().as_ptr()
        };

        let prog = program::Program::new(source, tags::Tags::new(),
                                         vec!(program::Instruction::Play(0, 0)));
        let add_prog = AddProgram::new(&prog);

        match (*xbtved).current_buffer_mut().apply(add_prog) {
            Err(f) => CString::new(f).unwrap().as_ptr(),
            Ok(_) => CString::new("Ok").unwrap().as_ptr()
        }
    }
}
<|endoftext|>