<commit_before>#![crate_type="dylib"]
#![crate_name="bassert"]
#![feature(plugin_registrar, quote)]
#![doc(html_logo_url = "https://avatars.io/gravatar/d0ad9c6f37bb5aceac2d7ac95ba82607?size=large",
       html_favicon_url="https://avatars.io/gravatar/d0ad9c6f37bb5aceac2d7ac95ba82607?size=small")]
#![feature(rustc_private)]

extern crate syntax;
extern crate rustc;

use syntax::codemap::Span;
use syntax::parse::token;
use syntax::ast::{self, TokenTree};
use syntax::ptr::P;
use syntax::ext::base::{DummyResult, ExtCtxt, MacResult, MacExpr};
use rustc::plugin::Registry;

#[macro_export]
macro_rules! bassert{
    ($e:expr) => ({
        bassert!($e,"");
    });

    ($e:expr, $fmt:expr) => ({
        bassert!($e,"{}",$e);
    });
    ($e:expr, $fmt:expr, $($args:tt)*) => ({
        let f = internal_bassert!($e); f(&format_args!(concat!("\n",$fmt), $($args)*));
    });
}

#[macro_export]
macro_rules! debug_bassert{
    ($e:expr) => ({
        if cfg!(not(ndebug)) { bassert!($e) }
    });
    ($e:expr, $fmt:expr) => ({
        if cfg!(not(ndebug)) { bassert!($e, $fmt) }
    });
    ($e:expr, $fmt:expr, $($args:tt)*) => ({
        if cfg!(not(ndebug)) { bassert!($e, $fmt, $($args)*) }
    });
}

fn expand_bassert(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
        -> Box<MacResult + 'static> {
    // Create the parser for the arguments.
    let mut parser = cx.new_parser_from_tts(args);

    // Parse the expression to be tested.
    let expr: P<ast::Expr> = parser.parse_expr();

    if parser.token != token::Eof {
        cx.span_err(sp, "Non terminated internal bassert macro!");
        return DummyResult::any(sp);
    }
    MacExpr::new(get_fmt_meth(cx, expr))
}

/// Get the P<Expr> that is a callable function that can be passed to format_args! for execution of
/// the actual check.
fn get_fmt_meth(cx: &mut ExtCtxt, expr: P<ast::Expr>) -> P<ast::Expr> {
    // NB `rest` is the function argument sent in by the closure we wrap this around. By the time
    // this code is executed it will be in the environment.
    let inner_check = match expr.node {
        ast::ExprBinary(cmp, ref given, ref expected) => {
            let chk_fun = get_check_func(cx, cmp);
            quote_expr!(cx,
                match (&($given), &($expected)) {
                    (given_val, expected_val) => {
                        let chk = $chk_fun;
                        if !chk(given_val, expected_val) {
                            panic!("assertion failed: {}:\n\
                                    left:  `{}` = `{:?}`\n\
                                    right: `{}` = `{:?}`{}",
                                stringify!($expr), stringify!($given), *given_val,
                                stringify!($expected), *expected_val, rest);
                        }
                    }
                }
            )
        },
        ast::ExprCall(ref fun, ref args) if args.len() > 0 && args.len() < 7 => {
            // Annoyingly the way that macro's are expanded means we cannot use them to define
            // these, we need to manually place all of them ourselves.
            match args.len() {
                1 => {
                    let a = &args[0];
                    quote_expr!(cx,
                        match (&($a),) {
                            (a,) => {
                                if !($fun(*a)) {
                                    panic!("assertion failed: {}:\n\
                                            {} = {:?}{}",
                                            stringify!($expr), stringify!($a), *a, rest);
                                };
                            }
                        };
                    )
                }
                2 => {
                    let a = &args[0]; let b = &args[1];
                    quote_expr!(cx,
                        match (&($a), &($b)) {
                            (a, b) => {
                                if !($fun(*a, *b)) {
                                    panic!("assertion failed: {}:\n\
                                            {} = {:?}\n\
                                            {} = {:?}{}",
                                            stringify!($expr), stringify!($a), *a, stringify!($b),
                                            *b, rest);
                                };
                            }
                        };
                    )
                }
                3 => {
                    let a = &args[0]; let b = &args[1]; let c = &args[2];
                    quote_expr!(cx,
                        match (&($a), &($b), &($c)) {
                            (a, b, c) => {
                                if !($fun(*a, *b, *c)) {
                                    panic!("assertion failed: {}:\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}{}",
                                            stringify!($expr), stringify!($a), *a, stringify!($b),
                                            *b, stringify!($c), *c, rest);
                                };
                            }
                        };
                    )
                }
                4 => {
                    let a = &args[0]; let b = &args[1]; let c = &args[2]; let d = &args[3];
                    quote_expr!(cx,
                        match (&($a), &($b), &($c), &($d)) {
                            (a, b, c, d) => {
                                if !($fun(*a, *b, *c, *d)) {
                                    panic!("assertion failed: {}:\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}{}",
                                            stringify!($expr), stringify!($a), *a, stringify!($b),
                                            *b, stringify!($c), *c, stringify!($d), *d, rest);
                                };
                            }
                        };
                    )
                }
                5 => {
                    let a = &args[0]; let b = &args[1]; let c = &args[2]; let d = &args[3]; let e = &args[4];
                    quote_expr!(cx,
                        match (&($a), &($b), &($c), &($d), &($e)) {
                            (a, b, c, d, e) => {
                                if !($fun(*a, *b, *c, *d, *e)) {
                                    panic!("assertion failed: {}:\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}{}",
                                            stringify!($expr), stringify!($a), *a, stringify!($b),
                                            *b, stringify!($c), *c, stringify!($d), *d,
                                            stringify!($e), *e, rest);
                                };
                            }
                        };
                    )
                }
                6 => {
                    let a = &args[0]; let b = &args[1]; let c = &args[2]; let d = &args[3]; let e = &args[4]; let f = &args[5];
                    quote_expr!(cx,
                        match (&($a), &($b), &($c), &($d), &($e), &($f)) {
                            (a, b, c, d, e, f) => {
                                if !($fun(*a, *b, *c, *d, *e, *f)) {
                                    panic!("assertion failed: {}:\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}{}",
                                            stringify!($expr),
                                            stringify!($a), *a, stringify!($b), *b, stringify!($c),
                                            *c, stringify!($d), *d, stringify!($e), *e,
                                            stringify!($f), *f, rest);
                                };
                            }
                        };
                    )
                }
                _ => { unreachable!() }
            }
        },
        _ => {
            quote_expr!(cx,
                if !($expr) {
                    panic!(concat!("assertion failed: ", stringify!($expr), "{}"), rest);
                }
            )
        }
    };
    // Wrap the actual check into a function capable of being passed to `format_args!` and make
    // sure that the variable `rest` is bound.
    quote_expr!(cx, |rest: &::std::fmt::Arguments| { $inner_check } )
}

/// Defines all the binary operations we might do, so we can handle them all.
fn get_check_func(cx: &mut ExtCtxt, cmp: ast::BinOp) -> P<ast::Expr> {
    match cmp.node {
        ast::BiEq  => {
            quote_expr!(cx, { fn chk<T: Eq>(x: &T, y: &T) -> bool { *x == *y }; chk })
        },
        ast::BiNe  => {
            quote_expr!(cx, { fn chk<T: Eq>(x: &T, y: &T) -> bool { *x != *y }; chk })
        },
        ast::BiLe  => {
            quote_expr!(cx, { fn chk<T: Ord>(x: &T, y: &T) -> bool { *x <= *y }; chk })
        },
        ast::BiGe  => {
            quote_expr!(cx, { fn chk<T: Ord>(x: &T, y: &T) -> bool { *x >= *y }; chk })
        },
        ast::BiLt  => {
            quote_expr!(cx, { fn chk<T: Ord>(x: &T, y: &T) -> bool { *x <  *y }; chk })
        },
        ast::BiGt  => {
            quote_expr!(cx, { fn chk<T: Ord>(x: &T, y: &T) -> bool { *x >  *y }; chk })
        },
        ast::BiOr  => {
            quote_expr!(cx, { fn chk(x: &bool, y: &bool)   -> bool { *x || *y }; chk })
        },
        ast::BiAnd => {
            quote_expr!(cx, { fn chk(x: &bool, y: &bool)   -> bool { *x && *y }; chk })
        },
        ast::BiAdd => {
            quote_expr!(cx, { fn chk<R, L: Add<R, bool>>(x: &L, y: &R) -> bool { *x + *y }; chk })
        },
        ast::BiSub => {
            quote_expr!(cx, { fn chk<R, L: Sub<R, bool>>(x: &L, y: &R) -> bool { *x - *y }; chk })
        },
        ast::BiMul => {
            quote_expr!(cx, { fn chk<R, L: Mul<R, bool>>(x: &L, y: &R) -> bool { *x * *y }; chk })
        },
        ast::BiDiv => {
            quote_expr!(cx, { fn chk<R, L: Div<R, bool>>(x: &L, y: &R) -> bool { *x / *y }; chk })
        },
        ast::BiRem => {
            quote_expr!(cx, { fn chk<R, L: Rem<R, bool>>(x: &L, y: &R) -> bool { *x % *y }; chk })
        },
        ast::BiShr => {
            quote_expr!(cx, { fn chk<R, L: Shr<R, bool>>(x: &L, y: &R) -> bool { *x >> *y }; chk })
        },
        ast::BiShl => {
            quote_expr!(cx, { fn chk<R, L: Shl<R, bool>>(x: &L, y: &R) -> bool { *x << *y }; chk })
        },
        ast::BiBitOr  => {
            quote_expr!(cx, { fn chk<R, L: BitOr<R, bool>>(x: &L, y: &R) -> bool { *x | *y }; chk })
        },
        ast::BiBitAnd => {
            quote_expr!(cx, { fn chk<R, L: BitAnd<R, bool>>(x: &L, y: &R)-> bool { *x & *y }; chk })
        },
        ast::BiBitXor => {
            quote_expr!(cx, { fn chk<R, L: BitXor<R, bool>>(x: &L, y: &R)-> bool { *x ^ *y }; chk })
        },
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) { reg.register_macro("internal_bassert", expand_bassert); }
<commit_msg>MacExpr -> MacEager<commit_after>#![crate_type="dylib"]
#![crate_name="bassert"]
#![feature(plugin_registrar, quote)]
#![doc(html_logo_url = "https://avatars.io/gravatar/d0ad9c6f37bb5aceac2d7ac95ba82607?size=large",
       html_favicon_url="https://avatars.io/gravatar/d0ad9c6f37bb5aceac2d7ac95ba82607?size=small")]
