<commit_before>use std::fmt::{Show,Formatter};
use std::fmt;
use std::cast::transmute;
use std::str::CharRange;

pub struct TokenValue {
    token: Token,
    value: ~str
}

impl TokenValue {
    pub fn new(tok: Token, val: ~str) -> TokenValue {
        TokenValue {
            token: tok,
            value: val
        }
    }
}

struct LexerIterator<'a> {
    string: &'a str,
    pos: uint,
    line: uint,
    next: uint,
    current: Option<char>,
    peek: Option<char>,
    previous: Option<char>
}

impl<'a> LexerIterator<'a> {
    pub fn new(string: &'a str) -> LexerIterator<'a> {
        LexerIterator {
            string: string,
            pos: 0,
            next: 0,
            line: 1,
            current: None,
            peek: None,
            previous: None
        }
    }

    pub fn next(&mut self) -> Option<char> {
        if self.string.len() != 0 && self.pos < self.string.len() {
            let CharRange {ch, next} = self.string.char_range_at(self.pos);
            self.pos = next;

            if self.current.is_some() {
                self.previous = self.current;
            }

            self.current = Some(ch);
            Some(ch)
        } else {
            None
        }
    }

    pub fn peek(&mut self) -> Option<char> {
        if self.string.len() != 0 && self.pos < self.string.len() {
            let CharRange {ch, next} = self.string.char_range_at(self.pos);
            self.peek = Some(ch);
            Some(ch)
        } else {
            None
        }
    }

}

/// Lexer tokens.
pub enum Token {
    PLUS,
    MINUS,
    INTEGER, // Any type of integer
    IDEN, // Identifier
    LPAREN,
    RPAREN,
    COLON
}

/// Lexer
pub struct Lexer<'a> {
    iter: *mut LexerIterator<'a>,
    done: bool
}

impl<'a> Lexer<'a> {
    pub fn new(input: &'a str) -> Lexer<'a> {
        Lexer {
            iter: unsafe { transmute(~LexerIterator::new(input)) },
            done: false
        }
    }

    pub fn next_token(&mut self) -> Option<TokenValue> {
        unsafe {
            for c in *self.iter {
                match c {
                    ' ' => continue,
                    '\r' => continue,
                    '\n' => {
                        (*self.iter).line += 1;
                        continue
                    },
                    '(' => return Some(TokenValue::new(LPAREN, ~"(")),
                    ')' => return Some(TokenValue::new(RPAREN, ~")")),
                    '+' => return Some(TokenValue::new(PLUS, ~"+")),
                    '-' => return Some(TokenValue::new(MINUS, ~"-")),
                    ':' => return Some(TokenValue::new(COLON, ~":")),
                    '9' => return Some(TokenValue::new(INTEGER, ~"9")),
                    '8' => return Some(TokenValue::new(INTEGER, ~"8")),
                    '7' => return Some(TokenValue::new(INTEGER, ~"7")),
                    '6' => return Some(TokenValue::new(INTEGER, ~"6")),
                    '5' => return Some(TokenValue::new(INTEGER, ~"5")),
                    '4' => return Some(TokenValue::new(INTEGER, ~"4")),
                    '3' => return Some(TokenValue::new(INTEGER, ~"3")),
                    '2' => return Some(TokenValue::new(INTEGER, ~"2")),
                    '1' => return Some(TokenValue::new(INTEGER, ~"1")),
                    '0' => return Some(TokenValue::new(INTEGER, ~"0")),
                    _ => {

                        let mut current = ~"";
                        let mut previous = ~"";

                        // Push the current character
                        current.push_char(c);

                        loop {
                            // Try the next character. If we get a valid identifier
                            // than we can move the position of the iterator.
                            match (*self.iter).peek() {
                                Some(character) => {
                                    // Lets save the current buffer as the previous.
                                    // This ensures that if this character makes the invalidation,
                                    // we can return the previously valid string.
                                    previous = current.clone();

                                    // Push the new chracter onto the current buffer.
                                    current.push_char(character);

                                    if is_iden(current) {
                                        (*self.iter).next();
                                    }

                                    if !is_iden(current) && is_iden(previous) {
                                        return Some(TokenValue::new(IDEN, previous));
                                    }
                                },
                                None => { break }
                            }
                        }

                        if !is_iden(current) && is_iden(previous) {
                            return Some(TokenValue::new(IDEN, previous));
                        }
                    }
                }
            }
        }
        None
    }
}

// An iden is identified by:
// /^([A-Za-z-+*^][A-Za-z0-9-_]*)$/
pub fn is_iden<'b>(ch: &'b str) -> bool {
    // Create a new iterator
    let mut iter = ch.chars().peekable();

    // Verify the first character.
    if !verify_iden_start(iter.next().unwrap()) {
        return false;
    }

    for x in iter {
        match x {
            '\n' => return false,
            '\r' => return false,
            ' ' => return false,
            _  =>  if !verify_iden_start(x) { return false }
        }
    }

    true
}

pub fn verify_iden_start(ch: char) -> bool {
    match ch {
        'A' => true,
        'a' => true,
        'B' => true,
        'b' => true,
        'C' => true,
        'c' => true,
        'D' => true,
        'd' => true,
        'E' => true,
        'e' => true,
        'F' => true,
        'f' => true,
        'G' => true,
        'g' => true,
        'H' => true,
        'h' => true,
        'I' => true,
        'i' => true,
        'J' => true,
        'j' => true,
        'K' => true,
        'k' => true,
        'L' => true,
        'l' => true,
        'M' => true,
        'm' => true,
        'N' => true,
        'n' => true,
        'O' => true,
        'o' => true,
        'P' => true,
        'p' => true,
        'Q' => true,
        'q' => true,
        'R' => true,
        'r' => true,
        'S' => true,
        's' => true,
        'T' => true,
        't' => true,
        'U' => true,
        'u' => true,
        'V' => true,
        'v' => true,
        'W' => true,
        'w' => true,
        'Y' => true,
        'y' => true,
        'Z' => true,
        'z' => true,
        '+' => true,
        '-' => true,
        '*' => true,
        _ => false
    }
}

impl Eq for Token {
    fn eq(&self, other: &Token) -> bool {
        match *self {
            PLUS => match *other { PLUS => true, _ => false },
            MINUS => match *other { MINUS => true, _ => false },
            INTEGER => match *other { INTEGER => true, _ => false },
            IDEN => match *other { IDEN => true, _ => false },
            LPAREN => match *other { LPAREN => true, _ => false },
            RPAREN => match *other { RPAREN => true, _ => false },
            COLON => match *other { COLON => true, _ => false }
        }
    }
}

impl Show for Token {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let c = match *self {
            PLUS => &"+",
            MINUS => &"-",
            INTEGER => &"integer",
            IDEN => &"iden",
            LPAREN => &"(",
            RPAREN => &")",
            COLON => ":"
        };

        write!(f.buf, "({})", c)
    }
}

#[cfg(test)]
mod test {
    use super::Lexer;
    use super::LPAREN;
    use super::TokenValue;

    #[test]
    fn next_token() {
        // Should spit out two tokens (LPAREN,RPAREN)
        let mut lex = Lexer::new(&"()");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~")");
    }

    #[test]
    fn return_complex_tokens() {
        let mut lex = Lexer::new(&"(+(():830");

        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~"+");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~")");
        assert!(lex.next_token().unwrap().value == ~":");
        assert!(lex.next_token().unwrap().value == ~"8");
        assert!(lex.next_token().unwrap().value == ~"3");
        assert!(lex.next_token().unwrap().value == ~"0");
    }

    #[test]
    fn should_tokenize_identifier() {
        let mut lex = Lexer::new(&"(let)");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~"let");
        assert_eq!(lex.next_token().unwrap().value, ~")");
    }

    #[test]
    fn should_forget_whitespace() {
        let mut lex = Lexer::new(&"( )");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~")");
    }

    #[test]
    fn should_count_lines() {
        let mut lex = Lexer::new(&"(\n)");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~")");

        assert_eq!(unsafe { (*lex.iter).line }, 2);
    }

    #[test]
    fn should_identify_an_iden_across_lines() {
        let mut lex = Lexer::new(&"(\nlet\n)");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~"let");
        assert_eq!(lex.next_token().unwrap().value, ~")");
    }
}<commit_msg>another test<commit_after>use std::fmt::{Show,Formatter};
use std::fmt;
use std::cast::transmute;
use std::str::CharRange;

pub struct TokenValue {
    token: Token,
    value: ~str
}

impl TokenValue {
    pub fn new(tok: Token, val: ~str) -> TokenValue {
        TokenValue {
            token: tok,
            value: val
        }
    }
}

struct LexerIterator<'a> {
    string: &'a str,
    pos: uint,
    line: uint,
    next: uint,
    current: Option<char>,
    peek: Option<char>,
    previous: Option<char>
}

impl<'a> LexerIterator<'a> {
    pub fn new(string: &'a str) -> LexerIterator<'a> {
        LexerIterator {
            string: string,
            pos: 0,
            next: 0,
            line: 1,
            current: None,
            peek: None,
            previous: None
        }
    }

    pub fn next(&mut self) -> Option<char> {
        if self.string.len() != 0 && self.pos < self.string.len() {
            let CharRange {ch, next} = self.string.char_range_at(self.pos);
            self.pos = next;

            if self.current.is_some() {
                self.previous = self.current;
            }

            self.current = Some(ch);
            Some(ch)
        } else {
            None
        }
    }

    pub fn peek(&mut self) -> Option<char> {
        if self.string.len() != 0 && self.pos < self.string.len() {
            let CharRange {ch, next} = self.string.char_range_at(self.pos);
            self.peek = Some(ch);
            Some(ch)
        } else {
            None
        }
    }

}

/// Lexer tokens.
pub enum Token {
    PLUS,
    MINUS,
    INTEGER, // Any type of integer
    IDEN, // Identifier
    LPAREN,
    RPAREN,
    COLON
}

/// Lexer
pub struct Lexer<'a> {
    iter: *mut LexerIterator<'a>,
    done: bool
}

