<commit_before>//! error provides newtypes and Error's for sqlib.

use std::error::{self, Error as Err};
use std::fmt::{self, Display};
use std::io;
use std::convert::From;
use std::net::AddrParseError;
use std::sync::PoisonError;
use std::result;
use escaping::unescape;

/// The standart result type of sqlib.
pub type Result<T> = result::Result<T, Error>;

/// A SQError contains a TS3 Server Query error.
///
/// # Example
/// ```
/// use sqlib::error::SQError;
///
/// let line = "error id=0 msg=ok".to_string();
///
/// let err_option = SQError::parse(&line);
/// let err = match err_option {
///     Some(err) => err,
///     None => { panic!("no error found"); },
/// };
/// assert_eq!(0, err.id());
/// ```
#[derive(Debug)]
pub struct SQError {
    id: u32,
    msg: String,
    full_msg: String,
}

// helping function for SQError::parse
fn is_seperator(c: char) -> bool {
    c == '=' || c.is_whitespace()
}

impl SQError {
    pub fn new(id: u32, msg: String) -> SQError {
        let full_msg_str = format!("error id={} msg={}", id, &msg);
        SQError {
            id: id,
            msg: msg,
            full_msg: full_msg_str,
        }
    }

    /// Creates an OK error.
    pub fn ok() -> SQError {
        SQError::new(0, "ok".to_string())
    }

    /// This function tries to parse a string into an Error.
    ///
    /// # Return values
    ///
    /// - If it fails to parse it returns Ok(false).
    /// - If it parses the string as an OK error it returns Ok(true).
    /// - If it parses the string as another error it returns Err(error).
    ///
    /// # Example
    /// ```
    /// use sqlib::error::{Error, SQError};
    ///
    /// let ok_str = "error id=0 msg=ok";
    /// let no_err_str = "this is no error";
    /// let err_str = "error id=1 msg=test";
    ///
    /// let test_err = SQError::new(1, "test".to_string());
    /// let to_test_error = match SQError::parse_is_ok(err_str).unwrap_err() {
    ///     Error::SQ(e) => e,
    ///     _ => SQError::ok(),
    /// };
    ///
    /// assert_eq!(SQError::parse_is_ok(ok_str).unwrap(), true);
    /// assert_eq!(SQError::parse_is_ok(no_err_str).unwrap(), false);
    /// assert_eq!(to_test_error, test_err);
    /// ```
    pub fn parse_is_ok(s: &str) -> Result<bool> {
        let err = match SQError::parse(s) {
            None => {
                return Ok(false);
            }
            Some(err) => err,
        };
        if err == SQError::ok() {
            Ok(true)
        } else {
            Err(Error::from(err))
        }
    }

    /// try to parse a String to a SQError
    pub fn parse(s: &str) -> Option<SQError> {
        // the str shouldn't be trimmed, because a real error is without
        // whitespace in the beginning
        let parts: Vec<&str> = s.splitn(6, is_seperator).collect();
        if parts.len() < 5 {
            return None;
        }
        if parts[0] != "error" {
            return None;
        }
        if parts[1] != "id" {
            return None;
        }
        let id_result = parts[2].clone().parse::<u32>();
        let id = match id_result {
            Err(_) => {
                return None;
            }
            Ok(val) => val,
        };
        if parts[3] != "msg" {
            return None;
        }
        let msg = parts[4].to_string().clone();
        Some(SQError::new(id, unescape(&msg)))
    }

    pub fn id(&self) -> u32 {
        self.id
    }

    pub fn msg(&self) -> String {
        self.msg.clone()
    }
}

impl PartialEq for SQError {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}

impl Eq for SQError {}

impl Display for SQError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.full_msg)
    }
}

impl error::Error for SQError {
    fn description(&self) -> &str {
        &self.full_msg
    }
}

/// Error is a custom Error type for the sqlib.
#[derive(Debug)]
pub enum Error {
    /// wraps io::Error
    Io(io::Error),
    /// server query error messages
    SQ(SQError),
    /// other errors
    Other(String),
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::Io(ref err) => err.description(),
            &Error::SQ(ref err) => err.description(),
            &Error::Other(ref s) => s,
        }
    }
}

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

impl<'a> From<&'a str> for Error {
    fn from(err: &'a str) -> Error {
        Error::Other(err.to_string())
    }
}

impl From<String> for Error {
    fn from(err: String) -> Error {
        Error::Other(err)
    }
}

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

impl From<SQError> for Error {
    fn from(err: SQError) -> Error {
        Error::SQ(err)
    }
}

impl From<AddrParseError> for Error {
    fn from(err: AddrParseError) -> Error {
        Error::Other(err.description().to_string())
    }
}

impl<T> From<PoisonError<T>> for Error {
    fn from(err: PoisonError<T>) -> Error {
        Error::Other(format!("{}", err))
    }
}
<commit_msg>adding some functions to sqlib::error<commit_after>//! error provides newtypes and Error's for sqlib.

use std::error::{self, Error as Err};
use std::fmt::{self, Display};
use std::io;
use std::convert::From;
use std::net::AddrParseError;
use std::sync::PoisonError;
use std::result;
use escaping::unescape;

/// The standart result type of sqlib.
pub type Result<T> = result::Result<T, Error>;

/// A SQError contains a TS3 Server Query error.
///
/// # Example
/// ```
/// use sqlib::error::SQError;
///
/// let line = "error id=0 msg=ok".to_string();
///
/// let err_option = SQError::parse(&line);
/// let err = match err_option {
///     Some(err) => err,
///     None => { panic!("no error found"); },
/// };
/// assert_eq!(0, err.id());
/// ```
#[derive(Debug)]
pub struct SQError {
    id: u32,
    msg: String,
    full_msg: String,
}

// helping function for SQError::parse
fn is_seperator(c: char) -> bool {
    c == '=' || c.is_whitespace()
}

impl SQError {
    pub fn new(id: u32, msg: String) -> SQError {
        let full_msg_str = format!("error id={} msg={}", id, &msg);
        SQError {
            id: id,
            msg: msg,
            full_msg: full_msg_str,
        }
    }

    /// Creates an OK error.
    pub fn ok() -> SQError {
        SQError::new(0, "ok".to_string())
    }

    /// This function tries to parse a string into an Error.
    ///
    /// # Return values
    ///
    /// - If it fails to parse it returns Ok(false).
    /// - If it parses the string as an OK error it returns Ok(true).
    /// - If it parses the string as another error it returns Err(error).
    ///
    /// # Example
    /// ```
    /// use sqlib::error::{Error, SQError};
    ///
    /// let ok_str = "error id=0 msg=ok";
    /// let no_err_str = "this is no error";
    /// let err_str = "error id=1 msg=test";
    ///
    /// let test_err = SQError::new(1, "test".to_string());
    /// let to_test_error = match SQError::parse_is_ok(err_str).unwrap_err() {
    ///     Error::SQ(e) => e,
    ///     _ => SQError::ok(),
    /// };
    ///
    /// assert_eq!(SQError::parse_is_ok(ok_str).unwrap(), true);
    /// assert_eq!(SQError::parse_is_ok(no_err_str).unwrap(), false);
    /// assert_eq!(to_test_error, test_err);
    /// ```
    pub fn parse_is_ok(s: &str) -> Result<bool> {
        let err = match SQError::parse(s) {
            None => {
                return Ok(false);
            }
            Some(err) => err,
        };
        if err == SQError::ok() {
            Ok(true)
        } else {
            Err(Error::from(err))
        }
    }

    /// try to parse a String to a SQError
    pub fn parse(s: &str) -> Option<SQError> {
        // the str shouldn't be trimmed, because a real error is without
        // whitespace in the beginning
        let parts: Vec<&str> = s.splitn(6, is_seperator).collect();
        if parts.len() < 5 {
            return None;
        }
        if parts[0] != "error" {
            return None;
        }
        if parts[1] != "id" {
            return None;
        }
        let id_result = parts[2].clone().parse::<u32>();
        let id = match id_result {
            Err(_) => {
                return None;
            }
            Ok(val) => val,
        };
        if parts[3] != "msg" {
            return None;
        }
        let msg = parts[4].to_string().clone();
        Some(SQError::new(id, unescape(&msg)))
    }

    pub fn id(&self) -> u32 {
        self.id
    }

    pub fn msg(&self) -> String {
        self.msg.clone()
    }
}

impl PartialEq for SQError {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}

impl Eq for SQError {}

impl Display for SQError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.full_msg)
    }
}

impl error::Error for SQError {
    fn description(&self) -> &str {
        &self.full_msg
    }
}

/// Error is a custom Error type for the sqlib.
#[derive(Debug)]
pub enum Error {
    /// wraps io::Error
    Io(io::Error),
    /// server query error messages
    SQ(SQError),
    /// other errors
    Other(String),
}

impl Error {
    pub fn is_io(&self) -> bool {
        match self {
            &Error::Io(_) => true,
            _ => false,
        }
    }

    pub fn is_sq(&self) -> bool {
        match self {
            &Error::SQ(_) => true,
            _ => false,
        }
    }

    pub fn is_other(&self) -> bool {
        match self {
            &Error::Other(_) => true,
            _ => false,
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::Io(ref err) => err.description(),
            &Error::SQ(ref err) => err.description(),
            &Error::Other(ref s) => s,
        }
    }
}

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

impl<'a> From<&'a str> for Error {
    fn from(err: &'a str) -> Error {
        Error::Other(err.to_string())
    }
}

impl From<String> for Error {
    fn from(err: String) -> Error {
        Error::Other(err)
    }
}

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

impl From<SQError> for Error {
    fn from(err: SQError) -> Error {
        Error::SQ(err)
    }
}

impl From<AddrParseError> for Error {
    fn from(err: AddrParseError) -> Error {
        Error::Other(err.description().to_string())
    }
}

impl<T> From<PoisonError<T>> for Error {
    fn from(err: PoisonError<T>) -> Error {
        Error::Other(format!("{}", err))
    }
}
<|endoftext|>


<commit_before>#[derive(Debug, PartialEq)]
pub enum ParserError {
    // KeywordError(usize, String),
    IllegalOperator(usize),
    MissingOpeningBracket(usize),
    MissingClosingBracket(usize),
}

