<commit_before>use token::{Token, Tok};
use regex::Regex;
use utils::get_caret_string;

static COMMENT_REGEX: Regex = regex!(r"^#.*");
static WHITESPACE_REGEX: Regex = regex!(r"^\s");

static SYMBOL_SPECS: &'static [(&'static str, Token<'static>)] = &[
    //Symbols
    (r":", Token::Assign),
    (r".", Token::Dot),
    (r"{", Token::OpenCurly),
    (r"}", Token::CloseCurly),
    (r"[", Token::OpenBrac),
    (r"]", Token::CloseBrac),
    (r"(", Token::OpenParen),
    (r")", Token::CloseParen),
    (r",", Token::Comma),
    (r"->", Token::Ret),
    //Binary Operators
    (r"*", Token::Mul),
    (r"/", Token::Div),
    (r"%", Token::Mod),
    (r"+", Token::Add),
    (r"-", Token::Sub),
    (r"<=", Token::Lte),
    (r"<", Token::Lt),
    (r">=", Token::Gte),
    (r">", Token::Gt),
    (r"==", Token::Same),
    (r"=", Token::Eq),
    (r"!==", Token::Nsame),
    (r"!=", Token::Neq),
    (r"&&", Token::And),
    (r"||", Token::Or),
    //Unary Operators
    (r"!", Token::Not),
    (r"$", Token::Get),
];

