<commit_before>use Query;
use Token;
use std::str::Chars;

// consts for character representing tokens
const TOKEN_VAR_START: char = '%';
const TOKEN_VAR_END: char = '%';
const TOKEN_FUNC_NAME_START: char = '$';
const TOKEN_FUNC_PARAM_START: char = '(';
const TOKEN_FUNC_PARAM_END: char = ')';
const TOKEN_FUNC_PARAM_SEP: char = ',';
const TOKEN_ESCAPE: char = '\\';

// TODO: Proper error type instead of String
pub type ParseResult<T> = Result<T, ParseError>;

/// Errors found in parsing query
#[derive(Debug)]
pub enum ParseError {
    /// Unknown escape sequence.
    /// String contains the sequece
    UnknownEscape(String),

    /// Escape squence at end of query
    EscapeAtEndOfQuery,

    /// Variable is missing closing character
    VariableMissingClosing,

    /// Function is missing start of parameters
    FuncMissingParameter,

    /// Function parameters is missing closing character
    FuncParameterNotClosed,

    /// End of Query
    EndOfQuery,
}

impl Query {
    pub fn parse(src: String) -> ParseResult<Query> {
        let mut iter = src.chars();
        match parse_scope(&mut iter) {
            Ok(t) => Ok(Query { tokens: t }),
            Err(e) => return Err(e),
        }
    }
}

fn parse_scope(iter: &mut Chars) -> ParseResult<Token> {
    let mut tokens = Vec::new();
    loop {
        let token = match iter.clone().peekable().peek() {
            Some(c) => {
                match *c {
                    TOKEN_VAR_START => parse_variable(iter),
                    TOKEN_FUNC_NAME_START => parse_function(iter),
                    TOKEN_FUNC_PARAM_END | TOKEN_FUNC_PARAM_SEP => break,
                    _ => parse_text(iter),
                }
            }
            None => Err(ParseError::EndOfQuery),
        };

        tokens.push(match token {
            Ok(t) => t,
            Err(e) => {
                match e {
                    ParseError::EndOfQuery => break,
                    _ => return Err(e),
                }
            }
        });
    }
    Ok(Token::Scope(tokens))
}

fn parse_text(iter: &mut Chars) -> ParseResult<Token> {
    let mut text = String::new();

    loop {
        // Peek to check for next expression
        if let Some(peek) = iter.clone().peekable().peek() {
            match *peek {
                TOKEN_VAR_START => break,
                TOKEN_FUNC_PARAM_SEP => break,
                TOKEN_FUNC_NAME_START => break,
                TOKEN_FUNC_PARAM_START => break,
                TOKEN_FUNC_PARAM_END => break,
                _ => (),
            }
        }

        if let Some(next) = iter.next() {
            match next {
                TOKEN_ESCAPE => {
                    text.push(match parse_escape(iter) {
                        Ok(esc) => esc,
                        Err(err) => return Err(err),
                    })
                }
                _ => text.push(next),
            }
        } else {
            // Made it to the end of the string
            break;
        }
    }
    Ok(Token::Text(text))
}

fn parse_escape(iter: &mut Chars) -> ParseResult<char> {
    if let Some(next) = iter.next() {
        Ok(match next {
            'n' => '\n',
            't' => '\t',
            TOKEN_ESCAPE => TOKEN_ESCAPE,
            TOKEN_VAR_START => TOKEN_VAR_START,
            TOKEN_FUNC_NAME_START => TOKEN_FUNC_NAME_START,
            TOKEN_FUNC_PARAM_SEP => TOKEN_FUNC_PARAM_SEP,
            _ => return Err(ParseError::UnknownEscape(format!("\\{}", next))),
        })
    } else {
        Err(ParseError::EscapeAtEndOfQuery)
    }
}

fn parse_variable(iter: &mut Chars) -> ParseResult<Token> {
    let _ = iter.next(); // ignore TOKEN_VAR_START

    let mut name = String::new();
    while let Some(c) = iter.next() {
        match c {
            TOKEN_VAR_END => return Ok(Token::Variable(name)),
            _ => name.push(c),
        };
    }
    Err(ParseError::VariableMissingClosing)
}

fn parse_function(iter: &mut Chars) -> ParseResult<Token> {
    let _ = iter.next(); // ignore TOKEN_FUNC_NAME_START
    let mut name = String::new();
    let mut args = Vec::<Token>::new();

    // get the name of the function
    loop {
        if let Some(c) = iter.next() {
            match c { // TODO: enforce name limits here
                TOKEN_FUNC_PARAM_START => break,
                _ => name.push(c),
            };
        } else {
            return Err(ParseError::FuncMissingParameter);
        }
    }

    // get the parameters of the function
    while let Some(c) = iter.clone().peekable().peek() {
        match *c { // TODO: parse tokens seperated by commas
            TOKEN_FUNC_PARAM_END => {
                let _ = iter.next();
                return Ok(Token::Function(name, args));
            }
            TOKEN_FUNC_PARAM_SEP => {
                let _ = iter.next();
                continue;
            }
            _ => {
                args.push(match parse_scope(iter) {
                    Ok(t) => t,
                    Err(e) => return Err(e),
                })
            }
        }
    }

    Err(ParseError::FuncParameterNotClosed)
}

#[cfg(test)]
mod tests {
    use ::Token::*;
    use ParseError;
    use Query;

    macro_rules! parse_test {
        ($name: ident, $input: expr, $out: expr) => {
            #[test]
            fn $name() {
                let out = Query::parse($input.to_owned()).unwrap();
                assert_eq!(out.tokens, Scope(vec![$out]));
            }
        };

        ($name: ident, $input: expr, $out: expr, $($more: expr),*) => {
            #[test]
            fn $name() {
                let out = Query::parse($input.to_owned()).unwrap();
                assert_eq!(out.tokens, Scope(vec![$out $(, $more)*]));
            }
        };
    }

    macro_rules! parse_fail_test {
        ($name: ident, $input: expr, $expt: pat) => {
            #[test]
            fn $name() {
                let out = Query::parse($input.to_owned());
                assert!(out.is_err());
                match out {
                    Ok(_) => unreachable!(),
                    Err(e) => match e {
                        $expt => (),
                        _ => unreachable!(),
                    }
                }
            }
        };
    }

    #[test]
    fn parse_empty() {
        let out = Query::parse("".to_owned()).unwrap();
        assert_eq!(out.tokens, Scope(vec![]));
    }

    // Single tokens tests
    parse_test!(parse_variable, "%hello%", Variable("hello".to_owned()));
    parse_test!(parse_text, "hello", Text("hello".to_owned()));
    parse_test!(parse_escape, "\\t", Text("\t".to_owned()));
    parse_test!(parse_func, "$func()", Function("func".to_owned(), vec![]));
    parse_test!(parse_func_param,
                "$func(expr, expr)",
                Function("func".to_owned(),
                         vec![Scope(vec![Text("expr".to_owned())]),
                              Scope(vec![Text(" expr".to_owned())])]));

    parse_test!(parse_func_param_var,
                "$func(expr, expr, %name%)",
                Function("func".to_owned(),
                         vec![Scope(vec![Text("expr".to_owned())]),
                              Scope(vec![Text(" expr".to_owned())]),
                              Scope(vec![Text(" ".to_owned()), Variable("name".to_owned())])]));

    parse_test!(parse_func_rec_params,
                "$i($f())",
                Function("i".to_owned(),
                         vec![Scope(vec![Function("f".to_owned(), vec![])])]));

    // Multi token tests
    parse_test!(parse_text_and_variable,
                "Hello %name%",
                Text("Hello ".to_owned()),
                Variable("name".to_owned()));

    parse_test!(parse_text_var_func,
                "Hello %name% $f()",
                Text("Hello ".to_owned()),
                Variable("name".to_owned()),
                Text(" ".to_owned()),
                Function("f".to_owned(), vec![]));

    parse_fail_test!(parse_fail_miss_matched_variable,
                     "%hello",
                     ParseError::VariableMissingClosing);
    parse_fail_test!(parse_fail_unknown_escape, "\\?", ParseError::UnknownEscape(_));

    parse_fail_test!(parse_fail_end_with_escape,
                     "\\",
                     ParseError::EscapeAtEndOfQuery);
    parse_fail_test!(parse_fail_func_no_para,
                     "$func",
                     ParseError::FuncMissingParameter);
    parse_fail_test!(parse_fail_func_no_close_para,
                     "$func(",
                     ParseError::FuncParameterNotClosed);

}
<commit_msg>test: add parse errors in functions tests<commit_after>use Query;
use Token;
use std::str::Chars;

// consts for character representing tokens
const TOKEN_VAR_START: char = '%';
const TOKEN_VAR_END: char = '%';
const TOKEN_FUNC_NAME_START: char = '$';
const TOKEN_FUNC_PARAM_START: char = '(';
const TOKEN_FUNC_PARAM_END: char = ')';
const TOKEN_FUNC_PARAM_SEP: char = ',';
const TOKEN_ESCAPE: char = '\\';

// TODO: Proper error type instead of String
pub type ParseResult<T> = Result<T, ParseError>;

/// Errors found in parsing query
#[derive(Debug)]
pub enum ParseError {
    /// Unknown escape sequence.
    /// String contains the sequece
    UnknownEscape(String),

    /// Escape squence at end of query
    EscapeAtEndOfQuery,

    /// Variable is missing closing character
    VariableMissingClosing,

    /// Function is missing start of parameters
    FuncMissingParameter,

    /// Function parameters is missing closing character
    FuncParameterNotClosed,

    /// End of Query
    EndOfQuery,
}

impl Query {
    pub fn parse(src: String) -> ParseResult<Query> {
        let mut iter = src.chars();
        match parse_scope(&mut iter) {
            Ok(t) => Ok(Query { tokens: t }),
            Err(e) => return Err(e),
        }
    }
}