impl<'a> Lexer<'a> {
    pub fn new(input: &'a str) -> Lexer<'a> {
        Lexer {
            iter: unsafe { transmute(~LexerIterator::new(input)) },
            done: false
        }
    }

    pub fn next_token(&mut self) -> Option<TokenValue> {
        unsafe {
            for c in *self.iter {
                match c {
                    ' ' => continue,
                    '\r' => continue,
                    '\n' => {
                        (*self.iter).line += 1;
                        continue
                    },
                    '(' => return Some(TokenValue::new(LPAREN, ~"(")),
                    ')' => return Some(TokenValue::new(RPAREN, ~")")),
                    '+' => return Some(TokenValue::new(PLUS, ~"+")),
                    '-' => return Some(TokenValue::new(MINUS, ~"-")),
                    ':' => return Some(TokenValue::new(COLON, ~":")),
                    '9' => return Some(TokenValue::new(INTEGER, ~"9")),
                    '8' => return Some(TokenValue::new(INTEGER, ~"8")),
                    '7' => return Some(TokenValue::new(INTEGER, ~"7")),
                    '6' => return Some(TokenValue::new(INTEGER, ~"6")),
                    '5' => return Some(TokenValue::new(INTEGER, ~"5")),
                    '4' => return Some(TokenValue::new(INTEGER, ~"4")),
                    '3' => return Some(TokenValue::new(INTEGER, ~"3")),
                    '2' => return Some(TokenValue::new(INTEGER, ~"2")),
                    '1' => return Some(TokenValue::new(INTEGER, ~"1")),
                    '0' => return Some(TokenValue::new(INTEGER, ~"0")),
                    _ => {

                        let mut current = ~"";
                        let mut previous = ~"";

                        // Push the current character
                        current.push_char(c);

                        loop {
                            // Try the next character. If we get a valid identifier
                            // than we can move the position of the iterator.
                            match (*self.iter).peek() {
                                Some(character) => {
                                    // Lets save the current buffer as the previous.
                                    // This ensures that if this character makes the invalidation,
                                    // we can return the previously valid string.
                                    previous = current.clone();

                                    // Push the new chracter onto the current buffer.
                                    current.push_char(character);

                                    if is_iden(current) {
                                        (*self.iter).next();
                                    }

                                    if !is_iden(current) && is_iden(previous) {
                                        return Some(TokenValue::new(IDEN, previous));
                                    }
                                },
                                None => { break }
                            }
                        }

                        if !is_iden(current) && is_iden(previous) {
                            return Some(TokenValue::new(IDEN, previous));
                        }
                    }
                }
            }
        }
        None
    }
}

// An iden is identified by:
// /^([A-Za-z-+*^][A-Za-z0-9-_]*)$/
pub fn is_iden<'b>(ch: &'b str) -> bool {
    // Create a new iterator
    let mut iter = ch.chars().peekable();

    // Verify the first character.
    if !verify_iden_start(iter.next().unwrap()) {
        return false;
    }

    for x in iter {
        match x {
            '\n' => return false,
            '\r' => return false,
            ' ' => return false,
            _  =>  if !verify_iden_start(x) { return false }
        }
    }

    true
}

pub fn verify_iden_start(ch: char) -> bool {
    match ch {
        'A' => true,
        'a' => true,
        'B' => true,
        'b' => true,
        'C' => true,
        'c' => true,
        'D' => true,
        'd' => true,
        'E' => true,
        'e' => true,
        'F' => true,
        'f' => true,
        'G' => true,
        'g' => true,
        'H' => true,
        'h' => true,
        'I' => true,
        'i' => true,
        'J' => true,
        'j' => true,
        'K' => true,
        'k' => true,
        'L' => true,
        'l' => true,
        'M' => true,
        'm' => true,
        'N' => true,
        'n' => true,
        'O' => true,
        'o' => true,
        'P' => true,
        'p' => true,
        'Q' => true,
        'q' => true,
        'R' => true,
        'r' => true,
        'S' => true,
        's' => true,
        'T' => true,
        't' => true,
        'U' => true,
        'u' => true,
        'V' => true,
        'v' => true,
        'W' => true,
        'w' => true,
        'Y' => true,
        'y' => true,
        'Z' => true,
        'z' => true,
        '+' => true,
        '-' => true,
        '*' => true,
        _ => false
    }
}

impl Eq for Token {
    fn eq(&self, other: &Token) -> bool {
        match *self {
            PLUS => match *other { PLUS => true, _ => false },
            MINUS => match *other { MINUS => true, _ => false },
            INTEGER => match *other { INTEGER => true, _ => false },
            IDEN => match *other { IDEN => true, _ => false },
            LPAREN => match *other { LPAREN => true, _ => false },
            RPAREN => match *other { RPAREN => true, _ => false },
            COLON => match *other { COLON => true, _ => false }
        }
    }
}

impl Show for Token {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let c = match *self {
            PLUS => &"+",
            MINUS => &"-",
            INTEGER => &"integer",
            IDEN => &"iden",
            LPAREN => &"(",
            RPAREN => &")",
            COLON => ":"
        };

        write!(f.buf, "({})", c)
    }
}

#[cfg(test)]
mod test {
    use super::Lexer;
    use super::LPAREN;
    use super::TokenValue;

    #[test]
    fn next_token() {
        // Should spit out two tokens (LPAREN,RPAREN)
        let mut lex = Lexer::new(&"()");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~")");
    }

    #[test]
    fn return_complex_tokens() {
        let mut lex = Lexer::new(&"(+(():830");

        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~"+");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~")");
        assert!(lex.next_token().unwrap().value == ~":");
        assert!(lex.next_token().unwrap().value == ~"8");
        assert!(lex.next_token().unwrap().value == ~"3");
        assert!(lex.next_token().unwrap().value == ~"0");
    }

    #[test]
    fn should_tokenize_identifier() {
        let mut lex = Lexer::new(&"(let)");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~"let");
        assert_eq!(lex.next_token().unwrap().value, ~")");
    }

    #[test]
    fn should_forget_whitespace() {
        let mut lex = Lexer::new(&"( )");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~")");
    }

    #[test]
    fn should_count_lines() {
        let mut lex = Lexer::new(&"(\n)");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~")");

        assert_eq!(unsafe { (*lex.iter).line }, 2);
    }

    #[test]
    fn should_identify_an_iden_across_lines() {
        let mut lex = Lexer::new(&"(\nlet\n)");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~"let");
        assert_eq!(lex.next_token().unwrap().value, ~")");
    }

    #[test]
    fn should_test_iden_patterns() {
        let mut lex = Lexer::new(&"(\n*true*\n)");
        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~"*true*");
        assert_eq!(lex.next_token().unwrap().value, ~")");
    }
}<|endoftext|>


<commit_before>use rustc_serialize::json::Json;

use query::Query;
use query::parser::{QueryParseContext, QueryParseError};
use query::parser::{parse as parse_query};

pub fn parse(context: &QueryParseContext, json: &Json) -> Result<Query, QueryParseError> {
    let object = try!(json.as_object().ok_or(QueryParseError::ExpectedObject));

    // Filtered queries contain two keys. The "filter" and the "query". Both keys are sub-queries
    // except that the one specified in "filter" has its score ignored
    //
    // {
    //     "filter": {
    //         "term": {
    //             "foo": "bar"
    //         }
    //     },
    //     "query": {
    //         "match": {
    //             "baz": "quux"
    //         }
    //    }
    // }
    //
    let mut query = Query::MatchAll;

    let mut filter = Query::MatchNone;
    let mut has_filter_key = false;

    for (key, value) in object.iter() {
        match key.as_ref() {
            "query" => {
                query = try!(parse_query(&context.clone(), value));
            }
            "filter" => {
                has_filter_key = true;
                filter = try!(parse_query(&context.clone().no_score(), value));
            }
            _ => return Err(QueryParseError::UnrecognisedKey(key.clone()))
        }
    }

    if !has_filter_key {
        return Err(QueryParseError::ExpectedKey("filter"))
    }

    return Ok(Query::Bool {
        must: vec![query],
        must_not: vec![],
        should: vec![],
        filter: vec![filter],
        minimum_should_match: 0,
    })
}

#[cfg(test)]
mod tests {
    use rustc_serialize::json::Json;

    use term::Term;
    use query::{Query, TermMatcher};
    use query::parser::{QueryParseContext, QueryParseError};
    use index::Index;

    use super::parse;

    #[test]
    fn test_filtered_query() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"query\": {
                \"term\": {
                    \"the\": \"query\"
                }
            },
            \"filter\": {
                \"term\": {
                    \"the\": \"filter\"
                }
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::Bool {
            must: vec![
                Query::MatchTerm {
                    field: "the".to_string(),
                    term: Term::String("query".to_string()),
                    matcher: TermMatcher::Exact
                }
            ],
            must_not: vec![],
            should: vec![],
            filter: vec![
                Query::MatchTerm {
                    field: "the".to_string(),
                    term: Term::String("filter".to_string()),
                    matcher: TermMatcher::Exact
                }
            ],
            minimum_should_match: 0,
        }))
    }

    #[test]
    fn test_without_sub_query() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"filter\": {
                \"term\": {
                    \"the\": \"filter\"
                }
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::Bool {
            must: vec![
                Query::MatchAll
            ],
            must_not: vec![],
            should: vec![],
            filter: vec![
                Query::MatchTerm {
                    field: "the".to_string(),
                    term: Term::String("filter".to_string()),
                    matcher: TermMatcher::Exact
                }
            ],
            minimum_should_match: 0,
        }))
    }

    #[test]
    fn test_gives_error_for_incorrect_type() {
        // String
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        \"hello\"
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Array
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        [
            \"foo\"
        ]
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Integer
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        123
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Float
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        123.1234
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));
    }

    #[test]
    fn test_gives_error_for_invalid_query() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"query\": \"foo\",
            \"filter\": {
                \"term\": {
                    \"the\": \"filter\"
                }
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));
    }

    #[test]
    fn test_gives_error_for_missing_filter() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"query\": {
                \"term\": {
                    \"the\": \"query\"
                }
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedKey("filter")));
    }

    #[test]
    fn test_gives_error_for_invalid_filter() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"query\": {
                \"term\": {
                    \"the\": \"query\"
                }
            },
            \"filter\": \"foo\"
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));
    }

    #[test]
    fn test_gives_error_for_unexpected_key() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"query\": {
                \"term\": {
                    \"the\": \"query\"
                }
            },
            \"filter\": {
                \"term\": {
                    \"the\": \"filter\"
                }
            },
            \"foo\": \"bar\"
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::UnrecognisedKey("foo".to_string())));
    }
}
<commit_msg>Rewrite filtered query to not use Bool query<commit_after>use rustc_serialize::json::Json;