#![feature(rustc_private)]

extern crate syntax;
extern crate rustc;

use syntax::codemap::Span;
use syntax::parse::token;
use syntax::ast::{self, TokenTree};
use syntax::ptr::P;
use syntax::ext::base::{DummyResult, ExtCtxt, MacResult, MacEager};
use rustc::plugin::Registry;

#[macro_export]
macro_rules! bassert{
    ($e:expr) => ({
        bassert!($e,"");
    });

    ($e:expr, $fmt:expr) => ({
        bassert!($e,"{}",$e);
    });
    ($e:expr, $fmt:expr, $($args:tt)*) => ({
        let f = internal_bassert!($e); f(&format_args!(concat!("\n",$fmt), $($args)*));
    });
}

#[macro_export]
macro_rules! debug_bassert{
    ($e:expr) => ({
        if cfg!(not(ndebug)) { bassert!($e) }
    });
    ($e:expr, $fmt:expr) => ({
        if cfg!(not(ndebug)) { bassert!($e, $fmt) }
    });
    ($e:expr, $fmt:expr, $($args:tt)*) => ({
        if cfg!(not(ndebug)) { bassert!($e, $fmt, $($args)*) }
    });
}

fn expand_bassert(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
        -> Box<MacResult + 'static> {
    // Create the parser for the arguments.
    let mut parser = cx.new_parser_from_tts(args);

    // Parse the expression to be tested.
    let expr: P<ast::Expr> = parser.parse_expr();

    if parser.token != token::Eof {
        cx.span_err(sp, "Non terminated internal bassert macro!");
        return DummyResult::any(sp);
    }
    MacEager::expr(get_fmt_meth(cx, expr))
}

/// Get the P<Expr> that is a callable function that can be passed to format_args! for execution of
/// the actual check.
fn get_fmt_meth(cx: &mut ExtCtxt, expr: P<ast::Expr>) -> P<ast::Expr> {
    // NB `rest` is the function argument sent in by the closure we wrap this around. By the time
    // this code is executed it will be in the environment.
    let inner_check = match expr.node {
        ast::ExprBinary(cmp, ref given, ref expected) => {
            let chk_fun = get_check_func(cx, cmp);
            quote_expr!(cx,
                match (&($given), &($expected)) {
                    (given_val, expected_val) => {
                        let chk = $chk_fun;
                        if !chk(given_val, expected_val) {
                            panic!("assertion failed: {}:\n\
                                    left:  `{}` = `{:?}`\n\
                                    right: `{}` = `{:?}`{}",
                                stringify!($expr), stringify!($given), *given_val,
                                stringify!($expected), *expected_val, rest);
                        }
                    }
                }
            )
        },
        ast::ExprCall(ref fun, ref args) if args.len() > 0 && args.len() < 7 => {
            // Annoyingly the way that macro's are expanded means we cannot use them to define
            // these, we need to manually place all of them ourselves.
            match args.len() {
                1 => {
                    let a = &args[0];
                    quote_expr!(cx,
                        match (&($a),) {
                            (a,) => {
                                if !($fun(*a)) {
                                    panic!("assertion failed: {}:\n\
                                            {} = {:?}{}",
                                            stringify!($expr), stringify!($a), *a, rest);
                                };
                            }
                        };
                    )
                }
                2 => {
                    let a = &args[0]; let b = &args[1];
                    quote_expr!(cx,
                        match (&($a), &($b)) {
                            (a, b) => {
                                if !($fun(*a, *b)) {
                                    panic!("assertion failed: {}:\n\
                                            {} = {:?}\n\
                                            {} = {:?}{}",
                                            stringify!($expr), stringify!($a), *a, stringify!($b),
                                            *b, rest);
                                };
                            }
                        };
                    )
                }
                3 => {
                    let a = &args[0]; let b = &args[1]; let c = &args[2];
                    quote_expr!(cx,
                        match (&($a), &($b), &($c)) {
                            (a, b, c) => {
                                if !($fun(*a, *b, *c)) {
                                    panic!("assertion failed: {}:\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}{}",
                                            stringify!($expr), stringify!($a), *a, stringify!($b),
                                            *b, stringify!($c), *c, rest);
                                };
                            }
                        };
                    )
                }
                4 => {
                    let a = &args[0]; let b = &args[1]; let c = &args[2]; let d = &args[3];
                    quote_expr!(cx,
                        match (&($a), &($b), &($c), &($d)) {
                            (a, b, c, d) => {
                                if !($fun(*a, *b, *c, *d)) {
                                    panic!("assertion failed: {}:\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}{}",
                                            stringify!($expr), stringify!($a), *a, stringify!($b),
                                            *b, stringify!($c), *c, stringify!($d), *d, rest);
                                };
                            }
                        };
                    )
                }
                5 => {
                    let a = &args[0]; let b = &args[1]; let c = &args[2]; let d = &args[3]; let e = &args[4];
                    quote_expr!(cx,
                        match (&($a), &($b), &($c), &($d), &($e)) {
                            (a, b, c, d, e) => {
                                if !($fun(*a, *b, *c, *d, *e)) {
                                    panic!("assertion failed: {}:\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}{}",
                                            stringify!($expr), stringify!($a), *a, stringify!($b),
                                            *b, stringify!($c), *c, stringify!($d), *d,
                                            stringify!($e), *e, rest);
                                };
                            }
                        };
                    )
                }
                6 => {
                    let a = &args[0]; let b = &args[1]; let c = &args[2]; let d = &args[3]; let e = &args[4]; let f = &args[5];
                    quote_expr!(cx,
                        match (&($a), &($b), &($c), &($d), &($e), &($f)) {
                            (a, b, c, d, e, f) => {
                                if !($fun(*a, *b, *c, *d, *e, *f)) {
                                    panic!("assertion failed: {}:\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}\n\
                                            {} = {:?}{}",
                                            stringify!($expr),
                                            stringify!($a), *a, stringify!($b), *b, stringify!($c),
                                            *c, stringify!($d), *d, stringify!($e), *e,
                                            stringify!($f), *f, rest);
                                };
                            }
                        };
                    )
                }
                _ => { unreachable!() }
            }
        },
        _ => {
            quote_expr!(cx,
                if !($expr) {
                    panic!(concat!("assertion failed: ", stringify!($expr), "{}"), rest);
                }
            )
        }
    };
    // Wrap the actual check into a function capable of being passed to `format_args!` and make
    // sure that the variable `rest` is bound.
    quote_expr!(cx, |rest: &::std::fmt::Arguments| { $inner_check } )
}