pub struct Lexer<'a> {
    input: String,
    toks: Vec<Tok<'a>>,
    lit_regexes: [(Regex, Box<Fn(&'a str) -> Token<'a> + 'static>); 4]
}

impl<'a> Lexer<'a> {

    pub fn new() -> Lexer<'a> {
        Lexer {
            input: String::new(),
            toks: Vec::new(),
            //TODO: There's gotta be a better way to do this
            lit_regexes: [
                (regex!(r"^[0-9]*\.[0-9]+(?:e[-+]?[0-9]+)?"), Box::new(|s: &'a str| Token::Float(s.parse().unwrap()))),
                (regex!(r"^[0-9]+"), Box::new(|s: &'a str| Token::Int(s.parse().unwrap()))),
                (regex!(r"^((\p{Alphabetic}|\p{M}|\p{Pc}|\p{Join_Control})\w*)"), Box::new(|s: &'a str| {
                    //Match keywords and idents
                    match s {
                        "def" => Token::Def,
                        "var" => Token::Var,
                        "nil" => Token::Nil,
                        "fn" => Token::Fn,
                        "return" => Token::Return,
                        "in" => Token::In,
                        "if" => Token::If,
                        "else" => Token::Else,
                        "elif" => Token::Elif,
                        "while" => Token::While,
                        "end" => Token::End,
                        "true" => Token::Bool(true),
                        "false" => Token::Bool(false),
                        s => Token::Ident(s)
                    }
                })),
                (regex!(r#"^"(?:[^"\\]|\\.)*""#), Box::new(|s: &'a str|{
                    let trimmed_slice = &s[1..s.len() - 1];
                    let escaped = trimmed_slice.replace(r#"\""#, "\"").replace(r"\\", r"\");
                    Token::String(escaped)
                }))
            ]
        }
    }

    pub fn lex(&'a mut self, s: String) -> Result<&Vec<Tok<'a>>, String> {
        let mut char_index = 0usize;
        self.input = s;
        for (line_index, l) in self.input.lines().enumerate() {
            let res = Lexer::lex_line(l, line_index, &mut char_index, &mut self.toks, &self.lit_regexes);
            match res {
                Ok(()) => {char_index += 1;},
                Err(col) => {
                    return Err(
                        format!(
                            "LEXING FAILURE at {},{}: invalid character {}\n{}\n{}",
                            line_index + 1,
                            col + 1,
                            l.chars().nth(col).unwrap(),
                            l,
                            get_caret_string(col)
                        )
                    );
                }
            }
        }
        Ok(&self.toks)
    }

    fn lex_line(line: &'a str, line_no: usize, char_index: &mut usize, toks: &mut Vec<Tok<'a>>, lit_regexes: &[(Regex, Box<Fn(&'a str) -> Token<'a> + 'static>)]) -> Result<(), usize> {
        let mut line_slice = line;
        let mut col = 0usize;
        let mut match_end = 0usize;
        while line_slice.len() > 0 {
            let mut found_token = false;
            //Return for this line once a comment is reached
            match COMMENT_REGEX.find(line_slice) {
                Some((_, end)) => {
                    match_end = end;
                    found_token = true;
                }
                None => ()
            }
            //Skip whitespace
            match WHITESPACE_REGEX.find(line_slice) {
                Some((_, end)) => {
                    match_end = end;
                    found_token = true;
                }
                None => ()
            };
            //Lex symbols
            if !found_token {
                for &(s, ref tok_type) in SYMBOL_SPECS.iter() {
                    let mut got_match = true;
                    if s.len() > line_slice.len() {
                        continue;
                    }
                    for (s_char, line_char) in s.chars().zip(line_slice.chars()) {
                        if s_char != line_char {
                            got_match = false;
                            break;
                        }
                    }
                    if got_match {
                        match_end = s.len();
                        let new_token = (*tok_type).clone();
                        toks.push(Tok{token: new_token, line: line_no, col: col, line_string: line, char_index: *char_index});
                        found_token = true;
                        break;
                    }

                }
            }
            //Lex regexes
            if !found_token {
                for &(ref re, ref tok_func) in lit_regexes.iter() {
                    let (start,end) = match re.find(line_slice) {
                        Some(range) => range,
                        None => continue
                    };
                    match_end = end;
                    let token_slice = &line_slice[start..end];
                    let new_token = tok_func(token_slice);
                    toks.push(Tok{token: new_token, line: line_no, col: col, line_string: line, char_index: *char_index});
                    found_token = true;
                    break;
                }
            }

            //No token was found, which means that something was invalid
            if !found_token {
                return Err(col);
            }

            //Push the column index to the end of what we just read
            col += match_end;
            *char_index += match_end;
            line_slice = &line_slice[match_end..];
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::Lexer;
    use token::Token;
    use test::Bencher;

    fn match_tokens(input: &str, output: Vec<Token>) {
        let mut lexer = Lexer::new();
        let results = lexer.lex(input.to_string()).ok().unwrap();
        for (res, test) in results.iter().zip(output.iter()) {
            assert_eq!(test, &res.token);
        }
    }

    #[test]
    fn test_keywords() {
        match_tokens(
            "def var nil return",
            vec![Token::Def, Token::Var, Token::Nil, Token::Return]
        );
    }

    #[test]
    fn test_ambiguous() {
        match_tokens(
            "-->> ->-> >== <<= !=",
            vec![
                Token::Sub,
                Token::Ret,
                Token::Gt,
                Token::Ret,
                Token::Ret,
                Token::Gte,
                Token::Eq,
                Token::Lt,
                Token::Lte,
                Token::Neq
            ]
        );
    }

    #[test]
    fn test_ident() {
        match_tokens(
            "else elser fn() nils dowhile returns defing tootrue falsehood",
            vec![
                Token::Else,
                Token::Ident("elser"),
                Token::Fn,
                Token::OpenParen,
                Token::CloseParen,
                Token::Ident("nils"),
                Token::Ident("dowhile"),
                Token::Ident("returns"),
                Token::Ident("defing"),
                Token::Ident("tootrue"),
                Token::Ident("falsehood")
            ]
        )
    }

    #[test]
    fn test_invalid_char() {
        let mut lexer = Lexer::new();
        match lexer.lex("this is @ invalid".to_string()){
            Err(s) => assert_eq!("LEXING FAILURE at 1,9: invalid character @\nthis is @ invalid\n        ^".to_string(), s),
            _ => assert!(false)
        }
    }

    #[test]
    fn test_char_data() {
        let mut lexer = Lexer::new();
        match lexer.lex("if 3 > 2\n    # do some stuff\n    stuff()\nend".to_string()){
            Err(_) => assert!(false),
            Ok(v) => {
                assert_eq!("    stuff()", v[5].line_string);
                assert_eq!(9, v[5].col);
                assert_eq!(2, v[5].line);
                assert_eq!(38, v[5].char_index);
            }
        }
    }

    #[test]
    fn test_unicode_space() {
        let mut lexer = Lexer::new();
        match lexer.lex("def x: ${  \n    def a: 1\n    def b: 2\n}".to_string()){
            Err(_) => assert!(false),
            Ok(v) => {
                assert_eq!(Token::Get, v[3].token);
                assert_eq!(Token::OpenCurly, v[4].token);
            }
        }
    }

    #[test]
    fn test_idents() {
        match_tokens(
            "_i1 i2_a ΔᎠβ_ⅠᏴγδⅡ",
            vec![
                Token::Ident("_i1"),
                Token::Ident("i2_a"),
                Token::Ident("ΔᎠβ_ⅠᏴγδⅡ")
            ]
        )
    }

    #[test]
    fn test_starting_with_number() {
        match_tokens(
            "3_i1 i2_a",
            vec![
                Token::Int(3),
                Token::Ident("_i1"),
                Token::Ident("i2_a"),
            ]
        )
    }

    #[bench]
    fn bench_symbols(b: &mut Bencher) {
        let num_copies = 1000;
        let symbol_string = ":.{}()[],->*/%+-<=<>=>===!==!=&&||!$";
        let mut test_string = String::with_capacity(symbol_string.len() * num_copies);
        for _ in 1..num_copies {
            test_string.push_str(symbol_string);
        }
        b.iter(|| {
            let mut lexer = Lexer::new();
            match lexer.lex(test_string.clone()) {
                Err(_) => assert!(false),
                Ok(_) => ()
            }
        });
    }
}
<commit_msg>Added tests for comments and strings for the lexer<commit_after>use token::{Token, Tok};
use regex::Regex;
use utils::get_caret_string;

static COMMENT_REGEX: Regex = regex!(r"^#.*");
static WHITESPACE_REGEX: Regex = regex!(r"^\s");

static SYMBOL_SPECS: &'static [(&'static str, Token<'static>)] = &[
    //Symbols
    (r":", Token::Assign),
    (r".", Token::Dot),
    (r"{", Token::OpenCurly),
    (r"}", Token::CloseCurly),
    (r"[", Token::OpenBrac),
    (r"]", Token::CloseBrac),
    (r"(", Token::OpenParen),
    (r")", Token::CloseParen),
    (r",", Token::Comma),
    (r"->", Token::Ret),
    //Binary Operators
    (r"*", Token::Mul),
    (r"/", Token::Div),
    (r"%", Token::Mod),
    (r"+", Token::Add),
    (r"-", Token::Sub),
    (r"<=", Token::Lte),
    (r"<", Token::Lt),
    (r">=", Token::Gte),
    (r">", Token::Gt),
    (r"==", Token::Same),
    (r"=", Token::Eq),
    (r"!==", Token::Nsame),
    (r"!=", Token::Neq),
    (r"&&", Token::And),
    (r"||", Token::Or),
    //Unary Operators
    (r"!", Token::Not),
    (r"$", Token::Get),
];

pub struct Lexer<'a> {
    input: String,
    toks: Vec<Tok<'a>>,
    lit_regexes: [(Regex, Box<Fn(&'a str) -> Token<'a> + 'static>); 4]
}

impl<'a> Lexer<'a> {

    pub fn new() -> Lexer<'a> {
        Lexer {
            input: String::new(),
            toks: Vec::new(),
            //TODO: There's gotta be a better way to do this
            lit_regexes: [
                (regex!(r"^[0-9]*\.[0-9]+(?:e[-+]?[0-9]+)?"), Box::new(|s: &'a str| Token::Float(s.parse().unwrap()))),
                (regex!(r"^[0-9]+"), Box::new(|s: &'a str| Token::Int(s.parse().unwrap()))),
                (regex!(r"^((\p{Alphabetic}|\p{M}|\p{Pc}|\p{Join_Control})\w*)"), Box::new(|s: &'a str| {
                    //Match keywords and idents
                    match s {
                        "def" => Token::Def,
                        "var" => Token::Var,
                        "nil" => Token::Nil,
                        "fn" => Token::Fn,
                        "return" => Token::Return,
                        "in" => Token::In,
                        "if" => Token::If,
                        "else" => Token::Else,
                        "elif" => Token::Elif,
                        "while" => Token::While,
                        "end" => Token::End,
                        "true" => Token::Bool(true),
                        "false" => Token::Bool(false),
                        s => Token::Ident(s)
                    }
                })),
                (regex!(r#"^"(?:[^"\\]|\\.)*""#), Box::new(|s: &'a str|{
                    let trimmed_slice = &s[1..s.len() - 1];
                    let escaped = trimmed_slice.replace(r#"\""#, "\"").replace(r"\\", r"\");
                    Token::String(escaped)
                }))
            ]
        }
    }

    pub fn lex(&'a mut self, s: String) -> Result<&Vec<Tok<'a>>, String> {
        let mut char_index = 0usize;
        self.input = s;
        for (line_index, l) in self.input.lines().enumerate() {
            let res = Lexer::lex_line(l, line_index, &mut char_index, &mut self.toks, &self.lit_regexes);
            match res {
                Ok(()) => {char_index += 1;},
                Err(col) => {
                    return Err(
                        format!(
                            "LEXING FAILURE at {},{}: invalid character {}\n{}\n{}",
                            line_index + 1,
                            col + 1,
                            l.chars().nth(col).unwrap(),
                            l,
                            get_caret_string(col)
                        )
                    );
                }
            }
        }
        Ok(&self.toks)
    }

    fn lex_line(line: &'a str, line_no: usize, char_index: &mut usize, toks: &mut Vec<Tok<'a>>, lit_regexes: &[(Regex, Box<Fn(&'a str) -> Token<'a> + 'static>)]) -> Result<(), usize> {
        let mut line_slice = line;
        let mut col = 0usize;
        let mut match_end = 0usize;
        while line_slice.len() > 0 {
            let mut found_token = false;
            //Return for this line once a comment is reached
            match COMMENT_REGEX.find(line_slice) {
                Some((_, end)) => {
                    match_end = end;
                    found_token = true;
                }
                None => ()
            }
            //Skip whitespace
            match WHITESPACE_REGEX.find(line_slice) {
                Some((_, end)) => {
                    match_end = end;
                    found_token = true;
                }
                None => ()
            };
            //Lex symbols
            if !found_token {
                for &(s, ref tok_type) in SYMBOL_SPECS.iter() {
                    let mut got_match = true;
                    if s.len() > line_slice.len() {
                        continue;
                    }
                    for (s_char, line_char) in s.chars().zip(line_slice.chars()) {
                        if s_char != line_char {
                            got_match = false;
                            break;
                        }
                    }
                    if got_match {
                        match_end = s.len();
                        let new_token = (*tok_type).clone();
                        toks.push(Tok{token: new_token, line: line_no, col: col, line_string: line, char_index: *char_index});
                        found_token = true;
                        break;
                    }

                }
            }
            //Lex regexes
            if !found_token {
                for &(ref re, ref tok_func) in lit_regexes.iter() {
                    let (start,end) = match re.find(line_slice) {
                        Some(range) => range,
                        None => continue
                    };
                    match_end = end;
                    let token_slice = &line_slice[start..end];
                    let new_token = tok_func(token_slice);
                    toks.push(Tok{token: new_token, line: line_no, col: col, line_string: line, char_index: *char_index});
                    found_token = true;
                    break;
                }
            }

            //No token was found, which means that something was invalid
            if !found_token {
                return Err(col);
            }

            //Push the column index to the end of what we just read
            col += match_end;
            *char_index += match_end;
            line_slice = &line_slice[match_end..];
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::Lexer;
    use token::Token;
    use test::Bencher;

    fn match_tokens(input: &str, output: Vec<Token>) {
        let mut lexer = Lexer::new();
        let results = lexer.lex(input.to_string()).ok().unwrap();
        for (res, test) in results.iter().zip(output.iter()) {
            assert_eq!(test, &res.token);
        }
    }

    #[test]
    fn test_keywords() {
        match_tokens(
            "def var nil return",
            vec![Token::Def, Token::Var, Token::Nil, Token::Return]
        );
    }

    #[test]
    fn test_ambiguous() {
        match_tokens(
            "-->> ->-> >== <<= !=",
            vec![
                Token::Sub,
                Token::Ret,
                Token::Gt,
                Token::Ret,
                Token::Ret,
                Token::Gte,
                Token::Eq,
                Token::Lt,
                Token::Lte,
                Token::Neq
            ]
        );
    }

    #[test]
    fn test_ident() {
        match_tokens(
            "else elser fn() nils dowhile returns defing tootrue falsehood",
            vec![
                Token::Else,
                Token::Ident("elser"),
                Token::Fn,
                Token::OpenParen,
                Token::CloseParen,
                Token::Ident("nils"),
                Token::Ident("dowhile"),
                Token::Ident("returns"),
                Token::Ident("defing"),
                Token::Ident("tootrue"),
                Token::Ident("falsehood")
            ]
        )
    }

    #[test]
    fn test_invalid_char() {
        let mut lexer = Lexer::new();
        match lexer.lex("this is @ invalid".to_string()){
            Err(s) => assert_eq!("LEXING FAILURE at 1,9: invalid character @\nthis is @ invalid\n        ^".to_string(), s),
            _ => assert!(false)
        }
    }

    #[test]
    fn test_char_data() {
        let mut lexer = Lexer::new();
        match lexer.lex("if 3 > 2\n    # do some stuff\n    stuff()\nend".to_string()){
            Err(_) => assert!(false),
            Ok(v) => {
                assert_eq!("    stuff()", v[5].line_string);
                assert_eq!(9, v[5].col);
                assert_eq!(2, v[5].line);
                assert_eq!(38, v[5].char_index);
            }
        }
    }

    #[test]
    fn test_unicode_space() {
        let mut lexer = Lexer::new();
        match lexer.lex("def x: ${  \n    def a: 1\n    def b: 2\n}".to_string()){
            Err(_) => assert!(false),
            Ok(v) => {
                assert_eq!(Token::Get, v[3].token);
                assert_eq!(Token::OpenCurly, v[4].token);
            }
        }
    }

    #[test]
    fn test_idents() {
        match_tokens(
            "_i1 i2_a ΔᎠβ_ⅠᏴγδⅡ",
            vec![
                Token::Ident("_i1"),
                Token::Ident("i2_a"),
                Token::Ident("ΔᎠβ_ⅠᏴγδⅡ")
            ]
        )
    }

    #[test]
    fn test_starting_with_number() {
        match_tokens(
            "3_i1 i2_a",
            vec![
                Token::Int(3),
                Token::Ident("_i1"),
                Token::Ident("i2_a"),
            ]
        )
    }

    #[test]
    fn test_comment() {
        let test_string = "if else #valid as is 3 + 3\n2 + 2 #comments #in #comments\n 5 + 5";
        match_tokens(
            test_string,
            vec![
                Token::If,
                Token::Else,
                Token::Int(2),
                Token::Add,
                Token::Int(2),
                Token::Int(5),
                Token::Add,
                Token::Int(5)
            ]
        )
    }

    #[test]
    fn test_strings() {
        match_tokens(
            "def a: \"hello there kind sir\"\ndef b: \"how are you \\\"doing\\\" today?\"",
            vec![
                Token::Def,
                Token::Ident("a"),
                Token::Assign,
                Token::String("hello there kind sir".to_string()),
                Token::Def,
                Token::Ident("b"),
                Token::Assign,
                Token::String("how are you \"doing\" today?".to_string())
            ]
        )
    }

    #[bench]
    fn bench_symbols(b: &mut Bencher) {
        let num_copies = 1000;
        let symbol_string = ":.{}()[],->*/%+-<=<>=>===!==!=&&||!$";
        let mut test_string = String::with_capacity(symbol_string.len() * num_copies);
        for _ in 1..num_copies {
            test_string.push_str(symbol_string);
        }
        b.iter(|| {
            let mut lexer = Lexer::new();
            match lexer.lex(test_string.clone()) {
                Err(_) => assert!(false),
                Ok(_) => ()
            }
        });
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate serde_json;
extern crate reqwest;
use self::iron::prelude::*;
use self::iron::{status, Request, Response, IronResult};

use util::{EnvVar, read_env_var};
use util::telegram::{register, unregister, send};
use util::twitter;
use model::telegram;

use std::io::Read;

pub fn telegram(req: &mut Request) -> IronResult<Response> {
    let mut body = String::new();
    req.body
        .read_to_string(&mut body)
        .map_err(|e| IronError::new(e, (status::BadRequest, "Error reading request")))?;
    let update: telegram::Update = serde_json::from_str(&body).unwrap();
    if let Some(msg) = update.message {
        if let Some(txt) = msg.text {
            let is_private = msg.chat.chat_type == "private";
            let identifier = format!("@{}", read_env_var(&EnvVar::Name));
            let has_identifier = txt.find(&identifier).is_some();
            let txt = strip_identifier(&txt);
            if is_private || has_identifier {
                let id = msg.chat.id;
                match txt.as_str() {
                    "/start" => respond_start(id),
                    "/help" => respond_help(id),
                    "/unsubscribe" => respond_unsubscribe(id),
                    "/delays" => respond_delays(id),
                    _ => {
                        if is_private {
                            respond_unknown(id)
                        } else {
                            Ok(())
                        }
                    }
                }?;
            }
        }
    }
    Ok(Response::with((status::Ok, "ok")))
}

fn strip_identifier(msg: &str) -> String {
    let identifier = format!("@{}", read_env_var(&EnvVar::Name));
    if let Some(pos) = msg.find(&identifier) {
        return msg[..pos].to_owned();
    }
    msg.to_owned()
}

fn respond_start(chat_id: i32) -> IronResult<()> {
    let new_registration = register(chat_id).unwrap();
    let msg = if new_registration {
        let acc = read_env_var(&EnvVar::TwitterAcc);
        let tweet = twitter::user_last_tweet(&acc).unwrap();
        format!("Successfully registered!\nLast delay: {}", tweet)
    } else {
        "This chat has already been registered".to_owned()
    };
    send(chat_id, &msg)?;
    Ok(())
}

fn respond_help(chat_id: i32) -> IronResult<()> {
    send(chat_id,
         "Available commands:\n\
        /start: Subscribes this chat to be notified of SBB delays\n\
        /unsubscribe - Unsubscribes this chat from the delay notifications\n\
        /help: Shows this window")?;
    Ok(())
}

fn respond_unsubscribe(chat_id: i32) -> IronResult<()> {
    let unsubscribed = unregister(chat_id).unwrap();
    let msg = if unsubscribed {
        "Successfully unsubscribed from the delay notifications.\n\
        Use /start to subscribe again"
    } else {
        "This chat was not subscribed to be notified of delays in the first place, silly!\n\
        Use /start if you want to subscribe"
    };
    send(chat_id, msg)?;
    Ok(())
}

fn respond_delays(_: i32) -> IronResult<()> {
    Ok(())
}

fn respond_unknown(chat_id: i32) -> IronResult<()> {
    send(chat_id, "Unknown command. Try using /help")?;
    Ok(())
}
<commit_msg>text change<commit_after>extern crate iron;
extern crate serde_json;
extern crate reqwest;
use self::iron::prelude::*;
use self::iron::{status, Request, Response, IronResult};

use util::{EnvVar, read_env_var};
use util::telegram::{register, unregister, send};
use util::twitter;
use model::telegram;

use std::io::Read;

pub fn telegram(req: &mut Request) -> IronResult<Response> {
    let mut body = String::new();
    req.body
        .read_to_string(&mut body)
        .map_err(|e| IronError::new(e, (status::BadRequest, "Error reading request")))?;
    let update: telegram::Update = serde_json::from_str(&body).unwrap();
    if let Some(msg) = update.message {
        if let Some(txt) = msg.text {
            let is_private = msg.chat.chat_type == "private";
            let identifier = format!("@{}", read_env_var(&EnvVar::Name));
            let has_identifier = txt.find(&identifier).is_some();
            let txt = strip_identifier(&txt);
            if is_private || has_identifier {
                let id = msg.chat.id;
                match txt.as_str() {
                    "/start" => respond_start(id),
                    "/help" => respond_help(id),
                    "/unsubscribe" => respond_unsubscribe(id),
                    "/delays" => respond_delays(id),
                    _ => {
                        if is_private {
                            respond_unknown(id)
                        } else {
                            Ok(())
                        }
                    }
                }?;
            }
        }
    }
    Ok(Response::with((status::Ok, "ok")))
}

fn strip_identifier(msg: &str) -> String {
    let identifier = format!("@{}", read_env_var(&EnvVar::Name));
    if let Some(pos) = msg.find(&identifier) {
        return msg[..pos].to_owned();
    }
    msg.to_owned()
}

fn respond_start(chat_id: i32) -> IronResult<()> {
    let new_registration = register(chat_id).unwrap();
    let msg = if new_registration {
        let acc = read_env_var(&EnvVar::TwitterAcc);
        let tweet = twitter::user_last_tweet(&acc).unwrap();
        format!("Successfully registered!\nLast delay:\n\n{}", tweet)
    } else {
        "This chat has already been registered".to_owned()
    };
    send(chat_id, &msg)?;
    Ok(())
}

fn respond_help(chat_id: i32) -> IronResult<()> {
    send(chat_id,
         "Available commands:\n\
        /start: Subscribes this chat to be notified of SBB delays\n\
        /unsubscribe - Unsubscribes this chat from the delay notifications\n\
        /help: Shows this window")?;
    Ok(())
}

fn respond_unsubscribe(chat_id: i32) -> IronResult<()> {
    let unsubscribed = unregister(chat_id).unwrap();
    let msg = if unsubscribed {
        "Successfully unsubscribed from the delay notifications.\n\
        Use /start to subscribe again"
    } else {
        "This chat was not subscribed to be notified of delays in the first place, silly!\n\
        Use /start if you want to subscribe"
    };
    send(chat_id, msg)?;
    Ok(())
}

fn respond_delays(_: i32) -> IronResult<()> {
    Ok(())
}

fn respond_unknown(chat_id: i32) -> IronResult<()> {
    send(chat_id, "Unknown command. Try using /help")?;
    Ok(())
}
<|endoftext|>


<commit_before>use std::env;
use std::ffi::OsStr;
use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf};
use std::process::Command;

pub use rustc_version::version_meta as version;

use serde_json::Value;
use serde_json;
use walkdir::WalkDir;

use CurrentDirectory;
use errors::*;
use extensions::CommandExt;
use {util, rustc};

fn command() -> Command {
    env::var_os("RUSTC")
        .map(Command::new)
        .unwrap_or_else(|| Command::new("rustc"))
}

/// `rustc --print target-list`
pub fn targets(verbose: bool) -> Result<Vec<String>> {
    command()
        .args(&["--print", "target-list"])
        .run_and_get_stdout(verbose)
        .map(|t| t.lines().map(|l| l.to_owned()).collect())
}

/// `rustc --print sysroot`
pub fn sysroot(verbose: bool) -> Result<Sysroot> {
    command()
        .args(&["--print", "sysroot"])
        .run_and_get_stdout(verbose)
        .map(|l| Sysroot { path: PathBuf::from(l.trim()) })
}
/// Path to Rust source
pub struct Src {
    path: PathBuf,
}

impl Src {
    pub fn from_env() -> Option<Self> {
        env::var_os("XARGO_RUST_SRC").map(|s| Src { path: PathBuf::from(s) })
    }

    pub fn path(&self) -> &Path {
        &self.path
    }
}

/// Path to `rustc`'s sysroot
pub struct Sysroot {
    path: PathBuf,
}

impl Sysroot {
    pub fn path(&self) -> &Path {
        &self.path
    }

    /// Returns the path to Rust source, `$SRC`, where `$SRC/libstd/Carg.toml`
    /// exists
    pub fn src(&self) -> Result<Src> {
        let src = self.path().join("lib/rustlib/src");

        if src.join("rust/src/libstd/Cargo.toml").is_file() {
            return Ok(Src { path: src.join("rust/src") });
        }

        for e in WalkDir::new(src) {
            let e = e.chain_err(|| "couldn't walk the sysroot")?;

            // Looking for $SRC/libstd/Cargo.toml
            if e.file_type().is_file() && e.file_name() == "Cargo.toml" {
                let toml = e.path();

                if let Some(std) = toml.parent() {
                    if let Some(src) = std.parent() {
                        if std.file_name() == Some(OsStr::new("libstd")) {
                            return Ok(Src { path: src.to_owned() });
                        }
                    }
                }
            }
        }

        Err("`rust-src` component not found. Run `rustup component add \
             rust-src`.")?
    }
}

#[derive(Debug)]
pub enum Target {
    Builtin { triple: String },
    Custom { json: PathBuf, triple: String },
}

impl Target {
    pub fn new(triple: &str,
               cd: &CurrentDirectory,
               verbose: bool)
               -> Result<Option<Target>> {
        let triple = triple.to_owned();

        if rustc::targets(verbose)?.iter().any(|t| t == &triple) {
            Ok(Some(Target::Builtin { triple: triple }))
        } else {
            let mut json = cd.path().join(&triple);
            json.set_extension("json");

            if json.exists() {
                return Ok(Some(Target::Custom {
                    json: json,
                    triple: triple,
                }));
            } else {
                if let Some(p) = env::var_os("RUST_TARGET_PATH") {
                    let mut json = PathBuf::from(p);
                    json.push(&triple);
                    json.set_extension("json");

                    if json.exists() {
                        return Ok(Some(Target::Custom {
                            json: json,
                            triple: triple,
                        }));
                    }
                }
            }

            Ok(None)
        }
    }

    pub fn triple(&self) -> &str {
        match *self {
            Target::Builtin { ref triple } => triple,
            Target::Custom { ref triple, .. } => triple,
        }
    }

    pub fn hash<H>(&self, hasher: &mut H) -> Result<()>
        where H: Hasher
    {
        if let Target::Custom { ref json, .. } = *self {
            // Here we roundtrip to/from JSON to get the same hash when some
            // fields of the JSON file has been shuffled around
            serde_json::from_str::<Value>(&util::read(json)?)
                .chain_err(|| format!("{} is not valid JSON", json.display()))?
                .to_string()
                .hash(hasher);
        }

        Ok(())
    }
}
<commit_msg>improve error message when the `rust-src` component is missing<commit_after>use std::env;
use std::ffi::OsStr;
use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf};
use std::process::Command;

pub use rustc_version::version_meta as version;

use serde_json::Value;
use serde_json;
use walkdir::WalkDir;

use CurrentDirectory;
use errors::*;
use extensions::CommandExt;
use {util, rustc};

fn command() -> Command {
    env::var_os("RUSTC")
        .map(Command::new)
        .unwrap_or_else(|| Command::new("rustc"))
}

/// `rustc --print target-list`
pub fn targets(verbose: bool) -> Result<Vec<String>> {
    command()
        .args(&["--print", "target-list"])
        .run_and_get_stdout(verbose)
        .map(|t| t.lines().map(|l| l.to_owned()).collect())
}

/// `rustc --print sysroot`
pub fn sysroot(verbose: bool) -> Result<Sysroot> {
    command()
        .args(&["--print", "sysroot"])
        .run_and_get_stdout(verbose)
        .map(|l| Sysroot { path: PathBuf::from(l.trim()) })
}
/// Path to Rust source
pub struct Src {
    path: PathBuf,
}

impl Src {
    pub fn from_env() -> Option<Self> {
        env::var_os("XARGO_RUST_SRC").map(|s| Src { path: PathBuf::from(s) })
    }

    pub fn path(&self) -> &Path {
        &self.path
    }
}

/// Path to `rustc`'s sysroot
pub struct Sysroot {
    path: PathBuf,
}

impl Sysroot {
    pub fn path(&self) -> &Path {
        &self.path
    }

    /// Returns the path to Rust source, `$SRC`, where `$SRC/libstd/Carg.toml`
    /// exists
    pub fn src(&self) -> Result<Src> {
        let src = self.path().join("lib/rustlib/src");

        if src.join("rust/src/libstd/Cargo.toml").is_file() {
            return Ok(Src { path: src.join("rust/src") });
        }

        if src.exists() {
            for e in WalkDir::new(src) {
                let e = e.chain_err(|| "couldn't walk the sysroot")?;

                // Looking for $SRC/libstd/Cargo.toml
                if e.file_type().is_file() && e.file_name() == "Cargo.toml" {
                    let toml = e.path();

                    if let Some(std) = toml.parent() {
                        if let Some(src) = std.parent() {
                            if std.file_name() == Some(OsStr::new("libstd")) {
                                return Ok(Src { path: src.to_owned() });
                            }
                        }
                    }
                }
            }
        }

        Err("`rust-src` component not found. Run `rustup component add \
             rust-src`.")?
    }
}

#[derive(Debug)]
pub enum Target {
    Builtin { triple: String },
    Custom { json: PathBuf, triple: String },
}

impl Target {
    pub fn new(triple: &str,
               cd: &CurrentDirectory,
               verbose: bool)
               -> Result<Option<Target>> {
        let triple = triple.to_owned();

        if rustc::targets(verbose)?.iter().any(|t| t == &triple) {
            Ok(Some(Target::Builtin { triple: triple }))
        } else {
            let mut json = cd.path().join(&triple);
            json.set_extension("json");

            if json.exists() {
                return Ok(Some(Target::Custom {
                    json: json,
                    triple: triple,
                }));
            } else {
                if let Some(p) = env::var_os("RUST_TARGET_PATH") {
                    let mut json = PathBuf::from(p);
                    json.push(&triple);
                    json.set_extension("json");

                    if json.exists() {
                        return Ok(Some(Target::Custom {
                            json: json,
                            triple: triple,
                        }));
                    }
                }
            }

            Ok(None)
        }
    }

    pub fn triple(&self) -> &str {
        match *self {
            Target::Builtin { ref triple } => triple,
            Target::Custom { ref triple, .. } => triple,
        }
    }

    pub fn hash<H>(&self, hasher: &mut H) -> Result<()>
        where H: Hasher
    {
        if let Target::Custom { ref json, .. } = *self {
            // Here we roundtrip to/from JSON to get the same hash when some
            // fields of the JSON file has been shuffled around
            serde_json::from_str::<Value>(&util::read(json)?)
                .chain_err(|| format!("{} is not valid JSON", json.display()))?
                .to_string()
                .hash(hasher);
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>use crate::common::{SearchBox, Text};
use crate::fuzzy::Candidate;

// TODO: Review StateUpdates, do I need all of them?
#[derive(Debug, Clone)]
pub enum StateUpdate {
    Query,
    Matches,
    Selection,
    All,
}

impl Default for StateUpdate {
    fn default() -> Self {
        Self::All
    }
}

#[derive(Debug, Clone, Default)]
pub struct State {
    search: Option<SearchBox>,
    matches: Vec<Candidate>,
    pool_len: usize,
    selection_idx: usize,
    last_update: StateUpdate,
}

impl State {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn set_search(&mut self, search: SearchBox) {
        self.search = Some(search);
        self.last_update = StateUpdate::Query;
    }

    pub fn query(&self) -> String {
        match &self.search {
            Some(sb) => sb.as_string(),
            None => "".into(),
        }
    }

    pub fn cursor_until_end(&self) -> usize {
        match &self.search {
            Some(sb) => sb.cursor_until_end(),
            None => 0,
        }
    }

    pub fn set_matches(&mut self, matches: (Vec<Candidate>, usize)) {
        self.matches = matches.0;
        self.pool_len = matches.1;
        self.selection_idx = 0;
        self.last_update = StateUpdate::Matches;
    }

    pub fn matches(&self) -> &Vec<Candidate> {
        &self.matches
    }

    pub fn pool_len(&self) -> usize {
        self.pool_len
    }

    pub fn last_update(&self) -> &StateUpdate {
        &self.last_update
    }

    pub fn select_up(&mut self) {
        if self.selection_idx == 0 {
            self.selection_idx = self.max_selection();
        } else {
            self.selection_idx -= 1;
        }
        self.last_update = StateUpdate::Selection;
    }

    pub fn select_down(&mut self) {
        if self.selection_idx == self.max_selection() {
            self.selection_idx = 0;
        } else {
            self.selection_idx += 1;
        }
        self.last_update = StateUpdate::Selection;
    }

    pub fn selection_idx(&self) -> usize {
        self.selection_idx
    }

    pub fn selection(&self) -> Option<Text> {
        match self.matches.iter().nth(self.selection_idx) {
            Some(candidate) => Some(candidate.text.clone()),
            None => None,
        }
    }

    fn max_selection(&self) -> usize {
        let len = self.matches.len();

        if len == 0 {
            0
        } else {
            len - 1
        }
    }
}
<commit_msg>Keep list selection between searches<commit_after>use crate::common::{SearchBox, Text};
use crate::fuzzy::Candidate;

// TODO: Review StateUpdates, do I need all of them?
#[derive(Debug, Clone)]
pub enum StateUpdate {
    Query,
    Matches,
    Selection,
    All,
}

impl Default for StateUpdate {
    fn default() -> Self {
        Self::All
    }
}

#[derive(Debug, Clone, Default)]
pub struct State {
    search: Option<SearchBox>,
    matches: Vec<Candidate>,
    pool_len: usize,
    selection_idx: usize,
    last_update: StateUpdate,
}

impl State {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn set_search(&mut self, search: SearchBox) {
        self.search = Some(search);
        self.last_update = StateUpdate::Query;
    }

    pub fn query(&self) -> String {
        match &self.search {
            Some(sb) => sb.as_string(),
            None => "".into(),
        }
    }

    pub fn cursor_until_end(&self) -> usize {
        match &self.search {
            Some(sb) => sb.cursor_until_end(),
            None => 0,
        }
    }

    pub fn set_matches(&mut self, matches: (Vec<Candidate>, usize)) {
        self.matches = matches.0;
        self.pool_len = matches.1;

        if self.selection_idx >= self.max_selection() {
            self.selection_idx = self.max_selection();
        }

        self.last_update = StateUpdate::Matches;
    }

    pub fn matches(&self) -> &Vec<Candidate> {
        &self.matches
    }

    pub fn pool_len(&self) -> usize {
        self.pool_len
    }

    pub fn last_update(&self) -> &StateUpdate {
        &self.last_update
    }

    pub fn select_up(&mut self) {
        if self.selection_idx == 0 {
            self.selection_idx = self.max_selection();
        } else {
            self.selection_idx -= 1;
        }
        self.last_update = StateUpdate::Selection;
    }

    pub fn select_down(&mut self) {
        if self.selection_idx == self.max_selection() {
            self.selection_idx = 0;
        } else {
            self.selection_idx += 1;
        }
        self.last_update = StateUpdate::Selection;
    }

    pub fn selection_idx(&self) -> usize {
        self.selection_idx
    }

    pub fn selection(&self) -> Option<Text> {
        match self.matches.iter().nth(self.selection_idx) {
            Some(candidate) => Some(candidate.text.clone()),
            None => None,
        }
    }

    fn max_selection(&self) -> usize {
        let len = self.matches.len();

        if len == 0 {
            0
        } else {
            len - 1
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;

const ROWS: i8 = 9;
const COLS: i8 = 12;
const TILES: i8 = 108;
const PLAYERS: i8 = 4;

#[derive(RustcDecodable, RustcEncodable)]
pub struct Game {
  players: Vec<Player>,
  board: Board
}

#[derive(RustcDecodable, RustcEncodable)]
struct Player {
  money: i32,
  shares: PlayerShares,
  tiles: Vec<Tile>
}

#[derive(RustcDecodable, RustcEncodable)]
struct PlayerShares {
  luxor: i8,
  tower: i8,
  american: i8,
  festival: i8,
  worldwide: i8,
  continental: i8,
  imperial: i8
}

#[derive(RustcDecodable, RustcEncodable, Clone, Debug)]
struct Tile { row: i8, col: i8 }

#[derive(RustcDecodable, RustcEncodable)]
struct Board {
  slots: Vec<Vec<Slot>>
}

#[derive(RustcDecodable, RustcEncodable)]
struct Slot {
  hotel: Option<Hotel>
}

#[derive(RustcDecodable, RustcEncodable)]
enum Hotel { Luxor, Tower, American, Festival, Worldwide, Continental, Imperial }

fn empty_shares() -> PlayerShares {
  PlayerShares { luxor: 0, tower: 0, american: 0, festival: 0, worldwide: 0, continental: 0, imperial: 0 }
}

fn new_player(tiles: Vec<Tile>) -> Player {
  Player { money: 6000, shares: empty_shares(), tiles: tiles }
}

fn choose_tiles(tiles: Vec<Tile>, count: usize) -> Vec<Tile> {
  let mut remaining_tiles = tiles.clone();
  let mut random_tiles = Vec::new();
  for _ in 0..count {
    let random_index = (rand::random::<i8>() as usize) % remaining_tiles.len();
    random_tiles.push(remaining_tiles.remove(random_index));
  }
  random_tiles
}

pub fn initial_state() -> Game {
  let slots = (0..COLS)
    .map(|_| (0..ROWS).map(|_| Slot { hotel: None } ).collect() )
    .collect();
  let tiles = (0..TILES).map(|i| Tile { row: i / COLS, col: i % ROWS }).collect();
  let mut chosen_tiles = choose_tiles(tiles, 6*PLAYERS as usize);
  let tiles1 = chosen_tiles.split_off(18);
  let tiles2 = chosen_tiles.split_off(12);
  let tiles3 = chosen_tiles.split_off(6);
  let tiles4 = chosen_tiles;
  let players = vec![
    new_player(tiles1),
    new_player(tiles2),
    new_player(tiles3),
    new_player(tiles4)];
  Game { board: Board { slots: slots }, players: players }
}
<commit_msg>Change from 2 spaces to 4<commit_after>extern crate rand;

const ROWS: i8 = 9;
const COLS: i8 = 12;
const TILES: i8 = 108;
const PLAYERS: i8 = 4;

#[derive(RustcDecodable, RustcEncodable)]
pub struct Game {
    players: Vec<Player>,
    board: Board
}

#[derive(RustcDecodable, RustcEncodable)]
struct Player {
    money: i32,
    shares: PlayerShares,
    tiles: Vec<Tile>
}

#[derive(RustcDecodable, RustcEncodable)]
struct PlayerShares {
    luxor: i8,
    tower: i8,
    american: i8,
    festival: i8,
    worldwide: i8,
    continental: i8,
    imperial: i8
}

#[derive(RustcDecodable, RustcEncodable, Clone, Debug)]
struct Tile { row: i8, col: i8 }

#[derive(RustcDecodable, RustcEncodable)]
struct Board {
    slots: Vec<Vec<Slot>>
}

#[derive(RustcDecodable, RustcEncodable)]
struct Slot {
    hotel: Option<Hotel>
}

#[derive(RustcDecodable, RustcEncodable)]
enum Hotel { Luxor, Tower, American, Festival, Worldwide, Continental, Imperial }

fn empty_shares() -> PlayerShares {
    PlayerShares { luxor: 0, tower: 0, american: 0, festival: 0, worldwide: 0, continental: 0, imperial: 0 }
}

fn new_player(tiles: Vec<Tile>) -> Player {
    Player { money: 6000, shares: empty_shares(), tiles: tiles }
}

fn choose_tiles(tiles: Vec<Tile>, count: usize) -> Vec<Tile> {
    let mut remaining_tiles = tiles.clone();
    let mut random_tiles = Vec::new();
    for _ in 0..count {
        let random_index = (rand::random::<i8>() as usize) % remaining_tiles.len();
        random_tiles.push(remaining_tiles.remove(random_index));
    }
    random_tiles
}

pub fn initial_state() -> Game {
    let slots = (0..COLS)
        .map(|_| (0..ROWS).map(|_| Slot { hotel: None } ).collect() )
        .collect();
    let tiles = (0..TILES).map(|i| Tile { row: i / COLS, col: i % ROWS }).collect();
    let mut chosen_tiles = choose_tiles(tiles, 6*PLAYERS as usize);
    let tiles1 = chosen_tiles.split_off(18);
    let tiles2 = chosen_tiles.split_off(12);
    let tiles3 = chosen_tiles.split_off(6);
    let tiles4 = chosen_tiles;
    let players = vec![
        new_player(tiles1),
        new_player(tiles2),
        new_player(tiles3),
        new_player(tiles4)];
    Game { board: Board { slots: slots }, players: players }
}
<|endoftext|>


<commit_before>//! Data structures that can be shared between the server and the client.
//!
//! All these structures should be serializable, so that they can be
//! transferred from the server to the client over the network.
use std::convert::Into;
use std::fmt;
use std::collections::HashMap;

use common::Vec2;
use shapes::Shape;

/// A unit identifier.
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Copy, Clone, Hash)]
pub struct UnitId(pub u32);

impl Into<UnitId> for u32 {
    fn into(self) -> UnitId {
        UnitId(self)
    }
}

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

/// A client/player identifier.
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Copy, Clone)]
pub struct ClientId(pub u32);

impl Into<ClientId> for u32 {
    fn into(self) -> ClientId {
        ClientId(self)
    }
}

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

pub const UNIT_SIZE: f64 = 50.0;

/// The state of a single unit
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct Unit {
    /// The unit identifier
    pub id: UnitId,

    /// X/Y position in the world in m
    pub position: Vec2,

    /// Angle of the unit in radiant
    pub angle: f64,

    /// Direction and speed of the movement. The angle of the movement may be different then the
    /// angle of the unit. The unit is m per milli second.
    pub speed_vector: Vec2,

    /// Health of the unit
    pub health: u64,
}

impl Unit {
    pub fn new<T: Into<UnitId>>(id: T, position: Vec2) -> Unit {
        println!("Create unit at {:?}", position);
        Unit {
            id: id.into(),
            position: position,
            angle: 0.0f64,
            speed_vector: Vec2::new(0.0, 0.0),
            health: 100_000,
        }
    }

    pub fn update(&mut self, dt_ms: f64) {
        self.position += self.speed_vector * dt_ms;
    }

    pub fn shoot(&self, size: f64, speed: f64) -> Bullet {
        let position = Vec2::new(
            self.position.x + self.angle.cos() * size,
            self.position.y + self.angle.sin() * size,
        );
        let speed = Vec2::new(
            self.angle.cos() * speed,
            self.angle.sin() * speed,
        );
        Bullet::new(position, speed)
    }
}

#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct Bullet {
    pub position: Vec2,
    pub speed_vector: Vec2,
}

impl Bullet {
    pub fn new(position: Vec2, speed: Vec2) -> Bullet {
        Bullet {
            position: position,
            speed_vector: speed,
        }
    }

    pub fn update(&mut self, dt_ms: f64) {
        self.position += self.speed_vector * dt_ms;
    }
}

/// A player has an ID and consists of 0..N `Unit`s
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct Player {
    pub id: ClientId,
    pub units: Vec<Unit>,
}

impl Player {
    pub fn new<T: Into<ClientId>>(id: T) -> Player {
        Player {
            id: id.into(),
            units: vec![],
        }
    }
}

/// Data related to the current game.
///
/// This needs to be transferred to the client every time the game state
/// changes.
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct GameState {
    /// List of players
    pub players: Vec<Player>,
    pub bullets: Vec<Bullet>,
}

impl GameState {
    pub fn new() -> GameState {
        GameState{
            players: vec![],
            bullets: vec![],
        }
    }

    pub fn update_targets(&mut self, unit_targets: &HashMap<UnitId, Vec2>) {
        for player in self.players.iter_mut() {
            for unit in player.units.iter_mut() {
                if let Some(target) = unit_targets.get(&unit.id) {
                    let speed = 0.0001;
                    unit.speed_vector = (target - unit.position) * speed;
                } else {
                    unit.speed_vector = Vec2::new(0.0, 0.0);
                }
            }
        }
    }

    pub fn update(&mut self, world: &WorldState, dt: f64) {

        for bullet in self.bullets.iter_mut() {
            bullet.update(dt);
        }

        // waiting for non-lexical lifetimes...
        {
            let bullets = &mut self.bullets;
            let players = &mut self.players;
            bullets.retain(|bullet|{
                // still inside world?
                if bullet.position[0] > world.x || bullet.position[1] > world.y ||
                    bullet.position[0] < 0.0 || bullet.position[1] < 0.0 {
                        return false;
                    }

                for player in players.iter_mut() {
                    for unit in player.units.iter_mut() {
                        if unit.health > 0 && unit.is_hit(UNIT_SIZE, bullet.position) {
                            if unit.health > 10000 {
                                unit.health -= 10000;
                            } else {
                                unit.health = 0;
                            }
                            println!("hit: {}", unit.health);
                            return false;
                        }
                    }
                }
                true
            });
        }

        // remove all units where health == 0
        for player in self.players.iter_mut() {
            player.units.retain(|unit| unit.health > 0);
            for unit in player.units.iter_mut() {
                unit.update(dt);
            }
        }
    }

    pub fn shoot(&mut self, id: UnitId) {
        for player in self.players.iter_mut() {
            for unit in player.units.iter() {
                if unit.id == id {
                    let bullet = unit.shoot(UNIT_SIZE, 0.1);
                    self.bullets.push(bullet);
                }
            }
        }
    }
}

/// Data related to the entire world, like width and height.
///
/// This needs to be transferred to the client only once, on connecting.
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct WorldState {
    /// Width of the world in m
    pub x: f64,
    /// Height of the world in m
    pub y: f64,
}

impl WorldState {
    pub fn new(x: f64, y: f64) -> WorldState {
        WorldState {
            x: x,
            y: y,
        }
    }
}

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

    #[test]
    fn test_unit_update_stationary() {
        //! The position of a unit should not change on update when no speed
        //! vector is defined.
        let pos = Vec2::new(20.0, 10.0);
        let mut unit = Unit::new(1, pos);
        assert_eq!(unit.position, pos);
        unit.update(10.0);
        assert_eq!(unit.position, pos);
        unit.update(1000.0);
        assert_eq!(unit.position, pos);
    }

    #[test]
    fn test_unit_update_moving() {
        //! The position of a unit should not change on update when no speed
        //! vector is defined.
        let mut unit = Unit::new(1, Vec2::new(20.0, 10.0));
        unit.speed_vector = Vec2::new(1.0, 2.0);
        assert_eq!(unit.position, Vec2::new(20.0, 10.0));
        unit.update(1.0);
        assert_eq!(unit.position, Vec2::new(21.0, 12.0));
        unit.update(100.0);
        assert_eq!(unit.position, Vec2::new(121.0, 212.0));
    }

    #[test]
    fn test_bullet_update_stationary() {
        //! The position of a bullet should not change on update when a zero
        //! speed vector is defined.
        let pos = Vec2::new(20.0, 10.0);
        let speed = Vec2::new(0.0, 0.0);
        let mut bullet = Bullet::new(pos, speed);
        assert_eq!(bullet.position, pos);
        bullet.update(10.0);
        assert_eq!(bullet.position, pos);
        bullet.update(1000.0);
        assert_eq!(bullet.position, pos);
    }

    #[test]
    fn test_bullet_update_moving() {
        //! The position of a bullet should not change on update when no speed
        //! vector is defined.
        let mut bullet = Bullet::new(Vec2::new(20.0, 10.0), Vec2::new(1.0, 2.0));
        assert_eq!(bullet.position, Vec2::new(20.0, 10.0));
        bullet.update(1.0);
        assert_eq!(bullet.position, Vec2::new(21.0, 12.0));
        bullet.update(100.0);
        assert_eq!(bullet.position, Vec2::new(121.0, 212.0));
    }
}
<commit_msg>Use collision avoidance<commit_after>//! Data structures that can be shared between the server and the client.
//!
//! All these structures should be serializable, so that they can be
//! transferred from the server to the client over the network.
use std::convert::Into;
use std::fmt;
use std::collections::HashMap;

use common::Vec2;
use shapes::Shape;

/// A unit identifier.
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Copy, Clone, Hash)]
pub struct UnitId(pub u32);

impl Into<UnitId> for u32 {
    fn into(self) -> UnitId {
        UnitId(self)
    }
}

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

/// A client/player identifier.
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Copy, Clone)]
pub struct ClientId(pub u32);

impl Into<ClientId> for u32 {
    fn into(self) -> ClientId {
        ClientId(self)
    }
}

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

pub const UNIT_SIZE: f64 = 50.0;

/// The state of a single unit
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct Unit {
    /// The unit identifier
    pub id: UnitId,

    /// X/Y position in the world in m
    pub position: Vec2,

    /// Angle of the unit in radiant
    pub angle: f64,

    /// Direction and speed of the movement. The angle of the movement may be different then the
    /// angle of the unit. The unit is m per milli second.
    pub speed_vector: Vec2,

    /// Health of the unit
    pub health: u64,
}

impl Unit {
    pub fn new<T: Into<UnitId>>(id: T, position: Vec2) -> Unit {
        println!("Create unit at {:?}", position);
        Unit {
            id: id.into(),
            position: position,
            angle: 0.0f64,
            speed_vector: Vec2::new(0.0, 0.0),
            health: 100_000,
        }
    }

    pub fn update(&mut self, dt_ms: f64) {
        self.position += self.speed_vector * dt_ms;
    }

    pub fn shoot(&self, size: f64, speed: f64) -> Bullet {
        let position = Vec2::new(
            self.position.x + self.angle.cos() * size,
            self.position.y + self.angle.sin() * size,
        );
        let speed = Vec2::new(
            self.angle.cos() * speed,
            self.angle.sin() * speed,
        );
        Bullet::new(position, speed)
    }
}

#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct Bullet {
    pub position: Vec2,
    pub speed_vector: Vec2,
}

impl Bullet {
    pub fn new(position: Vec2, speed: Vec2) -> Bullet {
        Bullet {
            position: position,
            speed_vector: speed,
        }
    }

    pub fn update(&mut self, dt_ms: f64) {
        self.position += self.speed_vector * dt_ms;
    }
}

/// A player has an ID and consists of 0..N `Unit`s
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct Player {
    pub id: ClientId,
    pub units: Vec<Unit>,
}

impl Player {
    pub fn new<T: Into<ClientId>>(id: T) -> Player {
        Player {
            id: id.into(),
            units: vec![],
        }
    }
}

/// Data related to the current game.
///
/// This needs to be transferred to the client every time the game state
/// changes.
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct GameState {
    /// List of players
    pub players: Vec<Player>,
    pub bullets: Vec<Bullet>,
}

impl GameState {
    pub fn new() -> GameState {
        GameState{
            players: vec![],
            bullets: vec![],
        }
    }

    pub fn update_targets(&mut self, unit_targets: &HashMap<UnitId, Vec2>) {
        for player in self.players.iter_mut() {
            for unit in player.units.iter_mut() {
                if let Some(target) = unit_targets.get(&unit.id) {
                    let speed = 0.0001;
                    unit.speed_vector = (target - unit.position) * speed;
                } else {
                    unit.speed_vector = Vec2::new(0.0, 0.0);
                }
            }
        }

        // Check for collisions between all units
        for p1 in 0..self.players.len() {
            for u1 in 0..self.players[p1].units.len() {

                for u2 in u1+1..self.players[p1].units.len() {
                    if self.players[p1].units[u1].collision_detect(&self.players[p1].units[u2], UNIT_SIZE) {
                        {
                            let (s1, s2) = {
                                let unit1 = &self.players[p1].units[u1];
                                let unit2 = &self.players[p1].units[u2];
                                unit1.collision_avoidance(unit2)
                            };
                            self.players[p1].units[u1].speed_vector = s1;
                            self.players[p1].units[u2].speed_vector = s2;
                        }
                    }
                }

                for p2 in p1+1..self.players.len() {
                    for u2 in 0..self.players[p2].units.len() {
                        if self.players[p1].units[u1].collision_detect(&self.players[p2].units[u2], UNIT_SIZE) {
                            let (s1, s2) = {
                                let unit1 = &self.players[p1].units[u1];
                                let unit2 = &self.players[p2].units[u2];
                                unit1.collision_avoidance(unit2)
                            };
                            self.players[p1].units[u1].speed_vector = s1;
                            self.players[p2].units[u2].speed_vector = s2;
                        }
                    }
                }
            }
        }
    }

    pub fn update(&mut self, world: &WorldState, dt: f64) {

        for bullet in self.bullets.iter_mut() {
            bullet.update(dt);
        }

        // waiting for non-lexical lifetimes...
        {
            let bullets = &mut self.bullets;
            let players = &mut self.players;
            bullets.retain(|bullet|{
                // still inside world?
                if bullet.position[0] > world.x || bullet.position[1] > world.y ||
                    bullet.position[0] < 0.0 || bullet.position[1] < 0.0 {
                        return false;
                    }

                for player in players.iter_mut() {
                    for unit in player.units.iter_mut() {
                        if unit.health > 0 && unit.is_hit(UNIT_SIZE, bullet.position) {
                            if unit.health > 10000 {
                                unit.health -= 10000;
                            } else {
                                unit.health = 0;
                            }
                            println!("hit: {}", unit.health);
                            return false;
                        }
                    }
                }
                true
            });
        }

        // remove all units where health == 0
        for player in self.players.iter_mut() {
            player.units.retain(|unit| unit.health > 0);
            for unit in player.units.iter_mut() {
                unit.update(dt);
            }
        }
    }

    pub fn shoot(&mut self, id: UnitId) {
        for player in self.players.iter_mut() {
            for unit in player.units.iter() {
                if unit.id == id {
                    let bullet = unit.shoot(UNIT_SIZE, 0.1);
                    self.bullets.push(bullet);
                }
            }
        }
    }
}

/// Data related to the entire world, like width and height.
///
/// This needs to be transferred to the client only once, on connecting.
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct WorldState {
    /// Width of the world in m
    pub x: f64,
    /// Height of the world in m
    pub y: f64,
}

impl WorldState {
    pub fn new(x: f64, y: f64) -> WorldState {
        WorldState {
            x: x,
            y: y,
        }
    }
}

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

    #[test]
    fn test_unit_update_stationary() {
        //! The position of a unit should not change on update when no speed
        //! vector is defined.
        let pos = Vec2::new(20.0, 10.0);
        let mut unit = Unit::new(1, pos);
        assert_eq!(unit.position, pos);
        unit.update(10.0);
        assert_eq!(unit.position, pos);
        unit.update(1000.0);
        assert_eq!(unit.position, pos);
    }

    #[test]
    fn test_unit_update_moving() {
        //! The position of a unit should not change on update when no speed
        //! vector is defined.
        let mut unit = Unit::new(1, Vec2::new(20.0, 10.0));
        unit.speed_vector = Vec2::new(1.0, 2.0);
        assert_eq!(unit.position, Vec2::new(20.0, 10.0));
        unit.update(1.0);
        assert_eq!(unit.position, Vec2::new(21.0, 12.0));
        unit.update(100.0);
        assert_eq!(unit.position, Vec2::new(121.0, 212.0));
    }

    #[test]
    fn test_bullet_update_stationary() {
        //! The position of a bullet should not change on update when a zero
        //! speed vector is defined.
        let pos = Vec2::new(20.0, 10.0);
        let speed = Vec2::new(0.0, 0.0);
        let mut bullet = Bullet::new(pos, speed);
        assert_eq!(bullet.position, pos);
        bullet.update(10.0);
        assert_eq!(bullet.position, pos);
        bullet.update(1000.0);
        assert_eq!(bullet.position, pos);
    }

    #[test]
    fn test_bullet_update_moving() {
        //! The position of a bullet should not change on update when no speed
        //! vector is defined.
        let mut bullet = Bullet::new(Vec2::new(20.0, 10.0), Vec2::new(1.0, 2.0));
        assert_eq!(bullet.position, Vec2::new(20.0, 10.0));
        bullet.update(1.0);
        assert_eq!(bullet.position, Vec2::new(21.0, 12.0));
        bullet.update(100.0);
        assert_eq!(bullet.position, Vec2::new(121.0, 212.0));
    }
}
<|endoftext|>


<commit_before>use std::net::{Ipv4Addr, Ipv6Addr, IpAddr};
use {Ipv4Network, Ipv6Network, IpNetwork};
use treebitmap::{self, IpLookupTable, IpLookupTableOps};

pub struct Table<T> {
    ipv4: IpLookupTable<Ipv4Addr, T>,
    ipv6: IpLookupTable<Ipv6Addr, T>,
}

impl<T> Table<T> {
    pub fn new() -> Self {
        Self {
            ipv4: IpLookupTable::new(),
            ipv6: IpLookupTable::new(),
        }
    }

    pub fn with_capacity(ipv4_size: usize, ipv6_size: usize) -> Self {
        Self {
            ipv4: IpLookupTable::with_capacity(ipv4_size),
            ipv6: IpLookupTable::with_capacity(ipv6_size),
        }
    }

    /// Insert a value for the IpNetwork. If prefix existed previously, the old value is returned.
    ///
    /// # Example
    ///
    /// ```
    /// use ip_network::table::Table;
    /// use ip_network::Ipv6Network;
    /// use std::net::Ipv6Addr;
    ///
    /// let mut table: Table<&str> = Table::new();
    /// let network = Ipv6Network::from(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0), 64).unwrap();
    ///
    /// assert_eq!(table.insert(network.clone(), "foo"), None);
    /// // Insert duplicate
    /// assert_eq!(table.insert(network.clone(), "bar"), Some("foo"));
    /// // Value is replaced
    /// assert_eq!(table.insert(network, "null"), Some("bar"));
    /// ```
    pub fn insert<N: Into<IpNetwork>>(&mut self, network: N, data: T) -> Option<T> {
        match network.into() {
            IpNetwork::V4(ipv4_network) => {
                self.ipv4.insert(ipv4_network.network_address, ipv4_network.netmask as u32, data)
            },
            IpNetwork::V6(ipv6_network) => {
                self.ipv6.insert(ipv6_network.network_address, ipv6_network.netmask as u32, data)
            },
        }
    }

    /// Insert a value for the IpNetwork. If prefix existed previously, the old value is returned.
    ///
    /// # Example
    ///
    /// ```
    /// use ip_network::table::Table;
    /// use ip_network::Ipv6Network;
    /// use std::net::Ipv6Addr;
    ///
    /// let mut table: Table<&str> = Table::new();
    /// let network = Ipv6Network::from(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0), 64).unwrap();
    ///
    /// assert_eq!(table.insert(network.clone(), "foo"), None);
    /// // Remove network from table
    /// assert_eq!(table.remove(network.clone()), Some("foo"));
    /// // Network is removed
    /// assert_eq!(table.exact_match(network), None);
    /// ```
    pub fn remove<N: Into<IpNetwork>>(&mut self, network: N) -> Option<T> {
        match network.into() {
            IpNetwork::V4(ipv4_network) => {
                self.ipv4.remove(ipv4_network.network_address, ipv4_network.netmask as u32)
            },
            IpNetwork::V6(ipv6_network) => {
                self.ipv6.remove(ipv6_network.network_address, ipv6_network.netmask as u32)
            },
        }
    }

    pub fn exact_match<N: Into<IpNetwork>>(&self, network: N) -> Option<&T> {
        match network.into() {
            IpNetwork::V4(ipv4_network) => {
                self.ipv4.exact_match(ipv4_network.network_address, ipv4_network.netmask as u32)
            },
            IpNetwork::V6(ipv6_network) => {
                self.ipv6.exact_match(ipv6_network.network_address, ipv6_network.netmask as u32)
            },
        }
    }

    pub fn longest_match<A: Into<IpAddr>>(&self, ip: A) -> Option<(IpNetwork, &T)> {
        match ip.into() {
            IpAddr::V4(ipv4) => self.longest_match_ipv4(ipv4),
            IpAddr::V6(ipv6) => self.longest_match_ipv6(ipv6),
        }
    }

    #[inline]
    pub fn longest_match_ipv4(&self, ip: Ipv4Addr) -> Option<(IpNetwork, &T)> {
        match self.ipv4.longest_match(ip) {
            Some((addr, mask, data)) => Some((
                IpNetwork::V4(Ipv4Network::from(addr, mask as u8).unwrap()),
                data
            )),
            None => None,
        }
    }

    #[inline]
    pub fn longest_match_ipv6(&self, ip: Ipv6Addr) -> Option<(IpNetwork, &T)> {
        match self.ipv6.longest_match(ip) {
            Some((addr, mask, data)) => Some((
                IpNetwork::V6(Ipv6Network::from(addr, mask as u8).unwrap()),
                data
            )),
            None => None,
        }
    }

    pub fn iter(&self) -> Iter<T> {
        Iter {
            ipv4: self.ipv4.iter(),
            ipv6: self.ipv6.iter(),
        }
    }
}

pub struct Iter<'a, T: 'a> {
    ipv4: treebitmap::Iter<'a, Ipv4Addr, T>,
    ipv6: treebitmap::Iter<'a, Ipv6Addr, T>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = (IpNetwork, &'a T);

    fn next(&mut self) -> Option<Self::Item> {
        match self.ipv4.next() {
            Some((addr, mask, data)) => Some((
                IpNetwork::V4(Ipv4Network::from(addr, mask as u8).unwrap()),
                data
            )),
            None => {
                match self.ipv6.next() {
                    Some((addr, mask, data)) => Some((
                        IpNetwork::V6(Ipv6Network::from(addr, mask as u8).unwrap()),
                        data
                    )),
                    None => None,
                }
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use table::Table;
    use std::net::{Ipv4Addr, Ipv6Addr};
    use {Ipv4Network, Ipv6Network};

    #[test]
    fn test() {
        let mut table: Table<u32> = Table::new();
        table.insert(Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 16).unwrap(), 1);
        table.insert(Ipv6Network::from(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 128).unwrap(), 1);
    }
}

<commit_msg>`Table::longest_match_ipv4` and `Table::longest_match_ipv6` returns Ipv4Network or Ipv6Network<commit_after>use std::net::{Ipv4Addr, Ipv6Addr, IpAddr};
use {Ipv4Network, Ipv6Network, IpNetwork};
use treebitmap::{self, IpLookupTable, IpLookupTableOps};

pub struct Table<T> {
    ipv4: IpLookupTable<Ipv4Addr, T>,
    ipv6: IpLookupTable<Ipv6Addr, T>,
}

impl<T> Table<T> {
    pub fn new() -> Self {
        Self {
            ipv4: IpLookupTable::new(),
            ipv6: IpLookupTable::new(),
        }
    }

    pub fn with_capacity(ipv4_size: usize, ipv6_size: usize) -> Self {
        Self {
            ipv4: IpLookupTable::with_capacity(ipv4_size),
            ipv6: IpLookupTable::with_capacity(ipv6_size),
        }
    }

    /// Insert a value for the IpNetwork. If prefix existed previously, the old value is returned.
    ///
    /// # Example
    ///
    /// ```
    /// use ip_network::table::Table;
    /// use ip_network::Ipv6Network;
    /// use std::net::Ipv6Addr;
    ///
    /// let mut table: Table<&str> = Table::new();
    /// let network = Ipv6Network::from(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0), 64).unwrap();
    ///
    /// assert_eq!(table.insert(network.clone(), "foo"), None);
    /// // Insert duplicate
    /// assert_eq!(table.insert(network.clone(), "bar"), Some("foo"));
    /// // Value is replaced
    /// assert_eq!(table.insert(network, "null"), Some("bar"));
    /// ```
    pub fn insert<N: Into<IpNetwork>>(&mut self, network: N, data: T) -> Option<T> {
        match network.into() {
            IpNetwork::V4(ipv4_network) => {
                self.ipv4.insert(ipv4_network.network_address, ipv4_network.netmask as u32, data)
            },
            IpNetwork::V6(ipv6_network) => {
                self.ipv6.insert(ipv6_network.network_address, ipv6_network.netmask as u32, data)
            },
        }
    }

    /// Insert a value for the IpNetwork. If prefix existed previously, the old value is returned.
    ///
    /// # Example
    ///
    /// ```
    /// use ip_network::table::Table;
    /// use ip_network::Ipv6Network;
    /// use std::net::Ipv6Addr;
    ///
    /// let mut table: Table<&str> = Table::new();
    /// let network = Ipv6Network::from(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0), 64).unwrap();
    ///
    /// assert_eq!(table.insert(network.clone(), "foo"), None);
    /// // Remove network from table
    /// assert_eq!(table.remove(network.clone()), Some("foo"));
    /// // Network is removed
    /// assert_eq!(table.exact_match(network), None);
    /// ```
    pub fn remove<N: Into<IpNetwork>>(&mut self, network: N) -> Option<T> {
        match network.into() {
            IpNetwork::V4(ipv4_network) => {
                self.ipv4.remove(ipv4_network.network_address, ipv4_network.netmask as u32)
            },
            IpNetwork::V6(ipv6_network) => {
                self.ipv6.remove(ipv6_network.network_address, ipv6_network.netmask as u32)
            },
        }
    }

    pub fn exact_match<N: Into<IpNetwork>>(&self, network: N) -> Option<&T> {
        match network.into() {
            IpNetwork::V4(ipv4_network) => {
                self.ipv4.exact_match(ipv4_network.network_address, ipv4_network.netmask as u32)
            },
            IpNetwork::V6(ipv6_network) => {
                self.ipv6.exact_match(ipv6_network.network_address, ipv6_network.netmask as u32)
            },
        }
    }

    pub fn longest_match<A: Into<IpAddr>>(&self, ip: A) -> Option<(IpNetwork, &T)> {
        match ip.into() {
            IpAddr::V4(ipv4) => self.longest_match_ipv4(ipv4).map(|(n, t)| (IpNetwork::V4(n), t)),
            IpAddr::V6(ipv6) => self.longest_match_ipv6(ipv6).map(|(n, t)| (IpNetwork::V6(n), t)),
        }
    }

    #[inline]
    pub fn longest_match_ipv4(&self, ip: Ipv4Addr) -> Option<(Ipv4Network, &T)> {
        match self.ipv4.longest_match(ip) {
            Some((addr, mask, data)) => Some((
                Ipv4Network::from(addr, mask as u8).unwrap(),
                data
            )),
            None => None,
        }
    }

    #[inline]
    pub fn longest_match_ipv6(&self, ip: Ipv6Addr) -> Option<(Ipv6Network, &T)> {
        match self.ipv6.longest_match(ip) {
            Some((addr, mask, data)) => Some((
                Ipv6Network::from(addr, mask as u8).unwrap(),
                data
            )),
            None => None,
        }
    }

    pub fn iter(&self) -> Iter<T> {
        Iter {
            ipv4: self.ipv4.iter(),
            ipv6: self.ipv6.iter(),
        }
    }
}

pub struct Iter<'a, T: 'a> {
    ipv4: treebitmap::Iter<'a, Ipv4Addr, T>,
    ipv6: treebitmap::Iter<'a, Ipv6Addr, T>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = (IpNetwork, &'a T);

    fn next(&mut self) -> Option<Self::Item> {
        match self.ipv4.next() {
            Some((addr, mask, data)) => Some((
                IpNetwork::V4(Ipv4Network::from(addr, mask as u8).unwrap()),
                data
            )),
            None => {
                match self.ipv6.next() {
                    Some((addr, mask, data)) => Some((
                        IpNetwork::V6(Ipv6Network::from(addr, mask as u8).unwrap()),
                        data
                    )),
                    None => None,
                }
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use table::Table;
    use std::net::{Ipv4Addr, Ipv6Addr};
    use {Ipv4Network, Ipv6Network};

    #[test]
    fn test() {
        let mut table: Table<u32> = Table::new();
        table.insert(Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 16).unwrap(), 1);
        table.insert(Ipv6Network::from(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 128).unwrap(), 1);
    }
}

<|endoftext|>


<commit_before>use super::rocket;
use rocket::local::Client;
use rocket::http::Status;
use diesel::prelude::*;
use schema::preferences::dsl::*;

#[test]
/// Tests connection to the database through the pool managed by rocket.
fn db_connection() {
    let conn = rocket().1;

    let expected_keys = vec!["session-key"];
    let actual_keys: Vec<String> = preferences.select(key).load(&*conn).unwrap();

    assert_eq!(expected_keys, actual_keys);
}

#[test]
/// Compares the session hash in the database to the one returned by /session
fn session_hash() {
    let (rocket, conn) = rocket();
    let client = Client::new(rocket).expect("valid rocket instance");
    let mut response = client.get("/session").dispatch();

    let session_key: Vec<String> = preferences
        .filter(key.eq("session-key"))
        .select(value)
        .load(&*conn)
        .unwrap();

    assert_eq!(response.status(), Status::Ok);
    assert_eq!(response.body_string().unwrap(), session_key[0]);
}
<commit_msg>Exposing host was killing a test. Unsure why tests are 'passing' then...<commit_after>use super::rocket;
use rocket::local::Client;
use rocket::http::Status;
use diesel::prelude::*;
use schema::preferences::dsl::*;

#[test]
/// Tests connection to the database through the pool managed by rocket.
fn db_connection() {
    let conn = rocket().1;

    let expected_keys = vec!["session-key"];
    let actual_keys: Vec<String> = preferences.select(key).load(&*conn).unwrap();

    assert_eq!(expected_keys, actual_keys);
}

#[test]
/// Compares the session hash in the database to the one returned by /session
fn session_hash() {
    let (rocket, conn, _) = rocket();
    let client = Client::new(rocket).expect("valid rocket instance");
    let mut response = client.get("/session").dispatch();

    let session_key: Vec<String> = preferences
        .filter(key.eq("session-key"))
        .select(value)
        .load(&*conn)
        .unwrap();

    assert_eq!(response.status(), Status::Ok);
    assert_eq!(response.body_string().unwrap(), session_key[0]);
}
<|endoftext|>