#[derive(Debug, PartialEq)]
pub enum EvaluatorError {
    // RadixError(usize),
    UnknownIdentifier(usize, String),
    MissingArgument(usize),
}
<commit_msg>Make KeywordError an EvaluatorError<commit_after>#[derive(Debug, PartialEq)]
pub enum ParserError {
    IllegalOperator(usize),
    MissingOpeningBracket(usize),
    MissingClosingBracket(usize),
}

#[derive(Debug, PartialEq)]
pub enum EvaluatorError {
    // RadixError(usize),
    // KeywordError(usize, String),
    UnknownIdentifier(usize, String),
    MissingArgument(usize),
}
<|endoftext|>


<commit_before>use ::*;

#[derive(Copy, Clone)]
pub struct Tile {
    pub wall : Option<char>,
}

impl Tile {
    pub fn new(wall : Option<char>) -> Self {
        if let Some(s) = wall {
            Self { wall: Some(s) }
        } else {
            Self { wall: None }
        }
    }
}

pub struct Floor {
    pub rows: usize,
    pub cols: usize,
    pub tiles: Vec<Vec<Tile>>
}

impl Floor {
    pub fn new(cols : usize, rows : usize) -> Self {
        // Tiles to use
        let horizontal   = Tile::new(Some('─')); // U-2500
        let vertical     = Tile::new(Some('│')); // U-2502
        let top_left     = Tile::new(Some('┌')); // U-250c
        let top_right    = Tile::new(Some('┐')); // U-2510
        let bottom_left  = Tile::new(Some('└')); // U-2514
        let bottom_right = Tile::new(Some('┘')); // U-2518
        let blank        = Tile::new(None);

        // Create tiles 2D Vec and populate with empty rows
        let mut tiles = Vec::<Vec<Tile>>::with_capacity(rows);
        for _ in 0..rows {
            tiles.push(Vec::<Tile>::with_capacity(rows));
        }
        // First row is all wall
        tiles[0].push(top_left);
        for _ in 1..cols-1 {
            tiles[0].push(horizontal);
        }
        tiles[0].push(top_right);
        // Middle rows are vertical sides and blank middles
        for row in 1..rows-1 {
            tiles[row].push(vertical);
            for _ in 1..cols-1 {
                tiles[row].push(blank);
            }
            tiles[row].push(vertical);
        }
        // Bottom row is also all wall
        tiles[rows-1].push(bottom_left);
        for _ in 1..cols-1 {
            tiles[rows-1].push(horizontal);
        }
        tiles[rows-1].push(bottom_right);

        // Create the floor
        Self {
            rows: rows,
            cols: cols,
            tiles: tiles,
        }
    }
    pub fn get_symbol(&self, coord : &Coord) -> String {
        if let Some(wall) = self.tiles[coord.row as usize][coord.col as usize].wall {
            wall.to_string()
        } else {
            " ".to_string()
        }
    }
    pub fn is_wall(&self, coord : &Coord) -> bool {
        self.tiles[coord.row as usize][coord.col as usize].wall.is_some()
    }
}
<commit_msg>Simplify Tile<commit_after>use ::*;

#[derive(Copy, Clone)]
pub struct Tile {
    pub wall : Option<char>,
}

pub struct Floor {
    pub rows: usize,
    pub cols: usize,
    pub tiles: Vec<Vec<Tile>>
}

impl Floor {
    pub fn new(cols : usize, rows : usize) -> Self {
        // Tiles to use
        let horizontal   = Tile { wall : Some('─') }; // U-2500
        let vertical     = Tile { wall : Some('│') }; // U-2502
        let top_left     = Tile { wall : Some('┌') }; // U-250c
        let top_right    = Tile { wall : Some('┐') }; // U-2510
        let bottom_left  = Tile { wall : Some('└') }; // U-2514
        let bottom_right = Tile { wall : Some('┘') }; // U-2518
        let blank        = Tile { wall : None };

        // Create tiles 2D Vec and populate with empty rows
        let mut tiles = Vec::<Vec<Tile>>::with_capacity(rows);
        for _ in 0..rows {
            tiles.push(Vec::<Tile>::with_capacity(rows));
        }
        // First row is all wall
        tiles[0].push(top_left);
        for _ in 1..cols-1 {
            tiles[0].push(horizontal);
        }
        tiles[0].push(top_right);
        // Middle rows are vertical sides and blank middles
        for row in 1..rows-1 {
            tiles[row].push(vertical);
            for _ in 1..cols-1 {
                tiles[row].push(blank);
            }
            tiles[row].push(vertical);
        }
        // Bottom row is also all wall
        tiles[rows-1].push(bottom_left);
        for _ in 1..cols-1 {
            tiles[rows-1].push(horizontal);
        }
        tiles[rows-1].push(bottom_right);

        // Create the floor
        Self {
            rows: rows,
            cols: cols,
            tiles: tiles,
        }
    }
    pub fn get_symbol(&self, coord : &Coord) -> String {
        if let Some(wall) = self.tiles[coord.row as usize][coord.col as usize].wall {
            wall.to_string()
        } else {
            " ".to_string()
        }
    }
    pub fn is_wall(&self, coord : &Coord) -> bool {
        self.tiles[coord.row as usize][coord.col as usize].wall.is_some()
    }
}
<|endoftext|>


<commit_before>use proc_macro2::{Delimiter, Span};

use error::Result;
use parse::ParseBuffer;
#[cfg(any(feature = "full", feature = "derive"))]
use parse::ParseStream;
use private;
use token;

pub struct Parens<'a> {
    pub token: token::Paren,
    pub content: ParseBuffer<'a>,
}

pub struct Braces<'a> {
    pub token: token::Brace,
    pub content: ParseBuffer<'a>,
}

pub struct Brackets<'a> {
    pub token: token::Bracket,
    pub content: ParseBuffer<'a>,
}

#[cfg(any(feature = "full", feature = "derive"))]
pub struct Group<'a> {
    pub token: token::Group,
    pub content: ParseBuffer<'a>,
}

impl<'a> ParseBuffer<'a> {
    fn parse_delimited(&self, delimiter: Delimiter) -> Result<(Span, ParseBuffer<'a>)> {
        self.step(|cursor| {
            if let Some((content, span, rest)) = cursor.group(delimiter) {
                let unexpected = private::get_unexpected(self);
                let content =
                    private::new_parse_buffer(span, cursor.advance(content), unexpected);
                Ok(((span, content), rest))
            } else {
                let message = match delimiter {
                    Delimiter::Parenthesis => "expected parentheses",
                    Delimiter::Brace => "expected curly braces",
                    Delimiter::Bracket => "expected square brackets",
                    Delimiter::None => "expected invisible group",
                };
                Err(cursor.error(message))
            }
        })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_parens(&self) -> Result<Parens<'a>> {
        self.parse_delimited(Delimiter::Parenthesis)
            .map(|(span, content)| Parens {
                token: token::Paren(span),
                content: content,
            })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_braces(&self) -> Result<Braces<'a>> {
        self.parse_delimited(Delimiter::Brace)
            .map(|(span, content)| Braces {
                token: token::Brace(span),
                content: content,
            })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_brackets(&self) -> Result<Brackets<'a>> {
        self.parse_delimited(Delimiter::Bracket)
            .map(|(span, content)| Brackets {
                token: token::Bracket(span),
                content: content,
            })
    }
}

#[cfg(any(feature = "full", feature = "derive"))]
impl private {
    pub fn parse_group(input: ParseStream) -> Result<Group> {
        input.parse_delimited(Delimiter::None)
            .map(|(span, content)| Group {
                token: token::Group(span),
                content: content,
            })
    }
}

/// Parse a set of parentheses and expose their content to subsequent parsers.
#[macro_export]
macro_rules! parenthesized {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_parens(&$cursor) {
            $crate::export::Ok(parens) => {
                $content = parens.content;
                parens.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}

/// Parse a set of curly braces and expose their content to subsequent parsers.
///
/// ```rust
/// # extern crate quote;
/// # use quote::quote;
/// #
/// extern crate syn;
///
/// use syn::{braced, token, Ident, Token, Type};
/// use syn::parse::{Parse, ParseStream, Result};
/// use syn::punctuated::Punctuated;
///
/// // Parse a simplified struct syntax like:
/// //
/// //     struct S {
/// //         a: A,
/// //         b: B,
/// //     }
/// struct Struct {
///     struct_token: Token![struct],
///     ident: Ident,
///     brace_token: token::Brace,
///     fields: Punctuated<Field, Token![,]>,
/// }
///
/// struct Field {
///     name: Ident,
///     colon_token: Token![:],
///     ty: Type,
/// }
///
/// impl Parse for Struct {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(Struct {
///             struct_token: input.parse()?,
///             ident: input.parse()?,
///             brace_token: braced!(content in input),
///             fields: content.parse_terminated(Field::parse)?,
///         })
///     }
/// }
///
/// impl Parse for Field {
///     fn parse(input: ParseStream) -> Result<Self> {
///         Ok(Field {
///             name: input.parse()?,
///             colon_token: input.parse()?,
///             ty: input.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         struct S {
/// #             a: A,
/// #             b: B,
/// #         }
/// #     };
/// #     syn::parse2::<Struct>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! braced {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_braces(&$cursor) {
            $crate::export::Ok(braces) => {
                $content = braces.content;
                braces.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}

/// Parse a set of square brackets and expose their content to subsequent
/// parsers.
#[macro_export]
macro_rules! bracketed {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_brackets(&$cursor) {
            $crate::export::Ok(brackets) => {
                $content = brackets.content;
                brackets.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}
<commit_msg>Example of parenthesized macro<commit_after>use proc_macro2::{Delimiter, Span};

use error::Result;
use parse::ParseBuffer;
#[cfg(any(feature = "full", feature = "derive"))]
use parse::ParseStream;
use private;
use token;

pub struct Parens<'a> {
    pub token: token::Paren,
    pub content: ParseBuffer<'a>,
}

pub struct Braces<'a> {
    pub token: token::Brace,
    pub content: ParseBuffer<'a>,
}

pub struct Brackets<'a> {
    pub token: token::Bracket,
    pub content: ParseBuffer<'a>,
}

#[cfg(any(feature = "full", feature = "derive"))]
pub struct Group<'a> {
    pub token: token::Group,
    pub content: ParseBuffer<'a>,
}