/// Defines all the binary operations we might do, so we can handle them all.
fn get_check_func(cx: &mut ExtCtxt, cmp: ast::BinOp) -> P<ast::Expr> {
    match cmp.node {
        ast::BiEq  => {
            quote_expr!(cx, { fn chk<T: Eq>(x: &T, y: &T) -> bool { *x == *y }; chk })
        },
        ast::BiNe  => {
            quote_expr!(cx, { fn chk<T: Eq>(x: &T, y: &T) -> bool { *x != *y }; chk })
        },
        ast::BiLe  => {
            quote_expr!(cx, { fn chk<T: Ord>(x: &T, y: &T) -> bool { *x <= *y }; chk })
        },
        ast::BiGe  => {
            quote_expr!(cx, { fn chk<T: Ord>(x: &T, y: &T) -> bool { *x >= *y }; chk })
        },
        ast::BiLt  => {
            quote_expr!(cx, { fn chk<T: Ord>(x: &T, y: &T) -> bool { *x <  *y }; chk })
        },
        ast::BiGt  => {
            quote_expr!(cx, { fn chk<T: Ord>(x: &T, y: &T) -> bool { *x >  *y }; chk })
        },
        ast::BiOr  => {
            quote_expr!(cx, { fn chk(x: &bool, y: &bool)   -> bool { *x || *y }; chk })
        },
        ast::BiAnd => {
            quote_expr!(cx, { fn chk(x: &bool, y: &bool)   -> bool { *x && *y }; chk })
        },
        ast::BiAdd => {
            quote_expr!(cx, { fn chk<R, L: Add<R, bool>>(x: &L, y: &R) -> bool { *x + *y }; chk })
        },
        ast::BiSub => {
            quote_expr!(cx, { fn chk<R, L: Sub<R, bool>>(x: &L, y: &R) -> bool { *x - *y }; chk })
        },
        ast::BiMul => {
            quote_expr!(cx, { fn chk<R, L: Mul<R, bool>>(x: &L, y: &R) -> bool { *x * *y }; chk })
        },
        ast::BiDiv => {
            quote_expr!(cx, { fn chk<R, L: Div<R, bool>>(x: &L, y: &R) -> bool { *x / *y }; chk })
        },
        ast::BiRem => {
            quote_expr!(cx, { fn chk<R, L: Rem<R, bool>>(x: &L, y: &R) -> bool { *x % *y }; chk })
        },
        ast::BiShr => {
            quote_expr!(cx, { fn chk<R, L: Shr<R, bool>>(x: &L, y: &R) -> bool { *x >> *y }; chk })
        },
        ast::BiShl => {
            quote_expr!(cx, { fn chk<R, L: Shl<R, bool>>(x: &L, y: &R) -> bool { *x << *y }; chk })
        },
        ast::BiBitOr  => {
            quote_expr!(cx, { fn chk<R, L: BitOr<R, bool>>(x: &L, y: &R) -> bool { *x | *y }; chk })
        },
        ast::BiBitAnd => {
            quote_expr!(cx, { fn chk<R, L: BitAnd<R, bool>>(x: &L, y: &R)-> bool { *x & *y }; chk })
        },
        ast::BiBitXor => {
            quote_expr!(cx, { fn chk<R, L: BitXor<R, bool>>(x: &L, y: &R)-> bool { *x ^ *y }; chk })
        },
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) { reg.register_macro("internal_bassert", expand_bassert); }
<|endoftext|>


<commit_before>//! natural_constants: a collection of constants and helper functions
//!
//! Written by Willi Kappler, Version 0.1 (2017.02.20)
//!
//! Repository: https://github.com/willi-kappler/natural_constants
//!
//! License: MIT
//!
//!
//! # Example:
//!
//! ```
//! extern crate natural_constants;
//! use natural_constants::physics::*;
//!
//!
//! fn main() {
//!     let c = speed_of_light_vac;
//!     let m0 = 100.0;
//!
//!     // Use c in your code:
//!     let E = m0 * c * c;
//! }
//! ```

// For clippy
// #![feature(plugin)]
//
// #![plugin(clippy)]

#![allow(non_upper_case_globals)]
#![allow(dead_code)]

pub mod math;
pub mod physics;
pub mod chemistry;
pub mod biology;
pub mod engineering;
pub mod conversion;
pub mod misc;
<commit_msg>Forgot to add geosciences as mod<commit_after>//! natural_constants: a collection of constants and helper functions
//!
//! Written by Willi Kappler, Version 0.1 (2017.02.20)
//!
//! Repository: https://github.com/willi-kappler/natural_constants
//!
//! License: MIT
//!
//!
//! # Example:
//!
//! ```
//! extern crate natural_constants;
//! use natural_constants::physics::*;
//!
//!
//! fn main() {
//!     let c = speed_of_light_vac;
//!     let m0 = 100.0;
//!
//!     // Use c in your code:
//!     let E = m0 * c * c;
//! }
//! ```

// For clippy
// #![feature(plugin)]
//
// #![plugin(clippy)]

#![allow(non_upper_case_globals)]
#![allow(dead_code)]

pub mod math;
pub mod physics;
pub mod chemistry;
pub mod biology;
pub mod engineering;
pub mod conversion;
pub mod misc;
pub mod geosciences;
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! Meta parsing and encoding for data oriented design

extern crate read_token;
extern crate range;

use range::Range;

pub use whitespace::{ Whitespace, WHITESPACE };

mod whitespace;

/// Types of properties.
pub enum Type {
    /// Either true or false.
    Bool,
    /// Text.
    String,
    /// Number.
    F64,
}

/// Errors reporting expected values.
pub enum Error<'a> {
    /// Not supported.
    NotSupported,
    /// Expected nodes with other names.
    ExpectedNode(&'a [&'a str]),
    /// Expected another propert type.
    ExpectedPropertyType(Type),
    /// Reaching end of node, but expected more properties.
    ExpectedMoreProperties(&'a [&'a str]),
}

/// Implemented by error handlers.
pub trait ErrorHandler {
    /// Report an error.
    fn error<'a>(range: Range, error: Error<'a>);
}

/// Implemented by meta readers.
///
/// A meta reader contains an internal state that corresponds to a virtual
/// tree structure. The meta parser communicates with the meta reader such
/// that parsing is interrupted if any error happens.
pub trait MetaReader {
    /// The state that points to a location in the parsed structure.
    type State;

    /// Starts parsing a node.
    fn start_node(&mut self, name: &str, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Ends parsing a node.
    fn end_node(&mut self, state: &Self::State) -> Result<Self::State, Error>;
    /// Starts optional section of a node.
    fn start_optional(&mut self, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Ends optional section of a node.
    fn end_optional(&mut self, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Starts selection.
    fn start_select(&mut self, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Ends selection.
    fn end_select(&mut self, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Sets a bool property of the node.
    fn set_as_bool(&mut self, name: &str, val: bool, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Sets a string property of the node.
    fn set_as_str(&mut self, name: &str, val: &str, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Sets a f64 property of the node.
    fn set_as_f64(&mut self, name: &str, val: f64, state: &Self::State) ->
        Result<Self::State, Error>;
}

/// Stores information about token.
pub struct Token<'a> {
    /// The text to match against.
    pub text: &'a str,
    /// Whether to set property to true or false (inverted).
    pub inverted: Option<bool>,
    /// Which predicate to set if token matches.
    /// This is the name of the property in current node.
    pub predicate: Option<&'a str>,
}

/// Stores information about a parameter.
pub struct Parameter<'a> {
    /// The name of the parameter.
    pub name: &'a str,
    /// The properties of the parameter.
    /// This is used to check the property names set by sub rules.
    /// If a property name does not match any of the arguments to the parameter,
    /// then an error is reported.
    pub args: &'a [&'a str],
    /// The property name of parent to set the value.
    pub value: Option<&'a str>,
    /// The body of the parameter.
    pub body: &'a [Rule<'a>],
}

/// A rule describes how some section of a document should be parsed.
pub enum Rule<'a> {
    /// Read whitespace.
    Whitespace(Whitespace),
    /// Match against a token.
    Token(Token<'a>),
    /// Select one of the sub rules.
    /// If the first one does not succeed, try another and so on.
    /// If all sub rules fail, then the rule fails.
    Select(&'a [Rule<'a>]),
    /// Read parameter.
    Parameter(Parameter<'a>),
}
<commit_msg>Forgot `&mut self` on `ErrorHandler`<commit_after>#![deny(missing_docs)]

//! Meta parsing and encoding for data oriented design

extern crate read_token;
extern crate range;

use range::Range;

pub use whitespace::{ Whitespace, WHITESPACE };

mod whitespace;

/// Types of properties.
pub enum Type {
    /// Either true or false.
    Bool,
    /// Text.
    String,
    /// Number.
    F64,
}

/// Errors reporting expected values.
pub enum Error<'a> {
    /// Not supported.
    NotSupported,
    /// Expected nodes with other names.
    ExpectedNode(&'a [&'a str]),
    /// Expected another propert type.
    ExpectedPropertyType(Type),
    /// Reaching end of node, but expected more properties.
    ExpectedMoreProperties(&'a [&'a str]),
}

/// Implemented by error handlers.
pub trait ErrorHandler {
    /// Report an error.
    fn error<'a>(&mut self, range: Range, error: Error<'a>);
}

/// Implemented by meta readers.
///
/// A meta reader contains an internal state that corresponds to a virtual
/// tree structure. The meta parser communicates with the meta reader such
/// that parsing is interrupted if any error happens.
pub trait MetaReader {
    /// The state that points to a location in the parsed structure.
    type State;