use query::Query;
use query::parser::{QueryParseContext, QueryParseError};
use query::parser::{parse as parse_query};

pub fn parse(context: &QueryParseContext, json: &Json) -> Result<Query, QueryParseError> {
    let object = try!(json.as_object().ok_or(QueryParseError::ExpectedObject));

    // Filtered queries contain two keys. The "filter" and the "query". Both keys are sub-queries
    // except that the one specified in "filter" has its score ignored
    //
    // {
    //     "filter": {
    //         "term": {
    //             "foo": "bar"
    //         }
    //     },
    //     "query": {
    //         "match": {
    //             "baz": "quux"
    //         }
    //    }
    // }
    //
    let mut query = Query::MatchAll;

    let mut filter = Query::MatchNone;
    let mut has_filter_key = false;

    for (key, value) in object.iter() {
        match key.as_ref() {
            "query" => {
                query = try!(parse_query(&context.clone(), value));
            }
            "filter" => {
                has_filter_key = true;
                filter = try!(parse_query(&context.clone().no_score(), value));
            }
            _ => return Err(QueryParseError::UnrecognisedKey(key.clone()))
        }
    }

    if !has_filter_key {
        return Err(QueryParseError::ExpectedKey("filter"))
    }

    return Ok(Query::Filter {
        query: Box::new(query),
        filter: Box::new(filter),
    })
}

#[cfg(test)]
mod tests {
    use rustc_serialize::json::Json;

    use term::Term;
    use query::{Query, TermMatcher};
    use query::parser::{QueryParseContext, QueryParseError};
    use index::Index;

    use super::parse;

    #[test]
    fn test_filtered_query() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"query\": {
                \"term\": {
                    \"the\": \"query\"
                }
            },
            \"filter\": {
                \"term\": {
                    \"the\": \"filter\"
                }
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::Filter {
            query: Box::new(Query::MatchTerm {
                field: "the".to_string(),
                term: Term::String("query".to_string()),
                matcher: TermMatcher::Exact
            }),
            filter: Box::new(Query::MatchTerm {
                field: "the".to_string(),
                term: Term::String("filter".to_string()),
                matcher: TermMatcher::Exact
            }),
        }))
    }

    #[test]
    fn test_without_sub_query() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"filter\": {
                \"term\": {
                    \"the\": \"filter\"
                }
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::Filter {
            query: Box::new(Query::MatchAll),
            filter: Box::new(Query::MatchTerm {
                field: "the".to_string(),
                term: Term::String("filter".to_string()),
                matcher: TermMatcher::Exact
            }),
        }))
    }

    #[test]
    fn test_gives_error_for_incorrect_type() {
        // String
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        \"hello\"
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Array
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        [
            \"foo\"
        ]
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Integer
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        123
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Float
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        123.1234
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));
    }

    #[test]
    fn test_gives_error_for_invalid_query() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"query\": \"foo\",
            \"filter\": {
                \"term\": {
                    \"the\": \"filter\"
                }
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));
    }

    #[test]
    fn test_gives_error_for_missing_filter() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"query\": {
                \"term\": {
                    \"the\": \"query\"
                }
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedKey("filter")));
    }

    #[test]
    fn test_gives_error_for_invalid_filter() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"query\": {
                \"term\": {
                    \"the\": \"query\"
                }
            },
            \"filter\": \"foo\"
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));
    }

    #[test]
    fn test_gives_error_for_unexpected_key() {
        let query = parse(&QueryParseContext::new(&Index::new()), &Json::from_str("
        {
            \"query\": {
                \"term\": {
                    \"the\": \"query\"
                }
            },
            \"filter\": {
                \"term\": {
                    \"the\": \"filter\"
                }
            },
            \"foo\": \"bar\"
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::UnrecognisedKey("foo".to_string())));
    }
}
<|endoftext|>


<commit_before>//! Implementations and traits for static analysis over Falcon IL.

pub mod ai;
pub mod calling_convention;
mod def_use;
pub mod fixed_point;
mod location_set;
mod reaching_definitions;
mod use_def;

// pub use self::def_use::def_use;
pub use self::location_set::LocationSet;
pub use self::reaching_definitions::reaching_definitions;
pub use self::use_def::use_def;<commit_msg>re-expose analysis::def_use<commit_after>//! Implementations and traits for static analysis over Falcon IL.

pub mod ai;
pub mod calling_convention;
mod def_use;
pub mod fixed_point;
mod location_set;
mod reaching_definitions;
mod use_def;

pub use self::def_use::def_use;
pub use self::location_set::LocationSet;
pub use self::reaching_definitions::reaching_definitions;
pub use self::use_def::use_def;<|endoftext|>


<commit_before>//! This pass checks HIR bodies that may be evaluated at compile-time (e.g., `const`, `static`,
//! `const fn`) for structured control flow (e.g. `if`, `while`), which is forbidden in a const
//! context.
//!
//! By the time the MIR const-checker runs, these high-level constructs have been lowered to
//! control-flow primitives (e.g., `Goto`, `SwitchInt`), making it tough to properly attribute
//! errors. We still look for those primitives in the MIR const-checker to ensure nothing slips
//! through, but errors for structured control flow in a `const` should be emitted here.

use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
use rustc::hir::map::Map;
use rustc::hir;
use rustc::session::Session;
use rustc::ty::TyCtxt;
use rustc::ty::query::Providers;
use syntax::span_err;
use syntax_pos::Span;

use std::fmt;

#[derive(Copy, Clone)]
enum ConstKind {
    Static,
    StaticMut,
    ConstFn,
    Const,
    AnonConst,
}

impl ConstKind {
    fn for_body(body: &hir::Body, hir_map: &Map<'_>) -> Option<Self> {
        let is_const_fn = |id| hir_map.fn_sig_by_hir_id(id).unwrap().header.is_const();

        let owner = hir_map.body_owner(body.id());
        let const_kind = match hir_map.body_owner_kind(owner) {
            hir::BodyOwnerKind::Const => Self::Const,
            hir::BodyOwnerKind::Static(hir::Mutability::MutMutable) => Self::StaticMut,
            hir::BodyOwnerKind::Static(hir::Mutability::MutImmutable) => Self::Static,

            hir::BodyOwnerKind::Fn if is_const_fn(owner) => Self::ConstFn,
            hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => return None,
        };

        Some(const_kind)
    }
}

impl fmt::Display for ConstKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self {
            Self::Static => "static",
            Self::StaticMut => "static mut",
            Self::Const | Self::AnonConst => "const",
            Self::ConstFn => "const fn",
        };

        write!(f, "{}", s)
    }
}

fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: DefId) {
    let mut vis = CheckConstVisitor::new(tcx);
    tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis.as_deep_visitor());
}

pub(crate) fn provide(providers: &mut Providers<'_>) {
    *providers = Providers {
        check_mod_const_bodies,
        ..*providers
    };
}

#[derive(Copy, Clone)]
struct CheckConstVisitor<'tcx> {
    sess: &'tcx Session,
    hir_map: &'tcx Map<'tcx>,
    const_kind: Option<ConstKind>,
}

impl<'tcx> CheckConstVisitor<'tcx> {
    fn new(tcx: TyCtxt<'tcx>) -> Self {
        CheckConstVisitor {
            sess: &tcx.sess,
            hir_map: tcx.hir(),
            const_kind: None,
        }
    }

    /// Emits an error when an unsupported expression is found in a const context.
    fn const_check_violated(&self, bad_op: &str, span: Span) {
        if self.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
            self.sess.span_warn(span, "skipping const checks");
            return;
        }

        let const_kind = self.const_kind
            .expect("`const_check_violated` may only be called inside a const context");

        span_err!(self.sess, span, E0744, "`{}` is not allowed in a `{}`", bad_op, const_kind);
    }

    /// Saves the parent `const_kind` before calling `f` and restores it afterwards.
    fn recurse_into(&mut self, kind: Option<ConstKind>, f: impl FnOnce(&mut Self)) {
        let parent_kind = self.const_kind;
        self.const_kind = kind;
        f(self);
        self.const_kind = parent_kind;
    }
}

impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::OnlyBodies(&self.hir_map)
    }

    fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
        let kind = Some(ConstKind::AnonConst);
        self.recurse_into(kind, |this| hir::intravisit::walk_anon_const(this, anon));
    }

    fn visit_body(&mut self, body: &'tcx hir::Body) {
        let kind = ConstKind::for_body(body, self.hir_map);
        self.recurse_into(kind, |this| hir::intravisit::walk_body(this, body));
    }

    fn visit_expr(&mut self, e: &'tcx hir::Expr) {
        match &e.kind {
            // Skip the following checks if we are not currently in a const context.
            _ if self.const_kind.is_none() => {}

            hir::ExprKind::Loop(_, _, source) => {
                self.const_check_violated(source.name(), e.span);
            }

            hir::ExprKind::Match(_, _, source) => {
                use hir::MatchSource::*;

                let op = match source {
                    Normal => Some("match"),
                    IfDesugar { .. } | IfLetDesugar { .. } => Some("if"),
                    TryDesugar => Some("?"),
                    AwaitDesugar => Some(".await"),

                    // These are handled by `ExprKind::Loop` above.
                    WhileDesugar | WhileLetDesugar | ForLoopDesugar => None,
                };

                if let Some(op) = op {
                    self.const_check_violated(op, e.span);
                }
            }

            _ => {},
        }

        hir::intravisit::walk_expr(self, e);
    }
}
<commit_msg>Use `ast::Mutability`<commit_after>//! This pass checks HIR bodies that may be evaluated at compile-time (e.g., `const`, `static`,
//! `const fn`) for structured control flow (e.g. `if`, `while`), which is forbidden in a const
//! context.
//!
//! By the time the MIR const-checker runs, these high-level constructs have been lowered to
//! control-flow primitives (e.g., `Goto`, `SwitchInt`), making it tough to properly attribute
//! errors. We still look for those primitives in the MIR const-checker to ensure nothing slips
//! through, but errors for structured control flow in a `const` should be emitted here.

use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
use rustc::hir::map::Map;
use rustc::hir;
use rustc::session::Session;
use rustc::ty::TyCtxt;
use rustc::ty::query::Providers;
use syntax::ast::Mutability;
use syntax::span_err;
use syntax_pos::Span;

use std::fmt;

#[derive(Copy, Clone)]
enum ConstKind {
    Static,
    StaticMut,
    ConstFn,
    Const,
    AnonConst,
}

