<commit_before>extern crate robin_core;

#[cfg(test)]
mod parser_tests {
    use robin_core::parser;
    use robin_core::ast::Expression;
    use robin_core::error::{Error, ErrorLevel, ErrorKind};

    #[test]
    fn booleans_should_return_a_boolean_node() {
        assert_eq!(parser::parse("true"), Ok(Expression::Boolean(true)))
    }

    #[test]
    fn identifiers_that_look_like_booleans_should_return_identifiers() {
        assert_eq!(parser::parse("truedog"),
                   Ok(Expression::Identifier("truedog".to_string())))
    }

    #[test]
    fn identifiers_should_return_a_identifier_node() {
        assert_eq!(parser::parse("hello"),
                   Ok(Expression::Identifier("hello".to_string())))
    }

    #[test]
    fn decimals_should_return_a_number_node() {
        assert_eq!(parser::parse("47"), Ok(Expression::Number(47.0)))
    }

    #[test]
    fn exponents_should_return_a_number_node() {
        assert_eq!(parser::parse("5e1"), Ok(Expression::Number(50.0)))
    }

    #[test]
    fn binary_should_return_a_number_node() {
        assert_eq!(parser::parse("0b1"), Ok(Expression::Number(1.0)))
    }

    #[test]
    fn octal_should_return_a_number_node() {
        assert_eq!(parser::parse("0o2"), Ok(Expression::Number(2.0)))
    }

    #[test]
    fn hexadecimal_should_return_a_number_node() {
        assert_eq!(parser::parse("0xA"), Ok(Expression::Number(10.0)))
    }

    #[test]
    fn list_should_return_a_list_node() {
        let expr = Expression::List(vec![Box::new(Expression::Boolean(true))]);

        assert_eq!(parser::parse("[true]"), Ok(expr));
    }

    #[test]
    fn function_literal_should_return_a_function_literal_node() {
        let expr = Expression::FuncLiteral("example".to_string(),
                                           vec!["x".to_string()],
                                           Box::new(Expression::Boolean(true)));

        assert_eq!(parser::parse("(example [x] true)"), Ok(expr));
    }

    #[test]
    fn function_literal_with_multiple_arguments() {
        let expr = Expression::FuncLiteral("example".to_string(),
                                           vec!["x".to_string(), "y".to_string()],
                                           Box::new(Expression::Boolean(true)));

        assert_eq!(parser::parse("(example [x y] true)"), Ok(expr));
    }

    #[test]
    fn function_call_should_return_a_function_call_node() {
        let expr = Expression::FuncCall("example".to_string(),
                                        vec![Box::new(Expression::Boolean(true))]);

        assert_eq!(parser::parse("(example true)"), Ok(expr));
    }

    #[test]
    fn function_call_with_multiple_arguments() {
        let expr = Expression::FuncCall("example".to_string(),
                                        vec![Box::new(Expression::Boolean(true)),
                                             Box::new(Expression::Boolean(false))]);

        assert_eq!(parser::parse("(example true false)"), Ok(expr));
    }
}
<commit_msg>Remove imports<commit_after>extern crate robin_core;

#[cfg(test)]
mod parser_tests {
    use robin_core::parser;
    use robin_core::ast::Expression;

    #[test]
    fn booleans_should_return_a_boolean_node() {
        assert_eq!(parser::parse("true"), Ok(Expression::Boolean(true)))
    }

    #[test]
    fn identifiers_that_look_like_booleans_should_return_identifiers() {
        assert_eq!(parser::parse("truedog"),
                   Ok(Expression::Identifier("truedog".to_string())))
    }

    #[test]
    fn identifiers_should_return_a_identifier_node() {
        assert_eq!(parser::parse("hello"),
                   Ok(Expression::Identifier("hello".to_string())))
    }

    #[test]
    fn decimals_should_return_a_number_node() {
        assert_eq!(parser::parse("47"), Ok(Expression::Number(47.0)))
    }

    #[test]
    fn exponents_should_return_a_number_node() {
        assert_eq!(parser::parse("5e1"), Ok(Expression::Number(50.0)))
    }

    #[test]
    fn binary_should_return_a_number_node() {
        assert_eq!(parser::parse("0b1"), Ok(Expression::Number(1.0)))
    }

    #[test]
    fn octal_should_return_a_number_node() {
        assert_eq!(parser::parse("0o2"), Ok(Expression::Number(2.0)))
    }

    #[test]
    fn hexadecimal_should_return_a_number_node() {
        assert_eq!(parser::parse("0xA"), Ok(Expression::Number(10.0)))
    }

    #[test]
    fn list_should_return_a_list_node() {
        let expr = Expression::List(vec![Box::new(Expression::Boolean(true))]);

        assert_eq!(parser::parse("[true]"), Ok(expr));
    }

    #[test]
    fn function_literal_should_return_a_function_literal_node() {
        let expr = Expression::FuncLiteral("example".to_string(),
                                           vec!["x".to_string()],
                                           Box::new(Expression::Boolean(true)));

        assert_eq!(parser::parse("(example [x] true)"), Ok(expr));
    }

    #[test]
    fn function_literal_with_multiple_arguments() {
        let expr = Expression::FuncLiteral("example".to_string(),
                                           vec!["x".to_string(), "y".to_string()],
                                           Box::new(Expression::Boolean(true)));

        assert_eq!(parser::parse("(example [x y] true)"), Ok(expr));
    }

    #[test]
    fn function_call_should_return_a_function_call_node() {
        let expr = Expression::FuncCall("example".to_string(),
                                        vec![Box::new(Expression::Boolean(true))]);

        assert_eq!(parser::parse("(example true)"), Ok(expr));
    }

    #[test]
    fn function_call_with_multiple_arguments() {
        let expr = Expression::FuncCall("example".to_string(),
                                        vec![Box::new(Expression::Boolean(true)),
                                             Box::new(Expression::Boolean(false))]);

        assert_eq!(parser::parse("(example true false)"), Ok(expr));
    }
}
<|endoftext|>


<commit_before>//! ----------------------------------------------
//! Framework <https://github.com/vain0x/procon>
//!
//! See the bottom of file for solution.
//! ----------------------------------------------

#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Display, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;

/// Print values to standard error if debug mode.
#[allow(unused_macros)]
macro_rules! debug {
    ($($e:expr),*) => {
        #[cfg(debug_assertions)]
        $({
            let (e, mut err) = (stringify!($e), stderr());
            writeln!(err, "\x1B[33m{}\x1B[0m = {:?}", e, $e).unwrap()
        })*
    };
}

/// Read from standard input and parse each word.
/// - `read!(T, U, ..)` parses a line as a tuple of words.
/// - `read![[T]]` parses a line as an array of words.
/// - `read![..; N]` parses `N` lines, using `read!(..)` repeatedly.
#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

/// Read a line from standard input.
#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();

    #[allow(deprecated)]
    buf.trim_right().to_owned()
}

// -----------------------------------------------
// Solution
// -----------------------------------------------

fn main() {
    println!("{}", 0)
}
<commit_msg>refactor: フレームワークを少し簡略化<commit_after>//! Framework <https://github.com/vain0x/procon>

#![allow(non_snake_case)]
#![allow(unused_imports)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Display, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, BufRead, Write};

/// Print values to standard error if debug mode.
#[allow(unused_macros)]
macro_rules! debug {
    ($($e:expr),*) => {
        #[cfg(debug_assertions)]
        $({
            let (e, mut err) = (stringify!($e), stderr());
            writeln!(err, "\x1B[33m{}\x1B[0m = {:?}", e, $e).unwrap()
        })*
    };
}

/// Read from standard input and parse each word.
/// - `read!(T, U, ..)` parses a line as a tuple of words.
/// - `read![[T]]` parses a line as an array of words.
/// - `read![..; N]` parses `N` lines, using `read!(..)` repeatedly.
#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

/// Read a line from standard input.
#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();

    #[allow(deprecated)]
    buf.trim_right().to_owned()
}

// ###############################################

fn main() {
    println!("{}", 0)
}
<|endoftext|>


<commit_before>extern crate robin_core;

extern crate nom;

#[cfg(test)]
mod parser_tests {
    use nom::IResult;

    use robin_core::parser::identifier;
    use robin_core::ast::Expression;

    // I think this test is correct
    #[test]
    fn do_not_parse_a_symbol_then_an_alpha() {
        assert_ne!(identifier::identifier_literal(b"+g"),
                   IResult::Done(&b""[..], Expression::Identifier("+g".to_string())));
    }

    #[test]
    fn parse_a_left_brace() {
        assert_eq!(identifier::symbol_identifier(b"{"),
                   IResult::Done(&b""[..], "{".to_string()));
    }

    #[test]
    fn parse_a_right_brace() {
        assert_eq!(identifier::symbol_identifier(b"}"),
                   IResult::Done(&b""[..], "}".to_string()));
    }

    #[test]
    fn parse_a_left_bracket() {
        assert_eq!(identifier::symbol_identifier(b"("),
                   IResult::Done(&b""[..], "(".to_string()));
    }

    #[test]
    fn parse_a_right_bracket() {
        assert_eq!(identifier::symbol_identifier(b")"),
                   IResult::Done(&b""[..], ")".to_string()));
    }

    #[test]
    fn parse_a_left_square_bracket() {
        assert_eq!(identifier::symbol_identifier(b"["),
                   IResult::Done(&b""[..], "[".to_string()));
    }

    #[test]
    fn parse_a_right_square_bracket() {
        assert_eq!(identifier::symbol_identifier(b"]"),
                   IResult::Done(&b""[..], "]".to_string()));
    }

    #[test]
    fn parse_a_fullstop() {
        assert_eq!(identifier::symbol_identifier(b"."),
                   IResult::Done(&b""[..], ".".to_string()));
    }

    #[test]
    fn parse_a_semicolon() {
        assert_eq!(identifier::symbol_identifier(b";"),
                   IResult::Done(&b""[..], ";".to_string()));
    }

    #[test]
    fn parse_a_comma() {
        assert_eq!(identifier::symbol_identifier(b","),
                   IResult::Done(&b""[..], ",".to_string()));
    }

    #[test]
    fn parse_less_than() {
        assert_eq!(identifier::symbol_identifier(b"<"),
                   IResult::Done(&b""[..], "<".to_string()));
    }

    #[test]
    fn parse_greater_than() {
        assert_eq!(identifier::symbol_identifier(b">"),
                   IResult::Done(&b""[..], ">".to_string()));
    }

    #[test]
    fn parse_equals() {
        assert_eq!(identifier::symbol_identifier(b"="),
                   IResult::Done(&b""[..], "=".to_string()));
    }

    #[test]
    fn parse_exclamation() {
        assert_eq!(identifier::symbol_identifier(b"!"),
                   IResult::Done(&b""[..], "!".to_string()));
    }