fn parse_scope(iter: &mut Chars) -> ParseResult<Token> {
    let mut tokens = Vec::new();
    loop {
        let token = match iter.clone().peekable().peek() {
            Some(c) => {
                match *c {
                    TOKEN_VAR_START => parse_variable(iter),
                    TOKEN_FUNC_NAME_START => parse_function(iter),
                    TOKEN_FUNC_PARAM_END | TOKEN_FUNC_PARAM_SEP => break,
                    _ => parse_text(iter),
                }
            }
            None => Err(ParseError::EndOfQuery),
        };

        tokens.push(match token {
            Ok(t) => t,
            Err(e) => {
                match e {
                    ParseError::EndOfQuery => break,
                    _ => return Err(e),
                }
            }
        });
    }
    Ok(Token::Scope(tokens))
}

fn parse_text(iter: &mut Chars) -> ParseResult<Token> {
    let mut text = String::new();

    loop {
        // Peek to check for next expression
        if let Some(peek) = iter.clone().peekable().peek() {
            match *peek {
                TOKEN_VAR_START => break,
                TOKEN_FUNC_PARAM_SEP => break,
                TOKEN_FUNC_NAME_START => break,
                TOKEN_FUNC_PARAM_START => break,
                TOKEN_FUNC_PARAM_END => break,
                _ => (),
            }
        }

        if let Some(next) = iter.next() {
            match next {
                TOKEN_ESCAPE => {
                    text.push(match parse_escape(iter) {
                        Ok(esc) => esc,
                        Err(err) => return Err(err),
                    })
                }
                _ => text.push(next),
            }
        } else {
            // Made it to the end of the string
            break;
        }
    }
    Ok(Token::Text(text))
}

fn parse_escape(iter: &mut Chars) -> ParseResult<char> {
    if let Some(next) = iter.next() {
        Ok(match next {
            'n' => '\n',
            't' => '\t',
            TOKEN_ESCAPE => TOKEN_ESCAPE,
            TOKEN_VAR_START => TOKEN_VAR_START,
            TOKEN_FUNC_NAME_START => TOKEN_FUNC_NAME_START,
            TOKEN_FUNC_PARAM_SEP => TOKEN_FUNC_PARAM_SEP,
            _ => return Err(ParseError::UnknownEscape(format!("\\{}", next))),
        })
    } else {
        Err(ParseError::EscapeAtEndOfQuery)
    }
}

fn parse_variable(iter: &mut Chars) -> ParseResult<Token> {
    let _ = iter.next(); // ignore TOKEN_VAR_START

    let mut name = String::new();
    while let Some(c) = iter.next() {
        match c {
            TOKEN_VAR_END => return Ok(Token::Variable(name)),
            _ => name.push(c),
        };
    }
    Err(ParseError::VariableMissingClosing)
}

fn parse_function(iter: &mut Chars) -> ParseResult<Token> {
    let _ = iter.next(); // ignore TOKEN_FUNC_NAME_START
    let mut name = String::new();
    let mut args = Vec::<Token>::new();

    // get the name of the function
    loop {
        if let Some(c) = iter.next() {
            match c { // TODO: enforce name limits here
                TOKEN_FUNC_PARAM_START => break,
                _ => name.push(c),
            };
        } else {
            return Err(ParseError::FuncMissingParameter);
        }
    }

    // get the parameters of the function
    while let Some(c) = iter.clone().peekable().peek() {
        match *c { // TODO: parse tokens seperated by commas
            TOKEN_FUNC_PARAM_END => {
                let _ = iter.next();
                return Ok(Token::Function(name, args));
            }
            TOKEN_FUNC_PARAM_SEP => {
                let _ = iter.next();
                continue;
            }
            _ => {
                args.push(match parse_scope(iter) {
                    Ok(t) => t,
                    Err(e) => return Err(e),
                })
            }
        }
    }

    Err(ParseError::FuncParameterNotClosed)
}

#[cfg(test)]
mod tests {
    use ::Token::*;
    use ParseError;
    use Query;

    macro_rules! parse_test {
        ($name: ident, $input: expr, $out: expr) => {
            #[test]
            fn $name() {
                let out = Query::parse($input.to_owned()).unwrap();
                assert_eq!(out.tokens, Scope(vec![$out]));
            }
        };

        ($name: ident, $input: expr, $out: expr, $($more: expr),*) => {
            #[test]
            fn $name() {
                let out = Query::parse($input.to_owned()).unwrap();
                assert_eq!(out.tokens, Scope(vec![$out $(, $more)*]));
            }
        };
    }

    macro_rules! parse_fail_test {
        ($name: ident, $input: expr, $expt: pat) => {
            #[test]
            fn $name() {
                let out = Query::parse($input.to_owned());
                assert!(out.is_err());
                match out {
                    Ok(_) => unreachable!(),
                    Err(e) => match e {
                        $expt => (),
                        _ => unreachable!(),
                    }
                }
            }
        };
    }

    #[test]
    fn parse_empty() {
        let out = Query::parse("".to_owned()).unwrap();
        assert_eq!(out.tokens, Scope(vec![]));
    }

    // Single tokens tests
    parse_test!(parse_variable, "%hello%", Variable("hello".to_owned()));
    parse_test!(parse_text, "hello", Text("hello".to_owned()));
    parse_test!(parse_escape, "\\t", Text("\t".to_owned()));
    parse_test!(parse_func, "$func()", Function("func".to_owned(), vec![]));

    // function tests
    parse_test!(parse_func_param,
                "$func(expr, expr)",
                Function("func".to_owned(),
                         vec![Scope(vec![Text("expr".to_owned())]),
                              Scope(vec![Text(" expr".to_owned())])]));

    parse_test!(parse_func_param_var,
                "$func(expr, expr, %name%)",
                Function("func".to_owned(),
                         vec![Scope(vec![Text("expr".to_owned())]),
                              Scope(vec![Text(" expr".to_owned())]),
                              Scope(vec![Text(" ".to_owned()), Variable("name".to_owned())])]));

    parse_test!(parse_func_rec_params,
                "$i($f())",
                Function("i".to_owned(),
                         vec![Scope(vec![Function("f".to_owned(), vec![])])]));

    // Multi token tests
    parse_test!(parse_text_and_variable,
                "Hello %name%",
                Text("Hello ".to_owned()),
                Variable("name".to_owned()));

    parse_test!(parse_text_var_func,
                "Hello %name% $f()",
                Text("Hello ".to_owned()),
                Variable("name".to_owned()),
                Text(" ".to_owned()),
                Function("f".to_owned(), vec![]));

    // parse failures
    parse_fail_test!(parse_fail_miss_matched_variable,
                     "%hello",
                     ParseError::VariableMissingClosing);
    parse_fail_test!(parse_fail_unknown_escape, "\\?", ParseError::UnknownEscape(_));

    parse_fail_test!(parse_fail_end_with_escape,
                     "\\",
                     ParseError::EscapeAtEndOfQuery);
    parse_fail_test!(parse_fail_func_no_para,
                     "$func",
                     ParseError::FuncMissingParameter);
    parse_fail_test!(parse_fail_func_no_close_para,
                     "$func(",
                     ParseError::FuncParameterNotClosed);

    // errors in scope of functions
    parse_fail_test!(parse_fail_miss_matched_variable_in_func,
                     "$test(%hello)",
                     ParseError::VariableMissingClosing);
    parse_fail_test!(parse_fail_unknown_escape_in_func,
                     "$test(\\?)", ParseError::UnknownEscape(_));

    parse_fail_test!(parse_fail_func_no_para_in_func,
                     "$test($func)",
                     ParseError::FuncMissingParameter);
}
<|endoftext|>


<commit_before>use regex::Regex;
use database::*;

macro_rules! regex { ($re:expr) => { ::regex::Regex::new($re).unwrap() } }

/// Represents a movie
// #[derive(Debug)]
// Brauchen wir das struct überhaupt?

// struct Film {
//     name: String,
//     votes: String,
//     rating: String,
//     year: String,
// }

// impl Film {
//     fn new() -> Self {
//         Film {
//             name: String::new(),
//             votes: String::new(),
//             rating: String::new(),
//             year: String::new(),
//         }
//     }
// }

// #[derive(Debug)]
// struct Genre {
//     movie: String,
//     genre: String,
// }
// impl Genre {
//     fn new() -> Self {
//         Genre {
//             movie: String::new(),
//             genre: String::new(),
//         }
//     }
// }

pub fn parse_rating(string: String) {
    // let re = Regex::new(r"(\n [\s]+ [\d|\.]{10}[\s]+ (\d+)[\s]+ ([\d|\.]{3}) (.+) [(](\d{4})[)])")
    let re = Regex::new("(\\n [\\s]+ [\\d|\\.]{10}[\\s]+ (\\d+)[\\s]+ \
                         ([\\d|\\.]{3})[\\s]{2}([^\u{0022}]{1}.+) \\(([\\d]{4})\\))")
        .unwrap(); //                    ^number     ^rating      ^title  ^year

    println!("{:?}", &re);

    for cap in re.captures_iter(string.as_str()) {
        let votes = &cap[2].parse::<i32>().unwrap();
        if *votes > 100000 {
            import_movie(&cap[4].trim(),
                         &cap[5].trim(),
                         &cap[3].trim(),
                         &cap[2].trim());
        }
    }
}

fn parse_genre(string: String) {
    let re = Regex::new(r"(\n(.+)[\s]+[(](\d{4})[)][\s]+(?:\(V\)|\(TV\))?[\s]*([^\{].+))").unwrap(); //        ^year           ^(TV|V) filter             ^genre
    // Series with form "NAME (YEAR)  {EPISODE INFO}   GENRE" are filtered out

    for cap in re.captures_iter(string.as_str()) {
        add_rating(&cap[4], &cap[5], &cap[3], &cap[2]);
    }
}

// TODO: Filter series with form "NAME (YEAR)   {EPISODE INFO}"
// pub fn parse_movies(string: String) {
// let re = Regex::new(r"(\n\u{0022}?[#|\+|\-|\*|\/|\.|\,|\!|\:|\&|\%|\$|\§|\w|\d|\s]*\u{0022}? \([\d]{4}\))").unwrap();
// let re = Regex::new("(\\n\u{0022}?[#|\\+|\\-|\\*|\\041|\\057|\\054|\\056|\\072|\\073|\\044|\\045|\\046|\\w|\\d|\\s]*\u{0022}? \\([\\d]{4}\\))")
// .unwrap();
// println!("{:?}", re);
// for cap in re.captures_iter(string.as_str()) {
// let mut movie = &cap[0];
// movie = movie.trim();
// let tmp: Vec<&str> = movie.rsplitn(2, ' ').collect();
// let mut year = tmp[0];
// year = year.trim();
// import_movie(tmp[1], &year[1..5]);
// }
// }