impl ConstKind {
    fn for_body(body: &hir::Body, hir_map: &Map<'_>) -> Option<Self> {
        let is_const_fn = |id| hir_map.fn_sig_by_hir_id(id).unwrap().header.is_const();

        let owner = hir_map.body_owner(body.id());
        let const_kind = match hir_map.body_owner_kind(owner) {
            hir::BodyOwnerKind::Const => Self::Const,
            hir::BodyOwnerKind::Static(Mutability::Mutable) => Self::StaticMut,
            hir::BodyOwnerKind::Static(Mutability::Immutable) => Self::Static,

            hir::BodyOwnerKind::Fn if is_const_fn(owner) => Self::ConstFn,
            hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => return None,
        };

        Some(const_kind)
    }
}

impl fmt::Display for ConstKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self {
            Self::Static => "static",
            Self::StaticMut => "static mut",
            Self::Const | Self::AnonConst => "const",
            Self::ConstFn => "const fn",
        };

        write!(f, "{}", s)
    }
}

fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: DefId) {
    let mut vis = CheckConstVisitor::new(tcx);
    tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis.as_deep_visitor());
}

pub(crate) fn provide(providers: &mut Providers<'_>) {
    *providers = Providers {
        check_mod_const_bodies,
        ..*providers
    };
}

#[derive(Copy, Clone)]
struct CheckConstVisitor<'tcx> {
    sess: &'tcx Session,
    hir_map: &'tcx Map<'tcx>,
    const_kind: Option<ConstKind>,
}

impl<'tcx> CheckConstVisitor<'tcx> {
    fn new(tcx: TyCtxt<'tcx>) -> Self {
        CheckConstVisitor {
            sess: &tcx.sess,
            hir_map: tcx.hir(),
            const_kind: None,
        }
    }

    /// Emits an error when an unsupported expression is found in a const context.
    fn const_check_violated(&self, bad_op: &str, span: Span) {
        if self.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
            self.sess.span_warn(span, "skipping const checks");
            return;
        }

        let const_kind = self.const_kind
            .expect("`const_check_violated` may only be called inside a const context");

        span_err!(self.sess, span, E0744, "`{}` is not allowed in a `{}`", bad_op, const_kind);
    }

    /// Saves the parent `const_kind` before calling `f` and restores it afterwards.
    fn recurse_into(&mut self, kind: Option<ConstKind>, f: impl FnOnce(&mut Self)) {
        let parent_kind = self.const_kind;
        self.const_kind = kind;
        f(self);
        self.const_kind = parent_kind;
    }
}

impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::OnlyBodies(&self.hir_map)
    }

    fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
        let kind = Some(ConstKind::AnonConst);
        self.recurse_into(kind, |this| hir::intravisit::walk_anon_const(this, anon));
    }

    fn visit_body(&mut self, body: &'tcx hir::Body) {
        let kind = ConstKind::for_body(body, self.hir_map);
        self.recurse_into(kind, |this| hir::intravisit::walk_body(this, body));
    }

    fn visit_expr(&mut self, e: &'tcx hir::Expr) {
        match &e.kind {
            // Skip the following checks if we are not currently in a const context.
            _ if self.const_kind.is_none() => {}

            hir::ExprKind::Loop(_, _, source) => {
                self.const_check_violated(source.name(), e.span);
            }

            hir::ExprKind::Match(_, _, source) => {
                use hir::MatchSource::*;

                let op = match source {
                    Normal => Some("match"),
                    IfDesugar { .. } | IfLetDesugar { .. } => Some("if"),
                    TryDesugar => Some("?"),
                    AwaitDesugar => Some(".await"),

                    // These are handled by `ExprKind::Loop` above.
                    WhileDesugar | WhileLetDesugar | ForLoopDesugar => None,
                };

                if let Some(op) = op {
                    self.const_check_violated(op, e.span);
                }
            }

            _ => {},
        }

        hir::intravisit::walk_expr(self, e);
    }
}
<|endoftext|>


<commit_before>#![feature(if_let)]
extern crate "pkg-config" as pkg_config;
use std::io;
use std::io::fs;
use std::io::fs::PathExtensions;
use std::io::process::Command;
use std::path::Path;
use std::os;

fn main() {
	io::println("Searching for LibJIT");
	match pkg_config::find_library("jit") {
		Ok(()) => return,
		Err(..) => {}
	}
	let ref out_dir = Path::new(os::getenv("OUT_DIR").expect("OUT_DIR needed for compilation"));
	let ref final_lib_dir = Path::new("native/jit/.libs");
	let ref submod_path = Path::new("native");
	if !final_lib_dir.exists() {
		if !final_lib_dir.exists() {
			if !submod_path.exists() {
				run(Command::new("git").arg("submodule").arg("init"));
			}
			run(Command::new("git").arg("submodule").arg("update"));
			run(Command::new("sh").arg("auto_gen.sh").cwd(submod_path));
			run(Command::new("sh").arg("configure").arg("--enable-shared").cwd(submod_path));
			run(Command::new("make").cwd(submod_path));
		}
	}
    println!("cargo:root={}", out_dir.display());
    println!("cargo:rustc-flags=-l jit:static");
	println!("cargo:rustc-flags=-L {}", final_lib_dir.display());
}
fn run(command: &mut Command) {
	println!("{}", command);
	match command.output() {
		Ok(ref process) if !process.status.success() => {
			panic!("failed with output: \n{}\n{}", String::from_utf8_lossy(process.output[]), String::from_utf8_lossy(process.error[]));
		},
		Ok(_) => (),
		Err(err) => panic!("failed due to {}", err)
	}
}<commit_msg>Check for static library, not the folder that contains it<commit_after>#![feature(if_let)]
extern crate "pkg-config" as pkg_config;
use std::io;
use std::io::fs;
use std::io::fs::PathExtensions;
use std::io::process::Command;
use std::path::Path;
use std::os;

fn main() {
	io::println("Searching for LibJIT");
	match pkg_config::find_library("jit") {
		Ok(()) => return,
		Err(..) => {}
	}
	let ref out_dir = Path::new(os::getenv("OUT_DIR").expect("OUT_DIR needed for compilation"));
	let ref final_lib_dir = Path::new("native/jit/.libs");
	let ref submod_path = Path::new("native");
	if !final_lib_dir.join("libjit.a").exists() {
		if !submod_path.exists() {
			run(Command::new("git").arg("submodule").arg("init"));
		}
		run(Command::new("git").arg("submodule").arg("update"));
		run(Command::new("sh").arg("auto_gen.sh").cwd(submod_path));
		run(Command::new("sh").arg("configure").arg("--enable-shared").cwd(submod_path));
		run(Command::new("make").cwd(submod_path));
	}
    println!("cargo:root={}", out_dir.display());
    println!("cargo:rustc-flags=-l jit:static");
	println!("cargo:rustc-flags=-L {}", final_lib_dir.display());
}
fn run(command: &mut Command) {
	println!("{}", command);
	match command.output() {
		Ok(ref process) if !process.status.success() => {
			panic!("failed with output: \n{}\n{}", String::from_utf8_lossy(process.output[]), String::from_utf8_lossy(process.error[]));
		},
		Ok(_) => (),
		Err(err) => panic!("failed due to {}", err)
	}
}<|endoftext|>


<commit_before>//! Defines error types used by this library.

use Value;

use xml::reader::Error as XmlError;
use xml::common::TextPosition;

use std::io;
use std::fmt::{self, Formatter, Display};
use std::error::Error;
use std::collections::BTreeMap;

/// A request could not be executed.
///
/// This can be a lower-level error (for example, the HTTP request failed), a problem with the
/// server (maybe it's not implementing XML-RPC correctly), or just a failure to execute the
/// operation.
#[derive(Debug)]
pub struct RequestError(RequestErrorKind);

impl RequestError {
    /// If this `RequestError` was caused by the server responding with a `<fault>` response,
    /// returns the `Fault` in question.
    pub fn fault(&self) -> Option<&Fault> {
        match self.0 {
            RequestErrorKind::Fault(ref fault) => Some(fault),
            _ => None,
        }
    }
}

impl From<RequestErrorKind> for RequestError {
    fn from(kind: RequestErrorKind) -> Self {
        RequestError(kind)
    }
}

impl Display for RequestError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        self.0.fmt(fmt)
    }
}

impl Error for RequestError {
    fn description(&self) -> &str {
        self.0.description()
    }

    fn cause(&self) -> Option<&Error> {
        self.0.cause()
    }
}

#[derive(Debug)]
pub enum RequestErrorKind {
    /// The response could not be parsed. This can happen when the server doesn't correctly
    /// implement the XML-RPC spec.
    ParseError(ParseError),

    /// A communication error originating from the transport used to perform the request.
    TransportError(Box<Error + 'static>),

    /// The server returned a `<fault>` response, indicating that the execution of the call
    /// encountered a problem (for example, an invalid (number of) arguments was passed).
    Fault(Fault),
}

impl From<ParseError> for RequestErrorKind {
    fn from(e: ParseError) -> Self {
        RequestErrorKind::ParseError(e)
    }
}

impl From<Fault> for RequestErrorKind {
    fn from(f: Fault) -> Self {
        RequestErrorKind::Fault(f)
    }
}

impl Display for RequestErrorKind {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            RequestErrorKind::ParseError(ref err) => write!(fmt, "parse error: {}", err),
            RequestErrorKind::TransportError(ref err) => write!(fmt, "transport error: {}", err),
            RequestErrorKind::Fault(ref err) => write!(fmt, "{}", err),
        }
    }
}

impl Error for RequestErrorKind {
    fn description(&self) -> &str {
        match *self {
            RequestErrorKind::ParseError(_) => "parse error",
            RequestErrorKind::TransportError(_) => "transport error",
            RequestErrorKind::Fault(_) => "server returned a fault",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            RequestErrorKind::ParseError(ref err) => Some(err),
            RequestErrorKind::TransportError(ref err) => Some(err.as_ref()),
            RequestErrorKind::Fault(ref err) => Some(err),
        }
    }
}

/// Describes possible error that can occur when parsing a `Response`.
#[derive(Debug, PartialEq)]
pub enum ParseError {
    /// Error while parsing (malformed?) XML.
    XmlError(XmlError),

    /// Could not parse the given CDATA as XML-RPC value.
    ///
    /// For example, `<value><int>AAA</int></value>` describes an invalid value.
    InvalidValue {
        /// The type for which an invalid value was supplied (eg. `int` or `dateTime.iso8601`).
        for_type: &'static str,
        /// The value we encountered, as a string.
        found: String,
        /// The position of the invalid value inside the XML document.
        position: TextPosition,
    },