impl<'a> ParseBuffer<'a> {
    fn parse_delimited(&self, delimiter: Delimiter) -> Result<(Span, ParseBuffer<'a>)> {
        self.step(|cursor| {
            if let Some((content, span, rest)) = cursor.group(delimiter) {
                let unexpected = private::get_unexpected(self);
                let content =
                    private::new_parse_buffer(span, cursor.advance(content), unexpected);
                Ok(((span, content), rest))
            } else {
                let message = match delimiter {
                    Delimiter::Parenthesis => "expected parentheses",
                    Delimiter::Brace => "expected curly braces",
                    Delimiter::Bracket => "expected square brackets",
                    Delimiter::None => "expected invisible group",
                };
                Err(cursor.error(message))
            }
        })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_parens(&self) -> Result<Parens<'a>> {
        self.parse_delimited(Delimiter::Parenthesis)
            .map(|(span, content)| Parens {
                token: token::Paren(span),
                content: content,
            })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_braces(&self) -> Result<Braces<'a>> {
        self.parse_delimited(Delimiter::Brace)
            .map(|(span, content)| Braces {
                token: token::Brace(span),
                content: content,
            })
    }

    // Not public API.
    #[doc(hidden)]
    pub fn parse_brackets(&self) -> Result<Brackets<'a>> {
        self.parse_delimited(Delimiter::Bracket)
            .map(|(span, content)| Brackets {
                token: token::Bracket(span),
                content: content,
            })
    }
}

#[cfg(any(feature = "full", feature = "derive"))]
impl private {
    pub fn parse_group(input: ParseStream) -> Result<Group> {
        input.parse_delimited(Delimiter::None)
            .map(|(span, content)| Group {
                token: token::Group(span),
                content: content,
            })
    }
}

/// Parse a set of parentheses and expose their content to subsequent parsers.
///
/// ```rust
/// # #[macro_use]
/// # extern crate quote;
/// #
/// extern crate syn;
///
/// use syn::{parenthesized, token, Ident, Token, Type};
/// use syn::parse::{Parse, ParseStream, Result};
/// use syn::punctuated::Punctuated;
///
/// // Parse a simplified tuple struct syntax like:
/// //
/// //     struct S(A, B);
/// struct TupleStruct {
///     struct_token: Token![struct],
///     ident: Ident,
///     paren_token: token::Paren,
///     fields: Punctuated<Type, Token![,]>,
///     semi_token: Token![;],
/// }
///
/// impl Parse for TupleStruct {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(TupleStruct {
///             struct_token: input.parse()?,
///             ident: input.parse()?,
///             paren_token: parenthesized!(content in input),
///             fields: content.parse_terminated(Type::parse)?,
///             semi_token: input.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         struct S(A, B);
/// #     };
/// #     syn::parse2::<TupleStruct>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! parenthesized {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_parens(&$cursor) {
            $crate::export::Ok(parens) => {
                $content = parens.content;
                parens.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}

/// Parse a set of curly braces and expose their content to subsequent parsers.
///
/// ```rust
/// # extern crate quote;
/// # use quote::quote;
/// #
/// extern crate syn;
///
/// use syn::{braced, token, Ident, Token, Type};
/// use syn::parse::{Parse, ParseStream, Result};
/// use syn::punctuated::Punctuated;
///
/// // Parse a simplified struct syntax like:
/// //
/// //     struct S {
/// //         a: A,
/// //         b: B,
/// //     }
/// struct Struct {
///     struct_token: Token![struct],
///     ident: Ident,
///     brace_token: token::Brace,
///     fields: Punctuated<Field, Token![,]>,
/// }
///
/// struct Field {
///     name: Ident,
///     colon_token: Token![:],
///     ty: Type,
/// }
///
/// impl Parse for Struct {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let content;
///         Ok(Struct {
///             struct_token: input.parse()?,
///             ident: input.parse()?,
///             brace_token: braced!(content in input),
///             fields: content.parse_terminated(Field::parse)?,
///         })
///     }
/// }
///
/// impl Parse for Field {
///     fn parse(input: ParseStream) -> Result<Self> {
///         Ok(Field {
///             name: input.parse()?,
///             colon_token: input.parse()?,
///             ty: input.parse()?,
///         })
///     }
/// }
/// #
/// # fn main() {
/// #     let input = quote! {
/// #         struct S {
/// #             a: A,
/// #             b: B,
/// #         }
/// #     };
/// #     syn::parse2::<Struct>(input).unwrap();
/// # }
/// ```
#[macro_export]
macro_rules! braced {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_braces(&$cursor) {
            $crate::export::Ok(braces) => {
                $content = braces.content;
                braces.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}

/// Parse a set of square brackets and expose their content to subsequent
/// parsers.
#[macro_export]
macro_rules! bracketed {
    ($content:ident in $cursor:expr) => {
        match $crate::parse::ParseBuffer::parse_brackets(&$cursor) {
            $crate::export::Ok(brackets) => {
                $content = brackets.content;
                brackets.token
            }
            $crate::export::Err(error) => {
                return $crate::export::Err(error);
            }
        }
    };
}
<|endoftext|>


<commit_before>//! Route match guards.
//!
//! Guards are one of the way how actix-web router chooses
//! handler service. In essence it just function that accepts
//! reference to a `RequestHead` instance and returns boolean.
//! It is possible to add guards to *scopes*, *resources*
//! and *routes*. Actix provide several guards by default, like various
//! http methods, header, etc. To become a guard, type must implement `Guard`
//! trait. Simple functions coulds guards as well.
//!
//! Guard can not modify request object. But it is possible to
//! to store extra attributes on a request by using `Extensions` container.
//! Extensions container available via `RequestHead::extensions()` method.
//!
//! ```rust
//! use actix_web::{web, http, dev, guard, App, HttpResponse};
//!
//! fn main() {
//!     App::new().service(web::resource("/index.html").route(
//!         web::route()
//!              .guard(guard::Post())
//!              .guard(guard::fn_guard(|head| head.method == http::Method::GET))
//!              .to(|| HttpResponse::MethodNotAllowed()))
//!     );
//! }
//! ```

#![allow(non_snake_case)]
use actix_http::http::{self, header, HttpTryFrom};
use actix_http::RequestHead;

/// Trait defines resource guards. Guards are used for routes selection.
///
/// Guard can not modify request object. But it is possible to
/// to store extra attributes on request by using `Extensions` container,
/// Extensions container available via `RequestHead::extensions()` method.
pub trait Guard {
    /// Check if request matches predicate
    fn check(&self, request: &RequestHead) -> bool;
}

/// Create guard object for supplied function.
///
/// ```rust
/// use actix_web::{guard, web, App, HttpResponse};
///
/// fn main() {
///     App::new().service(web::resource("/index.html").route(
///         web::route()
///             .guard(
///                 guard::fn_guard(
///                     |req| req.headers()
///                              .contains_key("content-type")))
///             .to(|| HttpResponse::MethodNotAllowed()))
///     );
/// }
/// ```
pub fn fn_guard<F>(f: F) -> impl Guard
where
    F: Fn(&RequestHead) -> bool,
{
    FnGuard(f)
}

struct FnGuard<F: Fn(&RequestHead) -> bool>(F);

impl<F> Guard for FnGuard<F>
where
    F: Fn(&RequestHead) -> bool,
{
    fn check(&self, head: &RequestHead) -> bool {
        (self.0)(head)
    }
}

impl<F> Guard for F
where
    F: Fn(&RequestHead) -> bool,
{
    fn check(&self, head: &RequestHead) -> bool {
        (self)(head)
    }
}

/// Return guard that matches if any of supplied guards.
///
/// ```rust
/// use actix_web::{web, guard, App, HttpResponse};
///
/// fn main() {
///     App::new().service(web::resource("/index.html").route(
///         web::route()
///              .guard(guard::Any(guard::Get()).or(guard::Post()))
///              .to(|| HttpResponse::MethodNotAllowed()))
///     );
/// }
/// ```
pub fn Any<F: Guard + 'static>(guard: F) -> AnyGuard {
    AnyGuard(vec![Box::new(guard)])
}

/// Matches if any of supplied guards matche.
pub struct AnyGuard(Vec<Box<dyn Guard>>);

impl AnyGuard {
    /// Add guard to a list of guards to check
    pub fn or<F: Guard + 'static>(mut self, guard: F) -> Self {
        self.0.push(Box::new(guard));
        self
    }
}

impl Guard for AnyGuard {
    fn check(&self, req: &RequestHead) -> bool {
        for p in &self.0 {
            if p.check(req) {
                return true;
            }
        }
        false
    }
}

/// Return guard that matches if all of the supplied guards.
///
/// ```rust
/// use actix_web::{guard, web, App, HttpResponse};
///
/// fn main() {
///     App::new().service(web::resource("/index.html").route(
///         web::route()
///             .guard(
///                 guard::All(guard::Get()).and(guard::Header("content-type", "text/plain")))
///             .to(|| HttpResponse::MethodNotAllowed()))
///     );
/// }
/// ```
pub fn All<F: Guard + 'static>(guard: F) -> AllGuard {
    AllGuard(vec![Box::new(guard)])
}

/// Matches if all of supplied guards.
pub struct AllGuard(Vec<Box<dyn Guard>>);

impl AllGuard {
    /// Add new guard to the list of guards to check
    pub fn and<F: Guard + 'static>(mut self, guard: F) -> Self {
        self.0.push(Box::new(guard));
        self
    }
}

impl Guard for AllGuard {
    fn check(&self, request: &RequestHead) -> bool {
        for p in &self.0 {
            if !p.check(request) {
                return false;
            }
        }
        true
    }
}

/// Return guard that matches if supplied guard does not match.
pub fn Not<F: Guard + 'static>(guard: F) -> NotGuard {
    NotGuard(Box::new(guard))
}

#[doc(hidden)]
pub struct NotGuard(Box<dyn Guard>);

impl Guard for NotGuard {
    fn check(&self, request: &RequestHead) -> bool {
        !self.0.check(request)
    }
}

/// Http method guard
#[doc(hidden)]
pub struct MethodGuard(http::Method);

impl Guard for MethodGuard {
    fn check(&self, request: &RequestHead) -> bool {
        request.method == self.0
    }
}