    /// Starts parsing a node.
    fn start_node(&mut self, name: &str, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Ends parsing a node.
    fn end_node(&mut self, state: &Self::State) -> Result<Self::State, Error>;
    /// Starts optional section of a node.
    fn start_optional(&mut self, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Ends optional section of a node.
    fn end_optional(&mut self, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Starts selection.
    fn start_select(&mut self, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Ends selection.
    fn end_select(&mut self, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Sets a bool property of the node.
    fn set_as_bool(&mut self, name: &str, val: bool, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Sets a string property of the node.
    fn set_as_str(&mut self, name: &str, val: &str, state: &Self::State) ->
        Result<Self::State, Error>;
    /// Sets a f64 property of the node.
    fn set_as_f64(&mut self, name: &str, val: f64, state: &Self::State) ->
        Result<Self::State, Error>;
}

/// Stores information about token.
pub struct Token<'a> {
    /// The text to match against.
    pub text: &'a str,
    /// Whether to set property to true or false (inverted).
    pub inverted: Option<bool>,
    /// Which predicate to set if token matches.
    /// This is the name of the property in current node.
    pub predicate: Option<&'a str>,
}

/// Stores information about a parameter.
pub struct Parameter<'a> {
    /// The name of the parameter.
    pub name: &'a str,
    /// The properties of the parameter.
    /// This is used to check the property names set by sub rules.
    /// If a property name does not match any of the arguments to the parameter,
    /// then an error is reported.
    pub args: &'a [&'a str],
    /// The property name of parent to set the value.
    pub value: Option<&'a str>,
    /// The body of the parameter.
    pub body: &'a [Rule<'a>],
}

/// A rule describes how some section of a document should be parsed.
pub enum Rule<'a> {
    /// Read whitespace.
    Whitespace(Whitespace),
    /// Match against a token.
    Token(Token<'a>),
    /// Select one of the sub rules.
    /// If the first one does not succeed, try another and so on.
    /// If all sub rules fail, then the rule fails.
    Select(&'a [Rule<'a>]),
    /// Read parameter.
    Parameter(Parameter<'a>),
}
<|endoftext|>


<commit_before>//! # Leaky Bucket Rate-Limiting (as a meter) in Rust
//! This crate implements
//! the
//! [generic cell rate algorithm](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm) (GCRA)
//! for rate-limiting and scheduling in Rust.
//!
//! ## Interface
//!
//! There is currently one rate limiter implementation in this crate,
//! the Generic Cell Rate Algorithm. Use it by creating a builder from
//! the [`GCRA`](algorithms/gcra/struct.GCRA.html) struct:
//!
//! ``` rust
//! use std::time::Duration;
//! use ratelimit_meter::{Decider, GCRA, Decision};
//!
//! let mut lim = GCRA::for_capacity(50).unwrap() // Allow 50 units of work
//!     .per(Duration::from_secs(1)) // We calculate per-second (this is the default).
//!     .cell_weight(1).unwrap() // Each cell is one unit of work "heavy".
//!     .build(); // Construct a non-threadsafe GCRA decider.
//! assert_eq!(Decision::Yes, lim.check().unwrap());
//! ```
//!
//! The rate-limiter interface is intentionally geared towards only
//! providing callers with the information they need to make decisions
//! about what to do with each cell. Whenever possible, additional
//! information about why a cell should be denied - the `GCRA`
//! implementation will return a `time::Instant` alongside the decision to
//! allow callers to e.g. provide better error messages to users.
//!
//! Due to this, the `ratelimit_meter` crate does not provide any facility
//! to wait until a cell would be allowed - if you require this, you
//! should use the `Instant` returned with negative decisions and wait
//! in your own, e.g. event loop.
//!
//! ## Rate-limiting Algorithms
//!
//! This crate implements two "serious" rate-limiting/traffic-shaping
//! algorithms:
//! [GCRA](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm)
//! and a [Leaky
//! Bucket](https://en.wikipedia.org/wiki/Leaky_bucket#As_a_meter). An
//! "unserious" implementation is provided also, the
//! [`Allower`](example_algorithms/struct.Allower.html), which returns
//! "Yes" to all rate-limiting queries.
//!
//! ### Design and implementation of GCRA
//!
//! The GCRA limits the rate of cells by determining when the "next"
//! cell is expected to arrive; any cells that arrive before that time
//! are classified as non-conforming; the methods for checking cells
//! also return an expected arrival time for these cells, so that
//! callers can choose to wait (adding jitter), or reject the cell.
//!
//! Since using the GCRA results in a much smoother usage pattern, it
//! appears to be very useful for "outgoing" traffic behaviors,
//! e.g. throttling API call rates, or emails sent to a person in a
//! period of time.
//!
//! Unlike token or leaky bucket algorithms, the GCRA assumes that all
//! units of work are of the same "weight", and so allows some
//! optimizations which result in much more concise and fast code (it
//! does not even use multiplication or division in the "hot" path).
//!
//! See [the documentation of the GCRA type](algorithms/gcra/struct.GCRA.html) for
//! more details on its implementation and on trade-offs that apply to
//! it.
//!
//! ### Design and implementation of the leaky bucket
//!
//! In contrast to the GCRA, the leaky bucket algorithm does not place
//! any constraints on the next cell's arrival time: Whenever there is
//! capacity left in the bucket, it can be used. This means that the
//! distribution of "yes" decisions from heavy usage on the leaky
//! bucket rate-limiter will be clustered together. On average, the
//! cell rates of both the GCRA and the leaky bucket will be the same,
//! but in terms of observable behavior, the leaky bucket will appear
//! to allow requests at a more predictable rate.
//!
//! This kind of behavior is usually what people of online APIs expect
//! these days, which makes the leaky bucket a very popular technique
//! for rate-limiting on these kinds of services.
//!
//! The leaky bucket algorithm implemented in this crate is fairly
//! standard: It only updates the bucket fill gauge when a cell is
//! checked, and supports checking "batches" of cells in a single call
//! with no problems.
//!
//! ## Thread-safe operation
//!
//! None of the stateful implementations in this crate can be used
//! across threads by default. However, there is a wrapper struct
//! [`Threadsafe`](algorithms/struct.Threadsafe.html), that wraps each
//! implementation's hot path in an atomically reference-counted
//! mutex. It still manages to be pretty fast (see the benchmarks
//! above), but the lock comes with an overhead even in
//! single-threaded operation.
//!
//! Example:
//!
//! ```
//! use std::time::Duration;
//! use ratelimit_meter::{Decider, GCRA, Decision};
//!
//! let mut lim = GCRA::for_capacity(50).unwrap() // Allow 50 units of work
//!     .per(Duration::from_secs(1)) // We calculate per-second (this is the default).
//!     .cell_weight(1).unwrap() // Each cell is one unit of work "heavy".
//!     .build_sync(); // Construct a threadsafe GCRA decider.
//! assert_eq!(Decision::Yes, lim.check().unwrap());
//! ```

pub mod example_algorithms;
pub mod errors;
pub mod algorithms;
mod implementation;

#[macro_use]
extern crate error_chain;

use std::time::{Instant};

pub use errors::*;
pub use self::algorithms::*;
use implementation::*;

#[derive(PartialEq, Debug)]
/// A decision on a single cell from the metered rate-limiter.
pub enum Decision<T> {
    /// The cell is conforming, allow it through.
    Yes,

    /// The cell is non-conforming. A rate-limiting algorithm
    /// implementation may return additional information for the
    /// caller, e.g. a time when the cell was expected to arrive.
    No(T),
}

impl<T> Decision<T> {
    /// Check if a decision on a cell indicates the cell is compliant
    /// or not. Returns `true` iff the cell was compliant, i.e. the
    /// decision was `Decision::Yes`.
    ///
    /// Note: This method is mostly useful in tests.
    pub fn is_compliant(&self) -> bool {
        match self {
            &Decision::Yes => true,
            &Decision::No(_) => false,
        }
    }
}

/// A prerequisite for implementing any Decider trait. It provides the
/// associated type for [`Decision`](enum.Decision.html)'s additional
/// information for negative decisions.
pub trait TypedDecider {
    /// The type for additional information on negative decisions.
    type T;
}

/// The main decision trait. It allows checking a single cell against
/// the rate-limiter, either at the current time instant, or at a
/// given instant in time, both destructively.
pub trait Decider: DeciderImpl {
    /// Tests if a single cell can be accommodated at
    /// `Instant::now()`. See [`check_at`](#method.check_at).
    fn check(&mut self) -> Result<Decision<Self::T>> {
        self.test_and_update(Instant::now())
    }

    /// Tests is a single cell can be accommodated at the given time
    /// stamp.
    fn check_at(&mut self, at: Instant) -> Result<Decision<Self::T>> {
        self.test_and_update(at)
    }
}

pub trait MultiDecider: MultiDeciderImpl {
    /// Tests if `n` cells can be accommodated at the given time
    /// stamp. An error [`ErrorKind::InsufficientCapacity`](errors/enum.ErrorKind.html) is
    /// returned if `n` exceeds the bucket capacity.
    fn check_n_at(&mut self, n: u32, at: Instant) -> Result<Decision<Self::T>> {
        self.test_n_and_update(n, at)
    }

    /// Tests if `n` cells can be accommodated at the current time
    /// (`Instant::now()`). An error [`ErrorKind::InsufficientCapacity`](errors/enum.ErrorKind.html) is
    /// returned if `n` exceeds the bucket capacity.
    fn check_n(&mut self, n: u32) -> Result<Decision<Self::T>> {
        self.test_n_and_update(n, Instant::now())
    }
}
<commit_msg>doc: Fix duplicated and incorrect text.<commit_after>//! # Leaky Bucket Rate-Limiting (as a meter) in Rust
//! This crate implements
//! the
//! [generic cell rate algorithm](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm) (GCRA)
//! for rate-limiting and scheduling in Rust.
//!
//! ## Interface
//!
//! This crate implements two "serious" rate-limiting/traffic-shaping
//! algorithms:
//! [GCRA](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm)
//! and a [Leaky
//! Bucket](https://en.wikipedia.org/wiki/Leaky_bucket#As_a_meter). An
//! "unserious" implementation is provided also, the
//! [`Allower`](example_algorithms/struct.Allower.html), which returns
//! "Yes" to all rate-limiting queries.
//!
//! The Generic Cell Rate Algorithm can be used by creating a builder
//! from the [`GCRA`](algorithms/gcra/struct.GCRA.html) struct:
//!
//! ``` rust
//! use std::time::Duration;
//! use ratelimit_meter::{Decider, GCRA, Decision};
//!
//! let mut lim = GCRA::for_capacity(50).unwrap() // Allow 50 units of work
//!     .per(Duration::from_secs(1)) // We calculate per-second (this is the default).
//!     .cell_weight(1).unwrap() // Each cell is one unit of work "heavy".
//!     .build(); // Construct a non-threadsafe GCRA decider.
//! assert_eq!(Decision::Yes, lim.check().unwrap());
//! ```
//!
//! The rate-limiter interface is intentionally geared towards only
//! providing callers with the information they need to make decisions
//! about what to do with each cell. Whenever possible, additional
//! information about why a cell should be denied - the `GCRA`
//! implementation will return a `time::Instant` alongside the decision to
//! allow callers to e.g. provide better error messages to users.
//!
//! Due to this, the `ratelimit_meter` crate does not provide any facility
//! to wait until a cell would be allowed - if you require this, you
//! should use the `Instant` returned with negative decisions and wait
//! in your own, e.g. event loop.
//!
//! ## Rate-limiting Algorithms
//!
//! ### Design and implementation of GCRA
//!
//! The GCRA limits the rate of cells by determining when the "next"
//! cell is expected to arrive; any cells that arrive before that time
//! are classified as non-conforming; the methods for checking cells
//! also return an expected arrival time for these cells, so that
//! callers can choose to wait (adding jitter), or reject the cell.
//!
//! Since using the GCRA results in a much smoother usage pattern, it
//! appears to be very useful for "outgoing" traffic behaviors,
//! e.g. throttling API call rates, or emails sent to a person in a
//! period of time.
//!
//! Unlike token or leaky bucket algorithms, the GCRA assumes that all
//! units of work are of the same "weight", and so allows some
//! optimizations which result in much more concise and fast code (it
//! does not even use multiplication or division in the "hot" path).
//!
//! See [the documentation of the GCRA type](algorithms/gcra/struct.GCRA.html) for
//! more details on its implementation and on trade-offs that apply to
//! it.
//!
//! ### Design and implementation of the leaky bucket
//!
//! In contrast to the GCRA, the leaky bucket algorithm does not place
//! any constraints on the next cell's arrival time: Whenever there is
//! capacity left in the bucket, it can be used. This means that the
//! distribution of "yes" decisions from heavy usage on the leaky
//! bucket rate-limiter will be clustered together. On average, the
//! cell rates of both the GCRA and the leaky bucket will be the same,
//! but in terms of observable behavior, the leaky bucket will appear
//! to allow requests at a more predictable rate.
//!
//! This kind of behavior is usually what people of online APIs expect
//! these days, which makes the leaky bucket a very popular technique
//! for rate-limiting on these kinds of services.
//!
//! The leaky bucket algorithm implemented in this crate is fairly
//! standard: It only updates the bucket fill gauge when a cell is
//! checked, and supports checking "batches" of cells in a single call
//! with no problems.
//!
//! ## Thread-safe operation
//!
//! None of the stateful implementations in this crate can be used
//! across threads by default. However, there is a wrapper struct
//! [`Threadsafe`](algorithms/struct.Threadsafe.html), that wraps each
//! implementation's hot path in an atomically reference-counted
//! mutex. It still manages to be pretty fast (see the benchmarks
//! above), but the lock comes with an overhead even in
//! single-threaded operation.
//!
//! Example:
//!
//! ```
//! use std::time::Duration;
//! use ratelimit_meter::{Decider, GCRA, Decision};
//!
//! let mut lim = GCRA::for_capacity(50).unwrap() // Allow 50 units of work
//!     .per(Duration::from_secs(1)) // We calculate per-second (this is the default).
//!     .cell_weight(1).unwrap() // Each cell is one unit of work "heavy".
//!     .build_sync(); // Construct a threadsafe GCRA decider.
//! assert_eq!(Decision::Yes, lim.check().unwrap());
//! ```

pub mod example_algorithms;
pub mod errors;
pub mod algorithms;
mod implementation;

#[macro_use]
extern crate error_chain;

use std::time::{Instant};

pub use errors::*;
pub use self::algorithms::*;
use implementation::*;

#[derive(PartialEq, Debug)]
/// A decision on a single cell from the metered rate-limiter.
pub enum Decision<T> {
    /// The cell is conforming, allow it through.
    Yes,

    /// The cell is non-conforming. A rate-limiting algorithm
    /// implementation may return additional information for the
    /// caller, e.g. a time when the cell was expected to arrive.
    No(T),
}

impl<T> Decision<T> {
    /// Check if a decision on a cell indicates the cell is compliant
    /// or not. Returns `true` iff the cell was compliant, i.e. the
    /// decision was `Decision::Yes`.
    ///
    /// Note: This method is mostly useful in tests.
    pub fn is_compliant(&self) -> bool {
        match self {
            &Decision::Yes => true,
            &Decision::No(_) => false,
        }
    }
}

/// A prerequisite for implementing any Decider trait. It provides the
/// associated type for [`Decision`](enum.Decision.html)'s additional
/// information for negative decisions.
pub trait TypedDecider {
    /// The type for additional information on negative decisions.
    type T;
}

/// The main decision trait. It allows checking a single cell against
/// the rate-limiter, either at the current time instant, or at a
/// given instant in time, both destructively.
pub trait Decider: DeciderImpl {
    /// Tests if a single cell can be accommodated at
    /// `Instant::now()`. See [`check_at`](#method.check_at).
    fn check(&mut self) -> Result<Decision<Self::T>> {
        self.test_and_update(Instant::now())
    }

    /// Tests is a single cell can be accommodated at the given time
    /// stamp.
    fn check_at(&mut self, at: Instant) -> Result<Decision<Self::T>> {
        self.test_and_update(at)
    }
}

pub trait MultiDecider: MultiDeciderImpl {
    /// Tests if `n` cells can be accommodated at the given time
    /// stamp. An error [`ErrorKind::InsufficientCapacity`](errors/enum.ErrorKind.html) is
    /// returned if `n` exceeds the bucket capacity.
    fn check_n_at(&mut self, n: u32, at: Instant) -> Result<Decision<Self::T>> {
        self.test_n_and_update(n, at)
    }

    /// Tests if `n` cells can be accommodated at the current time
    /// (`Instant::now()`). An error [`ErrorKind::InsufficientCapacity`](errors/enum.ErrorKind.html) is
    /// returned if `n` exceeds the bucket capacity.
    fn check_n(&mut self, n: u32) -> Result<Decision<Self::T>> {
        self.test_n_and_update(n, Instant::now())
    }
}
<|endoftext|>


<commit_before>#![crate_name = "logger"]
#![license = "MIT"]

//! Request logging middleware for Iron

#[deny(warnings)]

extern crate iron;
extern crate time;
extern crate term;
extern crate typemap;

use iron::{AfterMiddleware, BeforeMiddleware, IronResult, IronError, Request, Response, Error};
use iron::errors::FileError;
use iron::typemap::Assoc;
use term::{Terminal, WriterWrapper, stdout};

use std::io::IoResult;

use format::{Format, FormatText, Str, Method, URI, Status, ResponseTime,
             ConstantColor, FunctionColor, ConstantAttrs, FunctionAttrs};

pub mod format;

/// `Middleware` for logging request and response info to the terminal.
pub struct Logger {
    format: Option<Format>
}

impl Logger {
    /// Create a pair of `Logger` middlewares with the specified `format`. If a `None` is passed in, uses the default format:
    ///
    /// ```ignore
    /// {method} {uri} -> {status} ({response_time} ms)
    /// ```
    ///
    /// While the returned value can be passed straight to `Chain::link`, consider making the logger `BeforeMiddleware`
    /// the first in your chain and the logger `AfterMiddleware` the last by doing something like this:
    ///
    /// ```ignore
    /// let mut chain = ChainBuilder::new(handler);
    /// let (logger_before, logger_after) = Logger::new(None);
    /// chain.link_before(logger_before);
    /// // link other middlewares here...
    /// chain.link_after(logger_after);
    /// ```
    pub fn new(format: Option<Format>) -> (Logger, Logger) {
        (Logger { format: format.clone() }, Logger { format: format })
    }
}

struct StartTime;
impl Assoc<u64> for StartTime {}

impl BeforeMiddleware for Logger {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<StartTime, u64>(time::precise_time_ns());
        Ok(())
    }
}

impl AfterMiddleware for Logger {
    fn after(&self, req: &mut Request, res: &mut Response) -> IronResult<()> {
        let entry_time = *req.extensions.find::<StartTime, u64>().unwrap();
        let response_time_ms = (time::precise_time_ns() - entry_time) as f64 / 1000000.0;
        let Format(format) = self.format.clone().unwrap_or_default();

        let render = |text: &FormatText| {
            match *text {
                Str(ref string) => string.clone(),
                Method => format!("{}", req.method),
                URI => format!("{}", req.url),
                Status => format!("{}", res.status),
                ResponseTime => format!("{} ms", response_time_ms)
            }
        };

        let log = |mut t: Box<Terminal<WriterWrapper> + Send>| -> IoResult<()> {
            for unit in format.iter() {
                match unit.color {
                    ConstantColor(Some(color)) => { try!(t.fg(color)); }
                    ConstantColor(None) => (),
                    FunctionColor(f) => match f(req, res) {
                        Some(color) => { try!(t.fg(color)); }
                        None => ()
                    }
                }
                match unit.attrs {
                    ConstantAttrs(ref attrs) => {
                        for &attr in attrs.iter() {
                            try!(t.attr(attr));
                        }
                    }
                    FunctionAttrs(f) => {
                        for &attr in f(req, res).iter() {
                            try!(t.attr(attr));
                        }
                    }
                }
                try!(write!(t, "{}", render(&unit.text)));
                try!(t.reset());
            }
            try!(writeln!(t, ""));
            Ok(())
        };

        match stdout() {
            Some(terminal) => {
                match log(terminal) {
                    Err(e) => return Err(box FileError(e) as IronError),
                    _ => {}
                }
            }
            None => { return Err(box CouldNotOpenTerminal as IronError) }
        };

        Ok(())
    }
}

/// Error returned when logger cannout access stdout.
#[deriving(Show)]
pub struct CouldNotOpenTerminal;

impl Error for CouldNotOpenTerminal {
    fn name(&self) -> &'static str {
        "Could Not Open Terminal"
    }