    #[test]
    fn parse_plus() {
        assert_eq!(identifier::symbol_identifier(b"+"),
                   IResult::Done(&b""[..], "+".to_string()));
    }

    #[test]
    fn parse_minus() {
        assert_eq!(identifier::symbol_identifier(b"-"),
                   IResult::Done(&b""[..], "-".to_string()));
    }

    #[test]
    fn parse_times() {
        assert_eq!(identifier::symbol_identifier(b"*"),
                   IResult::Done(&b""[..], "*".to_string()));
    }

    #[test]
    fn parse_divide() {
        assert_eq!(identifier::symbol_identifier(b"/"),
                   IResult::Done(&b""[..], "/".to_string()));
    }

    #[test]
    fn parse_ampersand() {
        assert_eq!(identifier::symbol_identifier(b"&"),
                   IResult::Done(&b""[..], "&".to_string()));
    }

    #[test]
    fn parse_pipe() {
        assert_eq!(identifier::symbol_identifier(b"|"),
                   IResult::Done(&b""[..], "|".to_string()));
    }

    #[test]
    fn parse_power_of() {
        assert_eq!(identifier::symbol_identifier(b"^"),
                   IResult::Done(&b""[..], "^".to_string()));
    }

    #[test]
    fn parse_tilde() {
        assert_eq!(identifier::symbol_identifier(b"~"),
                   IResult::Done(&b""[..], "~".to_string()));
    }

    #[test]
    fn parse_question() {
        assert_eq!(identifier::symbol_identifier(b"?"),
                   IResult::Done(&b""[..], "?".to_string()));
    }

    #[test]
    fn parse_colon() {
        assert_eq!(identifier::symbol_identifier(b":"),
                   IResult::Done(&b""[..], ":".to_string()));
    }

    #[test]
    fn parse_multiple_symbols() {
        assert_eq!(identifier::symbol_identifier(b"|>+"),
                   IResult::Done(&b""[..], "|>+".to_string()));
    }

    #[test]
    fn parse_a_single_alpha_identifier() {
        assert_eq!(identifier::alpha_identifier(b"g"),
                   IResult::Done(&b""[..], "g".to_string()));
    }

    #[test]
    fn parse_multiple_alpha_identifiers() {
        assert_eq!(identifier::alpha_identifier(b"gbd"),
                   IResult::Done(&b""[..], "gbd".to_string()));
    }

    #[test]
    fn parse_a_symbol_and_an_alpha() {
        assert_eq!(identifier::alpha_identifier(b"gg{"),
                   IResult::Done(&b""[..], "gg{".to_string()));
    }
}
<commit_msg>Change parser test<commit_after>extern crate robin_core;

extern crate nom;

#[cfg(test)]
mod parser_tests {
    use nom::IResult;

    use robin_core::parser::identifier;
    use robin_core::ast::Expression;

    // I think this test is correct
    #[test]
    fn do_not_parse_a_symbol_then_an_alpha() {
        assert_ne!(identifier::identifier_literal(b"+g"),
                   IResult::Done(&b""[..], Expression::Identifier("+g".to_string())));
    }

    #[test]
    fn parse_a_left_brace() {
        assert_eq!(identifier::symbol_identifier(b"{"),
                   IResult::Done(&b""[..], "{".to_string()));
    }

    #[test]
    fn parse_a_right_brace() {
        assert_eq!(identifier::symbol_identifier(b"}"),
                   IResult::Done(&b""[..], "}".to_string()));
    }

    #[test]
    fn parse_a_left_bracket() {
        assert_eq!(identifier::symbol_identifier(b"("),
                   IResult::Done(&b""[..], "(".to_string()));
    }

    #[test]
    fn parse_a_right_bracket() {
        assert_eq!(identifier::symbol_identifier(b")"),
                   IResult::Done(&b""[..], ")".to_string()));
    }

    #[test]
    fn parse_a_left_square_bracket() {
        assert_eq!(identifier::symbol_identifier(b"["),
                   IResult::Done(&b""[..], "[".to_string()));
    }

    #[test]
    fn parse_a_right_square_bracket() {
        assert_eq!(identifier::symbol_identifier(b"]"),
                   IResult::Done(&b""[..], "]".to_string()));
    }

    #[test]
    fn parse_a_fullstop() {
        assert_eq!(identifier::symbol_identifier(b"."),
                   IResult::Done(&b""[..], ".".to_string()));
    }

    #[test]
    fn parse_a_semicolon() {
        assert_eq!(identifier::symbol_identifier(b";"),
                   IResult::Done(&b""[..], ";".to_string()));
    }

    #[test]
    fn parse_a_comma() {
        assert_eq!(identifier::symbol_identifier(b","),
                   IResult::Done(&b""[..], ",".to_string()));
    }

    #[test]
    fn parse_less_than() {
        assert_eq!(identifier::symbol_identifier(b"<"),
                   IResult::Done(&b""[..], "<".to_string()));
    }

    #[test]
    fn parse_greater_than() {
        assert_eq!(identifier::symbol_identifier(b">"),
                   IResult::Done(&b""[..], ">".to_string()));
    }

    #[test]
    fn parse_equals() {
        assert_eq!(identifier::symbol_identifier(b"="),
                   IResult::Done(&b""[..], "=".to_string()));
    }

    #[test]
    fn parse_exclamation() {
        assert_eq!(identifier::symbol_identifier(b"!"),
                   IResult::Done(&b""[..], "!".to_string()));
    }

    #[test]
    fn parse_plus() {
        assert_eq!(identifier::symbol_identifier(b"+"),
                   IResult::Done(&b""[..], "+".to_string()));
    }

    #[test]
    fn parse_minus() {
        assert_eq!(identifier::symbol_identifier(b"-"),
                   IResult::Done(&b""[..], "-".to_string()));
    }

    #[test]
    fn parse_times() {
        assert_eq!(identifier::symbol_identifier(b"*"),
                   IResult::Done(&b""[..], "*".to_string()));
    }

    #[test]
    fn parse_divide() {
        assert_eq!(identifier::symbol_identifier(b"/"),
                   IResult::Done(&b""[..], "/".to_string()));
    }

    #[test]
    fn parse_ampersand() {
        assert_eq!(identifier::symbol_identifier(b"&"),
                   IResult::Done(&b""[..], "&".to_string()));
    }

    #[test]
    fn parse_pipe() {
        assert_eq!(identifier::symbol_identifier(b"|"),
                   IResult::Done(&b""[..], "|".to_string()));
    }

    #[test]
    fn parse_power_of() {
        assert_eq!(identifier::symbol_identifier(b"^"),
                   IResult::Done(&b""[..], "^".to_string()));
    }

    #[test]
    fn parse_tilde() {
        assert_eq!(identifier::symbol_identifier(b"~"),
                   IResult::Done(&b""[..], "~".to_string()));
    }

    #[test]
    fn parse_question() {
        assert_eq!(identifier::symbol_identifier(b"?"),
                   IResult::Done(&b""[..], "?".to_string()));
    }

    #[test]
    fn parse_colon() {
        assert_eq!(identifier::symbol_identifier(b":"),
                   IResult::Done(&b""[..], ":".to_string()));
    }

    #[test]
    fn parse_multiple_symbols() {
        assert_eq!(identifier::symbol_identifier(b"|>+"),
                   IResult::Done(&b""[..], "|>+".to_string()));
    }

    #[test]
    fn parse_a_single_alpha_identifier() {
        assert_eq!(identifier::alpha_identifier(b"g"),
                   IResult::Done(&b""[..], "g".to_string()));
    }

    #[test]
    fn parse_multiple_alpha_identifiers() {
        assert_eq!(identifier::alpha_identifier(b"gbd"),
                   IResult::Done(&b""[..], "gbd".to_string()));
    }

    #[test]
    fn do_not_parse_a_symbol_and_an_alpha() {
        assert_eq!(identifier::alpha_identifier(b"gg{"),
                   IResult::Done(&b"{"[..], "gg".to_string()));
    }
}
<|endoftext|>


<commit_before>//! Type conversions for binding parameters and getting query results.

use super::{PreparedStatement, ResultRow,
            ColIx, ParamIx};
use super::{
    SqliteResult, SqliteErrorCode, SqliteError,
};
use super::ColumnType::SQLITE_NULL;

use time;

/// Values that can be bound to parameters in prepared statements.
pub trait ToSql {
    /// Bind the `ix`th parameter to this value (`self`).
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()>;
}

/// A trait for result values from a query.
///
/// cf [sqlite3 result values][column].
///
/// *inspired by sfackler's FromSql (and some haskell bindings?)*
///
/// [column]: http://www.sqlite.org/c3ref/column_blob.html
///
///   - *TODO: consider a `types` submodule*
///   - *TODO: many more implementors, including Option<T>*
pub trait FromSql {
    /// Try to extract a `Self` type value from the `col`th colum of a `ResultRow`.
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<Self>;
}

impl ToSql for i32 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int(ix, *self)
    }
}

impl FromSql for i32 {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<i32> { Ok(row.column_int(col)) }
}

impl ToSql for i64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int64(ix, *self)
    }
}

impl FromSql for i64 {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<i64> { Ok(row.column_int64(col)) }
}

impl ToSql for f64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_double(ix, *self)
    }
}

impl FromSql for f64 {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<f64> { Ok(row.column_double(col)) }
}

impl ToSql for u64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int64(ix as i64, *self);
    }
}

impl FromSql for u64 {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<i64> {
        Ok(row.column_int64(col) as u64);
    }
}

impl ToSql for bool {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int(ix, if *self { 1 } else { 0 })
    }
}

impl FromSql for bool {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<bool> { Ok(row.column_int(col)!=0) }
}

impl<T: ToSql + Clone> ToSql for Option<T> {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        match (*self).clone() {
            Some(x) => x.to_sql(s, ix),
            None => s.bind_null(ix)
        }
    }
}

impl<T: FromSql + Clone> FromSql for Option<T> {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<Option<T>> {
        match row.column_type(col) {
            SQLITE_NULL => Ok(None),
            _ => FromSql::from_sql(row, col).map(|x| Some(x))
        }
    }
}

impl ToSql for String {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_text(ix, (*self).as_ref())
    }
}

impl FromSql for String {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<String> {
        Ok(row.column_text(col).unwrap_or(String::new()))
    }
}

impl<'a> ToSql for &'a [u8] {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_blob(ix, *self)
    }
}

impl FromSql for Vec<u8> {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<Vec<u8>> {
        Ok(row.column_blob(col).unwrap_or(Vec::new()))
    }
}