/// Guard to match *GET* http method
pub fn Get() -> MethodGuard {
    MethodGuard(http::Method::GET)
}

/// Predicate to match *POST* http method
pub fn Post() -> MethodGuard {
    MethodGuard(http::Method::POST)
}

/// Predicate to match *PUT* http method
pub fn Put() -> MethodGuard {
    MethodGuard(http::Method::PUT)
}

/// Predicate to match *DELETE* http method
pub fn Delete() -> MethodGuard {
    MethodGuard(http::Method::DELETE)
}

/// Predicate to match *HEAD* http method
pub fn Head() -> MethodGuard {
    MethodGuard(http::Method::HEAD)
}

/// Predicate to match *OPTIONS* http method
pub fn Options() -> MethodGuard {
    MethodGuard(http::Method::OPTIONS)
}

/// Predicate to match *CONNECT* http method
pub fn Connect() -> MethodGuard {
    MethodGuard(http::Method::CONNECT)
}

/// Predicate to match *PATCH* http method
pub fn Patch() -> MethodGuard {
    MethodGuard(http::Method::PATCH)
}

/// Predicate to match *TRACE* http method
pub fn Trace() -> MethodGuard {
    MethodGuard(http::Method::TRACE)
}

/// Predicate to match specified http method
pub fn Method(method: http::Method) -> MethodGuard {
    MethodGuard(method)
}

/// Return predicate that matches if request contains specified header and
/// value.
pub fn Header(name: &'static str, value: &'static str) -> HeaderGuard {
    HeaderGuard(
        header::HeaderName::try_from(name).unwrap(),
        header::HeaderValue::from_static(value),
    )
}

#[doc(hidden)]
pub struct HeaderGuard(header::HeaderName, header::HeaderValue);

impl Guard for HeaderGuard {
    fn check(&self, req: &RequestHead) -> bool {
        if let Some(val) = req.headers.get(&self.0) {
            return val == self.1;
        }
        false
    }
}

// /// Return predicate that matches if request contains specified Host name.
// ///
// /// ```rust,ignore
// /// # extern crate actix_web;
// /// use actix_web::{pred, App, HttpResponse};
// ///
// /// fn main() {
// ///     App::new().resource("/index.html", |r| {
// ///         r.route()
// ///             .guard(pred::Host("www.rust-lang.org"))
// ///             .f(|_| HttpResponse::MethodNotAllowed())
// ///     });
// /// }
// /// ```
// pub fn Host<H: AsRef<str>>(host: H) -> HostGuard {
//     HostGuard(host.as_ref().to_string(), None)
// }

// #[doc(hidden)]
// pub struct HostGuard(String, Option<String>);

// impl HostGuard {
//     /// Set reuest scheme to match
//     pub fn scheme<H: AsRef<str>>(&mut self, scheme: H) {
//         self.1 = Some(scheme.as_ref().to_string())
//     }
// }

// impl Guard for HostGuard {
//     fn check(&self, _req: &RequestHead) -> bool {
//         // let info = req.connection_info();
//         // if let Some(ref scheme) = self.1 {
//         //     self.0 == info.host() && scheme == info.scheme()
//         // } else {
//         //     self.0 == info.host()
//         // }
//         false
//     }
// }

#[cfg(test)]
mod tests {
    use actix_http::http::{header, Method};

    use super::*;
    use crate::test::TestRequest;

    #[test]
    fn test_header() {
        let req = TestRequest::with_header(header::TRANSFER_ENCODING, "chunked")
            .to_http_request();

        let pred = Header("transfer-encoding", "chunked");
        assert!(pred.check(req.head()));

        let pred = Header("transfer-encoding", "other");
        assert!(!pred.check(req.head()));

        let pred = Header("content-type", "other");
        assert!(!pred.check(req.head()));
    }

    // #[test]
    // fn test_host() {
    //     let req = TestServiceRequest::default()
    //         .header(
    //             header::HOST,
    //             header::HeaderValue::from_static("www.rust-lang.org"),
    //         )
    //         .request();

    //     let pred = Host("www.rust-lang.org");
    //     assert!(pred.check(&req));

    //     let pred = Host("localhost");
    //     assert!(!pred.check(&req));
    // }

    #[test]
    fn test_methods() {
        let req = TestRequest::default().to_http_request();
        let req2 = TestRequest::default()
            .method(Method::POST)
            .to_http_request();

        assert!(Get().check(req.head()));
        assert!(!Get().check(req2.head()));
        assert!(Post().check(req2.head()));
        assert!(!Post().check(req.head()));

        let r = TestRequest::default().method(Method::PUT).to_http_request();
        assert!(Put().check(r.head()));
        assert!(!Put().check(req.head()));

        let r = TestRequest::default()
            .method(Method::DELETE)
            .to_http_request();
        assert!(Delete().check(r.head()));
        assert!(!Delete().check(req.head()));

        let r = TestRequest::default()
            .method(Method::HEAD)
            .to_http_request();
        assert!(Head().check(r.head()));
        assert!(!Head().check(req.head()));

        let r = TestRequest::default()
            .method(Method::OPTIONS)
            .to_http_request();
        assert!(Options().check(r.head()));
        assert!(!Options().check(req.head()));

        let r = TestRequest::default()
            .method(Method::CONNECT)
            .to_http_request();
        assert!(Connect().check(r.head()));
        assert!(!Connect().check(req.head()));

        let r = TestRequest::default()
            .method(Method::PATCH)
            .to_http_request();
        assert!(Patch().check(r.head()));
        assert!(!Patch().check(req.head()));

        let r = TestRequest::default()
            .method(Method::TRACE)
            .to_http_request();
        assert!(Trace().check(r.head()));
        assert!(!Trace().check(req.head()));
    }

    #[test]
    fn test_preds() {
        let r = TestRequest::default()
            .method(Method::TRACE)
            .to_http_request();

        assert!(Not(Get()).check(r.head()));
        assert!(!Not(Trace()).check(r.head()));

        assert!(All(Trace()).and(Trace()).check(r.head()));
        assert!(!All(Get()).and(Trace()).check(r.head()));

        assert!(Any(Get()).or(Trace()).check(r.head()));
        assert!(!Any(Get()).or(Get()).check(r.head()));
    }
}
<commit_msg>Re-implement Host predicate (#989)<commit_after>//! Route match guards.
//!
//! Guards are one of the way how actix-web router chooses
//! handler service. In essence it just function that accepts
//! reference to a `RequestHead` instance and returns boolean.
//! It is possible to add guards to *scopes*, *resources*
//! and *routes*. Actix provide several guards by default, like various
//! http methods, header, etc. To become a guard, type must implement `Guard`
//! trait. Simple functions coulds guards as well.
//!
//! Guard can not modify request object. But it is possible to
//! to store extra attributes on a request by using `Extensions` container.
//! Extensions container available via `RequestHead::extensions()` method.
//!
//! ```rust
//! use actix_web::{web, http, dev, guard, App, HttpResponse};
//!
//! fn main() {
//!     App::new().service(web::resource("/index.html").route(
//!         web::route()
//!              .guard(guard::Post())
//!              .guard(guard::fn_guard(|head| head.method == http::Method::GET))
//!              .to(|| HttpResponse::MethodNotAllowed()))
//!     );
//! }
//! ```

#![allow(non_snake_case)]
use actix_http::http::{self, header, HttpTryFrom, uri::Uri};
use actix_http::RequestHead;

/// Trait defines resource guards. Guards are used for routes selection.
///
/// Guard can not modify request object. But it is possible to
/// to store extra attributes on request by using `Extensions` container,
/// Extensions container available via `RequestHead::extensions()` method.
pub trait Guard {
    /// Check if request matches predicate
    fn check(&self, request: &RequestHead) -> bool;
}

/// Create guard object for supplied function.
///
/// ```rust
/// use actix_web::{guard, web, App, HttpResponse};
///
/// fn main() {
///     App::new().service(web::resource("/index.html").route(
///         web::route()
///             .guard(
///                 guard::fn_guard(
///                     |req| req.headers()
///                              .contains_key("content-type")))
///             .to(|| HttpResponse::MethodNotAllowed()))
///     );
/// }
/// ```
pub fn fn_guard<F>(f: F) -> impl Guard
where
    F: Fn(&RequestHead) -> bool,
{
    FnGuard(f)
}

struct FnGuard<F: Fn(&RequestHead) -> bool>(F);

impl<F> Guard for FnGuard<F>
where
    F: Fn(&RequestHead) -> bool,
{
    fn check(&self, head: &RequestHead) -> bool {
        (self.0)(head)
    }
}

impl<F> Guard for F
where
    F: Fn(&RequestHead) -> bool,
{
    fn check(&self, head: &RequestHead) -> bool {
        (self)(head)
    }
}

/// Return guard that matches if any of supplied guards.
///
/// ```rust
/// use actix_web::{web, guard, App, HttpResponse};
///
/// fn main() {
///     App::new().service(web::resource("/index.html").route(
///         web::route()
///              .guard(guard::Any(guard::Get()).or(guard::Post()))
///              .to(|| HttpResponse::MethodNotAllowed()))
///     );
/// }
/// ```
pub fn Any<F: Guard + 'static>(guard: F) -> AnyGuard {
    AnyGuard(vec![Box::new(guard)])
}

/// Matches if any of supplied guards matche.
pub struct AnyGuard(Vec<Box<dyn Guard>>);

impl AnyGuard {
    /// Add guard to a list of guards to check
    pub fn or<F: Guard + 'static>(mut self, guard: F) -> Self {
        self.0.push(Box::new(guard));
        self
    }
}

impl Guard for AnyGuard {
    fn check(&self, req: &RequestHead) -> bool {
        for p in &self.0 {
            if p.check(req) {
                return true;
            }
        }
        false
    }
}

/// Return guard that matches if all of the supplied guards.
///
/// ```rust
/// use actix_web::{guard, web, App, HttpResponse};
///
/// fn main() {
///     App::new().service(web::resource("/index.html").route(
///         web::route()
///             .guard(
///                 guard::All(guard::Get()).and(guard::Header("content-type", "text/plain")))
///             .to(|| HttpResponse::MethodNotAllowed()))
///     );
/// }
/// ```
pub fn All<F: Guard + 'static>(guard: F) -> AllGuard {
    AllGuard(vec![Box::new(guard)])
}