    fn description(&self) -> Option<&str> {
        Some("Logger could not open stdout as a terminal.")
    }
}

<commit_msg>(fix) Calculate exit_time immediately.<commit_after>#![crate_name = "logger"]
#![deny(missing_docs)]
#![deny(warnings)]
#![license = "MIT"]

//! Request logging middleware for Iron

extern crate iron;
extern crate time;
extern crate term;
extern crate typemap;

use iron::{AfterMiddleware, BeforeMiddleware, IronResult, IronError, Request, Response, Error};
use iron::errors::FileError;
use iron::typemap::Assoc;
use term::{Terminal, WriterWrapper, stdout};

use std::io::IoResult;

use format::{Format, FormatText, Str, Method, URI, Status, ResponseTime,
             ConstantColor, FunctionColor, ConstantAttrs, FunctionAttrs};

pub mod format;

/// `Middleware` for logging request and response info to the terminal.
pub struct Logger {
    format: Option<Format>
}

impl Logger {
    /// Create a pair of `Logger` middlewares with the specified `format`. If a `None` is passed in, uses the default format:
    ///
    /// ```ignore
    /// {method} {uri} -> {status} ({response_time} ms)
    /// ```
    ///
    /// While the returned value can be passed straight to `Chain::link`, consider making the logger `BeforeMiddleware`
    /// the first in your chain and the logger `AfterMiddleware` the last by doing something like this:
    ///
    /// ```ignore
    /// let mut chain = ChainBuilder::new(handler);
    /// let (logger_before, logger_after) = Logger::new(None);
    /// chain.link_before(logger_before);
    /// // link other middlewares here...
    /// chain.link_after(logger_after);
    /// ```
    pub fn new(format: Option<Format>) -> (Logger, Logger) {
        (Logger { format: format.clone() }, Logger { format: format })
    }
}

