<commit_before>#[macro_use]
extern crate pest;
#[macro_use]
extern crate pest_derive;

#[cfg(debug_assertions)]
const _GRAMMER: &'static str = include_str!("grammer.pest");

#[derive(Parser)]
#[grammar = "grammer.pest"]
struct TurtleParser;

#[test]
fn blank_node_property_list_test() {
    parses_to! {
        parser: TurtleParser,
        input: "[<http://verb> <http://object1>, <http://object2>; a <http://object3>]",
        rule: Rule::blank_node_property_list,
        tokens: [
            blank_node_property_list(0, 70, [
                predicate_object_list(1, 69, [
                    verb(1, 14, [ predicate(1, 14, [ iri(1, 14, [ iriref(1, 14)]) ]) ]),
                    object_list(15, 49, [
                        object(15, 31, [ iri(15, 31, [ iriref(15, 31)]) ]),
                        object(33, 49, [ iri(33, 49, [ iriref(33, 49)]) ])
                    ]),
                    verb(51, 52),
                    object_list(53, 69, [
                        object(53, 69, [ iri(53, 69, [ iriref(53, 69)]) ])
                    ])
                ])
            ])
        ]
    };
}

#[test]
fn collection_test() {
    parses_to! {
        parser: TurtleParser,
        input: "(<http://www.example.com> ([ ]))",
        rule: Rule::collection,
        tokens: [
            collection(0, 32, [
                object(1, 25, [
                    iri(1, 25, [ iriref(1, 25) ])
                ]),
                object(26, 31, [
                    collection(26, 31, [
                        object(27, 30, [ blank_node(27, 30, [ anon(27, 30) ]) ])
                    ])
                ])
            ])
        ]
    };
}