/// Format of sqlite date strings
///
/// From [Date And Time Functions][lang_datefunc]:
/// > The datetime() function returns "YYYY-MM-DD HH:MM:SS"
/// [lang_datefunc]: http://www.sqlite.org/lang_datefunc.html
pub static SQLITE_TIME_FMT: &'static str = "%F %T";

impl FromSql for time::Tm {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<time::Tm> {
        let txt = row.column_text(col).unwrap_or(String::new());
        Ok( try!(time::strptime(txt.as_ref(), SQLITE_TIME_FMT)) )
    }
}

impl From<time::ParseError> for SqliteError {
    fn from(err: time::ParseError) -> SqliteError {
        SqliteError {
            kind: SqliteErrorCode::SQLITE_MISMATCH,
            desc: "Time did not match expected format",
            detail: Some(format!("Time parsing error: {}", err)),
        }
    }
}

impl ToSql for time::Timespec {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        let timestr = time::at_utc(*self).strftime(SQLITE_TIME_FMT)
            .unwrap() // unit tests ensure SQLITE_TIME_FMT is ok
            .to_string();
        s.bind_text(ix, timestr.as_ref())
    }
}

impl FromSql for time::Timespec {
    /// TODO: propagate error message
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<time::Timespec> {
        let tmo: SqliteResult<time::Tm> = FromSql::from_sql(row, col);
        tmo.map(|tm| tm.to_timespec())
    }
}

#[cfg(test)]
mod tests {
    use time::Tm;
    use super::super::{DatabaseConnection, SqliteResult, ResultSet};
    use super::super::{ResultRowAccess};

    fn with_query<T, F>(sql: &str, mut f: F) -> SqliteResult<T>
        where F: FnMut(&mut ResultSet) -> T
    {
        let db = try!(DatabaseConnection::in_memory());
        let mut s = try!(db.prepare(sql));
        let mut rows = s.execute();
        Ok(f(&mut rows))
    }

    #[test]
    fn get_tm() {
        fn go() -> SqliteResult<()> {
            let conn = try!(DatabaseConnection::in_memory());
            let mut stmt = try!(
                conn.prepare("select datetime('2001-01-01', 'weekday 3', '3 hours')"));
            let mut results = stmt.execute();
            match results.step() {
                Ok(Some(ref mut row)) => {
                    assert_eq!(
                        row.get::<u32, Tm>(0),
                        Tm { tm_sec: 0,
                             tm_min: 0,
                             tm_hour: 3,
                             tm_mday: 3,
                             tm_mon: 0,
                             tm_year: 101,
                             tm_wday: 0,
                             tm_yday: 0,
                             tm_isdst: 0,
                             tm_utcoff: 0,
                             tm_nsec: 0
                        });
                    Ok(())
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            }
        }
        go().unwrap();
    }

    #[test]
    fn get_invalid_tm() {
        with_query("select 'not a time'", |results| {
            match results.step() {
                Ok(Some(ref mut row)) => {
                    let x : SqliteResult<Tm> = row.get_opt(0u32);
                    assert!(x.is_err());
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            };
        }).unwrap();
    }

    #[test]
    fn select_blob() {
        with_query("select x'ff0db0'", |results| {
            match results.step() {
                Ok(Some(ref mut row)) => {
                    let x : SqliteResult<Vec<u8>> = row.get_opt(0u32);
                    assert_eq!(x.ok().unwrap(), [0xff, 0x0d, 0xb0].to_vec());
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            };
        }).unwrap();
    }
}

// Local Variables:
// flycheck-rust-crate-root: "lib.rs"
// End:
<commit_msg>forgot to change return type<commit_after>//! Type conversions for binding parameters and getting query results.

use super::{PreparedStatement, ResultRow,
            ColIx, ParamIx};
use super::{
    SqliteResult, SqliteErrorCode, SqliteError,
};
use super::ColumnType::SQLITE_NULL;

use time;

/// Values that can be bound to parameters in prepared statements.
pub trait ToSql {
    /// Bind the `ix`th parameter to this value (`self`).
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()>;
}

/// A trait for result values from a query.
///
/// cf [sqlite3 result values][column].
///
/// *inspired by sfackler's FromSql (and some haskell bindings?)*
///
/// [column]: http://www.sqlite.org/c3ref/column_blob.html
///
///   - *TODO: consider a `types` submodule*
///   - *TODO: many more implementors, including Option<T>*
pub trait FromSql {
    /// Try to extract a `Self` type value from the `col`th colum of a `ResultRow`.
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<Self>;
}

impl ToSql for i32 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int(ix, *self)
    }
}

impl FromSql for i32 {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<i32> { Ok(row.column_int(col)) }
}

impl ToSql for i64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int64(ix, *self)
    }
}

impl FromSql for i64 {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<i64> { Ok(row.column_int64(col)) }
}

impl ToSql for f64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_double(ix, *self)
    }
}

impl FromSql for f64 {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<f64> { Ok(row.column_double(col)) }
}

impl ToSql for u64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int64(ix as i64, *self);
    }
}

impl FromSql for u64 {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<u64> {
        Ok(row.column_int64(col) as u64);
    }
}

impl ToSql for bool {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int(ix, if *self { 1 } else { 0 })
    }
}

impl FromSql for bool {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<bool> { Ok(row.column_int(col)!=0) }
}

impl<T: ToSql + Clone> ToSql for Option<T> {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        match (*self).clone() {
            Some(x) => x.to_sql(s, ix),
            None => s.bind_null(ix)
        }
    }
}

impl<T: FromSql + Clone> FromSql for Option<T> {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<Option<T>> {
        match row.column_type(col) {
            SQLITE_NULL => Ok(None),
            _ => FromSql::from_sql(row, col).map(|x| Some(x))
        }
    }
}

impl ToSql for String {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_text(ix, (*self).as_ref())
    }
}

impl FromSql for String {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<String> {
        Ok(row.column_text(col).unwrap_or(String::new()))
    }
}

impl<'a> ToSql for &'a [u8] {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_blob(ix, *self)
    }
}

impl FromSql for Vec<u8> {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<Vec<u8>> {
        Ok(row.column_blob(col).unwrap_or(Vec::new()))
    }
}

/// Format of sqlite date strings
///
/// From [Date And Time Functions][lang_datefunc]:
/// > The datetime() function returns "YYYY-MM-DD HH:MM:SS"
/// [lang_datefunc]: http://www.sqlite.org/lang_datefunc.html
pub static SQLITE_TIME_FMT: &'static str = "%F %T";

impl FromSql for time::Tm {
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<time::Tm> {
        let txt = row.column_text(col).unwrap_or(String::new());
        Ok( try!(time::strptime(txt.as_ref(), SQLITE_TIME_FMT)) )
    }
}

impl From<time::ParseError> for SqliteError {
    fn from(err: time::ParseError) -> SqliteError {
        SqliteError {
            kind: SqliteErrorCode::SQLITE_MISMATCH,
            desc: "Time did not match expected format",
            detail: Some(format!("Time parsing error: {}", err)),
        }
    }
}

impl ToSql for time::Timespec {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        let timestr = time::at_utc(*self).strftime(SQLITE_TIME_FMT)
            .unwrap() // unit tests ensure SQLITE_TIME_FMT is ok
            .to_string();
        s.bind_text(ix, timestr.as_ref())
    }
}

impl FromSql for time::Timespec {
    /// TODO: propagate error message
    fn from_sql(row: &ResultRow, col: ColIx) -> SqliteResult<time::Timespec> {
        let tmo: SqliteResult<time::Tm> = FromSql::from_sql(row, col);
        tmo.map(|tm| tm.to_timespec())
    }
}

#[cfg(test)]
mod tests {
    use time::Tm;
    use super::super::{DatabaseConnection, SqliteResult, ResultSet};
    use super::super::{ResultRowAccess};

    fn with_query<T, F>(sql: &str, mut f: F) -> SqliteResult<T>
        where F: FnMut(&mut ResultSet) -> T
    {
        let db = try!(DatabaseConnection::in_memory());
        let mut s = try!(db.prepare(sql));
        let mut rows = s.execute();
        Ok(f(&mut rows))
    }

    #[test]
    fn get_tm() {
        fn go() -> SqliteResult<()> {
            let conn = try!(DatabaseConnection::in_memory());
            let mut stmt = try!(
                conn.prepare("select datetime('2001-01-01', 'weekday 3', '3 hours')"));
            let mut results = stmt.execute();
            match results.step() {
                Ok(Some(ref mut row)) => {
                    assert_eq!(
                        row.get::<u32, Tm>(0),
                        Tm { tm_sec: 0,
                             tm_min: 0,
                             tm_hour: 3,
                             tm_mday: 3,
                             tm_mon: 0,
                             tm_year: 101,
                             tm_wday: 0,
                             tm_yday: 0,
                             tm_isdst: 0,
                             tm_utcoff: 0,
                             tm_nsec: 0
                        });
                    Ok(())
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            }
        }
        go().unwrap();
    }

    #[test]
    fn get_invalid_tm() {
        with_query("select 'not a time'", |results| {
            match results.step() {
                Ok(Some(ref mut row)) => {
                    let x : SqliteResult<Tm> = row.get_opt(0u32);
                    assert!(x.is_err());
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            };
        }).unwrap();
    }

    #[test]
    fn select_blob() {
        with_query("select x'ff0db0'", |results| {
            match results.step() {
                Ok(Some(ref mut row)) => {
                    let x : SqliteResult<Vec<u8>> = row.get_opt(0u32);
                    assert_eq!(x.ok().unwrap(), [0xff, 0x0d, 0xb0].to_vec());
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            };
        }).unwrap();
    }
}

// Local Variables:
// flycheck-rust-crate-root: "lib.rs"
// End:
<|endoftext|>


<commit_before>//! Custom input types
//!

use traits::{AsBytes, AtEof, Compare, CompareResult, ExtendInto, FindSubstring, FindToken, InputIter, InputLength, InputTake, Offset,
             ParseTo, Slice};

use std::str::{self, CharIndices, Chars, FromStr};
use std::ops::{Deref, Range, RangeFrom, RangeFull, RangeTo};
use std::iter::{Enumerate, Map};
use std::slice::Iter;

/// Holds a complete String, for which the `at_eof` method always returns true
///
/// This means that this input type will completely avoid nom's streaming features
/// and `Incomplete` results.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct CompleteStr<'a>(pub &'a str);

impl<'a> Deref for CompleteStr<'a> {
  type Target = str;

  fn deref(&self) -> &str {
    self.0
  }
}

impl<'a> AtEof for CompleteStr<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteStr<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteStr<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteStr<'a> {
  type Item = char;
  type RawItem = char;
  type Iter = CharIndices<'a>;
  type IterElem = Chars<'a>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteStr<'a> {
  fn take(&self, count: usize) -> Self {
    CompleteStr(self.0.take(count))
  }

  fn take_split(&self, count: usize) -> (Self, Self) {
    let (left, right) = self.0.take_split(count);
    (CompleteStr(left), CompleteStr(right))
  }
}

impl<'a> InputLength for CompleteStr<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteStr<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteStr<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteStr<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteStr<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteStr<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteStr<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse().ok()
  }
}

impl<'a> Offset for CompleteStr<'a> {
  fn offset(&self, second: &CompleteStr<'a>) -> usize {
    self.0.offset(second.0)
  }
}

impl<'a> AsBytes for CompleteStr<'a> {
  fn as_bytes(&self) -> &[u8] {
    AsBytes::as_bytes(self.0)
  }
}

#[cfg(feature = "std")]
impl<'a> ExtendInto for CompleteStr<'a> {
  type Item = char;
  type Extender = String;

  #[inline]
  fn new_builder(&self) -> String {
    String::new()
  }
  #[inline]
  fn extend_into(&self, acc: &mut String) {
    acc.extend(self.0.chars());
  }
}

/// Holds a complete String, for which the `at_eof` method always returns true
///
/// This means that this input type will completely avoid nom's streaming features
/// and `Incomplete` results.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct CompleteByteSlice<'a>(pub &'a [u8]);

impl<'a> Deref for CompleteByteSlice<'a> {
  type Target = [u8];

  fn deref(&self) -> &[u8] {
    self.0
  }
}

impl<'a> AtEof for CompleteByteSlice<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteByteSlice<'a> {
  type Item = u8;
  type RawItem = u8;
  type Iter = Enumerate<Self::IterElem>;
  type IterElem = Map<Iter<'a, Self::Item>, fn(&u8) -> u8>; //Iter<'a, Self::RawItem>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteByteSlice<'a> {
  fn take(&self, count: usize) -> Self {
    CompleteByteSlice(self.0.take(count))
  }

  fn take_split(&self, count: usize) -> (Self, Self) {
    let (left, right) = self.0.take_split(count);
    (CompleteByteSlice(left), CompleteByteSlice(right))
  }
}

impl<'a> InputLength for CompleteByteSlice<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b [u8]> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b [u8]> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b [u8]) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteByteSlice<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteByteSlice<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteByteSlice<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteByteSlice<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse_to()
  }
}