struct StartTime;
impl Assoc<u64> for StartTime {}

impl BeforeMiddleware for Logger {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<StartTime, u64>(time::precise_time_ns());
        Ok(())
    }
}

impl AfterMiddleware for Logger {
    fn after(&self, req: &mut Request, res: &mut Response) -> IronResult<()> {
        let exit_time = time::precise_time_ns();
        let entry_time = *req.extensions.find::<StartTime, u64>().unwrap();

        let response_time_ms = (exit_time - entry_time) as f64 / 1000000.0;
        let Format(format) = self.format.clone().unwrap_or_default();

        let render = |text: &FormatText| {
            match *text {
                Str(ref string) => string.clone(),
                Method => format!("{}", req.method),
                URI => format!("{}", req.url),
                Status => format!("{}", res.status),
                ResponseTime => format!("{} ms", response_time_ms)
            }
        };

        let log = |mut t: Box<Terminal<WriterWrapper> + Send>| -> IoResult<()> {
            for unit in format.iter() {
                match unit.color {
                    ConstantColor(Some(color)) => { try!(t.fg(color)); }
                    ConstantColor(None) => (),
                    FunctionColor(f) => match f(req, res) {
                        Some(color) => { try!(t.fg(color)); }
                        None => ()
                    }
                }
                match unit.attrs {
                    ConstantAttrs(ref attrs) => {
                        for &attr in attrs.iter() {
                            try!(t.attr(attr));
                        }
                    }
                    FunctionAttrs(f) => {
                        for &attr in f(req, res).iter() {
                            try!(t.attr(attr));
                        }
                    }
                }
                try!(write!(t, "{}", render(&unit.text)));
                try!(t.reset());
            }
            try!(writeln!(t, ""));
            Ok(())
        };

        match stdout() {
            Some(terminal) => {
                match log(terminal) {
                    Err(e) => return Err(box FileError(e) as IronError),
                    _ => {}
                }
            }
            None => { return Err(box CouldNotOpenTerminal as IronError) }
        };

        Ok(())
    }
}

/// Error returned when logger cannout access stdout.
#[deriving(Show)]
pub struct CouldNotOpenTerminal;

impl Error for CouldNotOpenTerminal {
    fn name(&self) -> &'static str {
        "Could Not Open Terminal"
    }

    fn description(&self) -> Option<&str> {
        Some("Logger could not open stdout as a terminal.")
    }
}

<|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/logger")]
#![crate_name = "logger"]
#![license = "MIT"]

//! Request logging middleware for Iron

extern crate iron;
extern crate http;
extern crate time;
extern crate term;

use iron::{Middleware, Alloy, Request, Response, Status, Continue};
use time::precise_time_ns;
use term::{Terminal, WriterWrapper, stdout};

use std::io::IoResult;

use format::{Format, FormatText, Str, Method, URI, Status, ResponseTime,
             ConstantColor, FunctionColor, ConstantAttrs, FunctionAttrs};

pub mod format;

/// `Middleware` for logging request and response info to the terminal.
#[deriving(Clone)]
pub struct Logger {
    entry_time: u64,
    format: Option<Format>
}

impl Logger {
    /// Create a new `Logger` with the specified `format`. If a `None` is passed in, uses the default format:
    ///
    /// ```
    /// {method} {uri} -> {status} ({response_time} ms)
    /// ```
    pub fn new(format: Option<Format>) -> Logger {
        Logger { entry_time: 0u64, format: format }
    }
}

impl Middleware for Logger {
    fn enter(&mut self, _req: &mut Request, _res: &mut Response, _alloy: &mut Alloy) -> Status {
        self.entry_time = precise_time_ns();
        Continue
    }
    fn exit(&mut self, req: &mut Request, res: &mut Response, _al: &mut Alloy) -> Status {
        let response_time_ms = (precise_time_ns() - self.entry_time) as f64 / 1000000.0;
        let Format(format) = self.format.clone().unwrap_or(Format::default());

        let render = |text: &FormatText| {
            match *text {
                Str(ref string) => string.clone(),
                Method => format!("{}", req.method),
                URI => format!("{}", req.url),
                Status => format!("{}", res.status),
                ResponseTime => format!("{} ms", response_time_ms)
            }
        };
        let log = |mut t: Box<Terminal<WriterWrapper> + Send>| -> IoResult<()> {
            for unit in format.iter() {
                match unit.color {
                    ConstantColor(Some(color)) => { try!(t.fg(color)); }
                    ConstantColor(None) => (),
                    FunctionColor(f) => match f(req, res) {
                        Some(color) => { try!(t.fg(color)); }
                        None => ()
                    }
                }
                match unit.attrs {
                    ConstantAttrs(ref attrs) => {
                        for &attr in attrs.iter() {
                            try!(t.attr(attr));
                        }
                    }
                    FunctionAttrs(f) => {
                        for &attr in f(req, res).iter() {
                            try!(t.attr(attr));
                        }
                    }
                }
                try!(write!(t, "{}", render(&unit.text)));
                try!(t.reset());
            }
            try!(writeln!(t, ""));
            Ok(())
        };

        match stdout() {
            Some(terminal) => {
                match log(terminal) {
                    Err(e) => { println!("Error logging to terminal: {}", e); },
                    Ok(_) => ()
                }
            }
            None => { println!("Logger could not open terminal"); }
        }
        Continue
    }
}
<commit_msg>(fix) Updated for Alloy move.<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/logger")]
#![crate_name = "logger"]
#![license = "MIT"]

//! Request logging middleware for Iron

extern crate iron;
extern crate http;
extern crate time;
extern crate term;

use iron::{Middleware, Request, Response, Status, Continue};
use time::precise_time_ns;
use term::{Terminal, WriterWrapper, stdout};

use std::io::IoResult;

use format::{Format, FormatText, Str, Method, URI, Status, ResponseTime,
             ConstantColor, FunctionColor, ConstantAttrs, FunctionAttrs};

pub mod format;

/// `Middleware` for logging request and response info to the terminal.
#[deriving(Clone)]
pub struct Logger {
    entry_time: u64,
    format: Option<Format>
}

impl Logger {
    /// Create a new `Logger` with the specified `format`. If a `None` is passed in, uses the default format:
    ///
    /// ```
    /// {method} {uri} -> {status} ({response_time} ms)
    /// ```
    pub fn new(format: Option<Format>) -> Logger {
        Logger { entry_time: 0u64, format: format }
    }
}

impl Middleware for Logger {
    fn enter(&mut self, _: &mut Request, _: &mut Response) -> Status {
        self.entry_time = precise_time_ns();
        Continue
    }
    fn exit(&mut self, req: &mut Request, res: &mut Response) -> Status {
        let response_time_ms = (precise_time_ns() - self.entry_time) as f64 / 1000000.0;
        let Format(format) = self.format.clone().unwrap_or(Format::default());

        let render = |text: &FormatText| {
            match *text {
                Str(ref string) => string.clone(),
                Method => format!("{}", req.method),
                URI => format!("{}", req.url),
                Status => format!("{}", res.status),
                ResponseTime => format!("{} ms", response_time_ms)
            }
        };
        let log = |mut t: Box<Terminal<WriterWrapper> + Send>| -> IoResult<()> {
            for unit in format.iter() {
                match unit.color {
                    ConstantColor(Some(color)) => { try!(t.fg(color)); }
                    ConstantColor(None) => (),
                    FunctionColor(f) => match f(req, res) {
                        Some(color) => { try!(t.fg(color)); }
                        None => ()
                    }
                }
                match unit.attrs {
                    ConstantAttrs(ref attrs) => {
                        for &attr in attrs.iter() {
                            try!(t.attr(attr));
                        }
                    }
                    FunctionAttrs(f) => {
                        for &attr in f(req, res).iter() {
                            try!(t.attr(attr));
                        }
                    }
                }
                try!(write!(t, "{}", render(&unit.text)));
                try!(t.reset());
            }
            try!(writeln!(t, ""));
            Ok(())
        };

        match stdout() {
            Some(terminal) => {
                match log(terminal) {
                    Err(e) => { println!("Error logging to terminal: {}", e); },
                    Ok(_) => ()
                }
            }
            None => { println!("Logger could not open terminal"); }
        }
        Continue
    }
}
<|endoftext|>


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

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

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

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

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

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

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

type Err = Box<Error>;
type ERes<T> = Result<T, Err>;

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

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

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

    fn take(&mut self) -> ERes<char> {
        let c = try!(self.peek());
        try!(self.next());
        Ok(c)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Parse Error {}:{}: {}", self.line, self.lpos, self.msg)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Parse Error {}:{}: {}", self.line, self.lpos, self.msg)
    }
}

impl fmt::Display for Atom {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
      Atom::S(ref s) => write!(f, "{}", s),
      Atom::Q(ref s) => write!(f, "\"{}\"", s),
      Atom::I(i)     => write!(f, "{}", i),
      Atom::F(d)     => write!(f, "{}", d),
    }
  }
}

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

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

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

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

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

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

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

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

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

pub fn parse_str(s: &str) -> Sexp {
    parse(s).unwrap()
}