    /// Found an unexpected tag, attribute, etc.
    UnexpectedXml {
        /// A short description of the kind of data that was expected.
        expected: String,
        found: Option<String>,
        /// The position of the unexpected data inside the XML document.
        position: TextPosition,
    }
}

impl From<XmlError> for ParseError {
    fn from(e: XmlError) -> Self {
        ParseError::XmlError(e)
    }
}

impl From<io::Error> for ParseError {
    fn from(e: io::Error) -> Self {
        ParseError::XmlError(XmlError::from(e))
    }
}

impl Display for ParseError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            ParseError::XmlError(ref err) => write!(fmt, "malformed XML: {}", err),
            ParseError::InvalidValue {
                for_type,
                ref found,
                ref position,
            } => write!(fmt, "invalid value for type '{}' at {}: {}", for_type, position, found),
            ParseError::UnexpectedXml {
                ref expected,
                ref position,
                found: None,
            } => {
                write!(fmt, "unexpected XML at {} (expected {})", position, expected)
            }
            ParseError::UnexpectedXml {
                ref expected,
                ref position,
                found: Some(ref found),
            } => {
                write!(fmt, "unexpected XML at {} (expected {}, found {})", position, expected, found)
            }
        }
    }
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::XmlError(ref err) => err.description(),
            ParseError::InvalidValue { .. } => "invalid value for type",
            ParseError::UnexpectedXml { .. } => "unexpected XML content",
        }
    }
}

/// A `<fault>` response, indicating that a request failed.
///
/// The XML-RPC specification requires that a `<faultCode>` and `<faultString>` is returned in the
/// `<fault>` case, further describing the error.
#[derive(Debug, PartialEq, Eq)]
pub struct Fault {
    pub fault_code: i32,
    pub fault_string: String,
}

impl Fault {
    /// Creates a `Fault` from a `Value`.
    ///
    /// The `Value` must be a `Value::Struct` with a `faultCode` and `faultString` field (and no
    /// other fields).
    ///
    /// Returns `None` if the value isn't a valid `Fault`.
    pub fn from_value(value: &Value) -> Option<Self> {
        match *value {
            Value::Struct(ref map) => {
                if map.len() != 2 {
                    // incorrect field count
                    return None;
                }

                match (map.get("faultCode"), map.get("faultString")) {
                    (Some(&Value::Int(fault_code)), Some(&Value::String(ref fault_string))) => {
                        Some(Fault {
                            fault_code,
                            fault_string: fault_string.to_string(),
                        })
                    }
                    _ => None
                }
            }
            _ => None
        }
    }

    /// Turns this `Fault` into an equivalent `Value`.
    ///
    /// The returned value can be parsed back into a `Fault` using `Fault::from_value` or returned
    /// as a `<fault>` error response by serializing it into a `<fault></fault>` tag.
    pub fn to_value(&self) -> Value {
        let mut map = BTreeMap::new();
        map.insert("faultCode".to_string(), Value::from(self.fault_code));
        map.insert("faultString".to_string(), Value::from(self.fault_string.as_ref()));

        Value::Struct(map)
    }
}

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

impl Error for Fault {
    fn description(&self) -> &str {
        &self.fault_string
    }
}

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

    use std::error::Error;

    #[test]
    fn fault_roundtrip() {
        let input = Fault {
            fault_code: -123456,
            fault_string: "The Bald Lazy House Jumps Over The Hyperactive Kitten".to_string()
        };

        assert_eq!(Fault::from_value(&input.to_value()), Some(input));
    }

    #[test]
    fn error_impls_error() {
        fn assert_error<T: Error>() {}

        assert_error::<RequestError>();
    }
}
<commit_msg>Hide internal impl from rustdoc<commit_after>//! Defines error types used by this library.

use Value;

use xml::reader::Error as XmlError;
use xml::common::TextPosition;

use std::io;
use std::fmt::{self, Formatter, Display};
use std::error::Error;
use std::collections::BTreeMap;

/// A request could not be executed.
///
/// This can be a lower-level error (for example, the HTTP request failed), a problem with the
/// server (maybe it's not implementing XML-RPC correctly), or just a failure to execute the
/// operation.
#[derive(Debug)]
pub struct RequestError(RequestErrorKind);

impl RequestError {
    /// If this `RequestError` was caused by the server responding with a `<fault>` response,
    /// returns the `Fault` in question.
    pub fn fault(&self) -> Option<&Fault> {
        match self.0 {
            RequestErrorKind::Fault(ref fault) => Some(fault),
            _ => None,
        }
    }
}

#[doc(hidden)]  // hide internal impl
impl From<RequestErrorKind> for RequestError {
    fn from(kind: RequestErrorKind) -> Self {
        RequestError(kind)
    }
}

impl Display for RequestError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        self.0.fmt(fmt)
    }
}

impl Error for RequestError {
    fn description(&self) -> &str {
        self.0.description()
    }

    fn cause(&self) -> Option<&Error> {
        self.0.cause()
    }
}

#[derive(Debug)]
pub enum RequestErrorKind {
    /// The response could not be parsed. This can happen when the server doesn't correctly
    /// implement the XML-RPC spec.
    ParseError(ParseError),

    /// A communication error originating from the transport used to perform the request.
    TransportError(Box<Error + 'static>),

    /// The server returned a `<fault>` response, indicating that the execution of the call
    /// encountered a problem (for example, an invalid (number of) arguments was passed).
    Fault(Fault),
}

impl From<ParseError> for RequestErrorKind {
    fn from(e: ParseError) -> Self {
        RequestErrorKind::ParseError(e)
    }
}

impl From<Fault> for RequestErrorKind {
    fn from(f: Fault) -> Self {
        RequestErrorKind::Fault(f)
    }
}

impl Display for RequestErrorKind {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            RequestErrorKind::ParseError(ref err) => write!(fmt, "parse error: {}", err),
            RequestErrorKind::TransportError(ref err) => write!(fmt, "transport error: {}", err),
            RequestErrorKind::Fault(ref err) => write!(fmt, "{}", err),
        }
    }
}

impl Error for RequestErrorKind {
    fn description(&self) -> &str {
        match *self {
            RequestErrorKind::ParseError(_) => "parse error",
            RequestErrorKind::TransportError(_) => "transport error",
            RequestErrorKind::Fault(_) => "server returned a fault",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            RequestErrorKind::ParseError(ref err) => Some(err),
            RequestErrorKind::TransportError(ref err) => Some(err.as_ref()),
            RequestErrorKind::Fault(ref err) => Some(err),
        }
    }
}

/// Describes possible error that can occur when parsing a `Response`.
#[derive(Debug, PartialEq)]
pub enum ParseError {
    /// Error while parsing (malformed?) XML.
    XmlError(XmlError),

    /// Could not parse the given CDATA as XML-RPC value.
    ///
    /// For example, `<value><int>AAA</int></value>` describes an invalid value.
    InvalidValue {
        /// The type for which an invalid value was supplied (eg. `int` or `dateTime.iso8601`).
        for_type: &'static str,
        /// The value we encountered, as a string.
        found: String,
        /// The position of the invalid value inside the XML document.
        position: TextPosition,
    },

    /// Found an unexpected tag, attribute, etc.
    UnexpectedXml {
        /// A short description of the kind of data that was expected.
        expected: String,
        found: Option<String>,
        /// The position of the unexpected data inside the XML document.
        position: TextPosition,
    }
}

impl From<XmlError> for ParseError {
    fn from(e: XmlError) -> Self {
        ParseError::XmlError(e)
    }
}

impl From<io::Error> for ParseError {
    fn from(e: io::Error) -> Self {
        ParseError::XmlError(XmlError::from(e))
    }
}

impl Display for ParseError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            ParseError::XmlError(ref err) => write!(fmt, "malformed XML: {}", err),
            ParseError::InvalidValue {
                for_type,
                ref found,
                ref position,
            } => write!(fmt, "invalid value for type '{}' at {}: {}", for_type, position, found),
            ParseError::UnexpectedXml {
                ref expected,
                ref position,
                found: None,
            } => {
                write!(fmt, "unexpected XML at {} (expected {})", position, expected)
            }
            ParseError::UnexpectedXml {
                ref expected,
                ref position,
                found: Some(ref found),
            } => {
                write!(fmt, "unexpected XML at {} (expected {}, found {})", position, expected, found)
            }
        }
    }
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::XmlError(ref err) => err.description(),
            ParseError::InvalidValue { .. } => "invalid value for type",
            ParseError::UnexpectedXml { .. } => "unexpected XML content",
        }
    }
}

/// A `<fault>` response, indicating that a request failed.
///
/// The XML-RPC specification requires that a `<faultCode>` and `<faultString>` is returned in the
/// `<fault>` case, further describing the error.
#[derive(Debug, PartialEq, Eq)]
pub struct Fault {
    pub fault_code: i32,
    pub fault_string: String,
}

impl Fault {
    /// Creates a `Fault` from a `Value`.
    ///
    /// The `Value` must be a `Value::Struct` with a `faultCode` and `faultString` field (and no
    /// other fields).
    ///
    /// Returns `None` if the value isn't a valid `Fault`.
    pub fn from_value(value: &Value) -> Option<Self> {
        match *value {
            Value::Struct(ref map) => {
                if map.len() != 2 {
                    // incorrect field count
                    return None;
                }

                match (map.get("faultCode"), map.get("faultString")) {
                    (Some(&Value::Int(fault_code)), Some(&Value::String(ref fault_string))) => {
                        Some(Fault {
                            fault_code,
                            fault_string: fault_string.to_string(),
                        })
                    }
                    _ => None
                }
            }
            _ => None
        }
    }

    /// Turns this `Fault` into an equivalent `Value`.
    ///
    /// The returned value can be parsed back into a `Fault` using `Fault::from_value` or returned
    /// as a `<fault>` error response by serializing it into a `<fault></fault>` tag.
    pub fn to_value(&self) -> Value {
        let mut map = BTreeMap::new();
        map.insert("faultCode".to_string(), Value::from(self.fault_code));
        map.insert("faultString".to_string(), Value::from(self.fault_string.as_ref()));

        Value::Struct(map)
    }
}

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