impl<'a> Offset for CompleteByteSlice<'a> {
  fn offset(&self, second: &CompleteByteSlice<'a>) -> usize {
    self.0.offset(second.0)
  }
}

impl<'a> AsBytes for CompleteByteSlice<'a> {
  fn as_bytes(&self) -> &[u8] {
    self.0.as_bytes()
  }
}

#[cfg(feature = "std")]
impl<'a> super::util::HexDisplay for CompleteByteSlice<'a> {
  fn to_hex(&self, chunk_size: usize) -> String {
    self.0.to_hex(chunk_size)
  }

  fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
    self.0.to_hex_from(chunk_size, from)
  }
}

#[derive(Clone, Copy, Debug, PartialEq, Hash)]
pub struct Input<T> {
  pub inner: T,
  pub at_eof: bool,
}

impl<T> AtEof for Input<T> {
  fn at_eof(&self) -> bool {
    self.at_eof
  }
}

impl<T: Slice<Range<usize>>> Slice<Range<usize>> for Input<T> {
  fn slice(&self, range: Range<usize>) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: Slice<RangeTo<usize>>> Slice<RangeTo<usize>> for Input<T> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: Slice<RangeFrom<usize>>> Slice<RangeFrom<usize>> for Input<T> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: Slice<RangeFull>> Slice<RangeFull> for Input<T> {
  fn slice(&self, range: RangeFull) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: InputIter> InputIter for Input<T> {
  type Item = <T as InputIter>::Item;
  type RawItem = <T as InputIter>::RawItem;
  type Iter = <T as InputIter>::Iter;
  type IterElem = <T as InputIter>::IterElem;

  fn iter_indices(&self) -> Self::Iter {
    self.inner.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.inner.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.inner.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.inner.slice_index(count)
  }
}

impl<T: InputTake> InputTake for Input<T> {
  fn take(&self, count: usize) -> Self {
    Input {
      inner: self.inner.take(count),
      at_eof: self.at_eof,
    }
  }

  fn take_split(&self, count: usize) -> (Self, Self) {
    let (left, right) = self.inner.take_split(count);
    (
      Input {
        inner: left,
        at_eof: self.at_eof,
      },
      Input {
        inner: right,
        at_eof: self.at_eof,
      },
    )
  }
}

impl<T: InputLength> InputLength for Input<T> {
  fn input_len(&self) -> usize {
    self.inner.input_len()
  }
}

impl<'b, T: Compare<&'b str>> Compare<&'b str> for Input<T> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.inner.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.inner.compare_no_case(t)
  }
}

impl<'b, T: FindSubstring<&'b str>> FindSubstring<&'b str> for Input<T> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.inner.find_substring(substr)
  }
}

impl<T: FindToken<char>> FindToken<char> for Input<T> {
  fn find_token(&self, token: char) -> bool {
    self.inner.find_token(token)
  }
}

impl<T: FindToken<u8>> FindToken<u8> for Input<T> {
  fn find_token(&self, token: u8) -> bool {
    self.inner.find_token(token)
  }
}

impl<'a, T: FindToken<&'a u8>> FindToken<&'a u8> for Input<T> {
  fn find_token(&self, token: &'a u8) -> bool {
    self.inner.find_token(token)
  }
}

impl<'a, R: FromStr, T: ParseTo<R>> ParseTo<R> for Input<T> {
  fn parse_to(&self) -> Option<R> {
    self.inner.parse_to()
  }
}

impl<T: Offset> Offset for Input<T> {
  fn offset(&self, second: &Input<T>) -> usize {
    self.inner.offset(&second.inner)
  }
}

impl<T: AsBytes> AsBytes for Input<T> {
  fn as_bytes(&self) -> &[u8] {
    AsBytes::as_bytes(&self.inner)
  }
}
<commit_msg>Add a conversion from &str to CompleteStr<commit_after>//! Custom input types
//!

use traits::{AsBytes, AtEof, Compare, CompareResult, ExtendInto, FindSubstring, FindToken, InputIter, InputLength, InputTake, Offset,
             ParseTo, Slice};

use std::str::{self, CharIndices, Chars, FromStr};
use std::convert::From;
use std::ops::{Deref, Range, RangeFrom, RangeFull, RangeTo};
use std::iter::{Enumerate, Map};
use std::slice::Iter;

/// Holds a complete String, for which the `at_eof` method always returns true
///
/// This means that this input type will completely avoid nom's streaming features
/// and `Incomplete` results.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct CompleteStr<'a>(pub &'a str);

impl<'a> From<&'a str> for CompleteStr<'a> {
  fn from(src: &'a str) -> Self {
    CompleteStr(src)
  }
}

impl<'a> Deref for CompleteStr<'a> {
  type Target = str;

  fn deref(&self) -> &str {
    self.0
  }
}

impl<'a> AtEof for CompleteStr<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteStr<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteStr<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteStr<'a> {
  type Item = char;
  type RawItem = char;
  type Iter = CharIndices<'a>;
  type IterElem = Chars<'a>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteStr<'a> {
  fn take(&self, count: usize) -> Self {
    CompleteStr(self.0.take(count))
  }

  fn take_split(&self, count: usize) -> (Self, Self) {
    let (left, right) = self.0.take_split(count);
    (CompleteStr(left), CompleteStr(right))
  }
}

impl<'a> InputLength for CompleteStr<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteStr<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteStr<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteStr<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteStr<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteStr<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteStr<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse().ok()
  }
}

impl<'a> Offset for CompleteStr<'a> {
  fn offset(&self, second: &CompleteStr<'a>) -> usize {
    self.0.offset(second.0)
  }
}

impl<'a> AsBytes for CompleteStr<'a> {
  fn as_bytes(&self) -> &[u8] {
    AsBytes::as_bytes(self.0)
  }
}

#[cfg(feature = "std")]
impl<'a> ExtendInto for CompleteStr<'a> {
  type Item = char;
  type Extender = String;

  #[inline]
  fn new_builder(&self) -> String {
    String::new()
  }
  #[inline]
  fn extend_into(&self, acc: &mut String) {
    acc.extend(self.0.chars());
  }
}

/// Holds a complete String, for which the `at_eof` method always returns true
///
/// This means that this input type will completely avoid nom's streaming features
/// and `Incomplete` results.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct CompleteByteSlice<'a>(pub &'a [u8]);

impl<'a> Deref for CompleteByteSlice<'a> {
  type Target = [u8];

  fn deref(&self) -> &[u8] {
    self.0
  }
}

impl<'a> AtEof for CompleteByteSlice<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteByteSlice<'a> {
  type Item = u8;
  type RawItem = u8;
  type Iter = Enumerate<Self::IterElem>;
  type IterElem = Map<Iter<'a, Self::Item>, fn(&u8) -> u8>; //Iter<'a, Self::RawItem>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteByteSlice<'a> {
  fn take(&self, count: usize) -> Self {
    CompleteByteSlice(self.0.take(count))
  }

  fn take_split(&self, count: usize) -> (Self, Self) {
    let (left, right) = self.0.take_split(count);
    (CompleteByteSlice(left), CompleteByteSlice(right))
  }
}

impl<'a> InputLength for CompleteByteSlice<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b [u8]> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b [u8]> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b [u8]) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteByteSlice<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteByteSlice<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteByteSlice<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteByteSlice<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse_to()
  }
}

impl<'a> Offset for CompleteByteSlice<'a> {
  fn offset(&self, second: &CompleteByteSlice<'a>) -> usize {
    self.0.offset(second.0)
  }
}

impl<'a> AsBytes for CompleteByteSlice<'a> {
  fn as_bytes(&self) -> &[u8] {
    self.0.as_bytes()
  }
}

#[cfg(feature = "std")]
impl<'a> super::util::HexDisplay for CompleteByteSlice<'a> {
  fn to_hex(&self, chunk_size: usize) -> String {
    self.0.to_hex(chunk_size)
  }

  fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
    self.0.to_hex_from(chunk_size, from)
  }
}

#[derive(Clone, Copy, Debug, PartialEq, Hash)]
pub struct Input<T> {
  pub inner: T,
  pub at_eof: bool,
}

impl<T> AtEof for Input<T> {
  fn at_eof(&self) -> bool {
    self.at_eof
  }
}