pub fn parse_file(name: &str) -> Sexp {
    let s = read_file(name).unwrap();
    parse(&s[..]).unwrap()
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    #[test]
    #[should_panic(expected="Parse Error 1:6: end of document reached")]
    fn test_invalid3() { parse_str("\"hello"); }
}
<commit_msg>add complex test<commit_after>// (c) 2015 Joost Yervante Damad <joost@damad.be>

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

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

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

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

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

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

type Err = Box<Error>;
type ERes<T> = Result<T, Err>;

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

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

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

    fn take(&mut self) -> ERes<char> {
        let c = try!(self.peek());
        try!(self.next());
        Ok(c)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Parse Error {}:{}: {}", self.line, self.lpos, self.msg)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Parse Error {}:{}: {}", self.line, self.lpos, self.msg)
    }
}

impl fmt::Display for Atom {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
      Atom::S(ref s) => write!(f, "{}", s),
      Atom::Q(ref s) => write!(f, "\"{}\"", s),
      Atom::I(i)     => write!(f, "{}", i),
      Atom::F(d)     => write!(f, "{}", d),
    }
  }
}

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

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

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

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

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

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

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

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

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

pub fn parse_str(s: &str) -> Sexp {
    parse(s).unwrap()
}

pub fn parse_file(name: &str) -> Sexp {
    let s = read_file(name).unwrap();
    parse(&s[..]).unwrap()
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


<commit_before>extern crate curl;

use std::str;
use curl::http;

mod util;

pub struct Firebase {
    base_uri: String,
}

impl Firebase {
    pub fn new(base_uri: &str) -> Self {
        Firebase {
            base_uri: base_uri.to_string(),
        }
    }

    pub fn authenticated(base_uri: &str, auth_token: &str) -> Self {
        let uri = util::trim_right(base_uri, "/");
        Firebase {
            base_uri: format!("{}?auth={}", uri, auth_token),
        }
    }

    pub fn at(&self, path: &str) -> Self {
        let mut components = self.base_uri.split('?');

        let base = components.next().unwrap();
        let base = util::trim_right(base, ".json");
        let path = util::trim_right(path, "/");
        let path = util::add_right(path, ".json");
        let url  = util::join(base, &path, "/");

        let url = if let Some(args) = components.next() {
            url + "?" + args
        } else {
            url
        };

        Firebase {
            base_uri: url,
        }
    }

    pub fn get(&self) -> Response {
        self.request(Method::GET, None)
    }

    fn get_params(&self, params: String) -> Response {
        let url = if self.base_uri.find("?").is_some() {
            format!("{}&{}", &self.base_uri, params)
        } else {
            format!("{}?{}", &self.base_uri, params)
        };

        Firebase::request_url(&url, Method::GET, None)
    }

    pub fn set(&self, data: &str) -> Response {
        self.request(Method::PUT, Some(data))
    }

    pub fn push(&self, data: &str) -> Response {
        self.request(Method::POST, Some(data))
    }

    pub fn update(&self, data: &str) -> Response {
        self.request(Method::PATCH, Some(data))
    }

    pub fn delete(&self) -> Response {
        self.request(Method::DELETE, None)
    }

    fn request(&self, method: Method, data: Option<&str>) -> Response {
        Firebase::request_url(&self.base_uri, method, data)
    }

    fn request_url(url: &str, method: Method, data: Option<&str>) -> Response {
        let mut handler = http::handle();

        let req = match method {
            Method::GET     => handler.get(url),
            Method::POST    => handler.post(url, data.unwrap()),
            Method::PUT     => handler.put(url, data.unwrap()),
            Method::PATCH   => handler.patch(url, data.unwrap()),
            Method::DELETE  => handler.delete(url)
        };
        let res = req.exec().unwrap();

        let body = match str::from_utf8(res.get_body()) {
            Ok(b) => b,
            Err(_) => "Unable to parse"
        };

        Response {
            body: body.to_string(),
            code: res.get_code(),
        }
    }

    pub fn get_url(&self) -> &str {
        return &self.base_uri;
    }

    pub fn orderBy(&self, key: &str) -> ParamsRequest {
        self.params_request(orderByStr(key))
    }

    pub fn limitToFirst(&self, count: u32) -> ParamsRequest {
        self.params_request(limitToFirstStr(count))
    }

    pub fn limitToLast(&self, count: u32) -> ParamsRequest {
        self.params_request(limitToLastStr(count))
    }

    pub fn startAt(&self, index: u32) -> ParamsRequest {
        self.params_request(startAtStr(index))
    }

    pub fn endAt(&self, index: u32) -> ParamsRequest {
        self.params_request(endAtStr(index))
    }

    pub fn equalTo(&self, value: u32) -> ParamsRequest {
        self.params_request(equalToStr(value))
    }

    pub fn shallow(&self, flag: bool) -> ParamsRequest {
        self.params_request(shallowStr(flag))
    }

    fn params_request(&self, param: String) -> ParamsRequest {
        ParamsRequest {
            firebase: &self,
            params: vec![param],
        }
    }
}

pub struct ParamsRequest<'l> {
    firebase: &'l Firebase,
    params: Vec<String>,
}

impl<'l> ParamsRequest<'l> {
    pub fn orderBy(&mut self, key: &str) -> &Self {
        self.params.push(orderByStr(key));
        self
    }

    pub fn limitToFirst(&mut self, count: u32) -> &Self {
        self.params.push(limitToFirstStr(count));
        self
    }

    pub fn limitToLast(&mut self, count: u32) -> &Self {
        self.params.push(limitToLastStr(count));
        self
    }

    pub fn startAt(&mut self, index: u32) -> &Self {
        self.params.push(startAtStr(index));
        self
    }

    pub fn endAt(&mut self, index: u32) -> &Self {
        self.params.push(endAtStr(index));
        self
    }

    pub fn equalTo(&mut self, value: u32) -> &Self {
        self.params.push(equalToStr(value));
        self
    }

    pub fn shallow(&mut self, flag: bool) -> &Self {
        self.params.push(shallowStr(flag));
        self
    }

    pub fn get(&self) -> Response {
        Firebase::get_params(self.firebase, self.params.connect("&"))
    }
}

fn orderByStr(key: &str) -> String {
    format!("orderBy={}", key)
}

fn limitToFirstStr(count: u32) -> String {
    format!("limitToFirst={}", count)
}

fn limitToLastStr(count: u32) -> String {
    format!("limitToLast={}", count)
}

fn startAtStr(index: u32) -> String {
    format!("startAt={}", index)
}

fn endAtStr(index: u32) -> String {
    format!("endAt={}", index)
}

fn equalToStr(value: u32) -> String {
    format!("equalTo={}", value)
}

fn shallowStr(flag: bool) -> String {
    format!("shallow={}", flag)
}

enum Method {
    GET,
    POST,
    PUT,
    PATCH,
    DELETE,
}

pub struct Response {
    pub body: String,
    pub code: u32,
}

impl Response {
    pub fn is_success(&self) -> bool {
        self.code < 400
    }
}
<commit_msg>fixed rust style warnings<commit_after>extern crate curl;

use std::str;
use curl::http;

mod util;

pub struct Firebase {
    base_uri: String,
}

impl Firebase {
    pub fn new(base_uri: &str) -> Self {
        Firebase {
            base_uri: base_uri.to_string(),
        }
    }

    pub fn authenticated(base_uri: &str, auth_token: &str) -> Self {
        let uri = util::trim_right(base_uri, "/");
        Firebase {
            base_uri: format!("{}?auth={}", uri, auth_token),
        }
    }

    pub fn at(&self, path: &str) -> Self {
        let mut components = self.base_uri.split('?');

        let base = components.next().unwrap();
        let base = util::trim_right(base, ".json");
        let path = util::trim_right(path, "/");
        let path = util::add_right(path, ".json");
        let url  = util::join(base, &path, "/");

        let url = if let Some(args) = components.next() {
            url + "?" + args
        } else {
            url
        };

        Firebase {
            base_uri: url,
        }
    }

    pub fn get(&self) -> Response {
        self.request(Method::GET, None)
    }

    fn get_params(&self, params: String) -> Response {
        let url = if self.base_uri.find("?").is_some() {
            format!("{}&{}", &self.base_uri, params)
        } else {
            format!("{}?{}", &self.base_uri, params)
        };

        Firebase::request_url(&url, Method::GET, None)
    }

    pub fn set(&self, data: &str) -> Response {
        self.request(Method::PUT, Some(data))
    }

    pub fn push(&self, data: &str) -> Response {
        self.request(Method::POST, Some(data))
    }

    pub fn update(&self, data: &str) -> Response {
        self.request(Method::PATCH, Some(data))
    }

    pub fn delete(&self) -> Response {
        self.request(Method::DELETE, None)
    }

    fn request(&self, method: Method, data: Option<&str>) -> Response {
        Firebase::request_url(&self.base_uri, method, data)
    }

    fn request_url(url: &str, method: Method, data: Option<&str>) -> Response {
        let mut handler = http::handle();

        let req = match method {
            Method::GET     => handler.get(url),
            Method::POST    => handler.post(url, data.unwrap()),
            Method::PUT     => handler.put(url, data.unwrap()),
            Method::PATCH   => handler.patch(url, data.unwrap()),
            Method::DELETE  => handler.delete(url)
        };
        let res = req.exec().unwrap();

        let body = match str::from_utf8(res.get_body()) {
            Ok(b) => b,
            Err(_) => "Unable to parse"
        };

        Response {
            body: body.to_string(),
            code: res.get_code(),
        }
    }

    pub fn get_url(&self) -> &str {
        return &self.base_uri;
    }

    pub fn order_by(&self, key: &str) -> ParamsRequest {
        self.params_request(order_by_str(key))
    }

    pub fn limit_to_first(&self, count: u32) -> ParamsRequest {
        self.params_request(limit_to_first_str(count))
    }

    pub fn limit_to_last(&self, count: u32) -> ParamsRequest {
        self.params_request(limit_to_last_str(count))
    }