pub fn parse_actors() {
    // TODO: implement it!
}

pub fn parse_directors() {
    // TODO: implement it!
}
<commit_msg>Change regex for parse_genre()<commit_after>use regex::Regex;
use database::*;

macro_rules! regex { ($re:expr) => { ::regex::Regex::new($re).unwrap() } }

/// Represents a movie
// #[derive(Debug)]
// Brauchen wir das struct überhaupt?

// struct Film {
//     name: String,
//     votes: String,
//     rating: String,
//     year: String,
// }

// impl Film {
//     fn new() -> Self {
//         Film {
//             name: String::new(),
//             votes: String::new(),
//             rating: String::new(),
//             year: String::new(),
//         }
//     }
// }

// #[derive(Debug)]
// struct Genre {
//     movie: String,
//     genre: String,
// }
// impl Genre {
//     fn new() -> Self {
//         Genre {
//             movie: String::new(),
//             genre: String::new(),
//         }
//     }
// }

pub fn parse_rating(string: String) {
    // let re = Regex::new(r"(\n [\s]+ [\d|\.]{10}[\s]+ (\d+)[\s]+ ([\d|\.]{3}) (.+) [(](\d{4})[)])")
    let re = Regex::new("(\\n [\\s]+ [\\d|\\.]{10}[\\s]+ (\\d+)[\\s]+ \
                         ([\\d|\\.]{3})[\\s]{2}([^\u{0022}]{1}.+) \\(([\\d]{4})\\))")
        .unwrap(); //                    ^number     ^rating      ^title  ^year

    println!("{:?}", &re);

    for cap in re.captures_iter(string.as_str()) {
        let votes = &cap[2].parse::<i32>().unwrap();
        if *votes > 100000 {
            import_movie(&cap[4].trim(),
                         &cap[5].trim(),
                         &cap[3].trim(),
                         &cap[2].trim());
        }
    }
}

fn parse_genre(string: String) {
    // Series starting with "quotation marks" are filtered out
    let re = Regex::new(
        "(\\n([^\u{0022}].*)[\\s]+[\\(](\\d{4})[\\)][\\s]+(?:\\(V\\)|\\(TV\\))?[\\s]*([^\\{].+))"
    ).unwrap();
    //                ^title             ^year               ^filter for (V)/(TV)           ^genre
    for cap in re.captures_iter(string.as_str()) {
        add_genres(&cap[2],
                   &cap[3],
                   &cap[4]);
    }
}

// TODO: Filter series with form "NAME (YEAR)   {EPISODE INFO}"
// pub fn parse_movies(string: String) {
// let re = Regex::new(r"(\n\u{0022}?[#|\+|\-|\*|\/|\.|\,|\!|\:|\&|\%|\$|\§|\w|\d|\s]*\u{0022}? \([\d]{4}\))").unwrap();
// let re = Regex::new("(\\n\u{0022}?[#|\\+|\\-|\\*|\\041|\\057|\\054|\\056|\\072|\\073|\\044|\\045|\\046|\\w|\\d|\\s]*\u{0022}? \\([\\d]{4}\\))")
// .unwrap();
// println!("{:?}", re);
// for cap in re.captures_iter(string.as_str()) {
// let mut movie = &cap[0];
// movie = movie.trim();
// let tmp: Vec<&str> = movie.rsplitn(2, ' ').collect();
// let mut year = tmp[0];
// year = year.trim();
// import_movie(tmp[1], &year[1..5]);
// }
// }

pub fn parse_actors() {
    // TODO: implement it!
    // Will it ever be implemented? :((
}

pub fn parse_directors() {
    // TODO: implement it!
}
<|endoftext|>


<commit_before>extern crate orbclient;

#[derive(Clone, Copy, Debug)]
pub struct Color {
    r: u8,
    g: u8,
    b: u8,
}

impl Color {
    pub fn new(r: u8, g: u8, b: u8) -> Color {
        Color {
            r: r,
            g: g,
            b: b,
        }
    }

    pub fn as_orbclient(&self) -> orbclient::color::Color {
        orbclient::color::Color::rgb(self.r, self.g, self.b)
    }

    pub fn from_orbclient(color: orbclient::color::Color) -> Color {
        let r = (color.data & 0x00FF0000) >> 16;
        let g = (color.data & 0x0000FF00) >> 8;
        let b = color.data & 0x000000FF;

        Color::new(r as u8, g as u8, b as u8)
    }
}

#[derive(Debug)]
pub struct Texture {
    pub width: usize,
    pub height: usize,
    frame: Vec<Color>,
}

impl Texture {
    pub fn new(w: usize, h: usize) -> Texture {
        let mut tex: Vec<Color> = Vec::new();

        for _ in 0..w*h {
            tex.push(Color::new(0, 0, 0));
        }

        Texture {
            width: w,
            height: h,
            frame: tex,
        }
    }

    pub fn load(path: &str) -> Texture {
        use std::ops::Deref;

        let bmp = orbclient::bmp::BmpFile::from_path(path);
        let w = bmp.width();
        let h = bmp.height();

        let orb_color_vec = bmp.deref();

        let mut color_vec: Vec<Color> = Vec::new();

        for i in 0..orb_color_vec.len() {
            color_vec.push(Color::from_orbclient(orb_color_vec[i]));
        }

        Texture {
            width: w,
            height: h,
            frame: color_vec,
        }
    }

    pub fn get_pixel(&self, x: u32, y: u32) -> Option<&Color> {
        self.frame.get(y as usize*self.width + x as usize)
    }

    pub fn get_by_float(&self, x: f32, y: f32) -> Option<&Color> {
        self.get_pixel((x * self.width as f32) as u32, (y * self.height as f32) as u32)
    }

    pub fn get_for_triangle(&self, alpha: f32, beta: f32, gamma: f32,
                            triangle: &super::geometry::Triangle) -> Option<&Color> {
        self.get_by_float(triangle.uv_p1.x * alpha + triangle.uv_p2.x * beta + triangle.uv_p3.x * gamma,
                          triangle.uv_p1.y * alpha + triangle.uv_p2.y * beta + triangle.uv_p3.y * gamma)
    }
}

pub struct Framebuffer {
    pub width: usize,
    pub height: usize,
    frame: Vec<Color>,
}

impl Framebuffer {
    pub fn new(w: usize, h: usize) -> Framebuffer {
        let mut frame: Vec<Color> = Vec::new();

        for _ in 0..w*h {
            frame.push(Color::new(0, 0, 0));
        }

        Framebuffer {
            width: w,
            height: h,
            frame: frame,
        }
    }

    pub fn get_pixel(&self, x: u32, y: u32) -> Option<&Color> {
        self.frame.get(y as usize*self.width + x as usize)
    }

    pub fn set_pixel(&mut self, x: u32, y: u32, color: &Color) {
        self.frame[y as usize*self.width + x as usize] = color.clone();
    }

    pub fn render_3d_triangles(&mut self, triangles: &Vec<&super::geometry::Triangle>, screen_h: i32) {
        let mut flat_triangles: Vec<super::geometry::FlatTriangle> = Vec::new();
        for triangle in triangles {
            flat_triangles.push(triangle.make_2d())
        }

        for x in 0..self.width {
            for y in 0..self.height {
                for triangle in &flat_triangles {
                    //self.set_pixel(triangle.p1.screen_point(), triangle.p1.y, &Color::new(255, 255, 255));
                    if triangle.inside(x as u32, y as u32, screen_h) {
                        self.set_pixel(x as u32, y as u32, &Color::new(255, 0, 0));
                        //print!("inside");
                    } else {
                        self.set_pixel(x as u32, y as u32, &Color::new(0, 0, 0));
                    }
                }
            }
        }
    }
}
<commit_msg>Added Z-buffer and made renderer contact orbclient directly to improve speeds<commit_after>extern crate orbclient;

use std;

#[derive(Clone, Copy, Debug)]
/// An RGB color
pub struct Color {
    r: u8,
    g: u8,
    b: u8,
}

impl Color {
    pub fn new(r: u8, g: u8, b: u8) -> Color {
        Color {
            r: r,
            g: g,
            b: b,
        }
    }

    pub fn as_orbclient(&self) -> orbclient::color::Color {
        orbclient::color::Color::rgb(self.r, self.g, self.b)
    }

    pub fn from_orbclient(color: orbclient::color::Color) -> Color {
        let r = (color.data & 0x00FF0000) >> 16;
        let g = (color.data & 0x0000FF00) >> 8;
        let b = color.data & 0x000000FF;

        Color::new(r as u8, g as u8, b as u8)
    }
}

#[derive(Clone, Copy, Debug)]
/// A color with Z depth data attached
pub struct ZBufColor {
    pub color: Color,
    pub z: f32,
}

impl ZBufColor {
    pub fn new(r: u8, g: u8, b: u8, z: f32) -> ZBufColor {
        ZBufColor {
            color: Color {
                r: r,
                g: g,
                b: b,
            },
            z: z,
        }
    }

    pub fn from_color(color: Color, z: f32) -> ZBufColor {
        ZBufColor {
            color: color,
            z: z,
        }
    }
}

#[derive(Debug)]
pub struct Texture {
    pub width: usize,
    pub height: usize,
    frame: Vec<Color>,
}

impl Texture {
    pub fn new(w: usize, h: usize) -> Texture {
        let mut tex: Vec<Color> = Vec::new();

        for _ in 0..w*h {
            tex.push(Color::new(0, 0, 0));
        }

        Texture {
            width: w,
            height: h,
            frame: tex,
        }
    }

    pub fn load(path: &str) -> Texture {
        use std::ops::Deref;

        let bmp = orbclient::bmp::BmpFile::from_path(path);
        let w = bmp.width();
        let h = bmp.height();

        let orb_color_vec = bmp.deref();

        let mut color_vec: Vec<Color> = Vec::new();

        for i in 0..orb_color_vec.len() {
            color_vec.push(Color::from_orbclient(orb_color_vec[i]));
        }

        Texture {
            width: w,
            height: h,
            frame: color_vec,
        }
    }