/// Matches if all of supplied guards.
pub struct AllGuard(Vec<Box<dyn Guard>>);

impl AllGuard {
    /// Add new guard to the list of guards to check
    pub fn and<F: Guard + 'static>(mut self, guard: F) -> Self {
        self.0.push(Box::new(guard));
        self
    }
}

impl Guard for AllGuard {
    fn check(&self, request: &RequestHead) -> bool {
        for p in &self.0 {
            if !p.check(request) {
                return false;
            }
        }
        true
    }
}

/// Return guard that matches if supplied guard does not match.
pub fn Not<F: Guard + 'static>(guard: F) -> NotGuard {
    NotGuard(Box::new(guard))
}

#[doc(hidden)]
pub struct NotGuard(Box<dyn Guard>);

impl Guard for NotGuard {
    fn check(&self, request: &RequestHead) -> bool {
        !self.0.check(request)
    }
}

/// Http method guard
#[doc(hidden)]
pub struct MethodGuard(http::Method);

impl Guard for MethodGuard {
    fn check(&self, request: &RequestHead) -> bool {
        request.method == self.0
    }
}

/// Guard to match *GET* http method
pub fn Get() -> MethodGuard {
    MethodGuard(http::Method::GET)
}

/// Predicate to match *POST* http method
pub fn Post() -> MethodGuard {
    MethodGuard(http::Method::POST)
}

/// Predicate to match *PUT* http method
pub fn Put() -> MethodGuard {
    MethodGuard(http::Method::PUT)
}

/// Predicate to match *DELETE* http method
pub fn Delete() -> MethodGuard {
    MethodGuard(http::Method::DELETE)
}

/// Predicate to match *HEAD* http method
pub fn Head() -> MethodGuard {
    MethodGuard(http::Method::HEAD)
}

/// Predicate to match *OPTIONS* http method
pub fn Options() -> MethodGuard {
    MethodGuard(http::Method::OPTIONS)
}

/// Predicate to match *CONNECT* http method
pub fn Connect() -> MethodGuard {
    MethodGuard(http::Method::CONNECT)
}

/// Predicate to match *PATCH* http method
pub fn Patch() -> MethodGuard {
    MethodGuard(http::Method::PATCH)
}

/// Predicate to match *TRACE* http method
pub fn Trace() -> MethodGuard {
    MethodGuard(http::Method::TRACE)
}

/// Predicate to match specified http method
pub fn Method(method: http::Method) -> MethodGuard {
    MethodGuard(method)
}

/// Return predicate that matches if request contains specified header and
/// value.
pub fn Header(name: &'static str, value: &'static str) -> HeaderGuard {
    HeaderGuard(
        header::HeaderName::try_from(name).unwrap(),
        header::HeaderValue::from_static(value),
    )
}

#[doc(hidden)]
pub struct HeaderGuard(header::HeaderName, header::HeaderValue);

impl Guard for HeaderGuard {
    fn check(&self, req: &RequestHead) -> bool {
        if let Some(val) = req.headers.get(&self.0) {
            return val == self.1;
        }
        false
    }
}

/// Return predicate that matches if request contains specified Host name.
///
/// ```rust,ignore
/// # extern crate actix_web;
/// use actix_web::{guard::Host, App, HttpResponse};
///
/// fn main() {
///     App::new().resource("/index.html", |r| {
///         r.route()
///             .guard(Host("www.rust-lang.org"))
///             .f(|_| HttpResponse::MethodNotAllowed())
///     });
/// }
/// ```
pub fn Host<H: AsRef<str>>(host: H) -> HostGuard {
    HostGuard(host.as_ref().to_string(), None)
}

fn get_host_uri(req: &RequestHead) -> Option<Uri> {
    use core::str::FromStr;
    let host_value = req.headers.get(header::HOST)?;
    let host = host_value.to_str().ok()?;
    let uri = Uri::from_str(host).ok()?;
    Some(uri)
}

#[doc(hidden)]
pub struct HostGuard(String, Option<String>);

impl HostGuard {
    /// Set request scheme to match
    pub fn scheme<H: AsRef<str>>(mut self, scheme: H) -> HostGuard {
        self.1 = Some(scheme.as_ref().to_string());
        self
    }
}

impl Guard for HostGuard {
    fn check(&self, req: &RequestHead) -> bool {
        let req_host_uri = if let Some(uri) = get_host_uri(req) {
            uri
        } else {
            return false;
        };

        if let Some(uri_host) = req_host_uri.host() {
            if self.0 != uri_host {
                return false;
            }
        } else {
            return false;
        }

        if let Some(ref scheme) = self.1 {
            if let Some(ref req_host_uri_scheme) = req_host_uri.scheme_str() {
                return scheme == req_host_uri_scheme;
            }
        }

        true
    }
}

#[cfg(test)]
mod tests {
    use actix_http::http::{header, Method};

    use super::*;
    use crate::test::TestRequest;

    #[test]
    fn test_header() {
        let req = TestRequest::with_header(header::TRANSFER_ENCODING, "chunked")
            .to_http_request();

        let pred = Header("transfer-encoding", "chunked");
        assert!(pred.check(req.head()));

        let pred = Header("transfer-encoding", "other");
        assert!(!pred.check(req.head()));

        let pred = Header("content-type", "other");
        assert!(!pred.check(req.head()));
    }

    #[test]
    fn test_host() {
        let req = TestRequest::default()
            .header(
                header::HOST,
                header::HeaderValue::from_static("www.rust-lang.org"),
            )
            .to_http_request();

        let pred = Host("www.rust-lang.org");
        assert!(pred.check(req.head()));

        let pred = Host("www.rust-lang.org").scheme("https");
        assert!(pred.check(req.head()));

        let pred = Host("blog.rust-lang.org");
        assert!(!pred.check(req.head()));

        let pred = Host("blog.rust-lang.org").scheme("https");
        assert!(!pred.check(req.head()));

        let pred = Host("crates.io");
        assert!(!pred.check(req.head()));

        let pred = Host("localhost");
        assert!(!pred.check(req.head()));
    }

    #[test]
    fn test_host_scheme() {
        let req = TestRequest::default()
            .header(
                header::HOST,
                header::HeaderValue::from_static("https://www.rust-lang.org"),
            )
            .to_http_request();

        let pred = Host("www.rust-lang.org").scheme("https");
        assert!(pred.check(req.head()));

        let pred = Host("www.rust-lang.org");
        assert!(pred.check(req.head()));

        let pred = Host("www.rust-lang.org").scheme("http");
        assert!(!pred.check(req.head()));

        let pred = Host("blog.rust-lang.org");
        assert!(!pred.check(req.head()));

        let pred = Host("blog.rust-lang.org").scheme("https");
        assert!(!pred.check(req.head()));

        let pred = Host("crates.io").scheme("https");
        assert!(!pred.check(req.head()));

        let pred = Host("localhost");
        assert!(!pred.check(req.head()));
    }

    #[test]
    fn test_methods() {
        let req = TestRequest::default().to_http_request();
        let req2 = TestRequest::default()
            .method(Method::POST)
            .to_http_request();

        assert!(Get().check(req.head()));
        assert!(!Get().check(req2.head()));
        assert!(Post().check(req2.head()));
        assert!(!Post().check(req.head()));

        let r = TestRequest::default().method(Method::PUT).to_http_request();
        assert!(Put().check(r.head()));
        assert!(!Put().check(req.head()));

        let r = TestRequest::default()
            .method(Method::DELETE)
            .to_http_request();
        assert!(Delete().check(r.head()));
        assert!(!Delete().check(req.head()));

        let r = TestRequest::default()
            .method(Method::HEAD)
            .to_http_request();
        assert!(Head().check(r.head()));
        assert!(!Head().check(req.head()));

        let r = TestRequest::default()
            .method(Method::OPTIONS)
            .to_http_request();
        assert!(Options().check(r.head()));
        assert!(!Options().check(req.head()));

        let r = TestRequest::default()
            .method(Method::CONNECT)
            .to_http_request();
        assert!(Connect().check(r.head()));
        assert!(!Connect().check(req.head()));

        let r = TestRequest::default()
            .method(Method::PATCH)
            .to_http_request();
        assert!(Patch().check(r.head()));
        assert!(!Patch().check(req.head()));

        let r = TestRequest::default()
            .method(Method::TRACE)
            .to_http_request();
        assert!(Trace().check(r.head()));
        assert!(!Trace().check(req.head()));
    }

    #[test]
    fn test_preds() {
        let r = TestRequest::default()
            .method(Method::TRACE)
            .to_http_request();

        assert!(Not(Get()).check(r.head()));
        assert!(!Not(Trace()).check(r.head()));

        assert!(All(Trace()).and(Trace()).check(r.head()));
        assert!(!All(Get()).and(Trace()).check(r.head()));

        assert!(Any(Get()).or(Trace()).check(r.head()));
        assert!(!Any(Get()).or(Get()).check(r.head()));
    }
}
<|endoftext|>


<commit_before>use std::path::Path;
use rustc_serialize::json::{self, Json};

use git2::build::RepoBuilder;
use git2::{Delta, DiffFormat, DiffDelta, DiffHunk, DiffLine, ObjectType, Tree, Repository, Oid,
           ErrorClass, Error as GitError};
use std::str;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

pub struct Index {
    repo: Repository,
}

#[derive(Ord, PartialOrd, Eq, PartialEq, Debug)]
pub enum ChangeType {
    Added,
    Yanked,
}

#[derive(Ord, PartialOrd, Eq, PartialEq, Debug)]
pub struct Crate {
    pub name: String,
    pub state: ChangeType,
    pub version: String,
}

enum CrateDecodeError {
    InvalidTopology { json: Json },
    MissingFieldError {
        object: json::Object,
        field: &'static str,
    },
    StringExpected { json: Json },
    BoolExpected { json: Json },
}

use self::CrateDecodeError::*;

impl Crate {
    fn from_json(value: Json) -> Result<Crate, CrateDecodeError> {
        fn extract<'a>(o: &'a json::Object,
                       field: &'static str)
                       -> Result<&'a Json, CrateDecodeError> {
            o.get("name").ok_or_else(|| {
                MissingFieldError {
                    object: o.clone(),
                    field: field,
                }
            })
        }