#[test]
fn numeric_literal_test() {
    parses_to! {
        parser: TurtleParser,
        input: "+10",
        rule: Rule::numeric_literal,
        tokens: [
            numeric_literal(0, 3, [
                integer(0, 3)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "+1.0",
        rule: Rule::numeric_literal,
        tokens: [
            numeric_literal(0, 4, [
                decimal(0, 4)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "+1.0e-9",
        rule: Rule::numeric_literal,
        tokens: [
            numeric_literal(0, 7, [
                double(0, 7)
            ])
        ]
    };
}

#[test]
fn rdf_literal_test() {
    parses_to! {
        parser: TurtleParser,
        input: r#""test"@en"#,
        rule: Rule::rdf_literal,
        tokens: [
            rdf_literal(0, 9, [
                string(0, 6, [
                    string_literal_quote(0, 6)
                ]),
                langtag(6, 9)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#""test"^^<http://www.example.com>"#,
        rule: Rule::rdf_literal,
        tokens: [
            rdf_literal(0, 32, [
                string(0, 6, [
                    string_literal_quote(0, 6)
                ]),
                iri(8, 32, [
                    iriref(8, 32)
                ])
            ])
        ]
    };
}

#[test]
fn boolean_literal_test() {
    parses_to! {
        parser: TurtleParser,
        input: "true",
        rule: Rule::boolean_literal,
        tokens: [
            boolean_literal(0, 4)
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "false",
        rule: Rule::boolean_literal,
        tokens: [
            boolean_literal(0, 5)
        ]
    };
}

#[test]
fn string_test() {
    parses_to! {
        parser: TurtleParser,
        input: r#""test""#,
        rule: Rule::string,
        tokens: [
            string(0, 6, [
                string_literal_quote(0, 6)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#"'test'"#,
        rule: Rule::string,
        tokens: [
            string(0, 6, [
                string_literal_single_quote(0, 6)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#""""test"test""""#,
        rule: Rule::string,
        tokens: [
            string(0, 15, [
                string_literal_long_quote(0, 15)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#"'''test'test'''"#,
        rule: Rule::string,
        tokens: [
            string(0, 15, [
                string_literal_long_single_quote(0, 15)
            ])
        ]
    };
}

#[test]
fn iri_test() {
    parses_to! {
        parser: TurtleParser,
        input: "<http://www.example.com>",
        rule: Rule::iri,
        tokens: [
            iri(0, 24, [
                iriref(0, 24)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "foaf:Person",
        rule: Rule::iri,
        tokens: [
            iri(0, 11, [
                prefixed_name(0, 11, [
                    pname_ln(0, 11)
                ])
            ])
        ]
    };
}

#[test]
fn prefixd_name_test() {
    parses_to! {
        parser: TurtleParser,
        input: "foaf:",
        rule: Rule::prefixed_name,
        tokens: [
            prefixed_name(0, 5, [
                pname_ns(0, 5)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "foaf:Person",
        rule: Rule::prefixed_name,
        tokens: [
            prefixed_name(0, 11, [
                pname_ln(0, 11)
            ])
        ]
    };
}

#[test]
fn blank_node_test() {
    parses_to! {
        parser: TurtleParser,
        input: "_:blank",
        rule: Rule::blank_node,
        tokens: [
            blank_node(0, 7, [
                blank_node_label(0, 7)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "[     ]",
        rule: Rule::blank_node,
        tokens: [
            blank_node(0, 7, [
                anon(0, 7)
            ])
        ]
    };
}
<commit_msg>Add literal_test<commit_after>#[macro_use]
extern crate pest;
#[macro_use]
extern crate pest_derive;

#[cfg(debug_assertions)]
const _GRAMMER: &'static str = include_str!("grammer.pest");

#[derive(Parser)]
#[grammar = "grammer.pest"]
struct TurtleParser;

#[test]
fn literal_test() {
    parses_to! {
        parser: TurtleParser,
        input: r#""test"@en"#,
        rule: Rule::literal,
        tokens: [
            literal(0, 9, [
                rdf_literal(0, 9, [
                    string(0, 6, [
                        string_literal_quote(0, 6)
                    ]),
                    langtag(6, 9)
                ])
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "+10",
        rule: Rule::literal,
        tokens: [
            literal(0, 3, [
                numeric_literal(0, 3, [
                    integer(0, 3)
                ])
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "true",
        rule: Rule::literal,
        tokens: [
            literal(0, 4, [
                boolean_literal(0, 4)
            ])
        ]
    };
}

#[test]
fn blank_node_property_list_test() {
    parses_to! {
        parser: TurtleParser,
        input: "[<http://verb> <http://object1>, <http://object2>; a <http://object3>]",
        rule: Rule::blank_node_property_list,
        tokens: [
            blank_node_property_list(0, 70, [
                predicate_object_list(1, 69, [
                    verb(1, 14, [ predicate(1, 14, [ iri(1, 14, [ iriref(1, 14)]) ]) ]),
                    object_list(15, 49, [
                        object(15, 31, [ iri(15, 31, [ iriref(15, 31)]) ]),
                        object(33, 49, [ iri(33, 49, [ iriref(33, 49)]) ])
                    ]),
                    verb(51, 52),
                    object_list(53, 69, [
                        object(53, 69, [ iri(53, 69, [ iriref(53, 69)]) ])
                    ])
                ])
            ])
        ]
    };
}

#[test]
fn collection_test() {
    parses_to! {
        parser: TurtleParser,
        input: "(<http://www.example.com> ([ ]))",
        rule: Rule::collection,
        tokens: [
            collection(0, 32, [
                object(1, 25, [
                    iri(1, 25, [ iriref(1, 25) ])
                ]),
                object(26, 31, [
                    collection(26, 31, [
                        object(27, 30, [ blank_node(27, 30, [ anon(27, 30) ]) ])
                    ])
                ])
            ])
        ]
    };
}

#[test]
fn numeric_literal_test() {
    parses_to! {
        parser: TurtleParser,
        input: "+10",
        rule: Rule::numeric_literal,
        tokens: [
            numeric_literal(0, 3, [
                integer(0, 3)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "+1.0",
        rule: Rule::numeric_literal,
        tokens: [
            numeric_literal(0, 4, [
                decimal(0, 4)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "+1.0e-9",
        rule: Rule::numeric_literal,
        tokens: [
            numeric_literal(0, 7, [
                double(0, 7)
            ])
        ]
    };
}

#[test]
fn rdf_literal_test() {
    parses_to! {
        parser: TurtleParser,
        input: r#""test"@en"#,
        rule: Rule::rdf_literal,
        tokens: [
            rdf_literal(0, 9, [
                string(0, 6, [
                    string_literal_quote(0, 6)
                ]),
                langtag(6, 9)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#""test"^^<http://www.example.com>"#,
        rule: Rule::rdf_literal,
        tokens: [
            rdf_literal(0, 32, [
                string(0, 6, [
                    string_literal_quote(0, 6)
                ]),
                iri(8, 32, [
                    iriref(8, 32)
                ])
            ])
        ]
    };
}

#[test]
fn boolean_literal_test() {
    parses_to! {
        parser: TurtleParser,
        input: "true",
        rule: Rule::boolean_literal,
        tokens: [
            boolean_literal(0, 4)
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "false",
        rule: Rule::boolean_literal,
        tokens: [
            boolean_literal(0, 5)
        ]
    };
}

#[test]
fn string_test() {
    parses_to! {
        parser: TurtleParser,
        input: r#""test""#,
        rule: Rule::string,
        tokens: [
            string(0, 6, [
                string_literal_quote(0, 6)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#"'test'"#,
        rule: Rule::string,
        tokens: [
            string(0, 6, [
                string_literal_single_quote(0, 6)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#""""test"test""""#,
        rule: Rule::string,
        tokens: [
            string(0, 15, [
                string_literal_long_quote(0, 15)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: r#"'''test'test'''"#,
        rule: Rule::string,
        tokens: [
            string(0, 15, [
                string_literal_long_single_quote(0, 15)
            ])
        ]
    };
}

#[test]
fn iri_test() {
    parses_to! {
        parser: TurtleParser,
        input: "<http://www.example.com>",
        rule: Rule::iri,
        tokens: [
            iri(0, 24, [
                iriref(0, 24)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "foaf:Person",
        rule: Rule::iri,
        tokens: [
            iri(0, 11, [
                prefixed_name(0, 11, [
                    pname_ln(0, 11)
                ])
            ])
        ]
    };
}

#[test]
fn prefixd_name_test() {
    parses_to! {
        parser: TurtleParser,
        input: "foaf:",
        rule: Rule::prefixed_name,
        tokens: [
            prefixed_name(0, 5, [
                pname_ns(0, 5)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "foaf:Person",
        rule: Rule::prefixed_name,
        tokens: [
            prefixed_name(0, 11, [
                pname_ln(0, 11)
            ])
        ]
    };
}

#[test]
fn blank_node_test() {
    parses_to! {
        parser: TurtleParser,
        input: "_:blank",
        rule: Rule::blank_node,
        tokens: [
            blank_node(0, 7, [
                blank_node_label(0, 7)
            ])
        ]
    };

    parses_to! {
        parser: TurtleParser,
        input: "[     ]",
        rule: Rule::blank_node,
        tokens: [
            blank_node(0, 7, [
                anon(0, 7)
            ])
        ]
    };
}
<|endoftext|>


<commit_before>#![crate_name="postgres_macros"]
#![crate_type="dylib"]
#![feature(plugin_registrar)]

extern crate libc;
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use std::c_str::CString;
use std::mem;
use std::gc::Gc;
use syntax::ast::{TokenTree, ExprLit, LitStr, Expr, Ident};
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::parse::token;
use syntax::parse::token::{InternedString, COMMA, EOF};
use syntax::parse;
use syntax::parse::parser::Parser;

mod ffi {
    use libc::{c_char, c_int};

    #[repr(C)]
    pub struct ParseResult {
        pub success: c_int,
        pub error_message: *const c_char,
        pub index: c_int,
        pub num_params: c_int,
    }

    #[link(name="parser", kind="static")]
    extern {
        pub fn init_parser();
        pub fn parse_query(query: *const c_char, result: *mut ParseResult);
    }
}

struct ParseInfo {
    num_params: uint,
}

struct ParseError {
    message: CString,
    index: uint,
}

#[plugin_registrar]
#[doc(hidden)]
pub fn registrar(reg: &mut Registry) {
    reg.register_macro("sql", expand_sql);
    reg.register_macro("execute", expand_execute);
    unsafe { ffi::init_parser() }
}

fn expand_sql(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
              -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                Vec::from_slice(tts));

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp)
    };

    match parse(query.get()) {
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    MacExpr::new(query_expr)
}

fn expand_execute(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                  -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                Vec::from_slice(tts));

    let conn = parser.parse_expr();

    if !parser.eat(&COMMA) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp),
    };

    if !parser.eat(&COMMA) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let args = match parse_args(cx, &mut parser) {
        Some(args) => args,
        None => return DummyResult::expr(sp),
    };

    match parse(query.get()) {
        Ok(ref info) if info.num_params != args.len() =>
            cx.span_err(sp, format!("Expected {} query parameters but got {}",
                                    info.num_params, args.len()).as_slice()),
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    let ident = Ident::new(token::intern("execute"));
    let args = cx.expr_vec(sp, args);
    MacExpr::new(cx.expr_method_call(sp, conn, ident, vec![query_expr, args]))
}

fn parse_error(cx: &mut ExtCtxt, sp: Span, err: ParseError) {
    cx.span_err(sp, format!("Invalid syntax at position {}: {}",
                            err.index,
                            err.message.as_str().unwrap()).as_slice());
}

fn parse_str_lit(cx: &mut ExtCtxt, e: &Expr) -> Option<InternedString> {
    match e.node {
        ExprLit(lit) => {
            match lit.node {
                LitStr(ref s, _) => Some(s.clone()),
                _ => {
                    cx.span_err(e.span, "expected string literal");
                    None
                }
            }
        }
        _ => {
            cx.span_err(e.span, "expected string literal");
            None
        }
    }
}

fn parse_args(cx: &mut ExtCtxt, parser: &mut Parser) -> Option<Vec<Gc<Expr>>> {
    let mut args = Vec::new();

    while parser.token != EOF {
        args.push(parser.parse_expr());

        if !parser.eat(&COMMA) && parser.token != EOF {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    Some(args)
}

fn parse(query: &str) -> Result<ParseInfo, ParseError> {
    unsafe {
        ffi::init_parser();
        let mut result = mem::uninitialized();
        query.with_c_str(|query| {
            ffi::parse_query(query, &mut result);
        });
        match result.success != 0 {
            true => Ok(ParseInfo {
                num_params: result.num_params as uint,
            }),
            false => Err(ParseError {
                message: CString::new(result.error_message, true),
                index: result.index as uint,
            }),
        }
    }
}
<commit_msg>Fix compilation errors<commit_after>#![crate_name="postgres_macros"]
#![crate_type="dylib"]
#![feature(plugin_registrar)]

extern crate libc;
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use std::c_str::CString;
use std::mem;
use syntax::ast::{TokenTree, ExprLit, LitStr, Expr, Ident};
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::parse::token;
use syntax::parse::token::{InternedString, COMMA, EOF};
use syntax::parse;
use syntax::parse::parser::Parser;
use syntax::ptr::P;

mod ffi {
    use libc::{c_char, c_int};

    #[repr(C)]
    pub struct ParseResult {
        pub success: c_int,
        pub error_message: *const c_char,
        pub index: c_int,
        pub num_params: c_int,
    }

    #[link(name="parser", kind="static")]
    extern {
        pub fn init_parser();
        pub fn parse_query(query: *const c_char, result: *mut ParseResult);
    }
}

struct ParseInfo {
    num_params: uint,
}

struct ParseError {
    message: CString,
    index: uint,
}

#[plugin_registrar]
#[doc(hidden)]
pub fn registrar(reg: &mut Registry) {
    reg.register_macro("sql", expand_sql);
    reg.register_macro("execute", expand_execute);
    unsafe { ffi::init_parser() }
}

fn expand_sql(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
              -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp)
    };

    match parse(query.get()) {
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    MacExpr::new(query_expr)
}

fn expand_execute(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                  -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let conn = parser.parse_expr();

    if !parser.eat(&COMMA) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp),
    };

    if !parser.eat(&COMMA) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let args = match parse_args(cx, &mut parser) {
        Some(args) => args,
        None => return DummyResult::expr(sp),
    };

    match parse(query.get()) {
        Ok(ref info) if info.num_params != args.len() =>
            cx.span_err(sp, format!("Expected {} query parameters but got {}",
                                    info.num_params, args.len()).as_slice()),
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    let ident = Ident::new(token::intern("execute"));
    let args = cx.expr_vec(sp, args);
    MacExpr::new(cx.expr_method_call(sp, conn, ident, vec![query_expr, args]))
}

fn parse_error(cx: &mut ExtCtxt, sp: Span, err: ParseError) {
    cx.span_err(sp, format!("Invalid syntax at position {}: {}",
                            err.index,
                            err.message.as_str().unwrap()).as_slice());
}

fn parse_str_lit(cx: &mut ExtCtxt, e: &Expr) -> Option<InternedString> {
    match e.node {
        ExprLit(ref lit) => {
            match lit.node {
                LitStr(ref s, _) => Some(s.clone()),
                _ => {
                    cx.span_err(e.span, "expected string literal");
                    None
                }
            }
        }
        _ => {
            cx.span_err(e.span, "expected string literal");
            None
        }
    }
}

fn parse_args(cx: &mut ExtCtxt, parser: &mut Parser) -> Option<Vec<P<Expr>>> {
    let mut args = Vec::new();

    while parser.token != EOF {
        args.push(parser.parse_expr());

        if !parser.eat(&COMMA) && parser.token != EOF {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    Some(args)
}

fn parse(query: &str) -> Result<ParseInfo, ParseError> {
    unsafe {
        ffi::init_parser();
        let mut result = mem::uninitialized();
        query.with_c_str(|query| {
            ffi::parse_query(query, &mut result);
        });
        match result.success != 0 {
            true => Ok(ParseInfo {
                num_params: result.num_params as uint,
            }),
            false => Err(ParseError {
                message: CString::new(result.error_message, true),
                index: result.index as uint,
            }),
        }
    }
}
<|endoftext|>


<commit_before>//! Simple crate that parses athenahealth Watertown's Nourish menu, and posts it to a slack channel
//! of choice.

#![warn(missing_docs)]

#[macro_use]
extern crate lazy_static;

extern crate chrono;
extern crate hyper;
extern crate inflector;
extern crate linked_hash_map;
extern crate regex;
extern crate select;
extern crate url;

use std::cmp;
use std::fmt::Write;

use chrono::{Datelike, Duration, NaiveDate};
use inflector::Inflector;
use linked_hash_map::LinkedHashMap;
use regex::Regex;
use select::document::Document;
use select::predicate::{Attr, Name};
use url::Url;

lazy_static! {
    /// This Regex matches nutritional information, to filter it out from the menu output.
    static ref NUTRITION_RE: Regex = Regex::new(r"Cal.*Fat.*Sat.*Sod.*Carbs.*Fib.*Pro").unwrap();

    /// This Regex matches the price information, to filter it out from the menu output.
    static ref PRICE_RE: Regex = Regex::new(r"^\d+\.\d+( / \d+\.\d+)?$").unwrap();
}

/// The Nourish menu for a given date.
#[derive(Debug, Clone, Default)]
pub struct Menu(LinkedHashMap<String, Vec<String>>);

impl Menu {
    /// Renders the menu as a Markdown string.
    pub fn to_markdown(&self) -> String {
        let mut output = String::default();

        for (ref category, ref items) in &self.0 {
            writeln!(output, "*{}*\n", category).unwrap();

            for item in items.iter() {
                writeln!(output, "• {}", item).unwrap();
            }

            writeln!(output, "").unwrap();
        }

        if (output.is_empty()) {
            writeln!(output,
                     "There is no menu today ¯\_(ツ)_/¯");
        }

        writeln!(output,
                 "> Made with :cnr: by @anrussell. Source available at \
                  https://github.com/euclio/nourishbot.")
            .unwrap();

        output
    }
}

/// Returns the URL pointing to the Nourish menu for a given day. On the weekends, returns Friday's
/// menu.
pub fn url_for_date(date: &NaiveDate) -> Url {
    let days_from_monday = cmp::min(date.weekday().num_days_from_monday(), 4);
    let monday = *date - Duration::days(date.weekday().num_days_from_monday() as i64);

    Url::parse(&format!("http://dining.guckenheimer.com/clients/athenahealth/fss/fss.\
                       nsf/weeklyMenuLaunch/8DURSE~{}/$file/day{}.htm",
                        monday.format("%m-%d-%Y"),
                        days_from_monday + 1))
        .unwrap()
}

/// Parses the menu information out of HTML.
pub fn parse_menu(html: &str) -> Menu {
    let document = Document::from(html);

    let mut menu: LinkedHashMap<String, Vec<String>> = LinkedHashMap::new();

    let mut last_category = None;

    let menu_node = document.find(Attr("id", "center_text")).first().unwrap();
    for node in menu_node.find(Name("div")).iter() {
        let text = node.text().trim().to_owned();

        if NUTRITION_RE.is_match(&text) || PRICE_RE.is_match(&text) {
            continue;
        }

        if let Some("font-weight:bold;") = node.attr("style") {
            let category = text.to_lower_case().to_title_case();

            // Filter out breakfast.
            if category != "Breakfast Special" {
                last_category = Some(text.to_lower_case().to_title_case());
            }
        } else {
            if let Some(ref category) = last_category {
                if menu.contains_key(category) {
                    let mut entries = menu.get_mut(category).unwrap();
                    entries.push(text);
                } else {
                    menu.insert(category.to_owned(), vec![text]);
                }

            }
        }
    }

    Menu(menu)
}

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

    use chrono::NaiveDate;

    #[test]
    fn monday() {
        let expected_url = "http://dining.guckenheimer.com/clients/athenahealth/fss/fss.\
                            nsf/weeklyMenuLaunch/8DURSE~04-18-2016/$file/day1.htm";

        assert_eq!(expected_url,
                   &url_for_date(&NaiveDate::from_ymd(2016, 4, 18)).serialize());
    }

    #[test]
    fn saturday() {
        let expected_url = "http://dining.guckenheimer.com/clients/athenahealth/fss/fss.\
                            nsf/weeklyMenuLaunch/8DURSE~04-11-2016/$file/day5.htm";

        assert_eq!(expected_url,
                   &url_for_date(&NaiveDate::from_ymd(2016, 4, 16)).serialize());

    }
}
<commit_msg>Fix string escaping issue<commit_after>//! Simple crate that parses athenahealth Watertown's Nourish menu, and posts it to a slack channel
//! of choice.

#![warn(missing_docs)]

#[macro_use]
extern crate lazy_static;

extern crate chrono;
extern crate hyper;
extern crate inflector;
extern crate linked_hash_map;
extern crate regex;
extern crate select;
extern crate url;

use std::cmp;
use std::fmt::Write;

use chrono::{Datelike, Duration, NaiveDate};
use inflector::Inflector;
use linked_hash_map::LinkedHashMap;
use regex::Regex;
use select::document::Document;
use select::predicate::{Attr, Name};
use url::Url;

lazy_static! {
    /// This Regex matches nutritional information, to filter it out from the menu output.
    static ref NUTRITION_RE: Regex = Regex::new(r"Cal.*Fat.*Sat.*Sod.*Carbs.*Fib.*Pro").unwrap();

    /// This Regex matches the price information, to filter it out from the menu output.
    static ref PRICE_RE: Regex = Regex::new(r"^\d+\.\d+( / \d+\.\d+)?$").unwrap();
}

/// The Nourish menu for a given date.
#[derive(Debug, Clone, Default)]
pub struct Menu(LinkedHashMap<String, Vec<String>>);

impl Menu {
    /// Renders the menu as a Markdown string.
    pub fn to_markdown(&self) -> String {
        let mut output = String::default();

        for (ref category, ref items) in &self.0 {
            writeln!(output, "*{}*\n", category).unwrap();

            for item in items.iter() {
                writeln!(output, "• {}", item).unwrap();
            }

            writeln!(output, "").unwrap();
        }

        if output.is_empty() {
            writeln!(output,
                     "There is no menu today ¯\\_(ツ)_/¯");
        }

        writeln!(output,
                 "> Made with :cnr: by @anrussell. Source available at \
                  https://github.com/euclio/nourishbot.")
            .unwrap();

        output
    }
}

/// Returns the URL pointing to the Nourish menu for a given day. On the weekends, returns Friday's
/// menu.
pub fn url_for_date(date: &NaiveDate) -> Url {
    let days_from_monday = cmp::min(date.weekday().num_days_from_monday(), 4);
    let monday = *date - Duration::days(date.weekday().num_days_from_monday() as i64);

    Url::parse(&format!("http://dining.guckenheimer.com/clients/athenahealth/fss/fss.\
                       nsf/weeklyMenuLaunch/8DURSE~{}/$file/day{}.htm",
                        monday.format("%m-%d-%Y"),
                        days_from_monday + 1))
        .unwrap()
}

/// Parses the menu information out of HTML.
pub fn parse_menu(html: &str) -> Menu {
    let document = Document::from(html);

    let mut menu: LinkedHashMap<String, Vec<String>> = LinkedHashMap::new();

    let mut last_category = None;

    let menu_node = document.find(Attr("id", "center_text")).first().unwrap();
    for node in menu_node.find(Name("div")).iter() {
        let text = node.text().trim().to_owned();

        if NUTRITION_RE.is_match(&text) || PRICE_RE.is_match(&text) {
            continue;
        }

        if let Some("font-weight:bold;") = node.attr("style") {
            let category = text.to_lower_case().to_title_case();

            // Filter out breakfast.
            if category != "Breakfast Special" {
                last_category = Some(text.to_lower_case().to_title_case());
            }
        } else {
            if let Some(ref category) = last_category {
                if menu.contains_key(category) {
                    let mut entries = menu.get_mut(category).unwrap();
                    entries.push(text);
                } else {
                    menu.insert(category.to_owned(), vec![text]);
                }

            }
        }
    }

    Menu(menu)
}

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

    use chrono::NaiveDate;

    #[test]
    fn monday() {
        let expected_url = "http://dining.guckenheimer.com/clients/athenahealth/fss/fss.\
                            nsf/weeklyMenuLaunch/8DURSE~04-18-2016/$file/day1.htm";

        assert_eq!(expected_url,
                   &url_for_date(&NaiveDate::from_ymd(2016, 4, 18)).serialize());
    }

    #[test]
    fn saturday() {
        let expected_url = "http://dining.guckenheimer.com/clients/athenahealth/fss/fss.\
                            nsf/weeklyMenuLaunch/8DURSE~04-11-2016/$file/day5.htm";

        assert_eq!(expected_url,
                   &url_for_date(&NaiveDate::from_ymd(2016, 4, 16)).serialize());

    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate url;

use libc::gethostname;
use serde_json::Value;
use std::collections::BTreeMap;
use std::io::prelude::*;
use std::net::TcpStream;
use std::sync::Mutex;
use std::io;

lazy_static!
{
    pub static ref EMITTER: Mutex<Emitter<'static>> = Mutex::new(Emitter::empty());
}

pub fn emitter() -> std::sync::MutexGuard<'static, Emitter<'static>>
{
    EMITTER.lock().unwrap()
}

pub type Point<'a> = BTreeMap<&'a str, serde_json::Value>;

pub struct Emitter<'e>
{
    defaults: Point<'e>,
    output: Option<TcpStream>,
    destination: String,
    app: String,
}

impl<'e> Emitter<'e>
{
    pub fn empty() -> Emitter<'e>
    {
        let mut opts: Point = Point::new();
        let hostname = hostname();
        opts.insert("host", serde_json::to_value(hostname));
        Emitter
        {
            defaults: opts,
            output: None,
            app: String::from(""),
            destination: String::from("")
        }
    }

    pub fn for_app(app: &str) -> Emitter<'e>
    {
        let mut opts: Point = Point::new();
        let hostname = hostname();
        opts.insert("host", serde_json::to_value(hostname));

        let mut t = String::from(app);
        t.push('.');

        Emitter
        {
            defaults: opts,
            output: None,
            app: t,
            destination: String::from("")
        }
    }

    pub fn init(&mut self, tmpl: BTreeMap<&'e str, Value>, app: &str)
    {
        let mut defaults = tmpl.clone();
        let hostname = hostname();
        defaults.insert("host", serde_json::to_value(hostname));

        let mut t = String::from(app);
        t.push('.');

        self.defaults = defaults;
        self.app = t;
    }

    pub fn new(tmpl: BTreeMap<&'e str, Value>, app: &str) -> Emitter<'e>
    {
        let mut defaults = tmpl.clone();
        let hostname = hostname();
        defaults.insert("host", serde_json::to_value(hostname));

        let mut t = String::from(app);
        t.push('.');

        Emitter
        {
            defaults: defaults,
            output: None,
            app: t,
            destination: String::from("")
        }
    }

    pub fn connect(&mut self, dest: &str)
    {
        self.destination = String::from(dest);
        self.output = create_connection(dest);
    }

    // The default write_all implementation doesn't do useful things.
    fn write_all(conn: &mut TcpStream, mut buf: &[u8]) -> Result<usize, io::Error>
    {
        // let total = buf.len();
        let mut written: usize = 0;
        while !buf.is_empty()
        {
            match conn.write(buf)
            {
                Ok(0) => return Err(io::Error::new(io::ErrorKind::Other, "zero bytes written")),
                Ok(n) => {
                    // println!("bytes={} of {}", n, total);
                    written += n;
                    buf = &buf[n..]
                },
                Err(e) => return Err(e),
            }
        }
        Ok(written)
    }

    fn write(&mut self, metric: BTreeMap<&'e str, Value>)
    {
        match self.output
        {
            None => { self.output = create_connection(&self.destination); },
            Some(_) => {},
        };

        match self.output
        {
            None => {},
            Some(ref mut conn) =>
            {
                let mline = serde_json::to_string(&metric).unwrap() + "\n";
                match Emitter::write_all(conn, mline.as_bytes())
                {
                    Ok(_) => {},
                    Err(e) => println!("ERR {:?}", e),
                }
            }
        }
    }

    pub fn emit_point(&mut self, point: BTreeMap<&'e str, Value>)
    {
        let mut metric = self.defaults.clone();
        metric.append(&mut point.clone());

        // Failing to set a name means the metrics point is invalid; we decline to send it.
        let name = match metric.remove("name")
        {
            Some(v) => v,
            None => { return; },
        };
        let mut fullname = self.app.clone();
        fullname.push_str(name.as_str().unwrap());

        metric.insert("name", serde_json::to_value(fullname));
        metric.entry("value").or_insert(serde_json::to_value(1));

        let now = time::get_time();
        let millis = now.sec * 1000 + (now.nsec / 1000000) as i64;
        metric.entry("time").or_insert(serde_json::to_value(millis));

        self.write(metric);
    }

    pub fn emit<T>(&mut self, name: &str, value: T)
        where T: serde::ser::Serialize
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        self.emit_point(metric);
    }

    pub fn emit_name(&mut self, name: &'e str)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        self.emit_point(metric);
    }

    pub fn emit_name_val_tag<T>(&mut self, name: &'e str, value: T, tag: &'e str, tagv: T)
        where T: serde::ser::Serialize
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        metric.insert(tag, serde_json::to_value(tagv));
        self.emit_point(metric);
    }
}

fn create_connection(dest: &str) -> Option<std::net::TcpStream>
{
    // TODO udp vs tcp for full compatibility
    // TODO reconnect on error
    let target = url::Url::parse(dest).ok().unwrap();
    match TcpStream::connect((target.host_str().unwrap(), target.port().unwrap()))
    {
        Ok(v) => { Some(v) },
        Err(_) => { None },
    }
}

pub fn hostname<'a>() -> String
{
    let bufsize = 255;
    let mut buf = Vec::<u8>::with_capacity(bufsize);
    let ptr = buf.as_mut_slice().as_mut_ptr();

    let err = unsafe
        { gethostname(ptr as *mut libc::c_char, bufsize as libc::size_t) }
        as libc::size_t;

    if err != 0
    {
        return "localhost".into();
    }

    let mut len = bufsize;
    let mut i = 0;

    loop
    {
        let byte = unsafe { *(((ptr as u64) + (i as u64)) as *const u8) };
        if byte == 0
        {
            len = i;
            break;
        }
        if i == bufsize { break; }
        i += 1;
    }

    unsafe { buf.set_len(len); }
    String::from_utf8_lossy(buf.as_slice()).into_owned()
}

impl<'e> Clone for Emitter<'e>
{
    fn clone(&self) -> Self
    {
        Emitter
        {
            defaults: self.defaults.clone(),
            destination: self.destination.clone(),
            app: self.app.clone(),
            output: match self.output
            {
                None => None,
                Some(ref o) => Some(o.try_clone().expect("expected TcpStream to clone"))
            }
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>chore: refactor constructing the `defaults` property<commit_after>#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate url;

use libc::gethostname;
use serde_json::Value;
use std::collections::BTreeMap;
use std::io::prelude::*;
use std::net::TcpStream;
use std::sync::Mutex;
use std::io;

lazy_static!
{
    pub static ref EMITTER: Mutex<Emitter<'static>> = Mutex::new(Emitter::empty());
}

pub fn emitter() -> std::sync::MutexGuard<'static, Emitter<'static>>
{
    EMITTER.lock().unwrap()
}

pub type Point<'a> = BTreeMap<&'a str, serde_json::Value>;

pub struct Emitter<'e>
{
    defaults: Point<'e>,
    output: Option<TcpStream>,
    destination: String,
    app: String,
}

impl<'e> Emitter<'e>
{
    pub fn empty() -> Emitter<'e>
    {
        Emitter
        {
            defaults: get_defaults(Point::new()),
            output: None,
            app: String::from(""),
            destination: String::from("")
        }
    }

    pub fn for_app(app: &str) -> Emitter<'e>
    {
        let mut t = String::from(app);
        t.push('.');

        Emitter
        {
            defaults: get_defaults(Point::new()),
            output: None,
            app: t,
            destination: String::from("")
        }
    }

    pub fn init(&mut self, tmpl: Point<'e>, app: &str)
    {
        let mut defaults = tmpl.clone();
        let hostname = hostname();
        defaults.insert("host", serde_json::to_value(hostname));

        let mut t = String::from(app);
        t.push('.');

        self.defaults = defaults;
        self.app = t;
    }

    pub fn new(tmpl: Point<'e>, app: &str) -> Emitter<'e>
    {
        let mut defaults = tmpl.clone();
        let hostname = hostname();
        defaults.insert("host", serde_json::to_value(hostname));

        let mut t = String::from(app);
        t.push('.');

        Emitter
        {
            defaults: get_defaults(tmpl),
            output: None,
            app: t,
            destination: String::from("")
        }
    }

    pub fn connect(&mut self, dest: &str)
    {
        self.destination = String::from(dest);
        self.output = create_connection(dest);
    }

    // The default write_all implementation doesn't do useful things.
    fn write_all(conn: &mut TcpStream, mut buf: &[u8]) -> Result<usize, io::Error>
    {
        // let total = buf.len();
        let mut written: usize = 0;
        while !buf.is_empty()
        {
            match conn.write(buf)
            {
                Ok(0) => return Err(io::Error::new(io::ErrorKind::Other, "zero bytes written")),
                Ok(n) => {
                    // println!("bytes={} of {}", n, total);
                    written += n;
                    buf = &buf[n..]
                },
                Err(e) => return Err(e),
            }
        }
        Ok(written)
    }

    fn write(&mut self, metric: BTreeMap<&'e str, Value>)
    {
        match self.output
        {
            None => { self.output = create_connection(&self.destination); },
            Some(_) => {},
        };

        match self.output
        {
            None => {},
            Some(ref mut conn) =>
            {
                let mline = serde_json::to_string(&metric).unwrap() + "\n";
                match Emitter::write_all(conn, mline.as_bytes())
                {
                    Ok(_) => {},
                    Err(e) => println!("ERR {:?}", e),
                }
            }
        }
    }

    pub fn emit_point(&mut self, point: BTreeMap<&'e str, Value>)
    {
        let mut metric = self.defaults.clone();
        metric.append(&mut point.clone());

        // Failing to set a name means the metrics point is invalid; we decline to send it.
        let name = match metric.remove("name")
        {
            Some(v) => v,
            None => { return; },
        };
        let mut fullname = self.app.clone();
        fullname.push_str(name.as_str().unwrap());

        metric.insert("name", serde_json::to_value(fullname));
        metric.entry("value").or_insert(serde_json::to_value(1));

        let now = time::get_time();
        let millis = now.sec * 1000 + (now.nsec / 1000000) as i64;
        metric.entry("time").or_insert(serde_json::to_value(millis));

        self.write(metric);
    }

    pub fn emit<T>(&mut self, name: &str, value: T)
        where T: serde::ser::Serialize
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        self.emit_point(metric);
    }

    pub fn emit_name(&mut self, name: &'e str)
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        self.emit_point(metric);
    }

    pub fn emit_name_val_tag<T>(&mut self, name: &'e str, value: T, tag: &'e str, tagv: T)
        where T: serde::ser::Serialize
    {
        let mut metric: BTreeMap<&str, Value> = BTreeMap::new();
        metric.insert("name", serde_json::to_value(name));
        metric.insert("value", serde_json::to_value(value));
        metric.insert(tag, serde_json::to_value(tagv));
        self.emit_point(metric);
    }
}

fn create_connection(dest: &str) -> Option<std::net::TcpStream>
{
    // TODO udp vs tcp for full compatibility
    // TODO reconnect on error
    let target = url::Url::parse(dest).ok().unwrap();
    match TcpStream::connect((target.host_str().unwrap(), target.port().unwrap()))
    {
        Ok(v) => { Some(v) },
        Err(_) => { None },
    }
}

pub fn hostname<'a>() -> String
{
    let bufsize = 255;
    let mut buf = Vec::<u8>::with_capacity(bufsize);
    let ptr = buf.as_mut_slice().as_mut_ptr();

    let err = unsafe
        { gethostname(ptr as *mut libc::c_char, bufsize as libc::size_t) }
        as libc::size_t;

    if err != 0
    {
        return "localhost".into();
    }

    let mut len = bufsize;
    let mut i = 0;

    loop
    {
        let byte = unsafe { *(((ptr as u64) + (i as u64)) as *const u8) };
        if byte == 0
        {
            len = i;
            break;
        }
        if i == bufsize { break; }
        i += 1;
    }

    unsafe { buf.set_len(len); }
    String::from_utf8_lossy(buf.as_slice()).into_owned()
}

fn get_defaults(tmpl: Point) -> Point {
    let defaults = tmpl.clone();
    defaults.insert("host", serde_json::to_value(hostname()));
    defaults
}

impl<'e> Clone for Emitter<'e>
{
    fn clone(&self) -> Self
    {
        Emitter
        {
            defaults: self.defaults.clone(),
            destination: self.destination.clone(),
            app: self.app.clone(),
            output: match self.output
            {
                None => None,
                Some(ref o) => Some(o.try_clone().expect("expected TcpStream to clone"))
            }
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>


<commit_before>#![crate_name = "schedule_gen"]
#![feature(convert, collections)]

extern crate uuid;
extern crate chrono;
extern crate rand;

use uuid::Uuid;

use chrono::Datelike;

use rand::{thread_rng, Rng};

use contract::{ Time, Date, LeagueSpec, TeamEvent };
use contract::TeamEvent::{ Game, Bye };
use convert::{ DateConvert, WeekdayConvert };

mod convert;
mod validate;
pub mod contract;

#[derive(Clone)]
struct GameShell {
    pub date: Date,
    pub time: Time,
    pub location: (String, String)
}

pub fn generate_games(spec: &LeagueSpec) -> Result<Vec<TeamEvent>, Vec<&'static str>> {
    let errors = validate::validate(spec);
    if errors.len() > 0 {
        return Err(errors);
    }

    let game_shells = generate_shells(spec);

    // Create a new list of teams which includes our fake bye team if needed
    let mut teams = spec.teams.clone();
    let mut bye_id_opt: Option<String> = None;
    let generated_uuid = Uuid::new_v4().to_hyphenated_string();
    if teams.len() % 2 == 1 {
        bye_id_opt = Some(generated_uuid.clone());
        teams.push((generated_uuid, String::from_str("Bye team")));
    }
    let teams = teams;
    let bye_id_opt: Option<String> = bye_id_opt;

    let mut round_robin = generate_round_robin(&teams);

    let mut result: Vec<TeamEvent> = vec!();

    for rotation in game_shells.as_slice().chunks((teams.len() - 1) * (spec.teams.len() / 2)) {
        shuffle_round_robin(&mut round_robin);
        for shells_teams in (&rotation).chunks(spec.teams.len() / 2).zip(round_robin.iter()) {
            let (shells, teams) = shells_teams;
            let non_byes = match bye_id_opt {
                Some(ref bye_id) => {
                    let bye_date = shells[0].date.clone();
                    let bye_pair = teams.iter().find(|pair| (pair.0).0 == *bye_id || (pair.1).0 == *bye_id).unwrap();
                    if (bye_pair.0).0 == *bye_id {
                        result.push(Bye(bye_pair.1.clone(), bye_date));
                    } else {
                        result.push(Bye(bye_pair.0.clone(), bye_date));
                    }
                    teams.iter().filter(|pair| (pair.0).0 != *bye_id && (pair.1).0 != *bye_id).collect::<Vec<_>>()
                }
                None => teams.iter().collect::<Vec<_>>()
            };
            for shell_team in shells.iter().zip(non_byes.iter()) {
                let (shell, team) = shell_team;
                result.push(Game(
                    team.0.clone(),
                    team.1.clone(),
                    shell.date.clone(),
                    shell.time.clone(),
                    shell.location.clone()));
            }
        }
    }

    Ok(result)
}

fn shuffle_round_robin(
    round_robin: &mut Vec<Vec<(&(String, String), &(String, String))>>) {
    let mut rng = thread_rng();
    let pair: (&(String, String), &(String, String)) = round_robin[round_robin.len() - 1][0];
    rng.shuffle(round_robin.as_mut_slice());
    while round_robin[0].iter().any(|pair2|
        ((pair2.0).0 == (pair.0).0 &&
        (pair2.1).0 == (pair.1).0) ||
        ((pair2.1).0 == (pair.0).0 &&
        (pair2.0).0 == (pair.1).0)) {
        rng.shuffle(round_robin.as_mut_slice());
    }

    for week in round_robin.iter_mut() {
        rng.shuffle(week.as_mut_slice());
    }
}

fn generate_round_robin(teams: &Vec<(String, String)>) -> Vec<Vec<(&(String, String), &(String, String))>> {
    let static_team: &(String, String) = &teams[0];
    let mut other_teams: Vec<&(String, String)> = teams.iter().skip(1).collect();

    let mut result: Vec<Vec<(&(String, String), &(String, String))>> = Vec::new();

    for _ in 0us..(teams.len() - 1) {
        let mut session: Vec<(&(String, String), &(String, String))> = Vec::new();
        session.push((other_teams[0], static_team));
        for i in 0us..((other_teams.len() - 1) / 2) {
            let team_1: &(String, String) = other_teams[i+1];
            let team_2: &(String, String) = other_teams[other_teams.len() - 1 - i];
            session.push((team_1, team_2));
        }

        // Rotate other_teams
        let temp = other_teams[0];
        for i in 0us..(other_teams.len() - 1) {
            other_teams[i] = other_teams[i + 1];
        }
        let other_teams_len = other_teams.len() - 1;
        other_teams[other_teams_len] = temp;

        result.push(session)
    }

    result
}

fn generate_shells(spec: &LeagueSpec) -> Vec<GameShell> {
    let games_per_night = spec.teams.len() as u8 / 2;

    let mut result: Vec<GameShell> = vec![];

    let start_date = spec.start_date.to_naive_date_opt().unwrap();
    let end_date = spec.end_date.to_naive_date_opt().unwrap();

    let mut i_date = start_date.clone();
    while i_date != end_date.succ() {
        if spec.game_weekday.day.to_chrono_weekday() == i_date.weekday() {
            let mut num_games = 0u8;
            for time in spec.game_weekday.game_times.iter() {
                for location in time.location_ids.iter() {
                    if num_games != games_per_night {
                        result.push( GameShell {
                            date: DateConvert::from_naive_date(&i_date),
                            time: time.time,
                            location: spec.locations.iter().find(|loc| loc.0 == *location).unwrap().clone()
                        });
                        num_games += 1;
                    }
                }
            }
        }
        i_date = i_date.succ();
    }

    result
}
<commit_msg>updating for newest rust<commit_after>#![crate_name = "schedule_gen"]
#![feature(convert, collections)]

extern crate uuid;
extern crate chrono;
extern crate rand;

use uuid::Uuid;

use chrono::Datelike;

use rand::{thread_rng, Rng};

use contract::{ Time, Date, LeagueSpec, TeamEvent };
use contract::TeamEvent::{ Game, Bye };
use convert::{ DateConvert, WeekdayConvert };

mod convert;
mod validate;
pub mod contract;

#[derive(Clone)]
struct GameShell {
    pub date: Date,
    pub time: Time,
    pub location: (String, String)
}

pub fn generate_games(spec: &LeagueSpec) -> Result<Vec<TeamEvent>, Vec<&'static str>> {
    let errors = validate::validate(spec);
    if errors.len() > 0 {
        return Err(errors);
    }

    let game_shells = generate_shells(spec);

    // Create a new list of teams which includes our fake bye team if needed
    let mut teams = spec.teams.clone();
    let mut bye_id_opt: Option<String> = None;
    let generated_uuid = Uuid::new_v4().to_hyphenated_string();
    if teams.len() % 2 == 1 {
        bye_id_opt = Some(generated_uuid.clone());
        teams.push((generated_uuid, String::from_str("Bye team")));
    }
    let teams = teams;
    let bye_id_opt: Option<String> = bye_id_opt;

    let mut round_robin = generate_round_robin(&teams);

    let mut result: Vec<TeamEvent> = vec!();

    for rotation in game_shells.as_slice().chunks((teams.len() - 1) * (spec.teams.len() / 2)) {
        shuffle_round_robin(&mut round_robin);
        for shells_teams in (&rotation).chunks(spec.teams.len() / 2).zip(round_robin.iter()) {
            let (shells, teams) = shells_teams;
            let non_byes = match bye_id_opt {
                Some(ref bye_id) => {
                    let bye_date = shells[0].date.clone();
                    let bye_pair = teams.iter().find(|pair| (pair.0).0 == *bye_id || (pair.1).0 == *bye_id).unwrap();
                    if (bye_pair.0).0 == *bye_id {
                        result.push(Bye(bye_pair.1.clone(), bye_date));
                    } else {
                        result.push(Bye(bye_pair.0.clone(), bye_date));
                    }
                    teams.iter().filter(|pair| (pair.0).0 != *bye_id && (pair.1).0 != *bye_id).collect::<Vec<_>>()
                }
                None => teams.iter().collect::<Vec<_>>()
            };
            for shell_team in shells.iter().zip(non_byes.iter()) {
                let (shell, team) = shell_team;
                result.push(Game(
                    team.0.clone(),
                    team.1.clone(),
                    shell.date.clone(),
                    shell.time.clone(),
                    shell.location.clone()));
            }
        }
    }

    Ok(result)
}

fn shuffle_round_robin(
    round_robin: &mut Vec<Vec<(&(String, String), &(String, String))>>) {
    let mut rng = thread_rng();
    let pair: (&(String, String), &(String, String)) = round_robin[round_robin.len() - 1][0];
    rng.shuffle(round_robin.as_mut_slice());
    while round_robin[0].iter().any(|pair2|
        ((pair2.0).0 == (pair.0).0 &&
        (pair2.1).0 == (pair.1).0) ||
        ((pair2.1).0 == (pair.0).0 &&
        (pair2.0).0 == (pair.1).0)) {
        rng.shuffle(round_robin.as_mut_slice());
    }

    for week in round_robin.iter_mut() {
        rng.shuffle(week.as_mut_slice());
    }
}

fn generate_round_robin(teams: &Vec<(String, String)>) -> Vec<Vec<(&(String, String), &(String, String))>> {
    let static_team: &(String, String) = &teams[0];
    let mut other_teams: Vec<&(String, String)> = teams.iter().skip(1).collect();

    let mut result: Vec<Vec<(&(String, String), &(String, String))>> = Vec::new();

    for _ in 0..(teams.len() - 1) {
        let mut session: Vec<(&(String, String), &(String, String))> = Vec::new();
        session.push((other_teams[0], static_team));
        for i in 0..((other_teams.len() - 1) / 2) {
            let team_1: &(String, String) = other_teams[i+1];
            let team_2: &(String, String) = other_teams[other_teams.len() - 1 - i];
            session.push((team_1, team_2));
        }

        // Rotate other_teams
        let temp = other_teams[0];
        for i in 0..(other_teams.len() - 1) {
            other_teams[i] = other_teams[i + 1];
        }
        let other_teams_len = other_teams.len() - 1;
        other_teams[other_teams_len] = temp;

        result.push(session)
    }

    result
}

fn generate_shells(spec: &LeagueSpec) -> Vec<GameShell> {
    let games_per_night = spec.teams.len() as u8 / 2;

    let mut result: Vec<GameShell> = vec![];

    let start_date = spec.start_date.to_naive_date_opt().unwrap();
    let end_date = spec.end_date.to_naive_date_opt().unwrap();

    let mut i_date = start_date.clone();
    while i_date != end_date.succ() {
        if spec.game_weekday.day.to_chrono_weekday() == i_date.weekday() {
            let mut num_games = 0u8;
            for time in spec.game_weekday.game_times.iter() {
                for location in time.location_ids.iter() {
                    if num_games != games_per_night {
                        result.push( GameShell {
                            date: DateConvert::from_naive_date(&i_date),
                            time: time.time,
                            location: spec.locations.iter().find(|loc| loc.0 == *location).unwrap().clone()
                        });
                        num_games += 1;
                    }
                }
            }
        }
        i_date = i_date.succ();
    }

    result
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt::{self, Debug, Display, Formatter};
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Condvar, Mutex, Weak};
use std::time::{Duration, SystemTime};

pub struct Pool<T, F> where F: Fn() -> T {
    create: F,
    items: Mutex<Items<T>>,
    item_available: Condvar,
    weak_self: Weak<Pool<T, F>>,
}

impl<T, F> Pool<T, F> where F: Fn() -> T {
    pub fn new(create: F) -> Arc<Pool<T, F>> {
        Pool::new_internal(create, None)
    }

    fn new_internal(create: F, max_items: Option<usize>) -> Arc<Pool<T, F>> {
        let pool = Arc::new(Pool {
            create: create,
            items: Mutex::new(Items {
                available: Vec::new(),
                count: 0,
                max: max_items,
            }),
            item_available: Condvar::new(),
            weak_self: Weak::new(),
        });
        unsafe {
            let ptr = &pool.weak_self as *const Weak<Pool<T, F>> as *mut Weak<Pool<T, F>>;
            *ptr = Arc::downgrade(&pool);
        }
        pool
    }

    pub fn get(&self) -> Item<T, F> {
        self.get_internal(None).unwrap()
    }

    pub fn get_timeout(&self, duration: Duration) -> Result<Item<T, F>, TimeoutError> {
        self.get_internal(Some(duration))
    }

    fn get_internal(&self, duration: Option<Duration>) -> Result<Item<T, F>, TimeoutError> {
        let mut items = self.items.lock().unwrap();
        let item = match items.available.pop() {
            Some(item) => item,
            None => {
                if items.count < items.max.unwrap_or(std::usize::MAX) {
                    items.count += 1;
                    drop(items);
                    (self.create)()
                } else {
                    let start = SystemTime::now();
                    while items.available.is_empty() {
                        items = match duration {
                            Some(duration) => {
                                let elapsed = match start.elapsed() {
                                    Ok(elapsed) => elapsed,
                                    Err(_) => Duration::from_secs(0),
                                };
                                if elapsed > duration {
                                    return Err(TimeoutError);
                                }
                                let (items, wait_result) =
                                    self.item_available.wait_timeout(items, duration - elapsed).unwrap();
                                if wait_result.timed_out() {
                                    return Err(TimeoutError);
                                }
                                items
                            },
                            None => self.item_available.wait(items).unwrap(),
                        }
                    }
                    items.available.pop().unwrap()
                }
            }
        };
        Ok(Item {
            item: Some(item),
            pool: self.weak_self.upgrade().unwrap(),
        })
    }

    fn put(&self, item: T) {
        self.items.lock().unwrap().available.push(item);
        self.item_available.notify_one();
    }
}

impl<T, F> Debug for Pool<T, F> where T: Debug, F: Fn() -> T {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Pool")
            .field("items", &*self.items.lock().unwrap())
            .finish()
    }
}

pub struct PoolBuilder<T, F> where F: Fn() -> T {
    create: F,
    max_items: Option<usize>,
}

impl<T, F> PoolBuilder<T, F> where F: Fn() -> T {
    pub fn new(create: F) -> PoolBuilder<T, F> {
        PoolBuilder { create: create, max_items: None }
    }

    pub fn max_items(mut self, max_items: usize) -> PoolBuilder<T, F> {
        self.max_items = Some(max_items);
        self
    }

    pub fn finalize(self) -> Arc<Pool<T, F>> {
        Pool::new_internal(self.create, self.max_items)
    }
}

struct Items<T> {
    available: Vec<T>,
    count: usize,
    max: Option<usize>,
}

impl<T> Debug for Items<T> where T: Debug {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Items")
            .field("available", &self.available.len())
            .field("count", &self.count)
            .field("max", &self.max)
            .finish()
    }
}

pub struct Item<T, F> where F: Fn() -> T {
    item: Option<T>,
    pool: Arc<Pool<T, F>>,
}

impl<T, F> Debug for Item<T, F> where T: Debug, F: Fn() -> T {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Item")
            .field("item", &self.item)
            .finish()
    }
}

impl<T, F> Deref for Item<T, F> where F: Fn() -> T {
    type Target = T;

    fn deref(&self) -> &T {
        self.item.as_ref().unwrap()
    }
}

impl<T, F> DerefMut for Item<T, F> where F: Fn() -> T {
    fn deref_mut(&mut self) -> &mut T {
        self.item.as_mut().unwrap()
    }
}

impl<T, F> Drop for Item<T, F> where F: Fn() -> T {
    fn drop(&mut self) {
        self.pool.put(self.item.take().unwrap());
    }
}

#[derive(Debug, Eq, PartialEq)]
pub struct TimeoutError;

impl Display for TimeoutError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.write_str("wait timed out")
    }
}

impl Error for TimeoutError {
    fn description(&self) -> &str {
        "wait timed out"
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error;
    use std::time::{Duration, SystemTime};
    use std::thread;
    use super::*;

    trait AsMillis {
        fn as_millis(&self) -> u64;
    }

    impl AsMillis for Duration {
        fn as_millis(&self) -> u64 {
            self.as_secs() * 1000 + self.subsec_nanos() as u64 / 1000000
        }
    }

    #[test]
    fn pool_builder() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let _x = pool.get();
        assert_eq!(pool.get_timeout(Duration::from_secs(0)).err(), Some(TimeoutError));
    }

    #[test]
    fn pool_get() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let x = pool.get();
        let p = pool.clone();
        let start = SystemTime::now();
        let handle = thread::spawn(move || {
            let _ = p.get();
        });
        thread::sleep(Duration::from_millis(100));
        drop(x);
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_get_mut() {
        let pool = Pool::new(|| 0);
        *pool.get() = 4;
        assert_eq!(*pool.get(), 4);
    }

    #[test]
    fn pool_get_timeout_ok() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let x = pool.get();
        let p = pool.clone();
        let start = SystemTime::now();
        let handle = thread::spawn(move || {
            let _ = p.get_timeout(Duration::from_secs(1)).unwrap();
        });
        thread::sleep(Duration::from_millis(100));
        drop(x);
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_get_timeout_err() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let _x = pool.get();
        let p = pool.clone();
        let start = SystemTime::now();
        let handle = thread::spawn(move || {
            assert_eq!(p.get_timeout(Duration::from_millis(100)).err(), Some(TimeoutError));
        });
        while start.elapsed().unwrap().as_millis() < 100 {
            pool.item_available.notify_one();
        }
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_debug() {
        let pool = PoolBuilder::new(|| 0).max_items(5).finalize();
        assert_eq!(format!("{:?}", pool),
            "Pool { items: Items { available: 0, count: 0, max: Some(5) } }");
        let x = pool.get();
        let _y = pool.get();
        let _z = pool.get();
        drop(x);
        assert_eq!(format!("{:?}", pool),
            "Pool { items: Items { available: 1, count: 3, max: Some(5) } }");
    }

    #[test]
    fn item_debug() {
        let pool = Pool::new(|| 0);
        let x = pool.get();
        assert_eq!(format!("{:?}", x), "Item { item: Some(0) }");
    }

    #[test]
    fn timeout_error() {
        assert_eq!(format!("{}", TimeoutError), "wait timed out");
        assert_eq!(TimeoutError.description(), "wait timed out");
    }
}
<commit_msg>add an example and rename some private methods<commit_after>//! # Examples
//!
//! ```
//! use objpool::PoolBuilder;
//! use std::thread;
//!
//! let p = PoolBuilder::new(|| 0).max_items(5).finalize();
//! let mut handles = Vec::new();
//! for _ in 0..10 {
//!     let pool = p.clone();
//!     handles.push(thread::spawn(move || {
//!         for _ in 0..1000 {
//!             *pool.get() += 1;
//!         }
//!     }));
//! }
//!
//! for handle in handles {
//!     handle.join().unwrap();
//! }
//! assert_eq!(*p.get() + *p.get() + *p.get() + *p.get() + *p.get(), 10000);
//! ```

use std::error::Error;
use std::fmt::{self, Debug, Display, Formatter};
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Condvar, Mutex, Weak};
use std::time::{Duration, SystemTime};

pub struct Pool<T, F> where F: Fn() -> T {
    create: F,
    items: Mutex<Items<T>>,
    item_available: Condvar,
    weak_self: Weak<Pool<T, F>>,
}

impl<T, F> Pool<T, F> where F: Fn() -> T {
    pub fn new(create: F) -> Arc<Pool<T, F>> {
        Pool::new_impl(create, None)
    }

    fn new_impl(create: F, max_items: Option<usize>) -> Arc<Pool<T, F>> {
        let pool = Arc::new(Pool {
            create: create,
            items: Mutex::new(Items {
                available: Vec::new(),
                count: 0,
                max: max_items,
            }),
            item_available: Condvar::new(),
            weak_self: Weak::new(),
        });
        unsafe {
            let ptr = &pool.weak_self as *const Weak<Pool<T, F>> as *mut Weak<Pool<T, F>>;
            *ptr = Arc::downgrade(&pool);
        }
        pool
    }

    pub fn get(&self) -> Item<T, F> {
        self.get_impl(None).unwrap()
    }

    pub fn get_timeout(&self, duration: Duration) -> Result<Item<T, F>, TimeoutError> {
        self.get_impl(Some(duration))
    }

    fn get_impl(&self, duration: Option<Duration>) -> Result<Item<T, F>, TimeoutError> {
        let mut items = self.items.lock().unwrap();
        let item = match items.available.pop() {
            Some(item) => item,
            None => {
                if items.count < items.max.unwrap_or(std::usize::MAX) {
                    items.count += 1;
                    drop(items);
                    (self.create)()
                } else {
                    let start = SystemTime::now();
                    while items.available.is_empty() {
                        items = match duration {
                            Some(duration) => {
                                let elapsed = match start.elapsed() {
                                    Ok(elapsed) => elapsed,
                                    Err(_) => Duration::from_secs(0),
                                };
                                if elapsed >= duration {
                                    return Err(TimeoutError);
                                }
                                let (items, wait_result) =
                                    self.item_available.wait_timeout(items, duration - elapsed).unwrap();
                                if wait_result.timed_out() {
                                    return Err(TimeoutError);
                                }
                                items
                            },
                            None => self.item_available.wait(items).unwrap(),
                        }
                    }
                    items.available.pop().unwrap()
                }
            }
        };
        Ok(Item {
            item: Some(item),
            pool: self.weak_self.upgrade().unwrap(),
        })
    }

    fn put(&self, item: T) {
        self.items.lock().unwrap().available.push(item);
        self.item_available.notify_one();
    }
}

impl<T, F> Debug for Pool<T, F> where F: Fn() -> T {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Pool")
            .field("items", &*self.items.lock().unwrap())
            .finish()
    }
}

pub struct PoolBuilder<T, F> where F: Fn() -> T {
    create: F,
    max_items: Option<usize>,
}

impl<T, F> PoolBuilder<T, F> where F: Fn() -> T {
    pub fn new(create: F) -> PoolBuilder<T, F> {
        PoolBuilder { create: create, max_items: None }
    }

    pub fn max_items(mut self, max_items: usize) -> PoolBuilder<T, F> {
        self.max_items = Some(max_items);
        self
    }

    pub fn finalize(self) -> Arc<Pool<T, F>> {
        Pool::new_impl(self.create, self.max_items)
    }
}

struct Items<T> {
    available: Vec<T>,
    count: usize,
    max: Option<usize>,
}

impl<T> Debug for Items<T> {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Items")
            .field("available", &self.available.len())
            .field("count", &self.count)
            .field("max", &self.max)
            .finish()
    }
}

pub struct Item<T, F> where F: Fn() -> T {
    item: Option<T>,
    pool: Arc<Pool<T, F>>,
}

impl<T, F> Debug for Item<T, F> where T: Debug, F: Fn() -> T {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Item")
            .field("item", &self.item)
            .finish()
    }
}

impl<T, F> Deref for Item<T, F> where F: Fn() -> T {
    type Target = T;

    fn deref(&self) -> &T {
        self.item.as_ref().unwrap()
    }
}

impl<T, F> DerefMut for Item<T, F> where F: Fn() -> T {
    fn deref_mut(&mut self) -> &mut T {
        self.item.as_mut().unwrap()
    }
}

impl<T, F> Drop for Item<T, F> where F: Fn() -> T {
    fn drop(&mut self) {
        self.pool.put(self.item.take().unwrap());
    }
}

#[derive(Debug, Eq, PartialEq)]
pub struct TimeoutError;

impl Display for TimeoutError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.write_str("wait timed out")
    }
}

impl Error for TimeoutError {
    fn description(&self) -> &str {
        "wait timed out"
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error;
    use std::time::{Duration, SystemTime};
    use std::thread;
    use super::*;

    trait AsMillis {
        fn as_millis(&self) -> u64;
    }

    impl AsMillis for Duration {
        fn as_millis(&self) -> u64 {
            self.as_secs() * 1000 + self.subsec_nanos() as u64 / 1000000
        }
    }

    #[test]
    fn pool_builder() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let _x = pool.get();
        assert_eq!(pool.get_timeout(Duration::from_secs(0)).err(), Some(TimeoutError));
    }

    #[test]
    fn pool_get() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let x = pool.get();
        let p = pool.clone();
        let start = SystemTime::now();
        let handle = thread::spawn(move || {
            let _ = p.get();
        });
        thread::sleep(Duration::from_millis(100));
        drop(x);
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_get_mut() {
        let pool = Pool::new(|| 0);
        *pool.get() = 4;
        assert_eq!(*pool.get(), 4);
    }

    #[test]
    fn pool_get_timeout_ok() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let x = pool.get();
        let p = pool.clone();
        let start = SystemTime::now();
        let handle = thread::spawn(move || {
            let _ = p.get_timeout(Duration::from_secs(1)).unwrap();
        });
        thread::sleep(Duration::from_millis(100));
        drop(x);
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_get_timeout_err() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let _x = pool.get();
        let p = pool.clone();
        let start = SystemTime::now();
        let handle = thread::spawn(move || {
            assert_eq!(p.get_timeout(Duration::from_millis(100)).err(), Some(TimeoutError));
        });
        while start.elapsed().unwrap().as_millis() < 100 {
            pool.item_available.notify_one();
        }
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_debug() {
        let pool = PoolBuilder::new(|| 0).max_items(5).finalize();
        assert_eq!(format!("{:?}", pool),
            "Pool { items: Items { available: 0, count: 0, max: Some(5) } }");
        let x = pool.get();
        let _y = pool.get();
        let _z = pool.get();
        drop(x);
        assert_eq!(format!("{:?}", pool),
            "Pool { items: Items { available: 1, count: 3, max: Some(5) } }");
    }

    #[test]
    fn item_debug() {
        let pool = Pool::new(|| 0);
        let x = pool.get();
        assert_eq!(format!("{:?}", x), "Item { item: Some(0) }");
    }

    #[test]
    fn timeout_error() {
        assert_eq!(format!("{}", TimeoutError), "wait timed out");
        assert_eq!(TimeoutError.description(), "wait timed out");
    }
}
<|endoftext|>


<commit_before>/*!
Rust bindings to the [sodium library](https://github.com/jedisct1/libsodium).

Sodium is a portable implementation of Dan Bernsteins [NaCl: Networking and
Cryptography library](http://nacl.cr.yp.to)

For most users, if you want public-key (asymmetric) cryptography you should use
the functions in `crypto::asymmetricbox` for encryption/decryption.

If you want secret-key (symmetric) cryptography you should be using the
functions in `crypto::secretbox` for encryption/decryption.

For public-key signatures you should use the functions in `crypto::sign` for
signature creation and verification.

Unless you know what you're doing you most certainly don't want to use the
functions in `crypto::scalarmult`, `crypto::stream`, `crypto::auth` and
`crypto::onetimeauth`.

## Thread Safety
All functions in this library are thread-safe provided that the `init()`
function has been called during program execution.

If `init()` hasn't been called then all functions except the random-number
generation functions and the key-generation functions are thread-safe.

# Public-key cryptography
 `crypto::asymmetricbox`

 `crypto::sign`

# Secret-key cryptography
 `crypto::secretbox`

 `crypto::stream`

 `crypto::auth`

 `crypto::onetimeauth`

# Low-level functions
 `crypto::hash`

 `crypto::verify`

 `crypto::shorthash`
 */
#![crate_name = "sodiumoxide"]
#![crate_type = "lib"]
#![warn(missing_docs)]
#![warn(non_upper_case_globals)]
#![warn(non_camel_case_types)]
#![warn(unused_qualifications)]
#![feature(globs)]
#![feature(macro_rules)]

extern crate "libsodium-sys" as ffi;
extern crate libc;

/**
 * `init()` initializes the sodium library and chooses faster versions of
 * the primitives if possible. `init()` also makes the random number generation
 * functions (`gen_key`, `gen_keypair`, `gen_nonce`, `randombytes`, `randombytes_into`)
 * thread-safe
 */
pub fn init() -> bool {
    unsafe {
        ffi::sodium_init() == 0
    }
}

mod utils;

pub mod randombytes;

/**
 * Cryptographic functions
 */
pub mod crypto {
    pub mod asymmetricbox;
    pub mod sign;
    pub mod scalarmult;
    pub mod auth;
    pub mod hash;
    pub mod secretbox;
    pub mod onetimeauth;
    pub mod stream;
    pub mod shorthash;
    pub mod verify;
}

<commit_msg>removed #[feature(globs)]<commit_after>/*!
Rust bindings to the [sodium library](https://github.com/jedisct1/libsodium).

Sodium is a portable implementation of Dan Bernsteins [NaCl: Networking and
Cryptography library](http://nacl.cr.yp.to)

For most users, if you want public-key (asymmetric) cryptography you should use
the functions in `crypto::asymmetricbox` for encryption/decryption.

If you want secret-key (symmetric) cryptography you should be using the
functions in `crypto::secretbox` for encryption/decryption.

For public-key signatures you should use the functions in `crypto::sign` for
signature creation and verification.

Unless you know what you're doing you most certainly don't want to use the
functions in `crypto::scalarmult`, `crypto::stream`, `crypto::auth` and
`crypto::onetimeauth`.

## Thread Safety
All functions in this library are thread-safe provided that the `init()`
function has been called during program execution.

If `init()` hasn't been called then all functions except the random-number
generation functions and the key-generation functions are thread-safe.

# Public-key cryptography
 `crypto::asymmetricbox`

 `crypto::sign`

# Secret-key cryptography
 `crypto::secretbox`

 `crypto::stream`

 `crypto::auth`

 `crypto::onetimeauth`

# Low-level functions
 `crypto::hash`

 `crypto::verify`

 `crypto::shorthash`
 */
#![crate_name = "sodiumoxide"]
#![crate_type = "lib"]
#![warn(missing_docs)]
#![warn(non_upper_case_globals)]
#![warn(non_camel_case_types)]
#![warn(unused_qualifications)]
#![feature(macro_rules)]

extern crate "libsodium-sys" as ffi;
extern crate libc;

/**
 * `init()` initializes the sodium library and chooses faster versions of
 * the primitives if possible. `init()` also makes the random number generation
 * functions (`gen_key`, `gen_keypair`, `gen_nonce`, `randombytes`, `randombytes_into`)
 * thread-safe
 */
pub fn init() -> bool {
    unsafe {
        ffi::sodium_init() == 0
    }
}

mod utils;

pub mod randombytes;

/**
 * Cryptographic functions
 */
pub mod crypto {
    pub mod asymmetricbox;
    pub mod sign;
    pub mod scalarmult;
    pub mod auth;
    pub mod hash;
    pub mod secretbox;
    pub mod onetimeauth;
    pub mod stream;
    pub mod shorthash;
    pub mod verify;
}

<|endoftext|>


<commit_before>//! Read ASPRS las files.

extern crate byteorder;
#[macro_use]
extern crate enum_primitive;
extern crate num;
extern crate rustc_serialize;

use std::result;

// Macros
#[macro_use]
pub mod macros;

// Private modules
mod io;

// Public modules
pub mod header;
pub mod point;
pub mod reader;
pub mod vlr;

pub use header::Header;
pub use point::Point;
pub use reader::Reader;
pub use vlr::Vlr;

#[derive(Debug)]
enum Error {
    ByteorderError(byteorder::Error),
    CharacterAfterNullByte,
    IoError(std::io::Error),
    ReadError(String),
}

impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Error {
        Error::IoError(err)
    }
}

impl From<byteorder::Error> for Error {
    fn from(err: byteorder::Error) -> Error {
        Error::ByteorderError(err)
    }
}

pub type Result<T> = result::Result<T, Error>;
<commit_msg>Make las::io public<commit_after>//! Read ASPRS las files.

extern crate byteorder;
#[macro_use]
extern crate enum_primitive;
extern crate num;
extern crate rustc_serialize;

use std::result;

// Macros
#[macro_use]
pub mod macros;

// Public modules
pub mod header;
pub mod io;
pub mod point;
pub mod reader;
pub mod vlr;

pub use header::Header;
pub use point::Point;
pub use reader::Reader;
pub use vlr::Vlr;

#[derive(Debug)]
enum Error {
    ByteorderError(byteorder::Error),
    CharacterAfterNullByte,
    IoError(std::io::Error),
    ReadError(String),
}

impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Error {
        Error::IoError(err)
    }
}

impl From<byteorder::Error> for Error {
    fn from(err: byteorder::Error) -> Error {
        Error::ByteorderError(err)
    }
}

pub type Result<T> = result::Result<T, Error>;
<|endoftext|>