    pub fn get_pixel(&self, x: u32, y: u32) -> Option<&Color> {
        self.frame.get(y as usize*self.width + x as usize)
    }

    pub fn get_by_float(&self, x: f32, y: f32) -> Option<&Color> {
        self.get_pixel((x * self.width as f32) as u32, (y * self.height as f32) as u32)
    }

    pub fn get_for_triangle(&self, alpha: f32, beta: f32, gamma: f32,
                            triangle: &super::geometry::Triangle) -> Option<&Color> {
        self.get_by_float(triangle.uv_p1.x * alpha + triangle.uv_p2.x * beta + triangle.uv_p3.x * gamma,
                          triangle.uv_p1.y * alpha + triangle.uv_p2.y * beta + triangle.uv_p3.y * gamma)
    }
}

//FIXME: This was a big mistake. Go back to rendering right to the output instead of some
// wrapper structs like this.
pub struct Framebuffer {
    pub width: usize,
    pub height: usize,
    cache: Vec<ZBufColor>, // workaround around orbclients lack of ability to read from the screen
    frame: super::init::Window,
}

impl Framebuffer {
    pub fn new(w: usize, h: usize, window: super::init::Window) -> Framebuffer {
        let mut cache: Vec<ZBufColor> = Vec::new();

        for _ in 0..w*h {
            cache.push(ZBufColor::new(0, 0, 0, std::f32::INFINITY));
        }

        Framebuffer {
            width: w,
            height: h,
            cache: cache,
            frame: window,
        }
    }

    pub fn get_pixel(&self, x: u32, y: u32) -> Option<&ZBufColor> {
        self.cache.get(y as usize*self.width + x as usize)
    }

    pub fn set_pixel(&mut self, x: u32, y: u32, color: &ZBufColor) {
        self.cache[y as usize*self.width + x as usize] = color.clone(); // cache
        self.frame.set_pixel(x as i32, y as i32, &color.color); // draw
    }

    pub fn clear(&mut self) {
        for pixel in 0..self.width*self.height {
            self.cache[pixel] = ZBufColor::new(0, 0, 0, std::f32::INFINITY); // cache
        }
        self.frame.clear(); // draw
    }

    pub fn sync(&mut self) {
        self.frame.sync();
    }

    pub fn render_3d_triangles(&mut self, triangles: &Vec<&super::geometry::Triangle>, screen_h: i32, screen_w: i32) {
        /*let mut flat_triangles: Vec<super::geometry::FlatTriangle> = Vec::new();
        for triangle in triangles {
            flat_triangles.push(triangle.make_2d())
        }

        for x in 0..self.width {
            for y in 0..self.height {
                for triangle in &flat_triangles {
                    //self.set_pixel(triangle.p1.screen_point(), triangle.p1.y, &Color::new(255, 255, 255));
                    if triangle.inside(x as u32, y as u32, screen_h) {
                        self.set_pixel(x as u32, y as u32, &ZBufColor::new(255, 0, 0, 0.0));
                        //TODO: Use real Z value.
                        //print!("inside");
                    } else {
                        self.set_pixel(x as u32, y as u32, &ZBufColor::new(0, 0, 0, 0.0));
                    }
                }
            }
        }*/

        for x in 0..self.width {
            for y in 0..self.height {
                for triangle in triangles {
                    let flat_triangle = triangle.make_2d();

                    let (alpha, beta, gamma) = flat_triangle.get_barycentric(x as u32, y as u32, screen_h, screen_w);

                    if alpha > 0.0 && beta > 0.0 && gamma > 0.0 {
                        self.set_pixel(x as u32, y as u32, &ZBufColor::new(255, 0, 0,
                            triangle.z_from_barycentric(alpha, beta, gamma)));
                        //TODO: Use real Z value.
                    } else {
                        //self.set_pixel(x as u32, y as u32, &ZBufColor::new(0, 0, 0, 0.0));
                    }
                }
            }
        }
    }