impl<T: Slice<Range<usize>>> Slice<Range<usize>> for Input<T> {
  fn slice(&self, range: Range<usize>) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: Slice<RangeTo<usize>>> Slice<RangeTo<usize>> for Input<T> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: Slice<RangeFrom<usize>>> Slice<RangeFrom<usize>> for Input<T> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: Slice<RangeFull>> Slice<RangeFull> for Input<T> {
  fn slice(&self, range: RangeFull) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: InputIter> InputIter for Input<T> {
  type Item = <T as InputIter>::Item;
  type RawItem = <T as InputIter>::RawItem;
  type Iter = <T as InputIter>::Iter;
  type IterElem = <T as InputIter>::IterElem;

  fn iter_indices(&self) -> Self::Iter {
    self.inner.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.inner.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.inner.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.inner.slice_index(count)
  }
}

impl<T: InputTake> InputTake for Input<T> {
  fn take(&self, count: usize) -> Self {
    Input {
      inner: self.inner.take(count),
      at_eof: self.at_eof,
    }
  }

  fn take_split(&self, count: usize) -> (Self, Self) {
    let (left, right) = self.inner.take_split(count);
    (
      Input {
        inner: left,
        at_eof: self.at_eof,
      },
      Input {
        inner: right,
        at_eof: self.at_eof,
      },
    )
  }
}

impl<T: InputLength> InputLength for Input<T> {
  fn input_len(&self) -> usize {
    self.inner.input_len()
  }
}

impl<'b, T: Compare<&'b str>> Compare<&'b str> for Input<T> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.inner.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.inner.compare_no_case(t)
  }
}

impl<'b, T: FindSubstring<&'b str>> FindSubstring<&'b str> for Input<T> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.inner.find_substring(substr)
  }
}

impl<T: FindToken<char>> FindToken<char> for Input<T> {
  fn find_token(&self, token: char) -> bool {
    self.inner.find_token(token)
  }
}

impl<T: FindToken<u8>> FindToken<u8> for Input<T> {
  fn find_token(&self, token: u8) -> bool {
    self.inner.find_token(token)
  }
}

impl<'a, T: FindToken<&'a u8>> FindToken<&'a u8> for Input<T> {
  fn find_token(&self, token: &'a u8) -> bool {
    self.inner.find_token(token)
  }
}

impl<'a, R: FromStr, T: ParseTo<R>> ParseTo<R> for Input<T> {
  fn parse_to(&self) -> Option<R> {
    self.inner.parse_to()
  }
}

impl<T: Offset> Offset for Input<T> {
  fn offset(&self, second: &Input<T>) -> usize {
    self.inner.offset(&second.inner)
  }
}

impl<T: AsBytes> AsBytes for Input<T> {
  fn as_bytes(&self) -> &[u8] {
    AsBytes::as_bytes(&self.inner)
  }
}
<|endoftext|>


<commit_before>use gpio::*;

// PL011 UART registers
pub const UART0_DR: Mmio<u8> =        Mmio::new(MMIO_BASE+0x00201000);
pub const UART0_FR: Mmio<u8> =        Mmio::new(MMIO_BASE+0x00201018);

pub const UART0_IBRD: Mmio<u32> =      Mmio::new(MMIO_BASE+0x00201024);
pub const UART0_FBRD: Mmio<u32> =      Mmio::new(MMIO_BASE+0x00201028);
pub const UART0_LCRH: Mmio<u32> =      Mmio::new(MMIO_BASE+0x0020102C);
pub const UART0_CR: Mmio<u32> =        Mmio::new(MMIO_BASE+0x00201030);
pub const UART0_IMSC: Mmio<u32> =      Mmio::new(MMIO_BASE+0x00201038);
pub const UART0_ICR: Mmio<u32> =       Mmio::new(MMIO_BASE+0x00201044);

fn nop_delay(r: u32) {
    for _ in 0..r {
        unsafe { asm!("nop" ::: "volatile"); }
    }
}

/// Set baud rate and characteristics (115200 8N1) and map to GPIO
pub fn init() {
    // initialize UART
    UART0_CR.write(0);         // turn off UART0

    /*
    // set up clock for consistent divisor values
    mbox[0] = 8*4;
    mbox[1] = MBOX_REQUEST;
    mbox[2] = MBOX_TAG_SETCLKRATE; // set clock rate
    mbox[3] = 12;
    mbox[4] = 8;
    mbox[5] = 2;           // UART clock
    mbox[6] = 4000000;     // 4Mhz
    mbox[7] = MBOX_TAG_LAST;
    mbox_call(MBOX_CH_PROP);
    */

    /* map UART0 to GPIO pins */
    let mut r = GPFSEL1.read();
    r &= !(7<<12 | 7<<15); // gpio14, gpio15
    r |= 4<<12 | 4<<15;    // alt0
    GPFSEL1.write(r);

    GPPUD.write(0);            // enable pins 14 and 15
    nop_delay(150);
    GPPUDCLK0.write(1<<14 | 1<<15);
    nop_delay(150);
    GPPUDCLK0.write(0);        // flush GPIO setup

    UART0_ICR.write(0x7FF);    // clear interrupts
    UART0_IBRD.write(2);       // 115200 baud
    UART0_FBRD.write(0xB);
    UART0_LCRH.write(0b11<<5); // 8n1
    UART0_CR.write(0x301);     // enable Tx, Rx, FIFO
}

/// Send a character
pub fn send(c: u8) {
    // wait until we can send
    while {
        unsafe { asm!("nop" ::: "volatile"); }
        UART0_FR.read() & 0x20 != 0
    } {}
    // write the character to the buffer
    UART0_DR.write(c);
}

/// Receive a character
pub fn receive() -> u8 {
    // wait until something is in the buffer
    while {
        unsafe { asm!("nop" ::: "volatile"); }
        UART0_FR.read() & 0x10 != 0
    } {}
    // read it and return
    UART0_DR.read()
}

/*
// Auxilary mini UART registers
const UART_BASE: usize = 0x3F201000;
//0x00215004

pub const AUX_ENABLE: Mmio<u8> =      Mmio::new(UART_BASE + 0x04);
pub const AUX_MU_IO: Mmio<u8> =       Mmio::new(UART_BASE + 0x40);
pub const AUX_MU_IER: Mmio<u8> =      Mmio::new(UART_BASE + 0x44);
pub const AUX_MU_IIR: Mmio<u8> =      Mmio::new(UART_BASE + 0x48);
pub const AUX_MU_LCR: Mmio<u8> =      Mmio::new(UART_BASE + 0x4C);
pub const AUX_MU_MCR: Mmio<u8> =      Mmio::new(UART_BASE + 0x50);
pub const AUX_MU_LSR: Mmio<u8> =      Mmio::new(UART_BASE + 0x54);
pub const AUX_MU_MSR: Mmio<u8> =      Mmio::new(UART_BASE + 0x58);
pub const AUX_MU_SCRATCH: Mmio<u8> =  Mmio::new(UART_BASE + 0x5C);
pub const AUX_MU_CNTL: Mmio<u8> =     Mmio::new(UART_BASE + 0x60);
pub const AUX_MU_STAT: Mmio<u32> =    Mmio::new(UART_BASE + 0x64);
pub const AUX_MU_BAUD: Mmio<u16> =    Mmio::new(UART_BASE + 0x68);

/// Set baud rate and characteristics (115200 8N1) and map to GPIO
pub fn init() {
    // initialize UART
    AUX_ENABLE.write(AUX_ENABLE.read() | 1);       // enable UART1, AUX mini uart
    AUX_MU_IER.write(0);
    AUX_MU_CNTL.write(0);
    AUX_MU_LCR.write(3);       // 8 bits
    AUX_MU_MCR.write(0);
    AUX_MU_IER.write(0);
    AUX_MU_IIR.write(0xc6);    // disable interrupts
    AUX_MU_BAUD.write(270);    // 115200 baud

    // map UART1 to GPIO pins
    let mut r = GPFSEL1.read();
    r &= !(7<<12 | 7<<15); // gpio14, gpio15
    r |= 2<<12 | 2<<15 ;    // alt5
    GPFSEL1.write(r);

    GPPUD.write(0);            // enable pins 14 and 15
    nop_delay(150);

    GPPUDCLK0.write(1<<14 | 1<<15);
    nop_delay(150);

    GPPUDCLK0.write(0);        // flush GPIO setup
    AUX_MU_CNTL.write(3);      // enable Tx, Rx
}

/// Send a character
pub fn send(c: u8) {
    // wait until we can send
    while {
        unsafe { asm!("nop" ::: "volatile"); }
        AUX_MU_LSR.read() & 0x20 != 0
    } {}
    // write the character to the buffer
    AUX_MU_IO.write(c);
}

/// Receive a character
pub fn receive() -> u8 {
    // wait until something is in the buffer
    while {
        unsafe { asm!("nop" ::: "volatile"); }
        AUX_MU_LSR.read() & 0x01 != 0
    } {}
    // read it and return
    AUX_MU_IO.read()
}

/*
/// Receive a character
pub fn getc() -> u8 {
    // wait until something is in the buffer
    do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x01));
    // read it and return
    let r = (char)(*AUX_MU_IO) as u8;
    // convert carrige return to newline
    if r == '\r' {
        '
    }
    return r=='\r'?'\n':r;
}
*/
*/

/// Display a string
pub fn puts(msg: &str) {
    for c in msg.chars() {
        // convert newline to carrige return + newline
        if c == '\n' {
            send(b'\r');
        }
        send(c as u8)
    }
}
<commit_msg>fix uart0.rs<commit_after>use gpio::*;

// PL011 UART registers
pub const UART0_DR: Mmio<u8> =        Mmio::new(MMIO_BASE+0x00201000);
pub const UART0_FR: Mmio<u8> =        Mmio::new(MMIO_BASE+0x00201018);

pub const UART0_IBRD: Mmio<u32> =      Mmio::new(MMIO_BASE+0x00201024);
pub const UART0_FBRD: Mmio<u32> =      Mmio::new(MMIO_BASE+0x00201028);
pub const UART0_LCRH: Mmio<u32> =      Mmio::new(MMIO_BASE+0x0020102C);
pub const UART0_CR: Mmio<u32> =        Mmio::new(MMIO_BASE+0x00201030);
pub const UART0_IMSC: Mmio<u32> =      Mmio::new(MMIO_BASE+0x00201038);
pub const UART0_ICR: Mmio<u32> =       Mmio::new(MMIO_BASE+0x00201044);

fn nop_delay(r: u32) {
    for _ in 0..r {
        unsafe { asm!("nop" ::: "volatile"); }
    }
}