impl Error for Fault {
    fn description(&self) -> &str {
        &self.fault_string
    }
}

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

    use std::error::Error;

    #[test]
    fn fault_roundtrip() {
        let input = Fault {
            fault_code: -123456,
            fault_string: "The Bald Lazy House Jumps Over The Hyperactive Kitten".to_string()
        };

        assert_eq!(Fault::from_value(&input.to_value()), Some(input));
    }

    #[test]
    fn error_impls_error() {
        fn assert_error<T: Error>() {}

        assert_error::<RequestError>();
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashSet, RingBuf, Deque};
use std::collections::hashmap::SetItems;

trait Graph<T> {
    /// Insert a new node, returning its index
    fn add_node(&mut self, val: T) -> NodeIndex;

    /// Insert a new edge, returning an error if one of the indices is invalid
    /// and a result otherwise
    fn add_edge(&mut self, i: NodeIndex, j: NodeIndex) -> GraphResult<bool>;

    fn adj<'a>(&'a self, i: NodeIndex) -> NodeIndices<'a>;

    /// Return the number of nodes in the graph
    fn num_nodes(&self) -> uint;

    /// Do a breadth-first search of the graph, returning the resulting breadth-
    /// first tree.
    fn bfs(&self) -> Digraph<NodeIndex> {
        let mut tree = Digraph::new();

        if self.num_nodes() == 0 {
            return tree;
        }

        let mut visited = HashSet::new();
        let mut discovered = RingBuf::new();

        discovered.push_back((0, None));
        loop {
            match discovered.pop_front() {
                None => break,
                Some((ind, parent)) => {
                    tree.add_node(ind);
                    if parent.is_some() {
                        tree.add_edge(parent.unwrap(), ind);
                    }
                    visited.insert(ind);

                    for i in self.adj(ind) {
                        if !visited.contains(i) {
                            discovered.push_back((*i, Some(ind)));
                        }
                    }
                }
            }
        }
        return tree;
    }

    fn dfs(&self) -> Digraph<NodeIndex> {
        let mut tree = Digraph::new();

        if self.num_nodes() == 0 {
            return tree;
        }

        let mut visited = HashSet::new();
        let mut discovered = vec!();

        discovered.push((0, None));
        loop {
            match discovered.pop() {
                None => break,
                Some((ind, parent)) => {
                    tree.add_node(ind);
                    if parent.is_some() {
                        tree.add_edge(parent.unwrap(), ind);
                    }
                    visited.insert(ind);

                    for i in self.adj(ind) {
                        if !visited.contains(i) {
                            discovered.push((*i, Some(ind)));
                        }
                    }
                }
            }
        }
        return tree;

    }
}

struct GraphError {
    error_type: GraphErrorType,
}

impl GraphError {
    fn invalid_index(ind: NodeIndex) -> GraphError {
        GraphError { error_type: InvalidNodeIndex(ind) }
    }
}

type GraphResult<T> = Result<T, GraphError>;

enum GraphErrorType {
    InvalidNodeIndex(NodeIndex),
}

type NodeIndex = uint;

#[deriving(Show)]
struct Node<T> {
    data: T,
    index: NodeIndex,
}

/// Undirected graph. Allows loops.
#[deriving(Show)]
struct UnGraph<T> {
    nodes: Vec<Node<T>>,
    adj: Vec<HashSet<NodeIndex>>,
    num_nodes: uint,
}

/// Directed graph. Allows loops.
#[deriving(Show)]
struct Digraph<T> {
    nodes: Vec<Node<T>>,
    in_adj: Vec<HashSet<NodeIndex>>,
    out_adj: Vec<HashSet<NodeIndex>>,
    num_nodes: uint,
}

impl<T> UnGraph<T> {
    pub fn new() -> UnGraph<T> {
        UnGraph { nodes: vec!(), adj: vec!(), num_nodes: 0 }
    }

    pub fn degree(&mut self, ind: NodeIndex) -> Result<uint, GraphError> {
        if ind >= self.num_nodes {
            Err(GraphError::invalid_index(ind))
        } else {
            Ok(self.adj[ind].len())
        }
    }
}

impl<T> Graph<T> for UnGraph<T> {
    fn add_node(&mut self, val: T) -> NodeIndex {
        let ind = self.num_nodes;
        self.nodes.push(Node { data: val, index: ind });
        self.adj.push(HashSet::new());
        self.num_nodes += 1;
        ind
    }

    fn add_edge(&mut self, i: NodeIndex, j: NodeIndex) -> GraphResult<bool> {
        if i >= self.num_nodes {
            Err(GraphError::invalid_index(i))
        } else if j >= self.num_nodes {
            Err(GraphError::invalid_index(j))
        } else {
            if self.adj[i].contains(&j) {
                Ok(false)
            } else {
                self.adj.get_mut(i).insert(j);
                self.adj.get_mut(j).insert(i);
                Ok(true)
            }
        }
    }

    fn adj<'a>(&'a self, i: NodeIndex) -> NodeIndices<'a> {
        NodeIndices::from_set(&self.adj[i])
    }

    fn num_nodes(&self) -> uint {
        self.num_nodes
    }
}

impl<T> Digraph<T> {
    pub fn new() -> Digraph<T> {
        Digraph { nodes: vec!(), in_adj: vec!(), out_adj: vec!(), num_nodes: 0 }
    }

    pub fn out_degree(&mut self, ind: NodeIndex) -> Result<uint, GraphError> {
        if ind >= self.num_nodes {
            Err(GraphError::invalid_index(ind))
        } else {
            Ok(self.out_adj[ind].len())
        }
    }

    pub fn in_degree(&mut self, ind: NodeIndex) -> Result<uint, GraphError> {
        if ind >= self.num_nodes {
            Err(GraphError::invalid_index(ind))
        } else {
            Ok(self.in_adj[ind].len())
        }
    }
}

impl<T> Graph<T> for Digraph<T> {
    fn add_node(&mut self, val: T) -> NodeIndex {
        let ind = self.num_nodes;
        self.nodes.push(Node { data: val, index: ind });
        self.in_adj.push(HashSet::new());
        self.out_adj.push(HashSet::new());
        self.num_nodes += 1;
        ind
    }

    fn add_edge(&mut self, i: NodeIndex, j: NodeIndex) -> GraphResult<bool> {
        if i >= self.num_nodes {
            Err(GraphError::invalid_index(i))
        } else if j >= self.num_nodes {
            Err(GraphError::invalid_index(j))
        } else {
            if self.out_adj[i].contains(&j) {
                Ok(false)
            } else {
                self.out_adj.get_mut(i).insert(j);
                self.in_adj.get_mut(j).insert(i);
                Ok(true)
            }
        }
    }

    fn adj<'a>(&'a self, i: NodeIndex) -> NodeIndices<'a> {
        NodeIndices::from_set(&self.out_adj[i])
    }

    fn num_nodes(&self) -> uint {
        self.num_nodes
    }
}

struct NodeIndices<'a> {
    indices: SetItems<'a, NodeIndex>,
}

impl<'a> Iterator<&'a NodeIndex> for NodeIndices<'a> {
    fn next(&mut self) -> Option<&'a NodeIndex> {
        self.indices.next()
    }
}

impl<'a> NodeIndices<'a> {
    fn from_set(set: &'a HashSet<NodeIndex>) -> NodeIndices<'a> {
        NodeIndices { indices: set.iter() }
    }
}
<commit_msg>Add methods for generating induced subgraphs<commit_after>use std::collections::{HashSet, HashMap, RingBuf, Deque};
use std::collections::hashmap::SetItems;

// call this Unigraph instead?
trait Graph<T> {
    /// Insert a new node, returning its index
    fn add_node(&mut self, val: T) -> NodeIndex;

    /// Insert a new edge, returning an error if one of the indices is invalid
    /// and a result otherwise
    fn add_edge(&mut self, i: NodeIndex, j: NodeIndex) -> GraphResult<bool>;

    /// Return an iterator over the out-neighbors for a given node
    fn adj<'a>(&'a self, i: NodeIndex) -> NodeIndices<'a>;

    /// Return the number of nodes in the graph
    fn num_nodes(&self) -> uint;

    /// Do a breadth-first search of the graph, returning the resulting breadth-
    /// first tree.
    fn bfs(&self) -> Digraph<NodeIndex> {
        let mut tree = Digraph::new();

        if self.num_nodes() == 0 {
            return tree;
        }

        let mut visited = HashSet::new();
        let mut discovered = RingBuf::new();

        discovered.push_back((0, None));
        loop {
            match discovered.pop_front() {
                None => break,
                Some((ind, parent)) => {
                    tree.add_node(ind);
                    if parent.is_some() {
                        tree.add_edge(parent.unwrap(), ind);
                    }
                    visited.insert(ind);

                    for i in self.adj(ind) {
                        if !visited.contains(i) {
                            discovered.push_back((*i, Some(ind)));
                        }
                    }
                }
            }
        }
        return tree;
    }

    fn dfs(&self) -> Digraph<NodeIndex> {
        let mut tree = Digraph::new();

        if self.num_nodes() == 0 {
            return tree;
        }

        let mut visited = HashSet::new();
        let mut discovered = vec!();

        discovered.push((0, None));
        loop {
            match discovered.pop() {
                None => break,
                Some((ind, parent)) => {
                    tree.add_node(ind);
                    if parent.is_some() {
                        tree.add_edge(parent.unwrap(), ind);
                    }
                    visited.insert(ind);

                    for i in self.adj(ind) {
                        if !visited.contains(i) {
                            discovered.push((*i, Some(ind)));
                        }
                    }
                }
            }
        }
        return tree;

    }
}

struct GraphError {
    error_type: GraphErrorType,
}

impl GraphError {
    fn invalid_index(ind: NodeIndex) -> GraphError {
        GraphError { error_type: InvalidNodeIndex(ind) }
    }
}

type GraphResult<T> = Result<T, GraphError>;

enum GraphErrorType {
    InvalidNodeIndex(NodeIndex),
}

type NodeIndex = uint;

#[deriving(Show, Clone)]
struct Node<T> {
    data: T,
    index: NodeIndex,
}

/// Undirected graph. Allows loops.
#[deriving(Show)]
struct UnGraph<T> {
    nodes: Vec<Node<T>>,
    adj: Vec<HashSet<NodeIndex>>,
    num_nodes: uint,
}

/// Directed graph. Allows loops.
#[deriving(Show)]
struct Digraph<T> {
    nodes: Vec<Node<T>>,
    in_adj: Vec<HashSet<NodeIndex>>,
    out_adj: Vec<HashSet<NodeIndex>>,
    num_nodes: uint,
}