    pub fn draw_cached_zbuf(&mut self) {
        for x in 0..self.width as u32 {
            for y in 0..self.height as u32 {
                let pixel = self.cache.get(y as usize*self.width + x as usize);

                if pixel.is_none() {
                    continue;
                } else {
                    let z_color = (((1.0 / -pixel.unwrap().z) * 255.0) + 255.0) as u8;
                    &self.frame.set_pixel(x as i32, y as i32, &Color::new(z_color, z_color, z_color));
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::string::ToString;
use std::collections::HashMap;

use task::Task;
use payload::Payload;
use route::RouteHandler;
use resource::Resource;
use recognizer::{RouteRecognizer, check_pattern};
use application::Application;
use httpcodes::HTTPNotFound;
use httprequest::HttpRequest;

pub(crate) trait Handler: 'static {
    fn handle(&self, req: HttpRequest, payload: Payload) -> Task;
}

/// Server routing map
pub struct Router {
    apps: HashMap<String, Box<Handler>>,
    resources: RouteRecognizer<Resource>,
}

impl Router {

    pub(crate) fn call(&self, req: HttpRequest, payload: Payload) -> Task
    {
        if let Some((params, h)) = self.resources.recognize(req.path()) {
            if let Some(params) = params {
                h.handle(
                    req.with_match_info(params), payload, Rc::new(()))
            } else {
                h.handle(req, payload, Rc::new(()))
            }
        } else {
            for (prefix, app) in &self.apps {
                if req.path().starts_with(prefix) {
                    return app.handle(req, payload)
                }
            }
            Task::reply(HTTPNotFound.response())
        }
    }
}

/// Request routing map builder
///
/// Resource may have variable path also. For instance, a resource with
/// the path '/a/{name}/c' would match all incoming requests with paths
/// such as '/a/b/c', '/a/1/c', and '/a/etc/c'.
///
/// A variable part is specified in the form {identifier}, where
/// the identifier can be used later in a request handler to access the matched
/// value for that part. This is done by looking up the identifier
/// in the Params object returned by `Request.match_info()` method.
///
/// By default, each part matches the regular expression [^{}/]+.
///
/// You can also specify a custom regex in the form {identifier:regex}:
///
/// For instance, to route Get requests on any route matching /users/{userid}/{friend} and
/// store userid and friend in the exposed Params object:
///
/// ```rust,ignore
/// let mut map = RoutingMap::default();
///
/// map.resource("/users/{userid}/{friend}", |r| r.get::<MyRoute>());
/// ```
pub struct RoutingMap {
    parts: Option<RoutingMapParts>,
}

struct RoutingMapParts {
    apps: HashMap<String, Box<Handler>>,
    resources: HashMap<String, Resource>,
}

impl Default for RoutingMap {
    fn default() -> Self {
        RoutingMap {
            parts: Some(RoutingMapParts {
                apps: HashMap::new(),
                resources: HashMap::new()}),
        }
    }
}

impl RoutingMap {

    /// Add `Application` object with specific prefix.
    /// Application prefixes all registered resources with specified prefix.
    ///
    /// ```rust,ignore
    ///
    /// struct MyRoute;
    ///
    /// fn main() {
    ///     let mut router =
    ///         RoutingMap::default()
    ///             .app("/pre", Application::default()
    ///                  .resource("/test", |r| {
    ///                      r.get::<MyRoute>();
    ///                      r.post::<MyRoute>();
    ///                 })
    ///                 .finish()
    ///         ).finish();
    /// }
    /// ```
    /// In this example, `MyRoute` route is available as `http://.../pre/test` url.
    pub fn app<P, S: 'static>(&mut self, prefix: P, app: Application<S>) -> &mut Self
        where P: ToString
    {
        {
            let parts = self.parts.as_mut().expect("Use after finish");

            // we can not override registered resource
            let prefix = prefix.to_string();
            if parts.apps.contains_key(&prefix) {
                panic!("Resource is registered: {}", prefix);
            }

            // add application
            parts.apps.insert(prefix.clone(), app.prepare(prefix));
        }
        self
    }

    /// Configure resource for specific path.
    ///
    /// ```rust,ignore
    ///
    /// struct MyRoute;
    ///
    /// fn main() {
    ///     RoutingMap::default().resource("/test", |r| {
    ///         r.post::<MyRoute>();
    ///     }).finish();
    /// }
    /// ```
    /// In this example, `MyRoute` route is available as `http://.../test` url.
    pub fn resource<P, F>(&mut self, path: P, f: F) -> &mut Self
        where F: FnOnce(&mut Resource<()>) + 'static,
              P: ToString,
    {
        {
            let parts = self.parts.as_mut().expect("Use after finish");

            // add resource
            let path = path.to_string();
            if !parts.resources.contains_key(&path) {
                check_pattern(&path);
                parts.resources.insert(path.clone(), Resource::default());
            }
            // configure resource
            f(parts.resources.get_mut(&path).unwrap());
        }
        self
    }

    /// Finish configuration and create `Router` instance
    pub fn finish(&mut self) -> Router
    {
        let parts = self.parts.take().expect("Use after finish");

        let mut routes = Vec::new();
        for (path, resource) in parts.resources {
            routes.push((path, resource))
        }

        Router {
            apps: parts.apps,
            resources: RouteRecognizer::new("/".to_owned(), routes),
        }
    }
}
<commit_msg>doc string<commit_after>use std::rc::Rc;
use std::string::ToString;
use std::collections::HashMap;

use task::Task;
use payload::Payload;
use route::RouteHandler;
use resource::Resource;
use recognizer::{RouteRecognizer, check_pattern};
use application::Application;
use httpcodes::HTTPNotFound;
use httprequest::HttpRequest;

pub(crate) trait Handler: 'static {
    fn handle(&self, req: HttpRequest, payload: Payload) -> Task;
}

/// Server routing map
pub struct Router {
    apps: HashMap<String, Box<Handler>>,
    resources: RouteRecognizer<Resource>,
}

impl Router {

    pub(crate) fn call(&self, req: HttpRequest, payload: Payload) -> Task
    {
        if let Some((params, h)) = self.resources.recognize(req.path()) {
            if let Some(params) = params {
                h.handle(
                    req.with_match_info(params), payload, Rc::new(()))
            } else {
                h.handle(req, payload, Rc::new(()))
            }
        } else {
            for (prefix, app) in &self.apps {
                if req.path().starts_with(prefix) {
                    return app.handle(req, payload)
                }
            }
            Task::reply(HTTPNotFound.response())
        }
    }
}

/// Request routing map builder
///
/// Resource may have variable path also. For instance, a resource with
/// the path */a/{name}/c* would match all incoming requests with paths
/// such as */a/b/c*, */a/1/c*, and */a/etc/c*.
///
/// A variable part is specified in the form `{identifier}`, where
/// the identifier can be used later in a request handler to access the matched
/// value for that part. This is done by looking up the identifier
/// in the Params object returned by `Request.match_info()` method.
///
/// By default, each part matches the regular expression `[^{}/]+`.
///
/// You can also specify a custom regex in the form `{identifier:regex}`:
///
/// For instance, to route Get requests on any route matching `/users/{userid}/{friend}` and
/// store userid and friend in the exposed Params object:
///
/// ```rust,ignore
/// let mut map = RoutingMap::default();
///
/// map.resource("/users/{userid}/{friend}", |r| r.get::<MyRoute>());
/// ```
pub struct RoutingMap {
    parts: Option<RoutingMapParts>,
}

struct RoutingMapParts {
    apps: HashMap<String, Box<Handler>>,
    resources: HashMap<String, Resource>,
}

impl Default for RoutingMap {
    fn default() -> Self {
        RoutingMap {
            parts: Some(RoutingMapParts {
                apps: HashMap::new(),
                resources: HashMap::new()}),
        }
    }
}

impl RoutingMap {

    /// Add `Application` object with specific prefix.
    /// Application prefixes all registered resources with specified prefix.
    ///
    /// ```rust,ignore
    ///
    /// struct MyRoute;
    ///
    /// fn main() {
    ///     let mut router =
    ///         RoutingMap::default()
    ///             .app("/pre", Application::default()
    ///                  .resource("/users/{userid}", |r| {
    ///                      r.get::<MyRoute>();
    ///                      r.post::<MyRoute>();
    ///                 })
    ///                 .finish()
    ///         ).finish();
    /// }
    /// ```
    /// In this example, `MyRoute` route is available as `http://.../pre/test` url.
    pub fn app<P, S: 'static>(&mut self, prefix: P, app: Application<S>) -> &mut Self
        where P: ToString
    {
        {
            let parts = self.parts.as_mut().expect("Use after finish");

            // we can not override registered resource
            let prefix = prefix.to_string();
            if parts.apps.contains_key(&prefix) {
                panic!("Resource is registered: {}", prefix);
            }

            // add application
            parts.apps.insert(prefix.clone(), app.prepare(prefix));
        }
        self
    }

    /// Configure resource for specific path.
    ///
    /// ```rust,ignore
    ///
    /// struct MyRoute;
    ///
    /// fn main() {
    ///     RoutingMap::default().resource("/test", |r| {
    ///         r.post::<MyRoute>();
    ///     }).finish();
    /// }
    /// ```
    /// In this example, `MyRoute` route is available as `http://.../test` url.
    pub fn resource<P, F>(&mut self, path: P, f: F) -> &mut Self
        where F: FnOnce(&mut Resource<()>) + 'static,
              P: ToString,
    {
        {
            let parts = self.parts.as_mut().expect("Use after finish");

            // add resource
            let path = path.to_string();
            if !parts.resources.contains_key(&path) {
                check_pattern(&path);
                parts.resources.insert(path.clone(), Resource::default());
            }
            // configure resource
            f(parts.resources.get_mut(&path).unwrap());
        }
        self
    }

    /// Finish configuration and create `Router` instance
    pub fn finish(&mut self) -> Router
    {
        let parts = self.parts.take().expect("Use after finish");

        let mut routes = Vec::new();
        for (path, resource) in parts.resources {
            routes.push((path, resource))
        }

        Router {
            apps: parts.apps,
            resources: RouteRecognizer::new("/".to_owned(), routes),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use num::complex::Complex;
use libc::{
    c_char,
    c_double,
    c_float,
    c_int,
    c_void,
};

pub trait Scalar<T, S> {
    fn as_const(self) -> T;
    fn as_mut(self) -> S;
}

macro_rules! scalar_impl(
    ($t: ty, $c_type: ty) => (
        impl<'a> Scalar<*const $t, *mut $t> for &'a $t {
            #[inline]
            fn as_const(self) -> *const $t {
                self as *const $c_type
            }

            #[inline]
            fn as_mut(self) -> *mut $t {
                &self as *const _ as *mut $c_type
            }
        }

        impl<'a> Scalar<*const c_void, *mut c_void> for &'a Complex<$t> {
            #[inline]
            fn as_const(self) -> *const c_void {
                self as *const _ as *const c_void
            }

            #[inline]
            fn as_mut(self) -> *mut c_void {
                self as *const _ as *mut c_void
            }
        }
    );
);

scalar_impl!(i8, c_char);
scalar_impl!(i32, c_int);
scalar_impl!(f32, c_float);
scalar_impl!(f64, c_double);
<commit_msg>Fix scalar as_mut extra reference<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use num::complex::Complex;
use libc::{
    c_char,
    c_double,
    c_float,
    c_int,
    c_void,
};

pub trait Scalar<T, S> {
    fn as_const(self) -> T;
    fn as_mut(self) -> S;
}

macro_rules! scalar_impl(
    ($t: ty, $c_type: ty) => (
        impl<'a> Scalar<*const $t, *mut $t> for &'a $t {
            #[inline]
            fn as_const(self) -> *const $t {
                self as *const $c_type
            }

            #[inline]
            fn as_mut(self) -> *mut $t {
                self as *const _ as *mut $c_type
            }
        }

        impl<'a> Scalar<*const c_void, *mut c_void> for &'a Complex<$t> {
            #[inline]
            fn as_const(self) -> *const c_void {
                self as *const _ as *const c_void
            }

            #[inline]
            fn as_mut(self) -> *mut c_void {
                self as *const _ as *mut c_void
            }
        }
    );
);

scalar_impl!(i8, c_char);
scalar_impl!(i32, c_int);
scalar_impl!(f32, c_float);
scalar_impl!(f64, c_double);
<|endoftext|>


<commit_before>use configuration::Configuration;
use std::slice::SliceExt;
use std::cmp::min;
use score::Score;
use sorted_result_set::SortedResultSet;
use std::ascii::AsciiExt;

#[derive(Debug)]
pub struct Search {
    pub config: Configuration,
    current: usize,
    pub query: String,
    pub selection: Option<String>,
    pub result: Vec<String>,
    result_stack: Vec<Vec<String>>,
    done: bool,
}

impl Search {
    pub fn blank(config: Configuration) -> Search {
        let query = config.initial_search.clone();
        let result = config.choices.clone();
        let mut result_stack: Vec<Vec<String>> = Vec::new();

        Search::new(config, query, result_stack, result, 0, false)
    }

    pub fn is_done(&self) -> bool {
        self.done
    }

    pub fn done(self) -> Search {
        Search::new(self.config, self.query, self.result_stack, self.result, self.current, true)
    }

    fn new(config: Configuration, query: String, result_stack: Vec<Vec<String>>, result: Vec<String>, index: usize, done: bool) -> Search {

        let selection = Search::select(&result, index);

        Search { config: config,
                 current: index,
                 query: query,
                 selection: selection,
                 result: result,
                 result_stack: result_stack,
                 done: done}
    }

    fn new_for_index(self, index: usize) -> Search {
        Search::new(self.config, self.query, self.result_stack, self.result, index, self.done)
    }

    fn new_for_query(mut self, new_query: String) -> Search {
        let new_result = Search::filter(new_query.as_slice(), &self.config.choices);
        self.result_stack.push(self.result);

        Search::new(self.config, new_query, self.result_stack, new_result, 0, self.done)
    }

    pub fn filter(query: &str, choices: &Vec<String>) -> Vec<String> {
        let mut results = SortedResultSet::new(20);
        let query = query.to_ascii_lowercase();

        for choice in choices.iter() {
            let lower_choice = choice.to_ascii_lowercase();

            match Score::score(lower_choice.as_slice(), query.as_slice()) {
                0.0     => continue,
                quality => results.push(quality,choice.clone()),
            };
        }
        results.sorted_vec()
    }

    fn select(result: &Vec<String>, index: usize) -> Option<String> {
        if result.len() > 0 {
            Some(result[index].to_string())
        } else {
            None
        }
    }

    pub fn down(self) -> Search {
        let next_index = self.next_index();
        self.new_for_index(next_index)
    }

    pub fn up(self) -> Search {
        let next_index = self.prev_index();
        self.new_for_index(next_index)
    }

    pub fn append_to_search(self, input: &str) -> Search {
        let mut new_query = self.query.clone();
        new_query.push_str(input.as_slice());

        self.new_for_query(new_query)
    }

    pub fn backspace(mut self) -> Search {
        let mut new_query = self.query.clone();
        new_query.pop();
        let new_result = self.result_stack.pop().unwrap();

        Search::new(self.config, new_query, self.result_stack, new_result, 0, self.done)
    }

    fn next_index(&self) -> usize {
        let next_index = self.current + 1;

        if next_index >= self.actual_limit() {
            0
        } else {
            next_index
        }
    }

    fn prev_index(&self) -> usize {
        if self.current == 0 {
            self.actual_limit() - 1
        } else {
            self.current - 1
        }
    }

    fn actual_limit(&self) -> usize {
        min(self.config.visible_limit, self.result.len())
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use configuration::Configuration;
    use super::*;
    use self::test::Bencher;

    fn one_two_three() -> Vec<String> {
        vec!["one".to_string(),
             "two".to_string(),
             "three".to_string()]
    }

    #[test]
    fn it_selects_the_first_choice_by_default() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn it_selets_the_second_when_down_is_called() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.down().selection, Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_end_of_list() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.down().down().down().down().selection, Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_top_of_list() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.up().up().selection, Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_visible_limit() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, Some(2));
        let search = Search::blank(config);

        assert_eq!(search.down().down().down().selection, Some("two".to_string()));
    }

    #[test]
    fn it_moves_down_the_filtered_search_results() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.append_to_search("t").down().selection, Some("three".to_string()));
    }

    #[test]
    fn it_moves_down_the_filtered_search_results_twice() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.append_to_search("t").append_to_search("w").selection, Some("two".to_string()));
    }

    #[test]
    fn it_handles_not_matching_anything() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.append_to_search("x").selection, None);
    }

    #[test]
    fn up_match_nothing_after_filtering_all_out() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("x");

        assert_eq!(search.up().selection, None);
    }

    #[test]
    fn down_match_nothing_after_filtering_all_out() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("x");

        assert_eq!(search.down().selection, None);
    }

    #[test]
    fn backspaces_over_characters() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("e");

        assert_eq!(search.query, "e");
        assert_eq!(search.backspace().query, "");
    }

    #[test]
    fn resets_the_index_when_removing_char_from_search() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("e");

        assert_eq!(search.down().backspace().current, 0);
    }

    #[test]
    fn resets_the_index_when_adding_char_to_seach() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).down();

        assert_eq!(search.append_to_search("o").current, 0);
    }

    #[test]
    fn previous_results_appear_after_backspace() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("t");

        assert_eq!(search.backspace().result.len(), 3);
    }

    #[test]
    fn initial_search_is_not_done() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert!(!search.is_done());
    }

    #[test]
    fn done_search_is_done() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).done();

        assert!(search.is_done());
    }

    #[test]
    fn done_search_has_selection() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).done();

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn loop_around_when_reaching_bottom_of_choices() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("n").down();

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn loop_around_when_reaching_top_of_choices() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("n").up();

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn search_is_case_insensitive() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("T");

        assert_eq!(search.result.len(), 2);
    }

    fn input_times(n: usize) -> Vec<String> {
        let mut result: Vec<String> = Vec::new();
        for thing in one_two_three().iter().cycle().take(n) {
            result.push(thing.clone());
        }
        result
    }

    //84114 ns/iter (+/- 33515)
    #[bench]
    fn filter_speed(b: &mut Bencher) {
        let input = input_times(1000);
        let query = "t";

        b.iter(||{
            Search::filter(query, &input)
        });
    }
}
<commit_msg>fixes result stack<commit_after>use configuration::Configuration;
use std::slice::SliceExt;
use std::cmp::min;
use score::Score;
use sorted_result_set::SortedResultSet;
use std::ascii::AsciiExt;