/// Set baud rate and characteristics (115200 8N1) and map to GPIO
pub fn init() {
    // initialize UART
    UART0_CR.write(0);         // turn off UART0

    /*
    // set up clock for consistent divisor values
    mbox[0] = 8*4;
    mbox[1] = MBOX_REQUEST;
    mbox[2] = MBOX_TAG_SETCLKRATE; // set clock rate
    mbox[3] = 12;
    mbox[4] = 8;
    mbox[5] = 2;           // UART clock
    mbox[6] = 4000000;     // 4Mhz
    mbox[7] = MBOX_TAG_LAST;
    mbox_call(MBOX_CH_PROP);
    */

    /* map UART0 to GPIO pins */
    let mut r = GPFSEL1.read();
    r &= !(7<<12 | 7<<15); // gpio14, gpio15
    r |= 4<<12 | 4<<15;    // alt0
    GPFSEL1.write(r);

    GPPUD.write(0);            // enable pins 14 and 15
    nop_delay(150);
    GPPUDCLK0.write(1<<14 | 1<<15);
    nop_delay(150);
    GPPUDCLK0.write(0);        // flush GPIO setup

    UART0_ICR.write(0x7FF);    // clear interrupts
    UART0_IBRD.write(2);       // 115200 baud
    UART0_FBRD.write(0xB);
    UART0_LCRH.write(0b11<<5); // 8n1
    UART0_CR.write(0x301);     // enable Tx, Rx, FIFO
}

/// Send a character
pub fn send(c: u8) {
    // wait until we can send
    while {
        unsafe { asm!("nop" ::: "volatile"); }
        UART0_FR.read() & 0x20 != 0
    } {}
    // write the character to the buffer
    UART0_DR.write(c);
}

/// Receive a character
pub fn receive() -> u8 {
    // wait until something is in the buffer
    while {
        unsafe { asm!("nop" ::: "volatile"); }
        UART0_FR.read() & 0x10 != 0
    } {}
    // read it and return
    UART0_DR.read()
}