impl<T> UnGraph<T> {
    pub fn new() -> UnGraph<T> {
        UnGraph { nodes: vec!(), adj: vec!(), num_nodes: 0 }
    }

    pub fn degree(&mut self, ind: NodeIndex) -> Result<uint, GraphError> {
        if ind >= self.num_nodes {
            Err(GraphError::invalid_index(ind))
        } else {
            Ok(self.adj[ind].len())
        }
    }
}
impl<T: Clone> UnGraph<T> {
    /// Returns a new graph induced by a set of node indices
    pub fn induced_subgraph(&self, nodes: &HashSet<NodeIndex>) -> UnGraph<T> {
        let mut new = UnGraph::new();
        let mut ind_map = HashMap::new();

        for (i, ind) in nodes.iter().enumerate() {
            ind_map.insert(ind, i);
            new.add_node(self.nodes[*ind].data.clone());
        }

        // Here we're assuming that NodeIndex = uint. Not sure how to easily do otherwise
        for i in range(0, self.num_nodes) {
            for j in self.adj[i].iter() {
                new.add_edge(i, *j);
            }
        }

        new
    }
}

impl<T> Graph<T> for UnGraph<T> {
    fn add_node(&mut self, val: T) -> NodeIndex {
        let ind = self.num_nodes;
        self.nodes.push(Node { data: val, index: ind });
        self.adj.push(HashSet::new());
        self.num_nodes += 1;
        ind
    }

    fn add_edge(&mut self, i: NodeIndex, j: NodeIndex) -> GraphResult<bool> {
        if i >= self.num_nodes {
            Err(GraphError::invalid_index(i))
        } else if j >= self.num_nodes {
            Err(GraphError::invalid_index(j))
        } else {
            if self.adj[i].contains(&j) {
                Ok(false)
            } else {
                self.adj.get_mut(i).insert(j);
                self.adj.get_mut(j).insert(i);
                Ok(true)
            }
        }
    }

    fn adj<'a>(&'a self, i: NodeIndex) -> NodeIndices<'a> {
        NodeIndices::from_set(&self.adj[i])
    }

    fn num_nodes(&self) -> uint {
        self.num_nodes
    }
}

impl<T> Digraph<T> {
    pub fn new() -> Digraph<T> {
        Digraph { nodes: vec!(), in_adj: vec!(), out_adj: vec!(), num_nodes: 0 }
    }

    pub fn out_degree(&mut self, ind: NodeIndex) -> Result<uint, GraphError> {
        if ind >= self.num_nodes {
            Err(GraphError::invalid_index(ind))
        } else {
            Ok(self.out_adj[ind].len())
        }
    }

    pub fn in_degree(&mut self, ind: NodeIndex) -> Result<uint, GraphError> {
        if ind >= self.num_nodes {
            Err(GraphError::invalid_index(ind))
        } else {
            Ok(self.in_adj[ind].len())
        }
    }
}

impl<T: Clone> Digraph<T> {
    /// Returns a new graph induced by a set of node indices
    pub fn induced_subgraph(&self, nodes: &HashSet<NodeIndex>) -> Digraph<T> {
        let mut new = Digraph::new();
        let mut ind_map = HashMap::new();

        for (i, ind) in nodes.iter().enumerate() {
            ind_map.insert(ind, i);
            new.add_node(self.nodes[*ind].data.clone());
        }

        // Here we're assuming that NodeIndex = uint. Not sure how to easily do otherwise
        for i in range(0, self.num_nodes) {
            for j in self.in_adj[i].iter() {
                new.add_edge(*j, i);
            }

            for j in self.out_adj[i].iter() {
                new.add_edge(i, *j);
            }
        }

        new
    }
}

impl<T> Graph<T> for Digraph<T> {
    fn add_node(&mut self, val: T) -> NodeIndex {
        let ind = self.num_nodes;
        self.nodes.push(Node { data: val, index: ind });
        self.in_adj.push(HashSet::new());
        self.out_adj.push(HashSet::new());
        self.num_nodes += 1;
        ind
    }

    fn add_edge(&mut self, i: NodeIndex, j: NodeIndex) -> GraphResult<bool> {
        if i >= self.num_nodes {
            Err(GraphError::invalid_index(i))
        } else if j >= self.num_nodes {
            Err(GraphError::invalid_index(j))
        } else {
            if self.out_adj[i].contains(&j) {
                Ok(false)
            } else {
                self.out_adj.get_mut(i).insert(j);
                self.in_adj.get_mut(j).insert(i);
                Ok(true)
            }
        }
    }

    fn adj<'a>(&'a self, i: NodeIndex) -> NodeIndices<'a> {
        NodeIndices::from_set(&self.out_adj[i])
    }

    fn num_nodes(&self) -> uint {
        self.num_nodes
    }
}

struct NodeIndices<'a> {
    indices: SetItems<'a, NodeIndex>,
}

impl<'a> Iterator<&'a NodeIndex> for NodeIndices<'a> {
    fn next(&mut self) -> Option<&'a NodeIndex> {
        self.indices.next()
    }
}

impl<'a> NodeIndices<'a> {
    fn from_set(set: &'a HashSet<NodeIndex>) -> NodeIndices<'a> {
        NodeIndices { indices: set.iter() }
    }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Display};

#[derive(Debug, Clone, Eq, Hash)]
pub struct Ident(String);

impl Ident {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        t.into()
    }
}

impl<'a> From<&'a str> for Ident {
    fn from(s: &str) -> Self {
        Ident(s.to_owned())
    }
}

impl From<String> for Ident {
    fn from(s: String) -> Self {
        Ident(s)
    }
}

impl From<usize> for Ident {
    fn from(u: usize) -> Self {
        Ident(u.to_string())
    }
}

impl AsRef<str> for Ident {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

impl Display for Ident {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}

impl<T: ?Sized> PartialEq<T> for Ident
    where T: AsRef<str>
{
    fn eq(&self, other: &T) -> bool {
        self.0 == other.as_ref()
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use space::whitespace;

    fn ident_ch(ch: char) -> bool {
        ch.is_alphanumeric() || ch == '_'
    }

    named!(pub ident -> Ident, preceded!(
        option!(whitespace),
        map!(take_while1!(ident_ch), Into::into)
    ));
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Ident {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(self.as_ref())
        }
    }
}
<commit_msg>Disallow non ident-looking idents<commit_after>use std::fmt::{self, Display};

#[derive(Debug, Clone, Eq, Hash)]
pub struct Ident(String);

impl Ident {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        t.into()
    }
}

impl<'a> From<&'a str> for Ident {
    fn from(s: &str) -> Self {
        Ident(s.to_owned())
    }
}

impl From<String> for Ident {
    fn from(s: String) -> Self {
        Ident(s)
    }
}

impl From<usize> for Ident {
    fn from(u: usize) -> Self {
        Ident(u.to_string())
    }
}

impl AsRef<str> for Ident {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

impl Display for Ident {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}

impl<T: ?Sized> PartialEq<T> for Ident
    where T: AsRef<str>
{
    fn eq(&self, other: &T) -> bool {
        self.0 == other.as_ref()
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use nom::IResult;
    use space::skip_whitespace;
    use unicode_xid::UnicodeXID;

    pub fn ident(mut input: &str) -> IResult<&str, Ident> {
        input = skip_whitespace(input);

        let mut chars = input.char_indices();
        match chars.next() {
            Some((_, ch)) if UnicodeXID::is_xid_start(ch) || ch == '_' => {}
            _ => return IResult::Error,
        }

        while let Some((i, ch)) = chars.next() {
            if !UnicodeXID::is_xid_continue(ch) {
                return IResult::Done(&input[i..], input[..i].into());
            }
        }

        IResult::Done("", input.into())
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Ident {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(self.as_ref())
        }
    }
}
<|endoftext|>


<commit_before>//! The idea here is basically we provide a Game type,
//! which can swap between several different Scene types.
//! Ideally Scenes can be nested and we can build a stack
//! of them?  Or something.
//! We also need hooks: Load, unload... more finely grained?
//! Kinda tricky to separate create/destroy vs. load and unload,
//! KISS for now.

use std::collections::BTreeMap;
use std::marker::Sized;

use ggez::GameResult;

struct SceneStateTest {
    state: i32,
}

trait SceneState {
    fn load_scene(self) -> Box<Scene<S=Self>>;
    fn unload_scene(s: Scene<S=Self>) -> Box<Self>;
    /*
    fn load_scene<S>(self) -> Box<S> where S: Scene + Sized  {
        S::load(Box::new(self))
    }

    fn unload_scene<S>(mut s: S) -> Self where S: Scene + Sized {
        s.unload()
    }
    */
}

trait Scene  {
    type S: SceneState;
    fn update(&mut self) -> GameResult<()>;

    fn draw(&mut self) -> GameResult<()>;

    fn unload(&mut self) -> Box<Self::S>;

    fn load(state: Box<Self::S>) -> Box<Self> where Self: Sized;

    /*
    fn load_from_default() -> GameResult<Self>
        where Self: Sized,
              S: Default {
        let state = S::default();
        Self::load(state)
    }
*/
}
/*
pub trait SceneState<S> where S: Scene {
    fn load_scene(self) -> GameResult<S>;
    fn unload_scene(scene: S) -> GameResult<Self>
        where Self: Sized;
}

use std::any::Any;

// Okay, the basic semantics are:
// A scene gets loaded and passed some state, which can be a default
// So what we need to actually store are a name, a scene constructor,
// and the state for that scene.
// The state can be different for every scene as far as the SceneRunner
// is concerned, it's only associated with that one type of scene.
struct SceneRunner {
    scenes: BTreeMap<String, Box<SceneState<i32>>>,
}

impl SceneRunner {
    fn add_scene<S>(&mut self, name: &str, initial_state: SceneState<S>) {
        self.scenes.insert(name.to_string(), Box::new(initial_state));
    }
}
*/

/*
use ggez;
use ggez::GameResult;
use ggez::conf;
use ggez::game::GameState;

use std::time::Duration;

pub trait Scene: GameState {}

pub struct SceneManager {
    current_scene: Option<Box<Scene>>,
    scene_stack: Vec<Box<Scene>>,
}

impl SceneManager {
    pub fn switch_scene<T>(&mut self, ctx: &mut ggez::Context, conf: &conf::Conf) -> GameResult<()>
        where T: Scene + 'static
    {
        let new_scene = T::load(ctx, conf)?;
        // let old_scene = &mut self.current_scene;
        self.current_scene = Some(Box::new(new_scene));
        Ok(())

    }
}

impl Default for SceneManager {
    fn default() -> Self {
        SceneManager {
            current_scene: None,
            scene_stack: Vec::default(),
        }
    }
}

impl GameState for SceneManager {
    fn load(ctx: &mut ggez::Context, conf: &conf::Conf) -> GameResult<Self> {
        Ok(SceneManager::default())
    }

    fn update(&mut self, ctx: &mut ggez::Context, dt: Duration) -> GameResult<()> {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut ggez::Context) -> GameResult<()> {
        Ok(())
    }
}
*/
<commit_msg>Seems to start to work so far...<commit_after>//! The idea here is basically we provide a Game type,
//! which can swap between several different Scene types.
//! Ideally Scenes can be nested and we can build a stack
//! of them?  Or something.
//! We also need hooks: Load, unload... more finely grained?
//! Kinda tricky to separate create/destroy vs. load and unload,
//! KISS for now.

use std::collections::BTreeMap;
use std::marker::Sized;

use ggez::GameResult;

/*
trait SceneState {
    fn load_scene(self) -> Box<Scene<S=Self>>;
    fn unload_scene(s: Scene<S=Self>) -> Box<Self>;
    /*
    fn load_scene<S>(self) -> Box<S> where S: Scene + Sized  {
        S::load(Box::new(self))
    }

    fn unload_scene<S>(mut s: S) -> Self where S: Scene + Sized {
        s.unload()
    }
    */
}
*/

trait Scene  {
    type S;
    fn update(&mut self) -> GameResult<()>;