#[derive(Debug)]
pub struct Search {
    pub config: Configuration,
    current: usize,
    pub query: String,
    pub selection: Option<String>,
    pub result: Vec<String>,
    result_stack: Vec<Vec<String>>,
    done: bool,
}

impl Search {
    pub fn blank(config: Configuration) -> Search {
        let query = config.initial_search.clone();
        let result = config.choices.clone();
        let result_stack: Vec<Vec<String>> = Vec::new();

        Search::new(config, query, result_stack, result, 0, false)
    }

    pub fn is_done(&self) -> bool {
        self.done
    }

    pub fn done(self) -> Search {
        Search::new(self.config, self.query, self.result_stack, self.result, self.current, true)
    }

    fn new(config: Configuration, query: String, result_stack: Vec<Vec<String>>, result: Vec<String>, index: usize, done: bool) -> Search {

        let selection = Search::select(&result, index);

        Search { config: config,
                 current: index,
                 query: query,
                 selection: selection,
                 result: result,
                 result_stack: result_stack,
                 done: done}
    }

    fn new_for_index(self, index: usize) -> Search {
        Search::new(self.config, self.query, self.result_stack, self.result, index, self.done)
    }

    fn new_for_query(mut self, new_query: String) -> Search {
        let new_result = Search::filter(new_query.as_slice(), &self.config.choices);
        self.result_stack.push(self.result);

        Search::new(self.config, new_query, self.result_stack, new_result, 0, self.done)
    }

    pub fn filter(query: &str, choices: &Vec<String>) -> Vec<String> {
        let mut results = SortedResultSet::new(20);
        let query = query.to_ascii_lowercase();

        for choice in choices.iter() {
            let lower_choice = choice.to_ascii_lowercase();

            match Score::score(lower_choice.as_slice(), query.as_slice()) {
                0.0     => continue,
                quality => results.push(quality,choice.clone()),
            };
        }
        results.sorted_vec()
    }

    fn select(result: &Vec<String>, index: usize) -> Option<String> {
        if result.len() > 0 {
            Some(result[index].to_string())
        } else {
            None
        }
    }

    pub fn down(self) -> Search {
        let next_index = self.next_index();
        self.new_for_index(next_index)
    }

    pub fn up(self) -> Search {
        let next_index = self.prev_index();
        self.new_for_index(next_index)
    }

    pub fn append_to_search(self, input: &str) -> Search {
        let mut new_query = self.query.clone();
        new_query.push_str(input.as_slice());

        self.new_for_query(new_query)
    }

    pub fn backspace(mut self) -> Search {
        let mut new_query = self.query.clone();
        new_query.pop();
        let new_result = self.result_stack.pop().unwrap_or(self.result);

        Search::new(self.config, new_query, self.result_stack, new_result, 0, self.done)
    }

    fn next_index(&self) -> usize {
        let next_index = self.current + 1;

        if next_index >= self.actual_limit() {
            0
        } else {
            next_index
        }
    }

    fn prev_index(&self) -> usize {
        if self.current == 0 {
            self.actual_limit() - 1
        } else {
            self.current - 1
        }
    }

    fn actual_limit(&self) -> usize {
        min(self.config.visible_limit, self.result.len())
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use configuration::Configuration;
    use super::*;
    use self::test::Bencher;

    fn one_two_three() -> Vec<String> {
        vec!["one".to_string(),
             "two".to_string(),
             "three".to_string()]
    }

    #[test]
    fn it_selects_the_first_choice_by_default() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn it_selets_the_second_when_down_is_called() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.down().selection, Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_end_of_list() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.down().down().down().down().selection, Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_top_of_list() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.up().up().selection, Some("two".to_string()));
    }

    #[test]
    fn it_loop_around_when_reaching_visible_limit() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, Some(2));
        let search = Search::blank(config);

        assert_eq!(search.down().down().down().selection, Some("two".to_string()));
    }

    #[test]
    fn it_moves_down_the_filtered_search_results() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.append_to_search("t").down().selection, Some("three".to_string()));
    }

    #[test]
    fn it_moves_down_the_filtered_search_results_twice() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.append_to_search("t").append_to_search("w").selection, Some("two".to_string()));
    }

    #[test]
    fn it_handles_not_matching_anything() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert_eq!(search.append_to_search("x").selection, None);
    }

    #[test]
    fn up_match_nothing_after_filtering_all_out() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("x");

        assert_eq!(search.up().selection, None);
    }

    #[test]
    fn down_match_nothing_after_filtering_all_out() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("x");

        assert_eq!(search.down().selection, None);
    }

    #[test]
    fn backspaces_over_characters() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("e");

        assert_eq!(search.query, "e");
        assert_eq!(search.backspace().query, "");
    }

    #[test]
    fn resets_the_index_when_removing_char_from_search() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("e");

        assert_eq!(search.down().backspace().current, 0);
    }

    #[test]
    fn resets_the_index_when_adding_char_to_seach() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).down();

        assert_eq!(search.append_to_search("o").current, 0);
    }

    #[test]
    fn previous_results_appear_after_backspace() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("t");

        assert_eq!(search.backspace().result.len(), 3);
    }

    #[test]
    fn initial_search_is_not_done() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config);

        assert!(!search.is_done());
    }

    #[test]
    fn done_search_is_done() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).done();

        assert!(search.is_done());
    }

    #[test]
    fn done_search_has_selection() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).done();

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn loop_around_when_reaching_bottom_of_choices() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("n").down();

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn loop_around_when_reaching_top_of_choices() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("n").up();

        assert_eq!(search.selection, Some("one".to_string()));
    }

    #[test]
    fn search_is_case_insensitive() {
        let input = one_two_three();
        let config = Configuration::from_inputs(input, None, None);
        let search = Search::blank(config).append_to_search("T");

        assert_eq!(search.result.len(), 2);
    }

    fn input_times(n: usize) -> Vec<String> {
        let mut result: Vec<String> = Vec::new();
        for thing in one_two_three().iter().cycle().take(n) {
            result.push(thing.clone());
        }
        result
    }

    //84114 ns/iter (+/- 33515)
    #[bench]
    fn filter_speed(b: &mut Bencher) {
        let input = input_times(1000);
        let query = "t";

        b.iter(||{
            Search::filter(query, &input)
        });
    }
}
<|endoftext|>


<commit_before>// Single-byte XOR cipher
// The hex encoded string:

// 1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736
// ... has been XOR'd against a single character. Find the key, decrypt the message.

// You can do this by hand. But don't: write code to do it for you.

// How? Devise some method for "scoring" a piece of English plaintext.
// Character frequency is a good metric. Evaluate each output and choose the one with the best score.

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

#[macro_use]
extern crate log;

use std::ascii::AsciiExt;
use std::num::Int;
use std::str;

#[cfg(not(test))]
fn main() {
	println!("Set 1, Challenge 3");
	let input = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736";
	println!("input: {:?}", input);
	let output = decode_single_byte_xor(input);
	println!("output string: {:?}", output);
}

fn decode_single_byte_xor(input: &str) -> String {
	if input.len() % 2 != 0 {
		panic!("Hex string length should be even.");
	}

	// make vector of hex-decoded values
	// for each value from 0 to 255
	//    for each char in vector, xor it and add it to a temp vector
	//    turn vector into string
	//    score string
	//    if string score better than best_string
	//       update best_string, best_string_score

	let mut decimal_values = vec!();

	let input_lower = input.to_ascii_lowercase();
	let bytes = input_lower.as_bytes();

	let mut tick = 1;
	let mut current_byte = 0;

	for &x in bytes.iter() {
		current_byte += convert_hex_char_to_decimal(x) * 16.pow(tick);
		tick = tick ^ 1;
		if tick == 1 {
			decimal_values.push(current_byte);
			current_byte = 0;
		}
	}

	let mut best_string = String::new();
	let mut best_string_score = 0;

	// starting with 0, test the current string just in case
	for test_val in 0..255 {
		debug!("{:?}", test_val);
		let mut decoded_values = vec!();
		for &x in decimal_values.iter() {
			decoded_values.push(x ^ test_val);
		}

		// turn the byte vector into a string
		match str::from_utf8(decoded_values.as_slice()) {
		    Ok(v) => {
		        let score = score_text(v);
		        if score > best_string_score {
		        	best_string = v.to_string();
		        	best_string_score = score;
		        }
		    }
		    Err(_) => { }
		}
	}

	best_string
}