/// Display a string
pub fn puts(msg: &str) {
    for c in msg.chars() {
        // convert newline to carrige return + newline
        if c == '\n' {
            send(b'\r');
        }
        send(c as u8)
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{convert::TryInto, fs::File, io::Write, path::Path};

use assert_cmd::Command;
use tempdir::TempDir;

static MAIN_RS: &str = include_str!("../../../demo/src/main.rs");
static INPUT_H: &str = include_str!("../../../demo/src/input.h");

#[test]
fn test_help() -> Result<(), Box<dyn std::error::Error>> {
    let mut cmd = Command::cargo_bin("autocxx-gen")?;
    cmd.arg("-h").assert().success();
    Ok(())
}

fn base_test<F>(tmp_dir: &TempDir, arg_modifier: F) -> Result<(), Box<dyn std::error::Error>>
where
    F: FnOnce(&mut Command),
{
    let demo_code_dir = tmp_dir.path().join("demo");
    std::fs::create_dir(&demo_code_dir).unwrap();
    write_to_file(&demo_code_dir, "input.h", INPUT_H.as_bytes());
    write_to_file(&demo_code_dir, "main.rs", MAIN_RS.as_bytes());
    let demo_rs = demo_code_dir.join("main.rs");
    let mut cmd = Command::cargo_bin("autocxx-gen")?;
    arg_modifier(&mut cmd);
    cmd.arg("--inc")
        .arg(demo_code_dir.to_str().unwrap())
        .arg(demo_rs)
        .arg("--outdir")
        .arg(tmp_dir.path().to_str().unwrap())
        .arg("--gen-cpp")
        .arg("--gen-rs-include")
        .assert()
        .success();
    assert_contentful(&tmp_dir, "gen0.cc");
    Ok(())
}

#[test]
fn test_gen() -> Result<(), Box<dyn std::error::Error>> {
    let tmp_dir = TempDir::new("example")?;
    base_test(&tmp_dir, |_| {})
}

#[test]
fn test_gen_fixed_num() -> Result<(), Box<dyn std::error::Error>> {
    let tmp_dir = TempDir::new("example")?;
    base_test(&tmp_dir, |cmd| {
        cmd.arg("--generate-exact")
            .arg("3")
            .arg("--fix-rs-include-name");
    })?;
    assert_contentful(&tmp_dir, "gen0.cc");
    assert_exists(&tmp_dir, "gen1.cc");
    assert_exists(&tmp_dir, "gen2.cc");
    assert_contentful(&tmp_dir, "gen0.include.rs");
    assert_exists(&tmp_dir, "gen1.include.rs");
    assert_exists(&tmp_dir, "gen2.include.rs");
    Ok(())
}

fn write_to_file(dir: &Path, filename: &str, content: &[u8]) {
    let path = dir.join(filename);
    let mut f = File::create(&path).expect("Unable to create file");
    f.write_all(content).expect("Unable to write file");
}

fn assert_contentful(outdir: &TempDir, fname: &str) {
    let p = outdir.path().join(fname);
    if !p.exists() {
        panic!("File {} didn't exist", p.to_string_lossy());
    }
    assert!(p.metadata().unwrap().len() > super::BLANK.len().try_into().unwrap());
}

fn assert_exists(outdir: &TempDir, fname: &str) {
    let p = outdir.path().join(fname);
    if !p.exists() {
        panic!("File {} didn't exist", p.to_string_lossy());
    }
}
<commit_msg>Add preprocessing test.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{convert::TryInto, fs::File, io::Write, path::Path};

use assert_cmd::Command;
use tempdir::TempDir;

static MAIN_RS: &str = include_str!("../../../demo/src/main.rs");
static INPUT_H: &str = include_str!("../../../demo/src/input.h");

#[test]
fn test_help() -> Result<(), Box<dyn std::error::Error>> {
    let mut cmd = Command::cargo_bin("autocxx-gen")?;
    cmd.arg("-h").assert().success();
    Ok(())
}

fn base_test<F>(tmp_dir: &TempDir, arg_modifier: F) -> Result<(), Box<dyn std::error::Error>>
where
    F: FnOnce(&mut Command),
{
    let demo_code_dir = tmp_dir.path().join("demo");
    std::fs::create_dir(&demo_code_dir).unwrap();
    write_to_file(&demo_code_dir, "input.h", INPUT_H.as_bytes());
    write_to_file(&demo_code_dir, "main.rs", MAIN_RS.as_bytes());
    let demo_rs = demo_code_dir.join("main.rs");
    let mut cmd = Command::cargo_bin("autocxx-gen")?;
    arg_modifier(&mut cmd);
    cmd.arg("--inc")
        .arg(demo_code_dir.to_str().unwrap())
        .arg(demo_rs)
        .arg("--outdir")
        .arg(tmp_dir.path().to_str().unwrap())
        .arg("--gen-cpp")
        .arg("--gen-rs-include")
        .assert()
        .success();
    assert_contentful(&tmp_dir, "gen0.cc");
    Ok(())
}

#[test]
fn test_gen() -> Result<(), Box<dyn std::error::Error>> {
    let tmp_dir = TempDir::new("example")?;
    base_test(&tmp_dir, |_| {})
}

#[test]
fn test_gen_fixed_num() -> Result<(), Box<dyn std::error::Error>> {
    let tmp_dir = TempDir::new("example")?;
    base_test(&tmp_dir, |cmd| {
        cmd.arg("--generate-exact")
            .arg("3")
            .arg("--fix-rs-include-name");
    })?;
    assert_contentful(&tmp_dir, "gen0.cc");
    assert_exists(&tmp_dir, "gen1.cc");
    assert_exists(&tmp_dir, "gen2.cc");
    assert_contentful(&tmp_dir, "gen0.include.rs");
    assert_exists(&tmp_dir, "gen1.include.rs");
    assert_exists(&tmp_dir, "gen2.include.rs");
    Ok(())
}

#[test]
fn test_gen_preprocess() -> Result<(), Box<dyn std::error::Error>> {
    let tmp_dir = TempDir::new("example")?;
    let prepro_path = tmp_dir.path().join("preprocessed.h");
    base_test(&tmp_dir, |cmd| {
        cmd.env("AUTOCXX_PREPROCESS", prepro_path.to_str().unwrap());
    })?;
    assert_contentful(&tmp_dir, "preprocessed.h");
    Ok(())
}

fn write_to_file(dir: &Path, filename: &str, content: &[u8]) {
    let path = dir.join(filename);
    let mut f = File::create(&path).expect("Unable to create file");
    f.write_all(content).expect("Unable to write file");
}

fn assert_contentful(outdir: &TempDir, fname: &str) {
    let p = outdir.path().join(fname);
    if !p.exists() {
        panic!("File {} didn't exist", p.to_string_lossy());
    }
    assert!(p.metadata().unwrap().len() > super::BLANK.len().try_into().unwrap());
}

fn assert_exists(outdir: &TempDir, fname: &str) {
    let p = outdir.path().join(fname);
    if !p.exists() {
        panic!("File {} didn't exist", p.to_string_lossy());
    }
}
<|endoftext|>


<commit_before>#![crate_type = "bin"]
extern crate script;
extern crate collections;
use script::lexer::Lexer;
use script::parser::Parser;
use script::exec::{Executor, Interpreter};
use script::ast::{Token, TComment};
use script::js::value::{Value, ResultValue, to_value, from_value};
use collections::treemap::TreeMap;
use std::path::posix::Path;
use std::io::fs::{File, walk_dir};
use std::io::BufferedReader;
fn find_attrs(tokens: Vec<Token>) -> TreeMap<~str, ~str> {
	let mut map = TreeMap::new();
	for tk in tokens.iter() {
		match tk.data {
			TComment(ref comm) => {
				let comm = comm.as_slice();
				for (_, to) in comm.match_indices("// @") {
					let current = comm.slice_from(to);
					let space_ind = current.find(' ').unwrap();
					let key = comm.slice_to(space_ind);
					let value = comm.slice_chars(space_ind, current.find('\n').unwrap());
					map.insert(key.into_owned(), value.into_owned());
				}
			},
			_ => ()
		}
	}
	map
}
fn assert(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	let val : bool = from_value(*args.get(0)).unwrap();
	if val {
		Ok(to_value(true))
	} else {
		Err(to_value(false))
	}
}
fn main() {
	for file in walk_dir(&Path::new("../tests/")).unwrap() {
		let file_name = file.to_c_str().as_str().unwrap().to_owned();
		if file_name.ends_with(".js") {
			let mut lexer = Lexer::new(BufferedReader::new(File::open(&file).unwrap()));
			lexer.lex().unwrap();
			let mut parser = Parser::new(lexer.tokens);
			let expr = match parser.parse_all() {
				Ok(v) => v,
				Err(v) => fail!("{}: {}", file_name, v)
			};
			let mut engine : Interpreter = Executor::new();
			engine.set_global("assert".into_maybe_owned(), to_value(assert));
			let result : Result<Value, Value> = engine.run(&expr);
			match result {
				Ok(v) => println!("{}: {}", file_name, v.borrow()),
				Err(v) => fail!("{}: Failed with {}", file_name, v.borrow())
			}
		}
	}
}<commit_msg>Simplify directory walking code in unit tester<commit_after>#![crate_type = "bin"]
extern crate script;
extern crate collections;
use script::lexer::Lexer;
use script::parser::Parser;
use script::exec::{Executor, Interpreter};
use script::ast::{Token, TComment};
use script::js::value::{Value, ResultValue, to_value, from_value};
use collections::treemap::TreeMap;
use std::path::posix::Path;
use std::io::fs::{File, walk_dir};
use std::io::BufferedReader;
fn find_attrs(tokens: Vec<Token>) -> TreeMap<~str, ~str> {
	let mut map = TreeMap::new();
	for tk in tokens.iter() {
		match tk.data {
			TComment(ref comm) => {
				let comm = comm.as_slice();
				for (_, to) in comm.match_indices("// @") {
					let current = comm.slice_from(to);
					let space_ind = current.find(' ').unwrap();
					let key = comm.slice_to(space_ind);
					let value = comm.slice_chars(space_ind, current.find('\n').unwrap());
					map.insert(key.into_owned(), value.into_owned());
				}
			},
			_ => ()
		}
	}
	map
}
fn assert(_:Value, _:Value, args:Vec<Value>) -> ResultValue {
	let val : bool = from_value(*args.get(0)).unwrap();
	if val {
		Ok(to_value(true))
	} else {
		Err(to_value(false))
	}
}
fn main() {
	for file in walk_dir(&Path::new("../tests/")).unwrap() {
		if file.is_file() && file.extension_str() == Some("js") {
			let file_str = file.as_str();
			let mut lexer = Lexer::new(BufferedReader::new(File::open(&file).unwrap()));
			lexer.lex().unwrap();
			let mut parser = Parser::new(lexer.tokens);
			let expr = match parser.parse_all() {
				Ok(v) => v,
				Err(v) => fail!("{}: {}", file_str, v)
			};
			let mut engine : Interpreter = Executor::new();
			engine.set_global("assert".into_maybe_owned(), to_value(assert));
			let result : Result<Value, Value> = engine.run(&expr);
			match result {
				Ok(v) => println!("{}: {}", file_str, v.borrow()),
				Err(v) => fail!("{}: Failed with {}", file_str, v.borrow())
			}
		}
	}
}<|endoftext|>


<commit_before>#![deny(warnings)]

// TODO support reading from standard input

extern crate extra;
extern crate termion;

use std::{cmp, str, thread};
use std::env::args;
use std::io::{self, Write, Read};
use std::process::{self, Command, Stdio};
use std::time::Duration;

use extra::option::OptionalExt;

use termion::{async_stdin, clear, cursor, style, terminal_size};
use termion::raw::IntoRawMode;

static MAN_PAGE: &'static str = /* @MANSTART{watch} */ r#"
NAME
    watch - execute a program periodically, showing output fullscreen

SYNOPSIS
    watch [-h | --help] command

DESCRIPTION
    Runs command repeatedly, displaying its output and errors. This allows you to watch the program
    output change over time. By default, the program is run every 2 seconds. By default, watch will
    run until interrupted.

OPTIONS
    --help, -h
        Print this manual page.

AUTHOR
    This program was written by Jeremy Soller for Redox OS. Bugs, issues, or feature requests
    should be reported in the Github repository, 'redox-os/extrautils'.

COPYRIGHT
    Copyright (c) 2016 Jeremy Soller

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software
    and associated documentation files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or
    substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
    BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#; /* @MANEND */

fn main() {
    let mut args = args().skip(1);
    let mut stdout = io::stdout();
    let mut stderr = io::stderr();

    let mut command = String::new();
    let mut interval = 2;

    while let Some(x) = args.next() {
        match x.as_str() {
            "--help" | "-h" => {
                // Print help.
                stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
                return;
            },
            "--interval" | "-n" => {
                if let Some(interval_str) = args.next() {
                    if let Ok(interval_num) = interval_str.parse::<u64>() {
                        interval = cmp::max(1, interval_num);
                    } else {
                        stderr.write(b"watch: interval argument not specified").unwrap();
                        process::exit(1);
                    }
                } else {
                    stderr.write(b"watch: interval argument not specified").unwrap();
                    process::exit(1);
                }
            },
            arg => {
                if !command.is_empty() {
                    command.push(' ');
                }
                command.push_str(arg);
            }
        }
    }

    if command.is_empty() {
        stderr.write(b"watch: command argument not specified").unwrap();
        process::exit(1);
    }

    run(command, interval, stdout).try(&mut stderr);
}

fn run<W: IntoRawMode>(command: String, interval: u64, stdout: W) -> std::io::Result<()> {
    let title = format!("Every {}s: {}", interval, command);

    let mut stdout = stdout.into_raw_mode()?;

    let (w, h) = terminal_size()?;

    let mut stdin = async_stdin();

    'watching: loop {
        write!(stdout, "{}{}{}", clear::All, style::Reset, cursor::Goto(1, 1))?;

        let child = Command::new("sh").arg("-c").arg(&command)
                        .stdin(Stdio::null()).stdout(Stdio::piped()).stderr(Stdio::piped())
                        .spawn()?;
        let mut output = String::new();
        if let Some(mut stdout) = child.stdout {
            stdout.read_to_string(&mut output)?;
        }

        let mut y = 0;
        for line in output.lines() {
            write!(stdout, "{}", cursor::Goto(1, y + 1))?;

            if line.len() > w as usize {
                stdout.write(line[..w as usize].as_bytes())?;
            } else {
                stdout.write(line.as_bytes())?;
            }

            y += 1;
            if y >= h as u16 {
                break;
            }
        }

        write!(stdout, "{}{}{}{}", cursor::Goto(1, h), style::Invert, title, style::NoInvert)?;

        stdout.flush()?;

        for _second in 0..interval*10 {
            for b in (&mut stdin).bytes() {
                if b? == b'q' {
                    break 'watching;
                }
            }

            thread::sleep(Duration::new(0, 100000000));
        }
    }

    write!(stdout, "{}{}{}", clear::All, style::Reset, cursor::Goto(1, 1))?;

    Ok(())
}
<commit_msg>Fix watch on Redox<commit_after>#![deny(warnings)]

// TODO support reading from standard input

extern crate extra;
extern crate termion;

use std::{cmp, str, thread};
use std::env::{self, args};
use std::io::{self, Write, Read};
use std::process::{self, Command, Stdio};
use std::time::Duration;

use extra::option::OptionalExt;

use termion::{async_stdin, clear, cursor, style, terminal_size};
use termion::raw::IntoRawMode;

static MAN_PAGE: &'static str = /* @MANSTART{watch} */ r#"
NAME
    watch - execute a program periodically, showing output fullscreen

SYNOPSIS
    watch [-h | --help] [-n N | --interval N] command

DESCRIPTION
    Runs command repeatedly, displaying its output and errors. This allows you to watch the program
    output change over time. By default, the program is run every 2 seconds. By default, watch will
    run until interrupted.

OPTIONS
    --help, -h
        Print this manual page.

AUTHOR
    This program was written by Jeremy Soller for Redox OS. Bugs, issues, or feature requests
    should be reported in the Github repository, 'redox-os/extrautils'.

COPYRIGHT
    Copyright (c) 2016 Jeremy Soller

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software
    and associated documentation files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or
    substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
    BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#; /* @MANEND */

fn main() {
    let mut args = args().skip(1);
    let mut stdout = io::stdout();
    let mut stderr = io::stderr();

    let mut command = String::new();
    let mut interval = 2;

    while let Some(x) = args.next() {
        match x.as_str() {
            "--help" | "-h" => {
                // Print help.
                stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
                return;
            },
            "--interval" | "-n" => {
                if let Some(interval_str) = args.next() {
                    if let Ok(interval_num) = interval_str.parse::<u64>() {
                        interval = cmp::max(1, interval_num);
                    } else {
                        stderr.write(b"watch: interval argument not specified").unwrap();
                        process::exit(1);
                    }
                } else {
                    stderr.write(b"watch: interval argument not specified").unwrap();
                    process::exit(1);
                }
            },
            arg => {
                if !command.is_empty() {
                    command.push(' ');
                }
                command.push_str(arg);
            }
        }
    }

    if command.is_empty() {
        stderr.write(b"watch: command argument not specified").unwrap();
        process::exit(1);
    }

    run(command, interval, stdout).try(&mut stderr);
}

fn run<W: IntoRawMode>(command: String, interval: u64, stdout: W) -> std::io::Result<()> {
    let title = format!("Every {}s: {}", interval, command);

    let shell = env::var("SHELL").unwrap_or(String::from("sh"));

    let mut stdout = stdout.into_raw_mode()?;

    let (w, h) = terminal_size()?;

    let mut stdin = async_stdin();

    'watching: loop {
        write!(stdout, "{}{}{}", clear::All, style::Reset, cursor::Goto(1, 1))?;

        let child = Command::new(&shell).arg("-c").arg(&command)
                        .stdin(Stdio::null()).stdout(Stdio::piped()).stderr(Stdio::piped())
                        .output()?;

        let output = String::from_utf8_lossy(&child.stdout);

        let mut y = 0;
        for line in output.lines() {
            write!(stdout, "{}", cursor::Goto(1, y + 1))?;

            if line.len() > w as usize {
                stdout.write(line[..w as usize].as_bytes())?;
            } else {
                stdout.write(line.as_bytes())?;
            }

            y += 1;
            if y >= h as u16 {
                break;
            }
        }

        write!(stdout, "{}{}{}{}", cursor::Goto(1, h), style::Invert, title, style::NoInvert)?;

        stdout.flush()?;

        for _second in 0..interval*10 {
            for b in (&mut stdin).bytes() {
                if b? == b'q' {
                    break 'watching;
                }
            }

            thread::sleep(Duration::new(0, 100000000));
        }
    }

    write!(stdout, "{}{}{}", clear::All, style::Reset, cursor::Goto(1, 1))?;

    Ok(())
}
<|endoftext|>


<commit_before>/// Character level parsers

use internal::{IResult,Needed};
use util::ErrorKind;
use std::ops::{Range,RangeFrom,RangeTo};
use traits::{AsChar,Compare,CompareResult,IterIndices,Slice};

/// matches one of the provided characters
#[macro_export]
macro_rules! one_of (
  ($i:expr, $inp: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        #[inline(always)]
        fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
          b.as_bytes()
        }

        let expected = $inp;
        let bytes = as_bytes(&expected);
        one_of_bytes!($i, bytes)
      }
    }
  );
);