        fn into_string(value: &Json) -> Result<String, CrateDecodeError> {
            value.as_string()
                .ok_or_else(|| StringExpected { json: value.clone() })
                .map(Into::into)
        }

        fn into_bool(value: &Json) -> Result<bool, CrateDecodeError> {
            value.as_boolean()
                .ok_or_else(|| BoolExpected { json: value.clone() })
                .map(Into::into)
        }

        value.as_object().ok_or_else(|| InvalidTopology { json: value.clone() }).and_then(|o| {
            extract(o, "name")
                .and_then(into_string)
                .and_then(|name| {
                    extract(o, "vers")
                        .and_then(into_string)
                        .and_then(|version| {
                            extract(o, "yanked").and_then(into_bool).map(|yanked| {
                                Crate {
                                    name: name,
                                    state: if yanked {
                                        ChangeType::Yanked
                                    } else {
                                        ChangeType::Added
                                    },
                                    version: version,
                                }
                            })
                        })
                })
        })
    }
}

impl Index {
    pub fn at_path<P>(path: P) -> Result<Index, GitError>
        where P: AsRef<Path>
    {
        let repo =
            Repository::open(path.as_ref()).or_else(|err| if err.class() == ErrorClass::Repository {
                    RepoBuilder::new().bare(true).clone(INDEX_GIT_URL, path.as_ref())
                } else {
                    Err(err)
                })?;

        Ok(Index { repo: repo })
    }

    pub fn changes<S1, S2>(&self, from: S1, to: S2) -> Result<Vec<Crate>, GitError>
        where S1: AsRef<str>,
              S2: AsRef<str>
    {
        fn into_tree<S: AsRef<str>>(repo: &Repository, rev: S) -> Result<Tree, GitError> {
            repo.revparse_single(rev.as_ref()).and_then(|obj| {
                repo.find_tree(match obj.kind() {
               Some(ObjectType::Commit) => obj.as_commit().expect("valid commit").tree_id(),
                _ => /* let it fail later */ obj.id()
            })
            })
        }

        let (from, to) = (into_tree(&self.repo, from)?, into_tree(&self.repo, to)?);
        let diff = self.repo.diff_tree_to_tree(Some(&from), Some(&to), None)?;
        let mut res = Vec::new();
        diff.print(DiffFormat::Patch,
                   |delta: DiffDelta, hunk: Option<DiffHunk>, diffline: DiffLine| -> bool {
                if !match delta.status() {
                    Delta::Added => true,
                    _ => false,
                } {
                    return true;
                }

                let hunk: DiffHunk = match hunk {
                    Some(h) => h,
                    None => return true,
                };
                let content = match str::from_utf8(diffline.content()) {
                    Ok(c) => c,
                    Err(_) => return true,
                };
                println!("json = {:?}", content);
                if let Some(c) = Json::from_str(content)
                    .ok()
                    .and_then(|json| Crate::from_json(json).ok()) {
                    res.push(c)
                }
                return true;
            })?;

        Ok(res)
    }
}
<commit_msg>chore(index): found an illegal-instruction error<commit_after>use std::path::Path;
use rustc_serialize::json::{self, Json};

use git2::build::RepoBuilder;
use git2::{Delta, DiffFormat, DiffDelta, DiffHunk, DiffLine, ObjectType, Tree, Repository,
    ErrorClass, Error as GitError};
use std::str;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

pub struct Index {
    repo: Repository,
}

#[derive(Ord, PartialOrd, Eq, PartialEq, Debug)]
pub enum ChangeType {
    Added,
    Yanked,
}

#[derive(Ord, PartialOrd, Eq, PartialEq, Debug)]
pub struct Crate {
    pub name: String,
    pub state: ChangeType,
    pub version: String,
}

#[derive(PartialOrd, PartialEq, Debug)]
enum CrateDecodeError {
    InvalidTopology {
        json: Json
    },
    MissingFieldError {
        object: json::Object,
        field: &'static str,
    },
    StringExpected {
        json: Json
    },
    BoolExpected {
        json: Json
    },
}

use self::CrateDecodeError::*;

impl Crate {
    fn from_json(value: Json) -> Result<Crate, CrateDecodeError> {
        fn extract<'a>(o: &'a json::Object,
                       field: &'static str)
                       -> Result<&'a Json, CrateDecodeError> {
            o.get("name").ok_or_else(|| {
                MissingFieldError {
                    object: o.clone(),
                    field: field,
                }
            })
        }

        fn into_string(value: &Json) -> Result<String, CrateDecodeError> {
            value.as_string()
                 .ok_or_else(|| StringExpected { json: value.clone() })
                 .map(Into::into)
        }

        fn into_bool(value: &Json) -> Result<bool, CrateDecodeError> {
            value.as_boolean()
                 .ok_or_else(|| BoolExpected { json: value.clone() })
                 .map(Into::into)
        }

        value.as_object().ok_or_else(|| InvalidTopology { json: value.clone() }).and_then(|o| {
            extract(o, "name")
                .and_then(into_string)
                .and_then(|name| {
                    extract(o, "vers")
                        .and_then(into_string)
                        .and_then(|version| {
                            extract(o, "yanked").and_then(into_bool).map(|yanked| {
                                Crate {
                                    name: name,
                                    state: if yanked {
                                        ChangeType::Yanked
                                    } else {
                                        ChangeType::Added
                                    },
                                    version: version,
                                }
                            })
                        })
                })
        })
    }
}

impl Index {
    pub fn at_path<P>(path: P) -> Result<Index, GitError>
        where P: AsRef<Path>
    {
        let repo =
        Repository::open(path.as_ref()).or_else(|err| if err.class() == ErrorClass::Repository {
            RepoBuilder::new().bare(true).clone(INDEX_GIT_URL, path.as_ref())
        } else {
            Err(err)
        })?;

        Ok(Index { repo: repo })
    }

    pub fn changes<S1, S2>(&self, from: S1, to: S2) -> Result<Vec<Crate>, GitError>
        where S1: AsRef<str>,
              S2: AsRef<str>
    {
        fn into_tree<S: AsRef<str>>(repo: &Repository, rev: S) -> Result<Tree, GitError> {
            repo.revparse_single(rev.as_ref()).and_then(|obj| {
                repo.find_tree(match obj.kind() {
                    Some(ObjectType::Commit) => obj.as_commit().expect("valid commit").tree_id(),
                    _ => /* let it fail later */ obj.id()
                })
            })
        }

        let (from, to) = (into_tree(&self.repo, from)?, into_tree(&self.repo, to)?);
        let diff = self.repo.diff_tree_to_tree(Some(&from), Some(&to), None)?;
        let mut res = Vec::new();
        diff.print(DiffFormat::Patch,
                   |delta: DiffDelta, hunk: Option<DiffHunk>, diffline: DiffLine| -> bool {
                       if !match delta.status() {
                           Delta::Added => true,
                           _ => false,
                       } {
                           return true;
                       }

                       let hunk: DiffHunk = match hunk {
                           Some(h) => h,
                           None => return true,
                       };
                       let content = match str::from_utf8(diffline.content()) {
                           Ok(c) => c,
                           Err(_) => return true,
                       };
                       println!("json = {:?}", Json::from_str(content));
                       println!("json = {:?}", content);
                       if let Some(c) = Json::from_str(content)
                           .ok()
                           .and_then(|json| Some(Crate::from_json(json).unwrap())) {
                           res.push(c)
                       }
                       return true;
                   })?;

        Ok(res)
    }
}
<|endoftext|>


<commit_before>use ParseResult;
use internal::State;
use internal::InputModify;

pub const DEFAULT: u32      = 0;
pub const END_OF_INPUT: u32 = 1;

/// Linear type containing the parser state, this type is threaded though `bind`.
#[must_use]
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Input<'a, I: 'a>(u32, &'a [I]);

pub fn new<I>(state: u32, buffer: &[I]) -> Input<I> {
    Input(state, buffer)
}

impl<'a, I> Input<'a, I> {
    // TODO: Remove, use parse_slice instead
    pub fn new(b: &'a [I]) -> Self {
        Input(END_OF_INPUT, b)
    }

    /// Returns the value `t` with the input context.
    #[inline]
    pub fn ret<T, E>(self, t: T) -> ParseResult<'a, I, T, E> {
        ParseResult(State::Data(self, t))
    }

    /// Returns the error value `e` with the input context.
    #[inline]
    pub fn err<T, E>(self, e: E) -> ParseResult<'a, I, T, E> {
        ParseResult(State::Error(self.1, e))
    }
}

/// Implementation of internal trait used to build parsers and combinators.
///
/// # Internal
///
/// Only used by fundamental parsers and combinators.
impl<'a, I> InputModify<'a> for Input<'a, I> {
    type Type = I;

    /// Creates a clone of the instance.
    #[inline(always)]
    fn clone_input(&self) -> Self {
        Input(self.0, self.1)
    }

    #[inline(always)]
    fn buffer(&self) -> &'a [Self::Type]
      where <Self as InputModify<'a>>::Type: 'a {
        self.1
    }

    /// Modifies the inner data without leaving the `Input` context.
    #[inline(always)]
    fn replace(self, b: &'a [Self::Type]) -> Self
      where <Self as InputModify<'a>>::Type: 'a {
        Input(self.0, b)
    }

    /// Modifies the inner data without leaving the `Input` context.
    #[inline(always)]
    fn modify<F>(self, f: F) -> Self
      where F: Fn(&'a [Self::Type]) -> &'a [Self::Type],
          <Self as InputModify<'a>>::Type: 'a {
        Input(self.0, f(self.1))
    }

    /// Notifies the combinator that a parser has reached the end of the currently supplied slice but
    /// requires more data.
    ///
    /// # Internal
    ///
    /// Only used by fundamental parsers and combinators.
    #[inline(always)]
    fn incomplete<T, E>(self, n: usize) -> ParseResult<'a, Self::Type, T, E> {
        ParseResult(State::Incomplete(n))
    }

    #[inline(always)]
    fn is_last_slice(&self) -> bool {
        self.0 & END_OF_INPUT == END_OF_INPUT
    }
}
<commit_msg>Rustdoc<commit_after>use ParseResult;
use internal::State;
use internal::InputModify;