fn convert_hex_char_to_decimal(character: u8) -> u8 {
	// if x is in the ascii range for numbers, subtract 48,
	// which is '0' in ascii. Otherwise, it should be a lowercase letter.
	// 'a' is 97, so subtract 87.
	match character < 58 {
		true => character - 48,
		false => character - 87
	}
}

// these are strings so that they can be used in StrExt.replace.
// this seemed easier than converting chars to strings every time.
// characters are taken from relative frequency of letters in the english language:
// https://en.wikipedia.org/wiki/Letter_frequency
static VALUED_CHARS: &'static[&'static str] = &["e", "t", "a", "o", "n"];

// this scoring function is extremely simple/fragile. that said,
// it completes this challenge
fn score_text(text: &str) -> usize {
	let mut score: usize = 0;
	for &test_char in VALUED_CHARS {
		let test_str = text.to_ascii_lowercase().replace(test_char, "");
		score += text.len() - test_str.len();
		debug!("input: {:?}, test: {:?}, score increase: {:?}", text, test_str, text.len() - test_str.len());
	}
	return score;
}

#[cfg(test)]
mod set1challenge3 {

	#[test]
	fn challenge() {
		let output = super::decode_single_byte_xor("4574626531626563787f76");
		assert_eq!(output, "Test string");
	}

}
<commit_msg>Move the lowercase out of the loop<commit_after>// Single-byte XOR cipher
// The hex encoded string:

// 1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736
// ... has been XOR'd against a single character. Find the key, decrypt the message.

// You can do this by hand. But don't: write code to do it for you.

// How? Devise some method for "scoring" a piece of English plaintext.
// Character frequency is a good metric. Evaluate each output and choose the one with the best score.

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

#[macro_use]
extern crate log;

use std::ascii::AsciiExt;
use std::num::Int;
use std::str;

#[cfg(not(test))]
fn main() {
	println!("Set 1, Challenge 3");
	let input = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736";
	println!("input: {:?}", input);
	let output = decode_single_byte_xor(input);
	println!("output string: {:?}", output);
}

fn decode_single_byte_xor(input: &str) -> String {
	if input.len() % 2 != 0 {
		panic!("Hex string length should be even.");
	}

	// make vector of hex-decoded values
	// for each value from 0 to 255
	//    for each char in vector, xor it and add it to a temp vector
	//    turn vector into string
	//    score string
	//    if string score better than best_string
	//       update best_string, best_string_score

	let mut decimal_values = vec!();

	let input_lower = input.to_ascii_lowercase();
	let bytes = input_lower.as_bytes();

	let mut tick = 1;
	let mut current_byte = 0;

	for &x in bytes.iter() {
		current_byte += convert_hex_char_to_decimal(x) * 16.pow(tick);
		tick = tick ^ 1;
		if tick == 1 {
			decimal_values.push(current_byte);
			current_byte = 0;
		}
	}

	let mut best_string = String::new();
	let mut best_string_score = 0;

	// starting with 0, test the current string just in case
	for test_val in 0..255 {
		debug!("{:?}", test_val);
		let mut decoded_values = vec!();
		for &x in decimal_values.iter() {
			decoded_values.push(x ^ test_val);
		}

		// turn the byte vector into a string
		match str::from_utf8(decoded_values.as_slice()) {
		    Ok(v) => {
		        let score = score_text(v);
		        if score > best_string_score {
		        	best_string = v.to_string();
		        	best_string_score = score;
		        }
		    }
		    Err(_) => { }
		}
	}

	best_string
}

fn convert_hex_char_to_decimal(character: u8) -> u8 {
	// if x is in the ascii range for numbers, subtract 48,
	// which is '0' in ascii. Otherwise, it should be a lowercase letter.
	// 'a' is 97, so subtract 87.
	match character < 58 {
		true => character - 48,
		false => character - 87
	}
}

// these are strings so that they can be used in StrExt.replace.
// this seemed easier than converting chars to strings every time.
// characters are taken from relative frequency of letters in the english language:
// https://en.wikipedia.org/wiki/Letter_frequency
static VALUED_CHARS: &'static[&'static str] = &["e", "t", "a", "o", "n"];

// this scoring function is extremely simple/fragile. that said,
// it completes this challenge
fn score_text(text: &str) -> usize {
	let mut score: usize = 0;
	let lowercase = text.to_ascii_lowercase();
	for &test_char in VALUED_CHARS {
		let test_str = lowercase.replace(test_char, "");
		score += text.len() - test_str.len();
		debug!("input: {:?}, test: {:?}, score increase: {:?}", text, test_str, text.len() - test_str.len());
	}
	return score;
}

#[cfg(test)]
mod set1challenge3 {

	#[test]
	fn challenge() {
		let output = super::decode_single_byte_xor("4574626531626563787f76");
		assert_eq!(output, "Test string");
	}

}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/SHA-256

#![feature(rustc_private)]

// note that for now the rustc::util::sha2::Sha256 docs state:
// This implementation is not intended for external use or for any use where security is
// important.
extern crate rustc;
use rustc::util::sha2::{Sha256, Digest};

fn main() {
    println!("{}", sha_256("Rosetta code"));
}

fn sha_256(input: &str) -> String {
    let mut sh = Sha256::new();
    sh.input_str(input);
    sh.result_str()
}

#[test]
fn test_rosetta() {
    assert_eq!(sha_256("Rosetta code"),
               "764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf".to_string());
}
<commit_msg>replace rustc's SHA-256 with rust-crypto<commit_after>// http://rosettacode.org/wiki/SHA-256

extern crate crypto;

use crypto::digest::Digest;
use crypto::sha2::Sha256;

fn main() {
    println!("{}", sha_256("Rosetta code"));
}

fn sha_256(input: &str) -> String {
    let mut sh = Sha256::new();
    sh.input_str(input);
    sh.result_str()
}

#[test]
fn test_rosetta() {
    assert_eq!(sha_256("Rosetta code"),
               "764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf".to_string());
}
<|endoftext|>


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

use std::io::{Reader, Writer, IoError};
use std::vec::{Vec};
#[allow(unused_imports)]
use std::io::{Truncate, Append, Open, Read, Write};
#[allow(unused_imports)]
use std::io::fs::{File};

/// The maximum line size as specified by RFC 5321.
static MAX_LINE_SIZE: uint = 512;

#[test]
fn test_static_vars() {
    assert_eq!(512, MAX_LINE_SIZE);
}

/// A stream specially made for reading SMTP commands.
///
/// It reads lines of input delimited by the <CRLF> sequence and with a maximum
/// size of 512 bytes, including the command word and the <CRLF> sequence. If
/// the input is not UTF8, non-UTF8 characters are replaced with `U+FFFD
/// REPLACEMENT CHARACTER` but no error is returned.
///
/// Returns `InvalidInput` if no line is found within 512 bytes of input.
///
/// # Example
/// ```no_run
/// use std::io::TcpStream;
/// use rsmtp::stream::SmtpStream;
///
/// let mut smtp = SmtpStream::new(TcpStream::connect("127.0.0.1", 2525).unwrap(), 65536);
///
/// println!("{}", smtp.read_line().unwrap());
/// ```
pub struct SmtpStream<S> {
    stream: S,
    /// The maximum message size, including headers and ending sequence.
    max_message_size: uint
}

#[deriving(Show, Eq, PartialEq)]
pub enum SmtpStreamError {
    ReadFailed(IoError),
    WriteFailed(IoError),
    LineTooLong,
    TooMuchData
}

#[deriving(Show, Eq, PartialEq)]
enum SmtpStreamPrivateError {
    PrivateReadFailed(IoError),
    TooLong
}

impl<S> SmtpStream<S> {
    /// Create a new `SmtpStream` from another stream.
    pub fn new(inner: S, max_message_size: uint) -> SmtpStream<S> {
        SmtpStream {
            stream: inner,
            max_message_size: max_message_size
        }
    }
}

impl<R: Reader> SmtpStream<R> {
    fn read_until(&mut self, end: &[u8], limit: uint) -> Result<Vec<u8>, SmtpStreamPrivateError> {
        let mut data: Vec<u8> = Vec::with_capacity(512);
        let mut last: Vec<u8> = Vec::with_capacity(end.len());
        let mut too_long = false;

        loop {
            // If we have previously read as much data as possible and still are not finished
            // reading, stop here.
            if data.len() >= limit && !too_long {
                too_long = true;
            }

            // Try to get more data and see if we have got it all.
            let byte_res = self.stream.read_byte();
            match byte_res {
                Ok(b) => {
                    // Only keep remaining data if we are allowed too. Otherwise, discard it too
                    // avoid out of memory errors.
                    if !too_long {
                        data.push(b);
                    }

                    // Update our last bytes for later comparison.
                    if last.len() == end.len() {
                        last.remove(0).unwrap();
                    }
                    last.push(b);

                    // Let's see if we have read all the data.
                    if last.as_slice() == end {
                        // If we didn't have too much data, we'll remove the end form it to clean up.
                        if !too_long {
                            let data_len = data.len();
                            data.truncate(data_len - end.len());
                        }
                        break;
                    }
                },
                Err(err) => {
                    return Err(PrivateReadFailed(err))
                }
            }
        }
        if too_long {
            Err(TooLong)
        } else {
            Ok(data)
        }
    }

    /// Read the data section of an email. Ends with "<CRLF>.<CRLF>".
    pub fn read_data(&mut self) -> Result<Vec<u8>, SmtpStreamError> {
        let max_data = self.max_message_size;
        match self.read_until(&[13, 10, 46, 13, 10], max_data) {
            Ok(data) => Ok(data),
            Err(err) => {
                match err {
                    TooLong => Err(TooMuchData),
                    PrivateReadFailed(err) => Err(ReadFailed(err))
                }
            }
        }
    }