    pub fn start_at(&self, index: u32) -> ParamsRequest {
        self.params_request(start_at_str(index))
    }

    pub fn end_at(&self, index: u32) -> ParamsRequest {
        self.params_request(end_at_str(index))
    }

    pub fn equal_to(&self, value: u32) -> ParamsRequest {
        self.params_request(equal_to_str(value))
    }

    pub fn shallow(&self, flag: bool) -> ParamsRequest {
        self.params_request(shallow_str(flag))
    }

    fn params_request(&self, param: String) -> ParamsRequest {
        ParamsRequest {
            firebase: &self,
            params: vec![param],
        }
    }
}

pub struct ParamsRequest<'l> {
    firebase: &'l Firebase,
    params: Vec<String>,
}

impl<'l> ParamsRequest<'l> {
    pub fn order_by(&mut self, key: &str) -> &Self {
        self.params.push(order_by_str(key));
        self
    }

    pub fn limit_to_first(&mut self, count: u32) -> &Self {
        self.params.push(limit_to_first_str(count));
        self
    }

    pub fn limit_to_last(&mut self, count: u32) -> &Self {
        self.params.push(limit_to_last_str(count));
        self
    }

    pub fn start_at(&mut self, index: u32) -> &Self {
        self.params.push(start_at_str(index));
        self
    }

    pub fn end_at(&mut self, index: u32) -> &Self {
        self.params.push(end_at_str(index));
        self
    }

    pub fn equal_to(&mut self, value: u32) -> &Self {
        self.params.push(equal_to_str(value));
        self
    }

    pub fn shallow(&mut self, flag: bool) -> &Self {
        self.params.push(shallow_str(flag));
        self
    }

    pub fn get(&self) -> Response {
        Firebase::get_params(self.firebase, self.params.connect("&"))
    }
}

fn order_by_str(key: &str) -> String {
    format!("order_by={}", key)
}

fn limit_to_first_str(count: u32) -> String {
    format!("limit_to_first={}", count)
}

fn limit_to_last_str(count: u32) -> String {
    format!("limit_to_last={}", count)
}

fn start_at_str(index: u32) -> String {
    format!("start_at={}", index)
}

fn end_at_str(index: u32) -> String {
    format!("end_at={}", index)
}

fn equal_to_str(value: u32) -> String {
    format!("equal_to={}", value)
}

fn shallow_str(flag: bool) -> String {
    format!("shallow={}", flag)
}

enum Method {
    GET,
    POST,
    PUT,
    PATCH,
    DELETE,
}

pub struct Response {
    pub body: String,
    pub code: u32,
}

impl Response {
    pub fn is_success(&self) -> bool {
        self.code < 400
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs,
missing_debug_implementations, missing_copy_implementations,
trivial_casts, trivial_numeric_casts,
unsafe_code,
unstable_features,
unused_import_braces, unused_qualifications)]

#![doc(html_root_url = "https://cannon10100.github.io/factor_graph/")]

//! Crate allowing creation and manipulation of probabilistic factor graphs.

extern crate dot;

mod render;
mod variable;
mod factor;

use std::collections::HashMap;
use std::io::Write;

use variable::{Variable, DiscreteVariable};
use factor::Factor;

type PotentialFunc = fn(&[u32]) -> i32;

/// Trait representing a generic item stored in the factor graph.
pub trait FactorGraphItem : std::fmt::Debug {
    /// Get the name of this item
    fn get_name(&self) -> String;

    /// Return whether the item is a factor
    fn is_factor(&self) -> bool;
}

/// Struct representing the full factor graph.
#[derive(Debug)]
pub struct FactorGraph {
    variables: HashMap<String, Box<Variable>>,
    factors: Vec<Factor>,
    all_items: Vec<Box<FactorGraphItem>>,
    next_id: u32,
}

impl FactorGraph {
    /// Create an empty FactorGraph
    pub fn new() -> FactorGraph {
        FactorGraph {
            variables: HashMap::new(),
            factors: vec!(),
            all_items: vec!(),
            next_id: 0
        }
    }

    /// Add a new variable with the specified name to the factor graph.
    pub fn add_discrete_var<T : std::fmt::Debug + Clone + 'static>(&mut self, name: &str, val_names: Vec<T>) {
        self.variables.insert(String::from(name),
                              Box::new(DiscreteVariable::new(self.next_id,name, val_names.clone())));
        self.all_items.insert(self.next_id as usize,
                              Box::new(DiscreteVariable::new(self.next_id,name, val_names)));
        self.next_id += 1;
    }

    /// Add a new factor with the specified variables to the factor graph.
    pub fn add_factor(&mut self, variables: Vec<String>, func: PotentialFunc) {
        for var in variables.iter() {
            match self.variables.get_mut(var) {
                Some(var_obj) => var_obj.add_factor(
                    Factor::new(self.next_id,variables.clone(), func)),
                None => panic!("The variable {} was not found in the factor graph.", var)
            }
        }

        self.factors.push(Factor::new(self.next_id, variables.clone(), func));
        self.all_items.insert(self.next_id as usize,
                              Box::new(
                                  Factor::new(self.next_id, variables.clone(), func)));
        self.next_id += 1;
    }

    /// Render this graph to a Graphviz file
    pub fn render_to<W: Write>(&self, output: &mut W) {
        match dot::render(self, output) {
            Ok(_) => println!("Wrote factor graph"),
            Err(_) => panic!("An error occurred writing the factor graph"),
        }
    }
}

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

    fn dummy_func(args: &[u32]) -> i32 {
        args.len() as i32
    }

    #[test]
    #[should_panic]
    fn factor_with_nonexistent_var() {
        let mut graph = FactorGraph::new();

        graph.add_discrete_var("first", vec![1, 2]);
        graph.add_factor(vec!(String::from("second")), dummy_func);
    }

    #[test]
    fn factor_is_added_to_var() {
        let mut graph = FactorGraph::new();

        graph.add_discrete_var("first", vec![1, 2]);
        graph.add_factor(vec!(String::from("first")), dummy_func);

        assert_eq!(graph.variables.get("first").unwrap().get_factors()[0].get_variables(),
                   graph.factors[0].get_variables())
    }
}
<commit_msg>Re-exported appropriate submodules<commit_after>#![deny(missing_docs,
missing_debug_implementations, missing_copy_implementations,
trivial_casts, trivial_numeric_casts,
unsafe_code,
unstable_features,
unused_import_braces, unused_qualifications)]

#![doc(html_root_url = "https://cannon10100.github.io/factor_graph/")]

//! Crate allowing creation and manipulation of probabilistic factor graphs.

extern crate dot;

mod render;
pub mod variable;
pub mod factor;

use std::collections::HashMap;
use std::io::Write;

pub use variable::{Variable, DiscreteVariable};
pub use factor::Factor;

type PotentialFunc = fn(&[u32]) -> i32;

/// Trait representing a generic item stored in the factor graph.
pub trait FactorGraphItem : std::fmt::Debug {
    /// Get the name of this item
    fn get_name(&self) -> String;

    /// Return whether the item is a factor
    fn is_factor(&self) -> bool;
}

/// Struct representing the full factor graph.
#[derive(Debug)]
pub struct FactorGraph {
    variables: HashMap<String, Box<Variable>>,
    factors: Vec<Factor>,
    all_items: Vec<Box<FactorGraphItem>>,
    next_id: u32,
}

impl FactorGraph {
    /// Create an empty FactorGraph
    pub fn new() -> FactorGraph {
        FactorGraph {
            variables: HashMap::new(),
            factors: vec!(),
            all_items: vec!(),
            next_id: 0
        }
    }

    /// Add a new variable with the specified name to the factor graph.
    pub fn add_discrete_var<T : std::fmt::Debug + Clone + 'static>(&mut self, name: &str, val_names: Vec<T>) {
        self.variables.insert(String::from(name),
                              Box::new(DiscreteVariable::new(self.next_id,name, val_names.clone())));
        self.all_items.insert(self.next_id as usize,
                              Box::new(DiscreteVariable::new(self.next_id,name, val_names)));
        self.next_id += 1;
    }

    /// Add a new factor with the specified variables to the factor graph.
    pub fn add_factor(&mut self, variables: Vec<String>, func: PotentialFunc) {
        for var in variables.iter() {
            match self.variables.get_mut(var) {
                Some(var_obj) => var_obj.add_factor(
                    Factor::new(self.next_id,variables.clone(), func)),
                None => panic!("The variable {} was not found in the factor graph.", var)
            }
        }

        self.factors.push(Factor::new(self.next_id, variables.clone(), func));
        self.all_items.insert(self.next_id as usize,
                              Box::new(
                                  Factor::new(self.next_id, variables.clone(), func)));
        self.next_id += 1;
    }

    /// Render this graph to a Graphviz file
    pub fn render_to<W: Write>(&self, output: &mut W) {
        match dot::render(self, output) {
            Ok(_) => println!("Wrote factor graph"),
            Err(_) => panic!("An error occurred writing the factor graph"),
        }
    }
}

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

    fn dummy_func(args: &[u32]) -> i32 {
        args.len() as i32
    }

    #[test]
    #[should_panic]
    fn factor_with_nonexistent_var() {
        let mut graph = FactorGraph::new();

        graph.add_discrete_var("first", vec![1, 2]);
        graph.add_factor(vec!(String::from("second")), dummy_func);
    }

    #[test]
    fn factor_is_added_to_var() {
        let mut graph = FactorGraph::new();

        graph.add_discrete_var("first", vec![1, 2]);
        graph.add_factor(vec!(String::from("first")), dummy_func);

        assert_eq!(graph.variables.get("first").unwrap().get_factors()[0].get_variables(),
                   graph.factors[0].get_variables())
    }
}
<|endoftext|>