    fn draw(&mut self) -> GameResult<()>;

    fn unload(&mut self) -> Box<Self::S>;

    fn load(state: Box<Self::S>) -> Box<Self> where Self: Sized;

    /*
    fn load_from_default() -> GameResult<Self>
        where Self: Sized,
              S: Default {
        let state = S::default();
        Self::load(state)
    }
*/
}

#[derive(Copy, Clone)]
struct SceneStateTest {
    state: i32,
}

struct TestScene {
    state: SceneStateTest,
}

impl Scene for TestScene {
    type S = SceneStateTest;

    fn update(&mut self) -> GameResult<()> {
        Ok(())
    }

    fn draw(&mut self) -> GameResult<()> {
        Ok(())
    }

    fn unload(&mut self) -> Box<Self::S> {
        Box::new(self.state)
    }

    fn load(state: Box<Self::S>) -> Box<Self> where Self: Sized {
        Box::new(TestScene {
            state: *state,
        })
    }
}

struct SceneRunner {
    scenes: BTreeMap<String, Box<SceneStateTest>>,
}

impl SceneRunner {
    fn add_scene<S>(&mut self, name: &str, initial_state: SceneStateTest) {
        self.scenes.insert(name.to_string(), Box::new(initial_state));
    }
}

/*
pub trait SceneState<S> where S: Scene {
    fn load_scene(self) -> GameResult<S>;
    fn unload_scene(scene: S) -> GameResult<Self>
        where Self: Sized;
}

use std::any::Any;

// Okay, the basic semantics are:
// A scene gets loaded and passed some state, which can be a default
// So what we need to actually store are a name, a scene constructor,
// and the state for that scene.
// The state can be different for every scene as far as the SceneRunner
// is concerned, it's only associated with that one type of scene.
struct SceneRunner {
    scenes: BTreeMap<String, Box<SceneState<i32>>>,
}

impl SceneRunner {
    fn add_scene<S>(&mut self, name: &str, initial_state: SceneState<S>) {
        self.scenes.insert(name.to_string(), Box::new(initial_state));
    }
}
*/

/*
use ggez;
use ggez::GameResult;
use ggez::conf;
use ggez::game::GameState;

use std::time::Duration;

pub trait Scene: GameState {}

pub struct SceneManager {
    current_scene: Option<Box<Scene>>,
    scene_stack: Vec<Box<Scene>>,
}

impl SceneManager {
    pub fn switch_scene<T>(&mut self, ctx: &mut ggez::Context, conf: &conf::Conf) -> GameResult<()>
        where T: Scene + 'static
    {
        let new_scene = T::load(ctx, conf)?;
        // let old_scene = &mut self.current_scene;
        self.current_scene = Some(Box::new(new_scene));
        Ok(())

    }
}

impl Default for SceneManager {
    fn default() -> Self {
        SceneManager {
            current_scene: None,
            scene_stack: Vec::default(),
        }
    }
}

impl GameState for SceneManager {
    fn load(ctx: &mut ggez::Context, conf: &conf::Conf) -> GameResult<Self> {
        Ok(SceneManager::default())
    }

    fn update(&mut self, ctx: &mut ggez::Context, dt: Duration) -> GameResult<()> {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut ggez::Context) -> GameResult<()> {
        Ok(())
    }
}
*/
<|endoftext|>


<commit_before>extern crate cgmath;

use image_types::Color;
use cgmath::{EuclideanVector, Point};
use cgmath::{Vector3, Point3, Ray3};
use cgmath::{dot};

#[deriving(Show, Clone)]
struct Sphere {
    origin: Point3<f32>,
    radius: f32
}

#[deriving(Clone)]
pub struct Scene {
    objects: Vec<Sphere>
}

pub fn build_scene(filename: &str) -> Scene {
    let objs = vec![Sphere::new((0.0, 0.0, 2.0), 1.0),
                    Sphere::new((0.0, 2.0, 4.0), 3.0)];

    Scene { objects: objs }
}

impl Scene {
    pub fn trace_ray(&self, ray: &Ray3<f32>) -> Color {
        for object in self.objects.iter() {
            if object.check_intersection(ray) {
                return Color { r: 1.0, g: 1.0, b: 1.0 }
            }
        }
        Color { r: 0.0, g: 0.0, b: 0.0 }
    }
}

impl Sphere {
    fn new(origin: (f32, f32, f32), radius: f32) -> Sphere {
        let (x, y, z) = origin;
        Sphere { origin: Point3 {x: x, y: y, z: z},
                 radius: radius }
    }
}

impl Intersectable for Sphere {
    fn check_intersection(&self, ray: &Ray3<f32>) -> bool {
        /* See http://en.wikipedia.org/wiki/Line%E2%80%93sphere_intersection */
        let delta = self.origin.sub_p(&ray.origin);
        let a = ray.direction.length2(); // Square magnitude
        let b = 2.0 * dot(ray.direction, delta);
        let c = delta.length2() - self.radius*self.radius;
        let discriminant = b*b - 4.0*a*c;
        if discriminant >= 0.0 {
            true
        } else {
            false
        }
    }

    fn intersection(&self, ray: &Ray3<f32>) -> Option<Intersection> {
        Some(Intersection { point: Point3 { x: 0.0, y: 0.0, z: 0.0 },
                            normal: Vector3 { x: 0.0, y: 0.0, z: 0.0 } })
    }
}

struct Intersection {
    point: Point3<f32>,
    normal: Vector3<f32>
}

trait Intersectable {
    fn check_intersection(&self, ray: &Ray3<f32>) -> bool;
    fn intersection(&self, ray: &Ray3<f32>) -> Option<Intersection>;
}
<commit_msg>Trace for closests sphere<commit_after>extern crate cgmath;

use std::rc::Rc;
use image_types::Color;
use cgmath::{EuclideanVector, Point};
use cgmath::{Vector3, Point3, Ray3};
use cgmath::{dot};

#[deriving(Show, Clone)]
struct Sphere {
    pos: Point3<f32>,
    radius: f32
}

#[deriving(Clone)]
pub struct Scene {
    objects: Vec<SceneObject>
}

#[deriving(Clone)]
struct Material {
    color: Color
}

#[deriving(Clone)]
struct SceneObject {
    material: Material,
    geometry: Sphere
}

enum Geometry {
    SphereGeometry(Sphere)
}

struct SceneLight {
    pos: Point3<f32>,
    color: Color,
    intensity: f32
}

pub fn build_scene(filename: &str) -> Scene {
    let mat1 = Material { color: Color { r: 0.9, g: 0.9, b: 0.9 } };
    let mat2 = Material { color: Color { r: 1.0, g: 0.0, b: 0.4 } };
    let objs = vec![SceneObject { geometry: Sphere::new((0.0, 0.0, 2.0), 1.0),
                                  material: mat1 },
                    SceneObject { geometry: Sphere::new((0.0, 2.0, 4.0), 3.0),
                                  material: mat2 }];

    Scene { objects: objs }
}

impl Scene {
    pub fn trace_ray(&self, ray: &Ray3<f32>) -> Color {
        let mut closest = None;
        let mut closest_distance = 99999999999.0;
        for object in self.objects.iter() {
            let result = object.geometry.intersection(ray);
            match result {
                Some(distance) => {
                    if distance < closest_distance {
                        closest = Some(object);
                        closest_distance = distance;
                    }
                },
                None => ()
            }
        }
        match closest {
            Some(object) => object.material.color,
            None         => sky_color(&ray.direction)
        }

    }
}

fn sky_color(direction: &Vector3<f32>) -> Color {
    Color { r: 0.0, g: 0.0, b: 0.0 }
}

impl Sphere {
    fn new(origin: (f32, f32, f32), radius: f32) -> Sphere {
        let (x, y, z) = origin;
        Sphere { pos: Point3 {x: x, y: y, z: z},
                 radius: radius }
    }
}

impl Intersectable for Sphere {
    fn intersection(&self, ray: &Ray3<f32>) -> Option<f32> {
        /* See http://en.wikipedia.org/wiki/Line%E2%80%93sphere_intersection */
        let delta = self.pos.sub_p(&ray.origin);
        let a = ray.direction.length2(); // Square magnitude
        let b = 2.0 * dot(ray.direction, delta);
        let c = delta.length2() - self.radius*self.radius;
        let discriminant = b*b - 4.0*a*c;
        if discriminant >= 0.0 {
            let distance = (-b - discriminant.sqrt()) / (2.0 * a);
            Some(distance)
        } else {
            None
        }
    }
}

struct Intersection {
    point: Point3<f32>,
    normal: Vector3<f32>
}

trait Intersectable {
    fn intersection(&self, ray: &Ray3<f32>) -> Option<f32>;
}

<|endoftext|>