    /// Read one line of input.
    pub fn read_line(&mut self) -> Result<Vec<u8>, SmtpStreamError> {
        match self.read_until(&[13, 10], MAX_LINE_SIZE) {
            Ok(data) => Ok(data),
            Err(err) => {
                match err {
                    TooLong => Err(LineTooLong),
                    PrivateReadFailed(err) => Err(ReadFailed(err))
                }
            }
        }
    }

}

impl<W: Writer> SmtpStream<W> {
    /// Write a line ended with <CRLF>.
    pub fn write_line(&mut self, s: &str) -> Result<(), SmtpStreamError> {
        match self.stream.write_str(format!("{}\r\n", s).as_slice()) {
            Ok(_) => Ok(()),
            Err(err) => Err(WriteFailed(err))
        }
    }
}

#[test]
fn test_new() {
    // Testing via `test_read_line()`.
}

#[test]
fn test_read_data() {
    let mut path: Path;
    let mut file: File;
    let mut stream: SmtpStream<File>;
    let mut expected: String;

    path = Path::new("tests/stream/data_ok");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    expected = String::from_utf8_lossy(stream.read_data().unwrap().as_slice()).into_string();
    assert_eq!("Hello world!\nBlabla\n", expected.as_slice());
}

#[test]
fn test_write_line() {
    // Use a block so the file gets closed at the end of it.
    {
        let mut path_write: Path;
        let mut file_write: File;
        let mut stream: SmtpStream<File>;

        path_write = Path::new("tests/stream/write_line");
        file_write = File::open_mode(&path_write, Truncate, Write).unwrap();
        stream = SmtpStream::new(file_write, 65536);
        stream.write_line("HelloWorld").unwrap();
        stream.write_line("ByeBye").unwrap();
    }
    let mut path_read: Path;
    let mut file_read: File;
    let mut expected: String;

    path_read = Path::new("tests/stream/write_line");
    file_read = File::open_mode(&path_read, Open, Read).unwrap();
    expected = file_read.read_to_string().unwrap();
    assert_eq!("HelloWorld\r\nByeBye\r\n", expected.as_slice());
}

#[test]
fn test_read_line() {
    let mut path: Path;
    let mut file: File;
    let mut stream: SmtpStream<File>;
    let mut expected: String;

    path = Path::new("tests/stream/0line1");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert!(!stream.read_line().is_ok());

    path = Path::new("tests/stream/0line2");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert!(!stream.read_line().is_ok());

    path = Path::new("tests/stream/0line3");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert!(!stream.read_line().is_ok());

    path = Path::new("tests/stream/1line1");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string().as_slice(), "hello world!");
    assert!(!stream.read_line().is_ok());

    path = Path::new("tests/stream/1line2");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string().as_slice(), "hello world!");
    assert!(!stream.read_line().is_ok());

    path = Path::new("tests/stream/2lines1");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string().as_slice(), "hello world!");
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string().as_slice(), "bye bye world!");
    assert!(!stream.read_line().is_ok());

    expected = String::from_char(62, 'x');
    path = Path::new("tests/stream/xlines1");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert!(!stream.read_line().is_ok());
}
<commit_msg>remove useless use statement<commit_after>// Copyright 2014 The Rustastic SMTP Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::io::{Reader, Writer, IoError};
use std::vec::{Vec};
#[allow(unused_imports)]
use std::io::{Truncate, Open, Read, Write};
#[allow(unused_imports)]
use std::io::fs::{File};

/// The maximum line size as specified by RFC 5321.
static MAX_LINE_SIZE: uint = 512;

#[test]
fn test_static_vars() {
    assert_eq!(512, MAX_LINE_SIZE);
}

/// A stream specially made for reading SMTP commands.
///
/// It reads lines of input delimited by the <CRLF> sequence and with a maximum
/// size of 512 bytes, including the command word and the <CRLF> sequence. If
/// the input is not UTF8, non-UTF8 characters are replaced with `U+FFFD
/// REPLACEMENT CHARACTER` but no error is returned.
///
/// Returns `InvalidInput` if no line is found within 512 bytes of input.
///
/// # Example
/// ```no_run
/// use std::io::TcpStream;
/// use rsmtp::stream::SmtpStream;
///
/// let mut smtp = SmtpStream::new(TcpStream::connect("127.0.0.1", 2525).unwrap(), 65536);
///
/// println!("{}", smtp.read_line().unwrap());
/// ```
pub struct SmtpStream<S> {
    stream: S,
    /// The maximum message size, including headers and ending sequence.
    max_message_size: uint
}

#[deriving(Show, Eq, PartialEq)]
pub enum SmtpStreamError {
    ReadFailed(IoError),
    WriteFailed(IoError),
    LineTooLong,
    TooMuchData
}

#[deriving(Show, Eq, PartialEq)]
enum SmtpStreamPrivateError {
    PrivateReadFailed(IoError),
    TooLong
}

impl<S> SmtpStream<S> {
    /// Create a new `SmtpStream` from another stream.
    pub fn new(inner: S, max_message_size: uint) -> SmtpStream<S> {
        SmtpStream {
            stream: inner,
            max_message_size: max_message_size
        }
    }
}

impl<R: Reader> SmtpStream<R> {
    fn read_until(&mut self, end: &[u8], limit: uint) -> Result<Vec<u8>, SmtpStreamPrivateError> {
        let mut data: Vec<u8> = Vec::with_capacity(512);
        let mut last: Vec<u8> = Vec::with_capacity(end.len());
        let mut too_long = false;

        loop {
            // If we have previously read as much data as possible and still are not finished
            // reading, stop here.
            if data.len() >= limit && !too_long {
                too_long = true;
            }

            // Try to get more data and see if we have got it all.
            let byte_res = self.stream.read_byte();
            match byte_res {
                Ok(b) => {
                    // Only keep remaining data if we are allowed too. Otherwise, discard it too
                    // avoid out of memory errors.
                    if !too_long {
                        data.push(b);
                    }

                    // Update our last bytes for later comparison.
                    if last.len() == end.len() {
                        last.remove(0).unwrap();
                    }
                    last.push(b);

                    // Let's see if we have read all the data.
                    if last.as_slice() == end {
                        // If we didn't have too much data, we'll remove the end form it to clean up.
                        if !too_long {
                            let data_len = data.len();
                            data.truncate(data_len - end.len());
                        }
                        break;
                    }
                },
                Err(err) => {
                    return Err(PrivateReadFailed(err))
                }
            }
        }
        if too_long {
            Err(TooLong)
        } else {
            Ok(data)
        }
    }

    /// Read the data section of an email. Ends with "<CRLF>.<CRLF>".
    pub fn read_data(&mut self) -> Result<Vec<u8>, SmtpStreamError> {
        let max_data = self.max_message_size;
        match self.read_until(&[13, 10, 46, 13, 10], max_data) {
            Ok(data) => Ok(data),
            Err(err) => {
                match err {
                    TooLong => Err(TooMuchData),
                    PrivateReadFailed(err) => Err(ReadFailed(err))
                }
            }
        }
    }

    /// Read one line of input.
    pub fn read_line(&mut self) -> Result<Vec<u8>, SmtpStreamError> {
        match self.read_until(&[13, 10], MAX_LINE_SIZE) {
            Ok(data) => Ok(data),
            Err(err) => {
                match err {
                    TooLong => Err(LineTooLong),
                    PrivateReadFailed(err) => Err(ReadFailed(err))
                }
            }
        }
    }

}

impl<W: Writer> SmtpStream<W> {
    /// Write a line ended with <CRLF>.
    pub fn write_line(&mut self, s: &str) -> Result<(), SmtpStreamError> {
        match self.stream.write_str(format!("{}\r\n", s).as_slice()) {
            Ok(_) => Ok(()),
            Err(err) => Err(WriteFailed(err))
        }
    }
}

#[test]
fn test_new() {
    // Testing via `test_read_line()`.
}

#[test]
fn test_read_data() {
    let mut path: Path;
    let mut file: File;
    let mut stream: SmtpStream<File>;
    let mut expected: String;

    path = Path::new("tests/stream/data_ok");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    expected = String::from_utf8_lossy(stream.read_data().unwrap().as_slice()).into_string();
    assert_eq!("Hello world!\nBlabla\n", expected.as_slice());
}

#[test]
fn test_write_line() {
    // Use a block so the file gets closed at the end of it.
    {
        let mut path_write: Path;
        let mut file_write: File;
        let mut stream: SmtpStream<File>;

        path_write = Path::new("tests/stream/write_line");
        file_write = File::open_mode(&path_write, Truncate, Write).unwrap();
        stream = SmtpStream::new(file_write, 65536);
        stream.write_line("HelloWorld").unwrap();
        stream.write_line("ByeBye").unwrap();
    }
    let mut path_read: Path;
    let mut file_read: File;
    let mut expected: String;

    path_read = Path::new("tests/stream/write_line");
    file_read = File::open_mode(&path_read, Open, Read).unwrap();
    expected = file_read.read_to_string().unwrap();
    assert_eq!("HelloWorld\r\nByeBye\r\n", expected.as_slice());
}

#[test]
fn test_read_line() {
    let mut path: Path;
    let mut file: File;
    let mut stream: SmtpStream<File>;
    let mut expected: String;

    path = Path::new("tests/stream/0line1");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert!(!stream.read_line().is_ok());

    path = Path::new("tests/stream/0line2");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert!(!stream.read_line().is_ok());

    path = Path::new("tests/stream/0line3");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert!(!stream.read_line().is_ok());

    path = Path::new("tests/stream/1line1");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string().as_slice(), "hello world!");
    assert!(!stream.read_line().is_ok());

    path = Path::new("tests/stream/1line2");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string().as_slice(), "hello world!");
    assert!(!stream.read_line().is_ok());

    path = Path::new("tests/stream/2lines1");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string().as_slice(), "hello world!");
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string().as_slice(), "bye bye world!");
    assert!(!stream.read_line().is_ok());

    expected = String::from_char(62, 'x');
    path = Path::new("tests/stream/xlines1");
    file = File::open(&path).unwrap();
    stream = SmtpStream::new(file, 65536);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert_eq!(String::from_utf8_lossy(stream.read_line().unwrap().as_slice()).into_string(), expected);
    assert!(!stream.read_line().is_ok());
}
<|endoftext|>