/// Default (empty) input state.
pub const DEFAULT: u32      = 0;
/// If set the current slice of input is the last one.
pub const END_OF_INPUT: u32 = 1;

/// Linear type containing the parser state, this type is threaded though `bind`.
#[must_use]
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Input<'a, I: 'a>(u32, &'a [I]);

/// Creates a new input from the given state and buffer.
///
/// # Internal
///
/// Only used by fundamental parsers and combinators.
pub fn new<I>(state: u32, buffer: &[I]) -> Input<I> {
    Input(state, buffer)
}

impl<'a, I> Input<'a, I> {
    // TODO: Remove, use parse_slice instead
    pub fn new(b: &'a [I]) -> Self {
        Input(END_OF_INPUT, b)
    }

    /// Returns the value `t` with the input context.
    #[inline]
    pub fn ret<T, E>(self, t: T) -> ParseResult<'a, I, T, E> {
        ParseResult(State::Data(self, t))
    }

    /// Returns the error value `e` with the input context.
    #[inline]
    pub fn err<T, E>(self, e: E) -> ParseResult<'a, I, T, E> {
        ParseResult(State::Error(self.1, e))
    }
}

/// Implementation of internal trait used to build parsers and combinators.
///
/// # Internal
///
/// Only used by fundamental parsers and combinators.
impl<'a, I> InputModify<'a> for Input<'a, I> {
    type Type = I;

    /// Creates a clone of the instance.
    #[inline(always)]
    fn clone_input(&self) -> Self {
        Input(self.0, self.1)
    }

    #[inline(always)]
    fn buffer(&self) -> &'a [Self::Type]
      where <Self as InputModify<'a>>::Type: 'a {
        self.1
    }

    /// Modifies the inner data without leaving the `Input` context.
    #[inline(always)]
    fn replace(self, b: &'a [Self::Type]) -> Self
      where <Self as InputModify<'a>>::Type: 'a {
        Input(self.0, b)
    }

    /// Modifies the inner data without leaving the `Input` context.
    #[inline(always)]
    fn modify<F>(self, f: F) -> Self
      where F: Fn(&'a [Self::Type]) -> &'a [Self::Type],
          <Self as InputModify<'a>>::Type: 'a {
        Input(self.0, f(self.1))
    }

    /// Notifies the combinator that a parser has reached the end of the currently supplied slice but
    /// requires more data.
    ///
    /// # Internal
    ///
    /// Only used by fundamental parsers and combinators.
    #[inline(always)]
    fn incomplete<T, E>(self, n: usize) -> ParseResult<'a, Self::Type, T, E> {
        ParseResult(State::Incomplete(n))
    }

    /// Returns true if this is the last input slice available.
    ///
    /// # Internal
    ///
    /// Only used by fundamental parsers and combinators.
    #[inline(always)]
    fn is_last_slice(&self) -> bool {
        self.0 & END_OF_INPUT == END_OF_INPUT
    }
}
<|endoftext|>


<commit_before>use std::io::{BufReader, BufferedReader, Reader};
use std::strbuf::StrBuf;
use std::char::from_u32;
use std::num::FromStrRadix;
use ast::{TIdent, TNumber, TString, TSemicolon, TColon, TDot, TEqual, TOpenParen, TCloseParen, TComma, TOpenBlock, TCloseBlock, TOpenArray, TCloseArray, TQuestion, TNumOp, TBitOp};
use ast::{OpAdd, OpSub, OpMul, OpDiv, OpMod};
use ast::{BitAnd, BitOr, BitXor};
use ast::Token;
use std::io::{IoResult, EndOfFile};
use std::char::is_whitespace;
#[deriving(Clone)]
#[deriving(Eq)]
#[deriving(Show)]
/// The type of string used
pub enum StringType {
	/// Double-quoted
	DoubleQuote,
	/// Single-quoted
	SingleQuote
}
/// The Javascript Lexer
pub struct Lexer {
	/// The list of tokens generated so far
	pub tokens : Vec<Token>,
	/// The string buffer for identities
	ident_buffer : StrBuf,
	/// The string buffer for strings
	string_buffer : StrBuf,
	/// The string buffer for numbers
	num_buffer : StrBuf,
	/// The kind of string - i.e. double quote or single quote or none if it isn't in a string
	string_start : Option<StringType>,
	/// If the lexer is currently inside a number
	in_num : bool,
	/// If a backwards slash has just been read
	escaped : bool
}
impl Lexer {
	/// Creates a new lexer with empty buffers
	pub fn new() -> ~Lexer {
		return ~Lexer {
			tokens: Vec::new(),
			ident_buffer: StrBuf::with_capacity(32),
			string_buffer: StrBuf::with_capacity(256),
			num_buffer: StrBuf::with_capacity(16),
			string_start: None,
			in_num: false,
			escaped: false
		};
	}
	fn clear_buffer(&mut self) {
		if self.ident_buffer.len() > 0 {
			self.tokens.push(TIdent(self.ident_buffer.clone().into_owned()));
			self.ident_buffer.truncate(0);
		}
		if self.in_num {
			self.tokens.push(TNumber(from_str(self.num_buffer.as_slice()).unwrap()));
			self.num_buffer.truncate(0);
			self.in_num = false;
		}
	}
	/// Processes an input stream from a string into an array of tokens
	pub fn lex_str(&mut self, script:~str) -> IoResult<()> {
		let script_bytes:&[u8] = script.as_bytes();
		let reader = BufReader::new(script_bytes);
		let buf_reader = BufferedReader::new(reader);
		self.lex(buf_reader)
	}
	/// Processes an input stream from a BufferedReader into an array of tokens
	pub fn lex<R : Reader>(&mut self, mut reader : BufferedReader<R>) -> IoResult<()> {
		loop {
			let ch = match reader.read_char() {
				Ok(c) => c,
				Err(ref e) if e.kind == EndOfFile => {
					self.clear_buffer();
					return Ok(())
				},
				Err(ref e) =>
					return Err(e.clone())
			};
			match ch {
				_ if self.escaped => {
					self.escaped = false;
					if ch != '\n' {
						self.string_buffer.push_char(match ch {
							'n' => '\n',
							'r' => '\r',
							't' => '\t',
							'b' => '\x08',
							'f' => '\x0c',
							'0' => '\0',
							'u' => {
								let mut nums = ~"";
								for _ in range(0, 4) {
									nums = format!("{}{}", nums, try!(reader.read_char()));
								}
								let as_num = match FromStrRadix::from_str_radix(nums, 16) {
									Some(v) => v,
									None => 0
								};
								match from_u32(as_num) {
									Some(v) => v,
									None => fail!("{} is not a valid unicode scalar value", as_num)
								}
							},
							'\'' if self.string_start == Some(SingleQuote) => '\'',
							'"' if self.string_start == Some(DoubleQuote) => '"',
							_ => fail!("Invalid escape `{}` after {}", ch, self.string_start)
						});
					}
				},
				'"' if self.string_start.is_some() && self.string_start.unwrap() == DoubleQuote => {
					self.string_start = None;
					self.tokens.push(TString(self.string_buffer.clone().into_owned()));
					self.string_buffer.truncate(0);
				},
				'\'' if self.string_start.is_some() && self.string_start.unwrap() == SingleQuote => {
					self.string_start = None;
					self.tokens.push(TString(self.string_buffer.clone().into_owned()));
					self.string_buffer.truncate(0);
				},
				'\\' if self.string_start.is_some() => self.escaped = true,
				_ if self.string_start.is_some() => self.string_buffer.push_char(ch),
				'"' if self.string_start.is_none() => self.string_start = Some(DoubleQuote),
				'0'.. '9' if self.string_start.is_none() && self.ident_buffer.len() == 0 => {
					self.num_buffer.push_char(ch);
					self.in_num = true;
				},
				'\'' if self.string_start.is_none() => self.string_start = Some(SingleQuote),
				'.' if self.in_num && !self.num_buffer.as_slice().contains(".") => {
					self.num_buffer.push_char(ch);
				},
				';' => {
					self.clear_buffer();
					self.tokens.push(TSemicolon)
				},
				':' => {
					self.clear_buffer();
					self.tokens.push(TColon)
				},
				'.' => {
					self.clear_buffer();
					self.tokens.push(TDot)
				},
				'(' => {
					self.clear_buffer();
					self.tokens.push(TOpenParen)
				},
				')' => {
					self.clear_buffer();
					self.tokens.push(TCloseParen)
				},
				',' => {
					self.clear_buffer();
					self.tokens.push(TComma)
				},
				'{' => {
					self.clear_buffer();
					self.tokens.push(TOpenBlock)
				},
				'}' => {
					self.clear_buffer();
					self.tokens.push(TCloseBlock)
				},
				'[' => {
					self.clear_buffer();
					self.tokens.push(TOpenArray)
				},
				']' => {
					self.clear_buffer();
					self.tokens.push(TCloseArray)
				},
				'?' => {
					self.clear_buffer();
					self.tokens.push(TQuestion)
				},
				'/' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpDiv))
				},
				'*' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpMul))
				},
				'+' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpAdd))
				},
				'-' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpSub))
				},
				'%' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpMod))
				},
				'|' => {
					self.clear_buffer();
					self.tokens.push(TBitOp(BitOr))
				},
				'&' => {
					self.clear_buffer();
					self.tokens.push(TBitOp(BitAnd))
				},
				'^' => {
					self.clear_buffer();
					self.tokens.push(TBitOp(BitXor))
				},
				'=' => {
					self.clear_buffer();
					self.tokens.push(TEqual)
				},
				_ if is_whitespace(ch) => self.clear_buffer(),
				_ => self.ident_buffer.push_char(ch)
			};
		}
	}
}<commit_msg>Shorten some of the cases in the lexer<commit_after>use std::io::{BufReader, BufferedReader, Reader};
use std::strbuf::StrBuf;
use std::char::from_u32;
use std::num::FromStrRadix;
use ast::{TIdent, TNumber, TString, TSemicolon, TColon, TDot, TEqual, TOpenParen, TCloseParen, TComma, TOpenBlock, TCloseBlock, TOpenArray, TCloseArray, TQuestion, TNumOp, TBitOp};
use ast::{OpAdd, OpSub, OpMul, OpDiv, OpMod};
use ast::{BitAnd, BitOr, BitXor};
use ast::Token;
use std::io::{IoResult, EndOfFile};
use std::char::is_whitespace;
#[deriving(Clone)]
#[deriving(Eq)]
#[deriving(Show)]
/// The type of string used
pub enum StringType {
	/// Double-quoted
	DoubleQuote,
	/// Single-quoted
	SingleQuote
}
/// The Javascript Lexer
pub struct Lexer {
	/// The list of tokens generated so far
	pub tokens : Vec<Token>,
	/// The string buffer for identities
	ident_buffer : StrBuf,
	/// The string buffer for strings
	string_buffer : StrBuf,
	/// The string buffer for numbers
	num_buffer : StrBuf,
	/// The kind of string - i.e. double quote or single quote or none if it isn't in a string
	string_start : Option<StringType>,
	/// If the lexer is currently inside a number
	in_num : bool,
	/// If a backwards slash has just been read
	escaped : bool
}
impl Lexer {
	/// Creates a new lexer with empty buffers
	pub fn new() -> ~Lexer {
		return ~Lexer {
			tokens: Vec::new(),
			ident_buffer: StrBuf::with_capacity(32),
			string_buffer: StrBuf::with_capacity(256),
			num_buffer: StrBuf::with_capacity(16),
			string_start: None,
			in_num: false,
			escaped: false
		};
	}
	fn clear_buffer(&mut self) {
		if self.ident_buffer.len() > 0 {
			self.tokens.push(TIdent(self.ident_buffer.clone().into_owned()));
			self.ident_buffer.truncate(0);
		}
		if self.in_num {
			self.tokens.push(TNumber(from_str(self.num_buffer.as_slice()).unwrap()));
			self.num_buffer.truncate(0);
			self.in_num = false;
		}
	}
	/// Processes an input stream from a string into an array of tokens
	pub fn lex_str(&mut self, script:~str) -> IoResult<()> {
		let script_bytes:&[u8] = script.as_bytes();
		let reader = BufReader::new(script_bytes);
		let buf_reader = BufferedReader::new(reader);
		self.lex(buf_reader)
	}
	/// Processes an input stream from a BufferedReader into an array of tokens
	pub fn lex<R : Reader>(&mut self, mut reader : BufferedReader<R>) -> IoResult<()> {
		loop {
			let ch = match reader.read_char() {
				Ok(c) => c,
				Err(ref e) if e.kind == EndOfFile => {
					self.clear_buffer();
					return Ok(())
				},
				Err(ref e) =>
					return Err(e.clone())
			};
			match ch {
				_ if self.escaped => {
					self.escaped = false;
					if ch != '\n' {
						self.string_buffer.push_char(match ch {
							'n' => '\n',
							'r' => '\r',
							't' => '\t',
							'b' => '\x08',
							'f' => '\x0c',
							'0' => '\0',
							'u' => {
								let mut nums = ~"";
								for _ in range(0, 4) {
									nums = format!("{}{}", nums, try!(reader.read_char()));
								}
								let as_num = match FromStrRadix::from_str_radix(nums, 16) {
									Some(v) => v,
									None => 0
								};
								match from_u32(as_num) {
									Some(v) => v,
									None => fail!("{} is not a valid unicode scalar value", as_num)
								}
							},
							'\'' if self.string_start == Some(SingleQuote) => '\'',
							'"' if self.string_start == Some(DoubleQuote) => '"',
							_ => fail!("Invalid escape `{}` after {}", ch, self.string_start)
						});
					}
				},
				'"' if self.string_start == Some(DoubleQuote) => {
					self.string_start = None;
					self.tokens.push(TString(self.string_buffer.clone().into_owned()));
					self.string_buffer.truncate(0);
				},
				'\'' if self.string_start == Some(SingleQuote) => {
					self.string_start = None;
					self.tokens.push(TString(self.string_buffer.clone().into_owned()));
					self.string_buffer.truncate(0);
				},
				'\\' if self.string_start.is_some() => self.escaped = true,
				_ if self.string_start.is_some() => self.string_buffer.push_char(ch),
				'"' if self.string_start.is_none() => self.string_start = Some(DoubleQuote),
				'0'.. '9' if self.string_start.is_none() && self.ident_buffer.len() == 0 => {
					self.num_buffer.push_char(ch);
					self.in_num = true;
				},
				'\'' if self.string_start.is_none() => self.string_start = Some(SingleQuote),
				'.' if self.in_num && !self.num_buffer.as_slice().contains(".") => {
					self.num_buffer.push_char(ch);
				},
				';' => {
					self.clear_buffer();
					self.tokens.push(TSemicolon)
				},
				':' => {
					self.clear_buffer();
					self.tokens.push(TColon)
				},
				'.' => {
					self.clear_buffer();
					self.tokens.push(TDot)
				},
				'(' => {
					self.clear_buffer();
					self.tokens.push(TOpenParen)
				},
				')' => {
					self.clear_buffer();
					self.tokens.push(TCloseParen)
				},
				',' => {
					self.clear_buffer();
					self.tokens.push(TComma)
				},
				'{' => {
					self.clear_buffer();
					self.tokens.push(TOpenBlock)
				},
				'}' => {
					self.clear_buffer();
					self.tokens.push(TCloseBlock)
				},
				'[' => {
					self.clear_buffer();
					self.tokens.push(TOpenArray)
				},
				']' => {
					self.clear_buffer();
					self.tokens.push(TCloseArray)
				},
				'?' => {
					self.clear_buffer();
					self.tokens.push(TQuestion)
				},
				'/' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpDiv))
				},
				'*' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpMul))
				},
				'+' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpAdd))
				},
				'-' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpSub))
				},
				'%' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpMod))
				},
				'|' => {
					self.clear_buffer();
					self.tokens.push(TBitOp(BitOr))
				},
				'&' => {
					self.clear_buffer();
					self.tokens.push(TBitOp(BitAnd))
				},
				'^' => {
					self.clear_buffer();
					self.tokens.push(TBitOp(BitXor))
				},
				'=' => {
					self.clear_buffer();
					self.tokens.push(TEqual)
				},
				_ if is_whitespace(ch) => self.clear_buffer(),
				_ => self.ident_buffer.push_char(ch)
			};
		}
	}
}<|endoftext|>