#[doc(hidden)]
#[macro_export]
macro_rules! one_of_bytes (
  ($i:expr, $bytes: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        let mut found = false;

        for &i in $bytes {
          if i == $i[0] {
            found = true;
            break;
          }
        }

        if found {
          $crate::IResult::Done(&$i[1..], $i[0] as char)
        } else {
          //$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::OneOf, $i))
          $crate::IResult::Error(error_position!($crate::ErrorKind::OneOf, $i))
        }
      }
    }
  );
);

/// matches anything but the provided characters
#[macro_export]
macro_rules! none_of (
  ($i:expr, $inp: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        #[inline(always)]
        fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
          b.as_bytes()
        }

        let expected = $inp;
        let bytes = as_bytes(&expected);
        none_of_bytes!($i, bytes)
      }
    }
  );
);

#[doc(hidden)]
#[macro_export]
macro_rules! none_of_bytes (
  ($i:expr, $bytes: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        let mut found = false;

        for &i in $bytes {
          if i == $i[0] {
            found = true;
            break;
          }
        }

        if !found {
          $crate::IResult::Done(&$i[1..], $i[0] as char)
        } else {
          $crate::IResult::Error(error_position!($crate::ErrorKind::NoneOf, $i))
        }
      }
    }
  );
);

/// matches one character: `char!(char) => &[u8] -> IResult<&[u8], char>
#[macro_export]
macro_rules! char (
  ($i:expr, $c: expr) => (
    {
      if $i.is_empty() {
        let res: $crate::IResult<&[u8], char> = $crate::IResult::Incomplete($crate::Needed::Size(1));
        res
      } else {
        if $i[0] == $c as u8 {
          $crate::IResult::Done(&$i[1..], $i[0] as char)
        } else {
          $crate::IResult::Error(error_position!($crate::ErrorKind::Char, $i))
        }
      }
    }
  );
);

named!(pub newline<char>, char!('\n'));

pub fn crlf<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, char> where
  &'a T:Slice<Range<usize>>+Slice<RangeFrom<usize>>+Slice<RangeTo<usize>>,
  &'a T: IterIndices,
  &'a T: Compare<&'static str> {
    match input.compare("\n") {
      CompareResult::Ok         => {
        let c = input.slice(0..1).iter_elements().next().unwrap().as_char();
        IResult::Done(input.slice(1..), c)
      },
      CompareResult::Incomplete => IResult::Incomplete(Needed::Size(1)),
      CompareResult::Error      => match input.compare("\r\n") {
        //FIXME: is this the right index?
        CompareResult::Ok         => {
          let c = input.slice(0..2).iter_elements().next().unwrap().as_char();
          IResult::Done(input.slice(2..), c)
        },
        CompareResult::Incomplete => IResult::Incomplete(Needed::Size(2)),
        CompareResult::Error      => IResult::Error(error_position!(ErrorKind::CrLf, input))
      }
    }
}

named!(pub eol<char>, alt!(newline | crlf));
named!(pub tab<char>, char!('\t'));

pub fn anychar(input:&[u8]) -> IResult<&[u8], char> {
  if input.is_empty() {
    IResult::Incomplete(Needed::Size(1))
  } else {
    IResult::Done(&input[1..], input[0] as char)
  }
}

#[cfg(test)]
mod tests {
  use internal::IResult::*;
  use util::ErrorKind;

  #[test]
  fn one_of() {
    named!(f<char>, one_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Done(&b"bcd"[..], 'a'));

    let b = &b"cde"[..];
    assert_eq!(f(b), Error(error_position!(ErrorKind::OneOf, b)));
  }

  #[test]
  fn none_of() {
    named!(f<char>, none_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Error(error_position!(ErrorKind::NoneOf, a)));

    let b = &b"cde"[..];
    assert_eq!(f(b), Done(&b"de"[..], 'c'));
  }

  #[test]
  fn char() {
    named!(f<char>, char!('c'));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Error(error_position!(ErrorKind::Char, a)));

    let b = &b"cde"[..];
    assert_eq!(f(b), Done(&b"de"[..], 'c'));
  }
}
<commit_msg>separate implementations for eol and crlf<commit_after>/// Character level parsers

use internal::{IResult,Needed};
use util::ErrorKind;
use std::ops::{Range,RangeFrom,RangeTo};
use traits::{AsChar,Compare,CompareResult,IterIndices,Slice};

/// matches one of the provided characters
#[macro_export]
macro_rules! one_of (
  ($i:expr, $inp: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        #[inline(always)]
        fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
          b.as_bytes()
        }

        let expected = $inp;
        let bytes = as_bytes(&expected);
        one_of_bytes!($i, bytes)
      }
    }
  );
);

#[doc(hidden)]
#[macro_export]
macro_rules! one_of_bytes (
  ($i:expr, $bytes: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        let mut found = false;

        for &i in $bytes {
          if i == $i[0] {
            found = true;
            break;
          }
        }

        if found {
          $crate::IResult::Done(&$i[1..], $i[0] as char)
        } else {
          //$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::OneOf, $i))
          $crate::IResult::Error(error_position!($crate::ErrorKind::OneOf, $i))
        }
      }
    }
  );
);

/// matches anything but the provided characters
#[macro_export]
macro_rules! none_of (
  ($i:expr, $inp: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        #[inline(always)]
        fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
          b.as_bytes()
        }

        let expected = $inp;
        let bytes = as_bytes(&expected);
        none_of_bytes!($i, bytes)
      }
    }
  );
);

#[doc(hidden)]
#[macro_export]
macro_rules! none_of_bytes (
  ($i:expr, $bytes: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        let mut found = false;

        for &i in $bytes {
          if i == $i[0] {
            found = true;
            break;
          }
        }

        if !found {
          $crate::IResult::Done(&$i[1..], $i[0] as char)
        } else {
          $crate::IResult::Error(error_position!($crate::ErrorKind::NoneOf, $i))
        }
      }
    }
  );
);

/// matches one character: `char!(char) => &[u8] -> IResult<&[u8], char>
#[macro_export]
macro_rules! char (
  ($i:expr, $c: expr) => (
    {
      if $i.is_empty() {
        let res: $crate::IResult<&[u8], char> = $crate::IResult::Incomplete($crate::Needed::Size(1));
        res
      } else {
        if $i[0] == $c as u8 {
          $crate::IResult::Done(&$i[1..], $i[0] as char)
        } else {
          $crate::IResult::Error(error_position!($crate::ErrorKind::Char, $i))
        }
      }
    }
  );
);

named!(pub newline<char>, char!('\n'));

//FIXME: this crlf implementation returns a char, while "\r\n" is two chars
// these should probably be removed or return a slice instead of a char
pub fn crlf<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, char> where
  &'a T:Slice<Range<usize>>+Slice<RangeFrom<usize>>+Slice<RangeTo<usize>>,
  &'a T: IterIndices,
  &'a T: Compare<&'static str> {
    match input.compare("\r\n") {
      //FIXME: is this the right index?
      CompareResult::Ok         => {
        let c = input.slice(0..2).iter_elements().next().unwrap().as_char();
        IResult::Done(input.slice(2..), c)
      },
      CompareResult::Incomplete => IResult::Incomplete(Needed::Size(2)),
      CompareResult::Error      => IResult::Error(error_position!(ErrorKind::CrLf, input))
    }
}

pub fn eol<'a, T: ?Sized>(input:&'a T) -> IResult<&'a T, char> where
  &'a T:Slice<Range<usize>>+Slice<RangeFrom<usize>>+Slice<RangeTo<usize>>,
  &'a T: IterIndices,
  &'a T: Compare<&'static str> {
    match input.compare("\n") {
      CompareResult::Ok         => {
        let c = input.slice(0..1).iter_elements().next().unwrap().as_char();
        IResult::Done(input.slice(1..), c)
      },
      CompareResult::Incomplete => IResult::Incomplete(Needed::Size(1)),
      CompareResult::Error      => match input.compare("\r\n") {
        //FIXME: is this the right index?
        CompareResult::Ok         => {
          let c = input.slice(0..2).iter_elements().next().unwrap().as_char();
          IResult::Done(input.slice(2..), c)
        },
        CompareResult::Incomplete => IResult::Incomplete(Needed::Size(2)),
        CompareResult::Error      => IResult::Error(error_position!(ErrorKind::CrLf, input))
      }
    }
}

named!(pub tab<char>, char!('\t'));

pub fn anychar(input:&[u8]) -> IResult<&[u8], char> {
  if input.is_empty() {
    IResult::Incomplete(Needed::Size(1))
  } else {
    IResult::Done(&input[1..], input[0] as char)
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use internal::IResult::*;
  use internal::Needed;
  use util::ErrorKind;

  #[test]
  fn one_of() {
    named!(f<char>, one_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Done(&b"bcd"[..], 'a'));

    let b = &b"cde"[..];
    assert_eq!(f(b), Error(error_position!(ErrorKind::OneOf, b)));
  }

  #[test]
  fn none_of() {
    named!(f<char>, none_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Error(error_position!(ErrorKind::NoneOf, a)));

    let b = &b"cde"[..];
    assert_eq!(f(b), Done(&b"de"[..], 'c'));
  }

  #[test]
  fn char() {
    named!(f<char>, char!('c'));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Error(error_position!(ErrorKind::Char, a)));

    let b = &b"cde"[..];
    assert_eq!(f(b), Done(&b"de"[..], 'c'));
  }

  #[test]
  fn cr_lf() {
    assert_eq!(crlf(&b"\r\na"[..]), Done(&b"a"[..], '\r'));
    assert_eq!(crlf(&b"\r"[..]),    Incomplete(Needed::Size(2)));
    assert_eq!(crlf(&b"\ra"[..]),   Error(error_position!(ErrorKind::CrLf, &b"\ra"[..])));

    assert_eq!(crlf("\r\na"), Done("a", '\r'));
    assert_eq!(crlf("\r"),    Incomplete(Needed::Size(2)));
    assert_eq!(crlf("\ra"),   Error(error_position!(ErrorKind::CrLf, "\ra")));
  }

  #[test]
  fn end_of_line() {
    assert_eq!(eol(&b"\na"[..]),   Done(&b"a"[..], '\n'));
    assert_eq!(eol(&b"\r\na"[..]), Done(&b"a"[..], '\r'));
    assert_eq!(eol(&b"\r"[..]),    Incomplete(Needed::Size(2)));
    assert_eq!(eol(&b"\ra"[..]),   Error(error_position!(ErrorKind::CrLf, &b"\ra"[..])));

    assert_eq!(eol("\na"),   Done("a", '\n'));
    assert_eq!(eol("\r\na"), Done("a", '\r'));
    assert_eq!(eol("\r"),    Incomplete(Needed::Size(2)));
    assert_eq!(eol("\ra"),   Error(error_position!(ErrorKind::CrLf, "\ra")));
  }
}
<|endoftext|>