<commit_before>use tokenize::tokenize;

struct NGram<'a> {
  text: &'a str,
  n: usize,
  pad: &'a str
}

impl<'a> NGram<'a> {
  fn calculate(&self) -> Vec<Vec<&'a str>> {
    let mut tokenized_sequence = tokenize(self.text);
    tokenized_sequence.shrink_to_fit();

    let count = tokenized_sequence.len() - self.n + 1;

    let mut ngram_result = Vec::new();

    //left-padding
    if !self.pad.is_empty() {
      for i in 1..self.n {
        let num_blanks = self.n - i;
        let mut this_sequence = Vec::new();
        for _ in 0..num_blanks {
          this_sequence.push(self.pad);
        }
        let sl = &tokenized_sequence[0 .. (self.n - num_blanks)];
        this_sequence.extend_from_slice(sl);
        ngram_result.push(this_sequence);
      }
    }

    //Fill the rest of the ngram
    for i in 0..count {
      let a = &tokenized_sequence[i..i + self.n];
      let sl = a.to_vec();
      ngram_result.push(sl);
    }

    //right-padding
    if !self.pad.is_empty() {
      for i in 1..self.n {
        let num_blanks = i;
        let last_entry = tokenized_sequence.len();
        let mut tc = Vec::new();
        tc.extend_from_slice(&tokenized_sequence[(last_entry - num_blanks) .. last_entry]);
        for _ in 0..num_blanks {
          tc.push(self.pad);
        }
        ngram_result.push(tc);
      }
    }
    ngram_result
  }
}

pub fn get_ngram<'a>(this_text: &'a str, this_n: usize) -> Vec<Vec<&'a str>> {
  let ng = NGram { text: this_text, n: this_n, pad: "" };
  ng.calculate()
}

pub fn get_ngram_with_padding<'a>(this_text: &'a str, this_n: usize, this_padding: &'a str) -> Vec<Vec<&'a str>> {
  let ng = NGram { text: this_text, n: this_n, pad: this_padding };
  ng.calculate()
}
<commit_msg>Fix right padding<commit_after>use tokenize::tokenize;

struct NGram<'a> {
  text: &'a str,
  n: usize,
  pad: &'a str
}

impl<'a> NGram<'a> {
  fn calculate(&self) -> Vec<Vec<&'a str>> {
    let mut tokenized_sequence = tokenize(self.text);
    tokenized_sequence.shrink_to_fit();

    let count = tokenized_sequence.len() - self.n + 1;

    let mut ngram_result = Vec::new();

    //left-padding
    if !self.pad.is_empty() {
      for i in 1..self.n {
        let num_blanks = self.n - i;
        let mut this_sequence = Vec::new();
        for _ in 0..num_blanks {
          this_sequence.push(self.pad);
        }
        let sl = &tokenized_sequence[0 .. (self.n - num_blanks)];
        this_sequence.extend_from_slice(sl);
        ngram_result.push(this_sequence);
      }
    }

    //Fill the rest of the ngram
    for i in 0..count {
      let a = &tokenized_sequence[i..i + self.n];
      let sl = a.to_vec();
      ngram_result.push(sl);
    }

    //right-padding
    if !self.pad.is_empty() {
      for i in 1..self.n {
        let num_blanks = self.n - i;
        let last_entry = tokenized_sequence.len();
        let mut tc = Vec::new();
        tc.extend_from_slice(&tokenized_sequence[(last_entry - i) .. last_entry]);
        for _ in 0..num_blanks {
          tc.push(self.pad);
        }
        ngram_result.push(tc);
      }
    }
    ngram_result
  }
}

pub fn get_ngram<'a>(this_text: &'a str, this_n: usize) -> Vec<Vec<&'a str>> {
  let ng = NGram { text: this_text, n: this_n, pad: "" };
  ng.calculate()
}

pub fn get_ngram_with_padding<'a>(this_text: &'a str, this_n: usize, this_padding: &'a str) -> Vec<Vec<&'a str>> {
  let ng = NGram { text: this_text, n: this_n, pad: this_padding };
  ng.calculate()
}
<|endoftext|>