<commit_before>#[derive(Debug, PartialEq)]
enum LexerErrorCode {
    InvalidSyntax,
    TrailingCharacters,
    EOFWhileReadingToken,
}

#[derive(Debug, PartialEq)]
enum LexerError {
    SyntaxError {
        code: LexerErrorCode,
        line: usize,
        col: usize,
    }
}

#[derive(Debug, PartialEq, Copy)]
enum ListState {
    Open,
    Item,
}

#[derive(Debug, PartialEq)]
enum Token {
    Number(f64),
    String(String),
    Symbol(String),
    ListStart,
    ListEnd,
    Error(LexerError),
}

#[derive(Debug, PartialEq)]
enum LexerState {
    Start,
    BeforeFinish,
    ReadList(ListState),
    Finish,
}

pub struct Lexer<T> {
    reader: T,
    cur_char: Option<char>,
    line: usize,
    col: usize,
    state: LexerState,
}

impl<T: Iterator<Item=char>> Iterator for Lexer<T> {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        match self.state {
            LexerState::Finish => {
                None
            },
            LexerState::BeforeFinish => {
                self.read_whitespaces();
                self.cur_char
                    .and(Some(self.error_token(LexerErrorCode::TrailingCharacters)))
                    .or_else(|| { self.state = LexerState::Finish; None })
            },
            _ => {
                Some(self.read())
            }
        }
    }
}

impl<T: Iterator<Item=char>> Lexer<T> {
    fn new(reader: T) -> Lexer<T> {
        let mut l = Lexer {
            reader: reader,
            cur_char: None,
            line: 1,
            col: 0,
            state: LexerState::Start,
        };
        l.bump();
        l
    }

    fn read(&mut self) -> Token {
        loop {
            self.read_whitespaces();
            match self.state {
                LexerState::Start => {
                    return self.read_start()
                },
                LexerState::ReadList(ls) => {
                    return self.read_list(ls)
                },
                _ => {
                    return self.error_token(LexerErrorCode::InvalidSyntax)
                }
            }
        }
    }

    fn read_start(&mut self) -> Token {
        let token = self.read_token();
        self.state = match token {
            Token::Error(_) => {
                LexerState::Finish
            },
            Token::ListStart => {
                LexerState::ReadList(ListState::Open)
            },
            _ => {
                LexerState::BeforeFinish
            },
        };
        token
    }

    fn read_token(&mut self) -> Token {
        if let Some(c) = self.cur_char {
            match c {
                'a' ... 'z' | 'A' ... 'Z' => {
                    self.read_symbol()
                },
                '0' ... '9' | '-' => {
                    self.read_number()
                },
                '"' => {
                    self.read_string()
                },
                '(' => {
                    self.bump();
                    Token::ListStart
                },
                _ => {
                    self.error_token(LexerErrorCode::InvalidSyntax)
                }
            }
        } else {
            self.error_token(LexerErrorCode::EOFWhileReadingToken)
        }
    }

    fn read_symbol(&mut self) -> Token {
        let mut res = String::new();

        while let Some(c) = self.cur_char {
            match c {
                ' ' | '\t' | '\r' | '\n' => {
                    break
                },
                _ => {
                    res.push(c);
                }
            }
            self.bump();
        }

        Token::Symbol(res)
    }

    fn read_number(&mut self) -> Token {
        let mut neg = false;

        if let Some('-') = self.cur_char {
            neg = true;
            self.bump();
        }

        let mut accum = 0_f64;

        while let Some(c) = self.cur_char {
            match c {
                '0' ... '9' => {
                    let c_as_usize = (c as usize) - ('0' as usize);
                    accum *= 10_f64;
                    accum += c_as_usize as f64;
                    self.bump()
                },
                '.' => {
                    self.bump();

                    let mut dec = 1.0;
                    while let Some(c) = self.cur_char {
                        match c {
                            '0' ... '9' => {
                                let c_as_usize = (c as usize) - ('0' as usize);
                                dec /= 10.0;
                                accum += (c_as_usize as f64) * dec;
                                self.bump();
                            },
                            _ => {
                                break
                            }
                        }
                    }
                },
                ' ' | '\t' | '\r' | '\n' | ')' => {
                    break
                },
                _ => {
                    return self.error_token(LexerErrorCode::InvalidSyntax)
                }
            }
        }

        if neg {
            accum *= -1_f64;
        }

        Token::Number(accum)
    }

    fn read_string(&mut self) -> Token {
        let mut res = String::new();

        self.bump();

        while let Some(c) = self.cur_char {
            match c {
                '"' => {
                    break
                },
                _ => {
                    res.push(c);
                }
            }
            self.bump();
        }

        self.bump();

        Token::String(res)
    }

    fn read_list(&mut self, ls: ListState) -> Token {
        if Some(')') == self.cur_char {
            match ls {
                ListState::Item => {
                    self.state = LexerState::BeforeFinish;
                    self.bump();
                    Token::ListEnd
                },
                _ => {
                    self.error_token(LexerErrorCode::InvalidSyntax)
                },
            }
        } else {
            let token = self.read_token();
            self.state = match token {
                Token::Error(_) => {
                    LexerState::Finish
                },
                Token::ListStart => {
                    LexerState::ReadList(ListState::Open)
                },
                _ => {
                    LexerState::ReadList(ListState::Item)
                }
            };
            token
        }
    }

    fn read_whitespaces(&mut self) {
        while let Some(c) = self.cur_char {
            match c {
                ' ' | '\t' | '\r' | '\n' => {
                    self.bump();
                },
                _ => {
                    break;
                }
            }
        }
    }

    fn bump(&mut self) {
        self.cur_char = self.reader.next();
        if Some('\n') == self.cur_char {
            self.line += 1;
            self.col = 1;
        } else {
            self.col += 1;
        }
    }

    fn error_token(&mut self, ec: LexerErrorCode) -> Token {
        self.state = LexerState::Finish;
        Token::Error(LexerError::SyntaxError {
            code: ec,
            line: self.line,
            col: self.col
        })
    }
}

#[cfg(test)]
mod tests {
    use super::{Lexer, Token, LexerError, LexerErrorCode};

    #[test]
    fn test_read_nil() {
        let sym_name = "nil".to_string();
        let mut lexer = Lexer::new(sym_name.chars());
        assert_eq!(Some(Token::Symbol(sym_name.clone())), lexer.next());
        assert_eq!(None, lexer.next());
    }

    #[test]
    fn test_read_integer_as_float() {
        let mut lexer = Lexer::new("64".chars());
        assert_eq!(Some(Token::Number(64_f64)), lexer.next());
        assert_eq!(None, lexer.next());
    }

    #[test]
    fn test_read_float() {
        let mut lexer = Lexer::new("64.5".chars());
        assert_eq!(Some(Token::Number(64.5)), lexer.next());
        assert_eq!(None, lexer.next());
    }

    #[test]
    fn test_read_string() {
        let s = "rust is beautiful".to_string();
        let actual_input = format!(r#""{}""#, s);
        let mut lexer = Lexer::new(actual_input.chars());
        assert_eq!(Some(Token::String(s)), lexer.next());
        assert_eq!(None, lexer.next());
    }

    #[test]
    fn test_read_symbol() {
        let sym_name = "my-symbol".to_string();
        let mut lexer = Lexer::new(sym_name.chars());
        assert_eq!(Some(Token::Symbol(sym_name.clone())), lexer.next());
        assert_eq!(None, lexer.next());
    }

    #[test]
    fn test_read_incorrect_symbol_starting_with_digit() {
        let sym_name = "6-my-incorrect-symbol".to_string();
        let mut lexer = Lexer::new(sym_name.chars());
        let expected_result = Some(Token::Error(LexerError::SyntaxError {
            code: LexerErrorCode::InvalidSyntax,
            line: 1,
            col: 2
        }));
        assert_eq!(expected_result, lexer.next());
        assert_eq!(None, lexer.next());
    }

    #[test]
    fn test_read_dense_expression() {
        let lexer = Lexer::new("(def a 1)".chars());
        let expected_result = vec![Token::ListStart,
                                   Token::Symbol("def".to_string()),
                                   Token::Symbol("a".to_string()),
                                   Token::Number(1_f64),
                                   Token::ListEnd];
        assert_eq!(expected_result, lexer.collect::<Vec<Token>>())
    }

    #[test]
    fn test_read_sparse_expression() {
        let lexer = Lexer::new(" ( \n def a\n1)   \n".chars());
        let expected_result = vec![Token::ListStart,
                                   Token::Symbol("def".to_string()),
                                   Token::Symbol("a".to_string()),
                                   Token::Number(1_f64),
                                   Token::ListEnd];
        assert_eq!(expected_result, lexer.collect::<Vec<Token>>())
    }
}
<commit_msg>Remove ListState, add nesting level tracking using lvl field<commit_after>#[derive(Debug, PartialEq)]
enum LexerErrorCode {
    InvalidSyntax,
    TrailingCharacters,
    EOFWhileReadingToken,
}

#[derive(Debug, PartialEq)]
enum LexerError {
    SyntaxError {
        code: LexerErrorCode,
        line: usize,
        col: usize,
    }
}

#[derive(Debug, PartialEq)]
enum Token {
    Number(f64),
    String(String),
    Symbol(String),
    ListStart,
    ListEnd,
    Error(LexerError),
}

#[derive(Debug, PartialEq)]
enum LexerState {
    Start,
    BeforeFinish,
    ReadList,
    Finish,
}

pub struct Lexer<T> {
    reader: T,
    cur_char: Option<char>,
    line: usize,
    col: usize,
    state: LexerState,
    lvl: isize,
}

impl<T: Iterator<Item=char>> Iterator for Lexer<T> {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        match self.state {
            LexerState::Finish => {
                None
            },
            LexerState::BeforeFinish => {
                self.read_whitespaces();
                self.cur_char
                    .and(Some(self.error_token(LexerErrorCode::TrailingCharacters)))
                    .or_else(|| { self.state = LexerState::Finish; None })
            },
            _ => {
                Some(self.read())
            }
        }
    }
}

impl<T: Iterator<Item=char>> Lexer<T> {
    fn new(reader: T) -> Lexer<T> {
        let mut l = Lexer {
            reader: reader,
            cur_char: None,
            line: 1,
            col: 0,
            state: LexerState::Start,
            lvl: 0,
        };
        l.bump();
        l
    }

    fn read(&mut self) -> Token {
        loop {
            self.read_whitespaces();
            match self.state {
                LexerState::Start => {
                    return self.read_start()
                },
                LexerState::ReadList => {
                    return self.read_list()
                },
                _ => {
                    return self.error_token(LexerErrorCode::InvalidSyntax)
                }
            }
        }
    }

    fn read_start(&mut self) -> Token {
        let token = self.read_token();
        self.state = match token {
            Token::Error(_) => {
                LexerState::Finish
            },
            Token::ListStart => {
                LexerState::ReadList
            },
            _ => {
                LexerState::BeforeFinish
            },
        };
        token
    }

    fn read_token(&mut self) -> Token {
        if let Some(c) = self.cur_char {
            match c {
                'a' ... 'z' | 'A' ... 'Z' => {
                    self.read_symbol()
                },
                '0' ... '9' | '-' => {
                    self.read_number()
                },
                '"' => {
                    self.read_string()
                },
                '(' => {
                    self.bump();
                    Token::ListStart
                },
                ')' => {
                    self.bump();
                    Token::ListEnd
                },
                _ => {
                    self.error_token(LexerErrorCode::InvalidSyntax)
                }
            }
        } else {
            self.error_token(LexerErrorCode::EOFWhileReadingToken)
        }
    }

    fn read_symbol(&mut self) -> Token {
        let mut res = String::new();

        while let Some(c) = self.cur_char {
            match c {
                ' ' | '\t' | '\r' | '\n' => {
                    break
                },
                _ => {
                    res.push(c);
                }
            }
            self.bump();
        }

        Token::Symbol(res)
    }

    fn read_number(&mut self) -> Token {
        let mut neg = false;

        if let Some('-') = self.cur_char {
            neg = true;
            self.bump();
        }

        let mut accum = 0_f64;

        while let Some(c) = self.cur_char {
            match c {
                '0' ... '9' => {
                    let c_as_usize = (c as usize) - ('0' as usize);
                    accum *= 10_f64;
                    accum += c_as_usize as f64;
                    self.bump()
                },
                '.' => {
                    self.bump();

                    let mut dec = 1.0;
                    while let Some(c) = self.cur_char {
                        match c {
                            '0' ... '9' => {
                                let c_as_usize = (c as usize) - ('0' as usize);
                                dec /= 10.0;
                                accum += (c_as_usize as f64) * dec;
                                self.bump();
                            },
                            _ => {
                                break
                            }
                        }
                    }
                },
                ' ' | '\t' | '\r' | '\n' | ')' => {
                    break
                },
                _ => {
                    return self.error_token(LexerErrorCode::InvalidSyntax)
                }
            }
        }

        if neg {
            accum *= -1_f64;
        }

        Token::Number(accum)
    }

    fn read_string(&mut self) -> Token {
        let mut res = String::new();

        self.bump();

        while let Some(c) = self.cur_char {
            match c {
                '"' => {
                    break
                },
                _ => {
                    res.push(c);
                }
            }
            self.bump();
        }

        self.bump();

        Token::String(res)
    }

    fn read_list(&mut self) -> Token {
        let token = self.read_token();
        self.state = match token {
            Token::Error(_) => {
                LexerState::Finish
            },
            Token::ListStart => {
                self.lvl += 1;
                LexerState::ReadList
            },
            Token::ListEnd => {
                if self.lvl > 0 {
                    self.lvl -= 1;
                    LexerState::ReadList
                } else {
                    LexerState::BeforeFinish
                }
            },
            _ => {
                LexerState::ReadList
            }
        };
        token
    }

    fn read_whitespaces(&mut self) {
        while let Some(c) = self.cur_char {
            match c {
                ' ' | '\t' | '\r' | '\n' => {
                    self.bump();
                },
                _ => {
                    break;
                }
            }
        }
    }

    fn bump(&mut self) {
        self.cur_char = self.reader.next();
        if Some('\n') == self.cur_char {
            self.line += 1;
            self.col = 1;
        } else {
            self.col += 1;
        }
    }

    fn error_token(&mut self, ec: LexerErrorCode) -> Token {
        self.state = LexerState::Finish;
        Token::Error(LexerError::SyntaxError {
            code: ec,
            line: self.line,
            col: self.col
        })
    }
}

#[cfg(test)]
mod tests {
    use super::{Lexer, Token, LexerError, LexerErrorCode};

    #[test]
    fn test_read_nil() {
        let sym_name = "nil".to_string();
        let mut lexer = Lexer::new(sym_name.chars());
        assert_eq!(Some(Token::Symbol(sym_name.clone())), lexer.next());
        assert_eq!(None, lexer.next());
    }

    #[test]
    fn test_read_integer_as_float() {
        let mut lexer = Lexer::new("64".chars());
        assert_eq!(Some(Token::Number(64_f64)), lexer.next());
        assert_eq!(None, lexer.next());
    }

    #[test]
    fn test_read_float() {
        let mut lexer = Lexer::new("64.5".chars());
        assert_eq!(Some(Token::Number(64.5)), lexer.next());
        assert_eq!(None, lexer.next());
    }

    #[test]
    fn test_read_string() {
        let s = "rust is beautiful".to_string();
        let actual_input = format!(r#""{}""#, s);
        let mut lexer = Lexer::new(actual_input.chars());
        assert_eq!(Some(Token::String(s)), lexer.next());
        assert_eq!(None, lexer.next());
    }

    #[test]
    fn test_read_symbol() {
        let sym_name = "my-symbol".to_string();
        let mut lexer = Lexer::new(sym_name.chars());
        assert_eq!(Some(Token::Symbol(sym_name.clone())), lexer.next());
        assert_eq!(None, lexer.next());
    }

    #[test]
    fn test_read_incorrect_symbol_starting_with_digit() {
        let sym_name = "6-my-incorrect-symbol".to_string();
        let mut lexer = Lexer::new(sym_name.chars());
        let expected_result = Some(Token::Error(LexerError::SyntaxError {
            code: LexerErrorCode::InvalidSyntax,
            line: 1,
            col: 2
        }));
        assert_eq!(expected_result, lexer.next());
        assert_eq!(None, lexer.next());
    }

    #[test]
    fn test_read_dense_expression() {
        let lexer = Lexer::new("(def a 1)".chars());
        let expected_result = vec![Token::ListStart,
                                   Token::Symbol("def".to_string()),
                                   Token::Symbol("a".to_string()),
                                   Token::Number(1_f64),
                                   Token::ListEnd];
        assert_eq!(expected_result, lexer.collect::<Vec<Token>>())
    }

    #[test]
    fn test_read_sparse_expression() {
        let lexer = Lexer::new(" ( \n def a\n1)   \n".chars());
        let expected_result = vec![Token::ListStart,
                                   Token::Symbol("def".to_string()),
                                   Token::Symbol("a".to_string()),
                                   Token::Number(1_f64),
                                   Token::ListEnd];
        assert_eq!(expected_result, lexer.collect::<Vec<Token>>())
    }
}
<|endoftext|>


<commit_before>use ast::{TIdent, TNumber, TString, TSemicolon, TComment, TColon, TDot, TEqual, TOpenParen, TCloseParen, TComma, TOpenBlock, TCloseBlock, TOpenArray, TCloseArray, TQuestion, TNumOp, TBitOp, TCompOp, TLogOp, TArrow};
use ast::{OpAdd, OpSub, OpMul, OpDiv, OpMod};
use ast::{BitAnd, BitOr, BitXor};
use ast::{CompEqual, CompNotEqual, CompLessThan, CompGreaterThan, CompLessThanOrEqual, CompGreaterThanOrEqual};
use ast::{LogAnd, LogOr};
use ast::{Token, TokenData};
use std::io::{BufReader, BufferedReader, Reader};
use std::strbuf::StrBuf;
use std::char::from_u32;
use std::num::from_str_radix;
use std::io::{IoResult, EndOfFile};
use std::char::is_whitespace;
#[deriving(Clone)]
#[deriving(Eq)]
#[deriving(Show)]
/// The type of string used
pub enum StringType {
	/// Double-quoted
	DoubleQuote,
	/// Single-quoted
	SingleQuote
}
#[deriving(Clone)]
#[deriving(Eq)]
#[deriving(Show)]
/// The type of comment used
pub enum CommentType {
	/// Multi-line comment
	MultiLineComment,
	/// Single-line comment
	SingleLineComment
}
#[deriving(Clone, Eq, Show)]
/// The type of number used
pub enum NumberType {
	/// Decimal number
	DecimalNumber,
	/// Hexadecimal number
	HexadecimalNumber,
	/// Octal number
	OctalNumber
}
/// The Javascript Lexer
pub struct Lexer {
	/// The list of tokens generated so far
	pub tokens : Vec<Token>,
	/// The string buffer for identities
	ident_buffer : StrBuf,
	/// The string buffer for strings
	string_buffer : StrBuf,
	/// The string buffer for comments
	comment_buffer : StrBuf,
	/// The string buffer for numbers
	num_buffer : StrBuf,
	/// The kind of string - i.e. double quote or single quote or none if it isn't in a string
	string_start : Option<StringType>,
	/// The kind of comment
	current_comment : Option<CommentType>,
	/// The kind of number
	current_number : Option<NumberType>,
	/// If a backwards slash has just been read
	escaped : bool,
	/// The current line number
	line_number : uint,
	/// The current column number
	column_number : uint
}
impl Lexer {
	/// Creates a new lexer with empty buffers
	pub fn new() -> ~Lexer {
		return ~Lexer {
			tokens: Vec::new(),
			ident_buffer: StrBuf::with_capacity(32),
			string_buffer: StrBuf::with_capacity(256),
			num_buffer: StrBuf::with_capacity(16),
			comment_buffer: StrBuf::with_capacity(32),
			string_start: None,
			current_comment: None,
			current_number: None,
			escaped: false,
			line_number: 1,
			column_number: 0
		};
	}
	fn clear_buffer(&mut self) {
		if self.ident_buffer.len() > 0 {
			let ident = self.ident_buffer.clone().into_owned();
			self.push_token(TIdent(ident));
			self.ident_buffer.truncate(0);
		}
		if self.current_number.is_some() {
			let num : f64 = match self.current_number {
				Some(HexadecimalNumber) => from_str_radix(self.num_buffer.as_slice(), 16).unwrap(),
				Some(OctalNumber) => from_str_radix(self.num_buffer.as_slice(), 8).unwrap(),
				Some(DecimalNumber) => from_str(self.num_buffer.as_slice()).unwrap(),
				None => unreachable!()
			};
			self.push_token(TNumber(num));
			self.num_buffer.truncate(0);
			self.current_number = None;
		}
	}
	fn push_token(&mut self, tk:TokenData) {
		self.tokens.push(Token::new(tk, self.line_number, self.column_number))
	}
	/// Processes an input stream from a string into an array of tokens
	pub fn lex_str(&mut self, script:~str) -> IoResult<()> {
		let script_bytes:&[u8] = script.as_bytes();
		let reader = BufReader::new(script_bytes);
		let buf_reader = BufferedReader::new(reader);
		self.lex(buf_reader)
	}
	/// Processes an input stream from a BufferedReader into an array of tokens
	pub fn lex<R : Reader>(&mut self, mut reader : BufferedReader<R>) -> IoResult<()> {
		let mut iter = reader.chars().peekable();
		loop {
			let ch = match iter.next() {
				Some(Ok(ch)) => ch,
				Some(Err(ref err)) if err.kind == EndOfFile => break,
				Some(Err(err)) => return Err(err),
				None => break
			};
			self.column_number += 1;
			match ch {
				_ if self.escaped => {
					self.escaped = false;
					if ch != '\n' {
						self.string_buffer.push_char(match ch {
							'n' => '\n',
							'r' => '\r',
							't' => '\t',
							'b' => '\x08',
							'f' => '\x0c',
							'0' => '\0',
							'x' => {
								let mut nums = ~"";
								for _ in range(0, 2) {
									nums = format!("{}{}", nums, try!(iter.next().unwrap().clone()));
								}
								self.column_number += 2;
								let as_num = match from_str_radix(nums, 16) {
									Some(v) => v,
									None => 0
								};
								match from_u32(as_num) {
									Some(v) => v,
									None => fail!("Line {}, Column {}: {} is not a valid unicode scalar value", self.line_number, self.column_number, as_num)
								}
							},
							'u' => {
								let mut nums = ~"";
								for _ in range(0, 4) {
									nums = format!("{}{}", nums, try!(iter.next().unwrap().clone()));
								}
								self.column_number += 4;
								let as_num = match from_str_radix(nums, 16) {
									Some(v) => v,
									None => 0
								};
								match from_u32(as_num) {
									Some(v) => v,
									None => fail!("Line {}, Column {}: {} is not a valid unicode scalar value", self.line_number, self.column_number, as_num)
								}
							},
							'\'' if self.string_start == Some(SingleQuote) => '\'',
							'"' if self.string_start == Some(DoubleQuote) => '"',
							_ => fail!("Line {}, Column {}: Invalid escape `{}`", self.line_number, self.column_number, ch)
						});
					}
				},
				'\n' if self.current_comment == Some(SingleLineComment) => {
					let comment = self.comment_buffer.clone().into_owned();
					self.push_token(TComment(comment));
					self.comment_buffer.truncate(0);
					self.current_comment = None;
				},
				'*' if self.current_comment == Some(MultiLineComment) && try!(iter.peek().unwrap().clone()) == '/' => {
					iter.next();
					let comment = self.comment_buffer.clone().into_owned();
					self.push_token(TComment(comment));
					self.comment_buffer.truncate(0);
					self.current_comment = None;
				},
				_ if self.current_comment.is_some() => {
					self.comment_buffer.push_char(ch);
				},
				'"' if self.string_start == Some(DoubleQuote) => {
					self.string_start = None;
					let string = self.string_buffer.clone().into_owned();
					self.push_token(TString(string));
					self.string_buffer.truncate(0);
				},
				'\'' if self.string_start == Some(SingleQuote) => {
					self.string_start = None;
					let string = self.string_buffer.clone().into_owned();
					self.push_token(TString(string));
					self.string_buffer.truncate(0);
				},
				'\\' if self.string_start.is_some() => self.escaped = true,
				_ if self.string_start.is_some() => self.string_buffer.push_char(ch),
				'"' if self.string_start.is_none() => self.string_start = Some(DoubleQuote),
				'0' if try!(iter.peek().unwrap().clone()) == 'x' => {
					iter.next();
					self.current_number = Some(HexadecimalNumber);
				},
				'0' if self.string_start.is_none() && self.ident_buffer.len() == 0 => {
					self.num_buffer.push_char(ch);
					self.current_number = Some(OctalNumber);
				},
				'8' .. '9' if self.current_number == Some(OctalNumber) => {
					self.num_buffer.push_char(ch);
					self.current_number = Some(DecimalNumber);
				},
				'0'.. '9' if self.string_start.is_none() && self.ident_buffer.len() == 0 => {
					self.num_buffer.push_char(ch);
					self.current_number = Some(DecimalNumber);
				},
				'A'.. 'F' | 'a' .. 'f' if self.current_number == Some(HexadecimalNumber) => {
					self.num_buffer.push_char(ch);
				},
				'\'' if self.string_start.is_none() => self.string_start = Some(SingleQuote),
				'.' if self.current_number.is_some() && !self.num_buffer.as_slice().contains(".") => {
					self.num_buffer.push_char(ch);
				},
				';' => {
					self.clear_buffer();
					self.push_token(TSemicolon);
				},
				':' => {
					self.clear_buffer();
					self.push_token(TColon);
				},
				'.' => {
					self.clear_buffer();
					self.push_token(TDot);
				},
				'(' => {
					self.clear_buffer();
					self.push_token(TOpenParen);
				},
				')' => {
					self.clear_buffer();
					self.push_token(TCloseParen);
				},
				',' => {
					self.clear_buffer();
					self.push_token(TComma);
				},
				'{' => {
					self.clear_buffer();
					self.push_token(TOpenBlock);
				},
				'}' => {
					self.clear_buffer();
					self.push_token(TCloseBlock);
				},
				'[' => {
					self.clear_buffer();
					self.push_token(TOpenArray);
				},
				']' => {
					self.clear_buffer();
					self.push_token(TCloseArray);
				},
				'?' => {
					self.clear_buffer();
					self.push_token(TQuestion);
				},
				'/' if try!(iter.peek().unwrap().clone()) == '/' => {
					iter.next();
					self.current_comment = Some(SingleLineComment);
				},
				'/' if try!(iter.peek().unwrap().clone()) == '*' => {
					iter.next();
					self.current_comment = Some(MultiLineComment);
				},
				'/' => {
					self.clear_buffer();
					self.push_token(TNumOp(OpDiv));
				},
				'*' => {
					self.clear_buffer();
					self.push_token(TNumOp(OpMul));
				},
				'+' => {
					self.clear_buffer();
					self.push_token(TNumOp(OpAdd));
				},
				'-' => {
					self.clear_buffer();
					self.push_token(TNumOp(OpSub));
				},
				'%' => {
					self.clear_buffer();
					self.push_token(TNumOp(OpMod));
				},
				'|' if try!(iter.peek().unwrap().clone()) == '|' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TLogOp(LogOr));
				},
				'|' => {
					self.clear_buffer();
					self.push_token(TBitOp(BitOr));
				},
				'&' if try!(iter.peek().unwrap().clone()) == '&' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TLogOp(LogAnd));
				},
				'&' => {
					self.clear_buffer();
					self.push_token(TBitOp(BitAnd));
				},
				'^' => {
					self.clear_buffer();
					self.push_token(TBitOp(BitXor));
				},
				'=' if try!(iter.peek().unwrap().clone()) == '>' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TArrow);
				},
				'=' if try!(iter.peek().unwrap().clone()) == '=' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TCompOp(CompEqual));
				},
				'=' => {
					self.clear_buffer();
					self.push_token(TEqual);
				},
				'<' if try!(iter.peek().unwrap().clone()) == '=' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TCompOp(CompLessThanOrEqual));
				},
				'<' => {
					self.clear_buffer();
					self.push_token(TCompOp(CompLessThan));
				},
				'>' if try!(iter.peek().unwrap().clone()) == '=' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TCompOp(CompGreaterThanOrEqual));
				},
				'>' => {
					self.clear_buffer();
					self.push_token(TCompOp(CompGreaterThan));
				},
				'!' if try!(iter.peek().unwrap().clone()) == '=' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TCompOp(CompNotEqual));
				},
				'\n' => {
					self.clear_buffer();
					self.line_number += 1;
					self.column_number = 0;
				},
				'\r' => {
					self.clear_buffer();
					self.column_number = 0;
				},
				_ if is_whitespace(ch) => self.clear_buffer(),
				_ => self.ident_buffer.push_char(ch)
			};
		}
		self.clear_buffer();
		Ok(())
	}
}<commit_msg>Simplify number parsing in lexer<commit_after>use ast::{TIdent, TNumber, TString, TSemicolon, TComment, TColon, TDot, TEqual, TOpenParen, TCloseParen, TComma, TOpenBlock, TCloseBlock, TOpenArray, TCloseArray, TQuestion, TNumOp, TBitOp, TCompOp, TLogOp, TArrow};
use ast::{OpAdd, OpSub, OpMul, OpDiv, OpMod};
use ast::{BitAnd, BitOr, BitXor};
use ast::{CompEqual, CompNotEqual, CompLessThan, CompGreaterThan, CompLessThanOrEqual, CompGreaterThanOrEqual};
use ast::{LogAnd, LogOr};
use ast::{Token, TokenData};
use std::io::{BufReader, BufferedReader, Reader};
use std::strbuf::StrBuf;
use std::char::from_u32;
use std::num::from_str_radix;
use std::io::{IoResult, EndOfFile};
use std::char::is_whitespace;
#[deriving(Clone)]
#[deriving(Eq)]
#[deriving(Show)]
/// The type of string used
pub enum StringType {
	/// Double-quoted
	DoubleQuote,
	/// Single-quoted
	SingleQuote
}
#[deriving(Clone)]
#[deriving(Eq)]
#[deriving(Show)]
/// The type of comment used
pub enum CommentType {
	/// Multi-line comment
	MultiLineComment,
	/// Single-line comment
	SingleLineComment
}
#[deriving(Clone, Eq, Show)]
/// The type of number used
pub enum NumberType {
	/// Decimal number
	DecimalNumber,
	/// Hexadecimal number
	HexadecimalNumber,
	/// Octal number
	OctalNumber
}
/// The Javascript Lexer
pub struct Lexer {
	/// The list of tokens generated so far
	pub tokens : Vec<Token>,
	/// The string buffer for identities
	ident_buffer : StrBuf,
	/// The string buffer for strings
	string_buffer : StrBuf,
	/// The string buffer for comments
	comment_buffer : StrBuf,
	/// The string buffer for numbers
	num_buffer : StrBuf,
	/// The kind of string - i.e. double quote or single quote or none if it isn't in a string
	string_start : Option<StringType>,
	/// The kind of comment
	current_comment : Option<CommentType>,
	/// The kind of number
	current_number : Option<NumberType>,
	/// If a backwards slash has just been read
	escaped : bool,
	/// The current line number
	line_number : uint,
	/// The current column number
	column_number : uint
}
impl Lexer {
	/// Creates a new lexer with empty buffers
	pub fn new() -> ~Lexer {
		return ~Lexer {
			tokens: Vec::new(),
			ident_buffer: StrBuf::with_capacity(32),
			string_buffer: StrBuf::with_capacity(256),
			num_buffer: StrBuf::with_capacity(16),
			comment_buffer: StrBuf::with_capacity(32),
			string_start: None,
			current_comment: None,
			current_number: None,
			escaped: false,
			line_number: 1,
			column_number: 0
		};
	}
	fn clear_buffer(&mut self) {
		if self.ident_buffer.len() > 0 {
			let ident = self.ident_buffer.clone().into_owned();
			self.push_token(TIdent(ident));
			self.ident_buffer.truncate(0);
		}
		if self.current_number.is_some() {
			let num = from_str_radix(self.num_buffer.as_slice(), match self.current_number.unwrap() {
				HexadecimalNumber => 16,
				OctalNumber => 8,
				DecimalNumber => 10
			}).unwrap();
			self.push_token(TNumber(num));
			self.num_buffer.truncate(0);
			self.current_number = None;
		}
	}
	fn push_token(&mut self, tk:TokenData) {
		self.tokens.push(Token::new(tk, self.line_number, self.column_number))
	}
	/// Processes an input stream from a string into an array of tokens
	pub fn lex_str(&mut self, script:~str) -> IoResult<()> {
		let script_bytes:&[u8] = script.as_bytes();
		let reader = BufReader::new(script_bytes);
		let buf_reader = BufferedReader::new(reader);
		self.lex(buf_reader)
	}
	/// Processes an input stream from a BufferedReader into an array of tokens
	pub fn lex<R : Reader>(&mut self, mut reader : BufferedReader<R>) -> IoResult<()> {
		let mut iter = reader.chars().peekable();
		loop {
			let ch = match iter.next() {
				Some(Ok(ch)) => ch,
				Some(Err(ref err)) if err.kind == EndOfFile => break,
				Some(Err(err)) => return Err(err),
				None => break
			};
			self.column_number += 1;
			match ch {
				_ if self.escaped => {
					self.escaped = false;
					if ch != '\n' {
						self.string_buffer.push_char(match ch {
							'n' => '\n',
							'r' => '\r',
							't' => '\t',
							'b' => '\x08',
							'f' => '\x0c',
							'0' => '\0',
							'x' => {
								let mut nums = ~"";
								for _ in range(0, 2) {
									nums = format!("{}{}", nums, try!(iter.next().unwrap().clone()));
								}
								self.column_number += 2;
								let as_num = match from_str_radix(nums, 16) {
									Some(v) => v,
									None => 0
								};
								match from_u32(as_num) {
									Some(v) => v,
									None => fail!("Line {}, Column {}: {} is not a valid unicode scalar value", self.line_number, self.column_number, as_num)
								}
							},
							'u' => {
								let mut nums = ~"";
								for _ in range(0, 4) {
									nums = format!("{}{}", nums, try!(iter.next().unwrap().clone()));
								}
								self.column_number += 4;
								let as_num = match from_str_radix(nums, 16) {
									Some(v) => v,
									None => 0
								};
								match from_u32(as_num) {
									Some(v) => v,
									None => fail!("Line {}, Column {}: {} is not a valid unicode scalar value", self.line_number, self.column_number, as_num)
								}
							},
							'\'' if self.string_start == Some(SingleQuote) => '\'',
							'"' if self.string_start == Some(DoubleQuote) => '"',
							_ => fail!("Line {}, Column {}: Invalid escape `{}`", self.line_number, self.column_number, ch)
						});
					}
				},
				'\n' if self.current_comment == Some(SingleLineComment) => {
					let comment = self.comment_buffer.clone().into_owned();
					self.push_token(TComment(comment));
					self.comment_buffer.truncate(0);
					self.current_comment = None;
				},
				'*' if self.current_comment == Some(MultiLineComment) && try!(iter.peek().unwrap().clone()) == '/' => {
					iter.next();
					let comment = self.comment_buffer.clone().into_owned();
					self.push_token(TComment(comment));
					self.comment_buffer.truncate(0);
					self.current_comment = None;
				},
				_ if self.current_comment.is_some() => {
					self.comment_buffer.push_char(ch);
				},
				'"' if self.string_start == Some(DoubleQuote) => {
					self.string_start = None;
					let string = self.string_buffer.clone().into_owned();
					self.push_token(TString(string));
					self.string_buffer.truncate(0);
				},
				'\'' if self.string_start == Some(SingleQuote) => {
					self.string_start = None;
					let string = self.string_buffer.clone().into_owned();
					self.push_token(TString(string));
					self.string_buffer.truncate(0);
				},
				'\\' if self.string_start.is_some() => self.escaped = true,
				_ if self.string_start.is_some() => self.string_buffer.push_char(ch),
				'"' if self.string_start.is_none() => self.string_start = Some(DoubleQuote),
				'0' if try!(iter.peek().unwrap().clone()) == 'x' => {
					iter.next();
					self.current_number = Some(HexadecimalNumber);
				},
				'0' if self.string_start.is_none() && self.ident_buffer.len() == 0 => {
					self.num_buffer.push_char(ch);
					self.current_number = Some(OctalNumber);
				},
				'8' .. '9' if self.current_number == Some(OctalNumber) => {
					self.num_buffer.push_char(ch);
					self.current_number = Some(DecimalNumber);
				},
				'0'.. '9' if self.string_start.is_none() && self.ident_buffer.len() == 0 => {
					self.num_buffer.push_char(ch);
					self.current_number = Some(DecimalNumber);
				},
				'A'.. 'F' | 'a' .. 'f' if self.current_number == Some(HexadecimalNumber) => {
					self.num_buffer.push_char(ch);
				},
				'\'' if self.string_start.is_none() => self.string_start = Some(SingleQuote),
				'.' if self.current_number.is_some() && !self.num_buffer.as_slice().contains(".") => {
					self.num_buffer.push_char(ch);
				},
				';' => {
					self.clear_buffer();
					self.push_token(TSemicolon);
				},
				':' => {
					self.clear_buffer();
					self.push_token(TColon);
				},
				'.' => {
					self.clear_buffer();
					self.push_token(TDot);
				},
				'(' => {
					self.clear_buffer();
					self.push_token(TOpenParen);
				},
				')' => {
					self.clear_buffer();
					self.push_token(TCloseParen);
				},
				',' => {
					self.clear_buffer();
					self.push_token(TComma);
				},
				'{' => {
					self.clear_buffer();
					self.push_token(TOpenBlock);
				},
				'}' => {
					self.clear_buffer();
					self.push_token(TCloseBlock);
				},
				'[' => {
					self.clear_buffer();
					self.push_token(TOpenArray);
				},
				']' => {
					self.clear_buffer();
					self.push_token(TCloseArray);
				},
				'?' => {
					self.clear_buffer();
					self.push_token(TQuestion);
				},
				'/' if try!(iter.peek().unwrap().clone()) == '/' => {
					iter.next();
					self.current_comment = Some(SingleLineComment);
				},
				'/' if try!(iter.peek().unwrap().clone()) == '*' => {
					iter.next();
					self.current_comment = Some(MultiLineComment);
				},
				'/' => {
					self.clear_buffer();
					self.push_token(TNumOp(OpDiv));
				},
				'*' => {
					self.clear_buffer();
					self.push_token(TNumOp(OpMul));
				},
				'+' => {
					self.clear_buffer();
					self.push_token(TNumOp(OpAdd));
				},
				'-' => {
					self.clear_buffer();
					self.push_token(TNumOp(OpSub));
				},
				'%' => {
					self.clear_buffer();
					self.push_token(TNumOp(OpMod));
				},
				'|' if try!(iter.peek().unwrap().clone()) == '|' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TLogOp(LogOr));
				},
				'|' => {
					self.clear_buffer();
					self.push_token(TBitOp(BitOr));
				},
				'&' if try!(iter.peek().unwrap().clone()) == '&' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TLogOp(LogAnd));
				},
				'&' => {
					self.clear_buffer();
					self.push_token(TBitOp(BitAnd));
				},
				'^' => {
					self.clear_buffer();
					self.push_token(TBitOp(BitXor));
				},
				'=' if try!(iter.peek().unwrap().clone()) == '>' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TArrow);
				},
				'=' if try!(iter.peek().unwrap().clone()) == '=' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TCompOp(CompEqual));
				},
				'=' => {
					self.clear_buffer();
					self.push_token(TEqual);
				},
				'<' if try!(iter.peek().unwrap().clone()) == '=' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TCompOp(CompLessThanOrEqual));
				},
				'<' => {
					self.clear_buffer();
					self.push_token(TCompOp(CompLessThan));
				},
				'>' if try!(iter.peek().unwrap().clone()) == '=' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TCompOp(CompGreaterThanOrEqual));
				},
				'>' => {
					self.clear_buffer();
					self.push_token(TCompOp(CompGreaterThan));
				},
				'!' if try!(iter.peek().unwrap().clone()) == '=' => {
					iter.next();
					self.clear_buffer();
					self.push_token(TCompOp(CompNotEqual));
				},
				'\n' => {
					self.clear_buffer();
					self.line_number += 1;
					self.column_number = 0;
				},
				'\r' => {
					self.clear_buffer();
					self.column_number = 0;
				},
				_ if is_whitespace(ch) => self.clear_buffer(),
				_ => self.ident_buffer.push_char(ch)
			};
		}
		self.clear_buffer();
		Ok(())
	}
}<|endoftext|>


<commit_before>use time::get_time;
use time::Timespec;

use std::sync::Mutex;

use ewma::EWMA;
use metric::Metric;

const WINDOW: [f64, ..3] = [1f64, 5f64, 15f64];

// A MeterSnapshot
pub struct MeterSnapshot {
    count: i64,
    rates: [f64, ..3],
    mean: f64
}

// A StdMeter struct
pub struct StdMeter {
    data: Mutex<MeterSnapshot>,
    ewma: [EWMA, ..3],
    start: Timespec
}

// A Meter trait
pub trait Meter : Metric {
    fn snapshot(&self) -> MeterSnapshot;

    fn mark(&self, n: i64);

    fn tick(&mut self);

    fn rate(&self, rate: f64) -> f64;

    fn mean(&self) -> f64;

    fn count(&self) -> i64;
}

impl Meter for StdMeter {
    fn snapshot(&self) -> MeterSnapshot {
        let s = self.data.lock();

        MeterSnapshot {
            count: s.count,
            rates: s.rates,
            mean: s.mean
        }
    }

    fn mark(&self, n: i64) {
        let mut s = self.data.lock();

        s.count += n;

        for i in range(0, WINDOW.len()) {
            self.ewma[i].update(n as uint);
        }

        self.update_snapshot(*s);
    }

    fn tick(&mut self) {
        let s = self.data.lock();

        for i in range(0, WINDOW.len()) {
            self.ewma[i].tick();
        }

        self.update_snapshot(*s);
    }

    // Return the given EWMA for a rate like 1, 5, 15 minutes
    fn rate(&self, rate: f64) -> f64 {
        let mut s = self.data.lock();

        let pos = WINDOW.position_elem(&rate);

        if pos.is_some() {
            let r: f64 = s.rates[pos.unwrap()];
            return r;
        }
    }

    // Return the mean rate
    fn mean(&self) -> f64 {
        let s = self.data.lock();
        s.mean
    }

    fn count(&self) -> i64 {
        let s = self.data.lock();
        s.count
    }
}

impl Metric for StdMeter {
}

impl StdMeter {
    fn update_snapshot(&self, mut s: MeterSnapshot) {
        for i in range(0, WINDOW.len()) {
            s.rates[i] = self.ewma[i].rate();
        }

        let diff = get_time() - self.start;
        s.mean = s.count as f64 / diff.num_seconds() as f64;
    }

    pub fn new() -> StdMeter {
        let data: MeterSnapshot = MeterSnapshot{
            count: 0i64,
            rates: [0f64, 0f64, 0f64],
            mean: 0f64
        };

        let ewma: [EWMA, ..3] = [EWMA::new(1f64), EWMA::new(5f64), EWMA::new(15f64)];

        StdMeter {
            data: Mutex::new(data),
            ewma: ewma,
            start: get_time()
        }
    }

}

#[cfg(test)]
mod test {
    use meter::{Meter,MeterSnapshot,StdMeter};

    #[test]
    fn zero() {
        let m: StdMeter = StdMeter::new();
        let s: MeterSnapshot = m.snapshot();
        assert_eq!(s.count, 0);
    }

    #[test]
    fn non_zero() {
        let m: StdMeter = StdMeter::new();
        m.mark(3);
        let s: MeterSnapshot = m.snapshot();
        assert_eq!(s.count, 3);
    }

    #[test]
    fn snapshot() {
        let m: StdMeter = StdMeter::new();
        m.mark(1);
        m.mark(1);

        let s = m.snapshot();

        m.mark(1);

        assert_eq!(s.count, 2);
        assert_eq!(m.snapshot().count, 3);
    }

    // Test that decay works correctly
    #[test]
    fn decay() {
        let mut m: StdMeter = StdMeter::new();

        m.tick();
    }
}<commit_msg>Use if-let syntax<commit_after>#![feature(if_let)]

use time::get_time;
use time::Timespec;

use std::sync::Mutex;

use ewma::EWMA;
use metric::Metric;

const WINDOW: [f64, ..3] = [1f64, 5f64, 15f64];

// A MeterSnapshot
pub struct MeterSnapshot {
    count: i64,
    rates: [f64, ..3],
    mean: f64
}

// A StdMeter struct
pub struct StdMeter {
    data: Mutex<MeterSnapshot>,
    ewma: [EWMA, ..3],
    start: Timespec
}

// A Meter trait
pub trait Meter : Metric {
    fn snapshot(&self) -> MeterSnapshot;

    fn mark(&self, n: i64);

    fn tick(&mut self);

    fn rate(&self, rate: f64) -> f64;

    fn mean(&self) -> f64;

    fn count(&self) -> i64;
}

impl Meter for StdMeter {
    fn snapshot(&self) -> MeterSnapshot {
        let s = self.data.lock();

        MeterSnapshot {
            count: s.count,
            rates: s.rates,
            mean: s.mean
        }
    }

    fn mark(&self, n: i64) {
        let mut s = self.data.lock();

        s.count += n;

        for i in range(0, WINDOW.len()) {
            self.ewma[i].update(n as uint);
        }

        self.update_snapshot(*s);
    }

    fn tick(&mut self) {
        let s = self.data.lock();

        for i in range(0, WINDOW.len()) {
            self.ewma[i].tick();
        }

        self.update_snapshot(*s);
    }

    // Return the given EWMA for a rate like 1, 5, 15 minutes
    #[experimental]
    fn rate(&self, rate: f64) -> f64 {
        let mut s = self.data.lock();

        if let Some(pos) = WINDOW.position_elem(&rate) {
            let r: f64 = s.rates[pos];
            return r;
        }
        0f64
    }

    // Return the mean rate
    fn mean(&self) -> f64 {
        let s = self.data.lock();
        s.mean
    }

    fn count(&self) -> i64 {
        let s = self.data.lock();
        s.count
    }
}

impl Metric for StdMeter {
}

impl StdMeter {
    fn update_snapshot(&self, mut s: MeterSnapshot) {
        for i in range(0, WINDOW.len()) {
            s.rates[i] = self.ewma[i].rate();
        }

        let diff = get_time() - self.start;
        s.mean = s.count as f64 / diff.num_seconds() as f64;
    }

    pub fn new() -> StdMeter {
        let data: MeterSnapshot = MeterSnapshot{
            count: 0i64,
            rates: [0f64, 0f64, 0f64],
            mean: 0f64
        };

        let ewma: [EWMA, ..3] = [EWMA::new(1f64), EWMA::new(5f64), EWMA::new(15f64)];

        StdMeter {
            data: Mutex::new(data),
            ewma: ewma,
            start: get_time()
        }
    }

}

#[cfg(test)]
mod test {
    use meter::{Meter,MeterSnapshot,StdMeter};

    #[test]
    fn zero() {
        let m: StdMeter = StdMeter::new();
        let s: MeterSnapshot = m.snapshot();
        assert_eq!(s.count, 0);
    }

    #[test]
    fn non_zero() {
        let m: StdMeter = StdMeter::new();
        m.mark(3);
        let s: MeterSnapshot = m.snapshot();
        assert_eq!(s.count, 3);
    }

    #[test]
    fn snapshot() {
        let m: StdMeter = StdMeter::new();
        m.mark(1);
        m.mark(1);

        let s = m.snapshot();

        m.mark(1);

        assert_eq!(s.count, 2);
        assert_eq!(m.snapshot().count, 3);
    }

    // Test that decay works correctly
    #[test]
    fn decay() {
        let mut m: StdMeter = StdMeter::new();

        m.tick();
    }
}<|endoftext|>


<commit_before>//! Dimension-unspecific tree implementations

use std::mem;
use tree::{NodeState, DataQuery, ObjectQuery, AssociatedData, Node, Position};
use partition::Partition;

/// A pure N-dimensional tree
pub struct PureTree<P, O> {
    state: NodeState<O, Vec<PureTree<P, O>>>,
    partition: P,
}

impl<P, O> PureTree<P, O>
    where P: Partition<<O as Position>::Point>,
          O: Position,
{
    fn empty(partition: P) -> PureTree<P, O> {
        PureTree {
            state: NodeState::Empty,
            partition: partition,
        }
    }
}

impl<P, O> PureTree<P, O>
    where O: Position,
          P: Partition<<O as Position>::Point>,
{
    /// Construct a tree without checking the geometry of the input data
    pub fn new<I: Iterator<Item=O>>(iter: I, partition: P) -> PureTree<P, O> {
        let mut tree = PureTree::empty(partition);
        let mut iter = iter;
        for object in iter {
            tree.insert(object)
        }
        tree
    }

    fn dispatch(&self, nodes: &mut Vec<PureTree<P, O>>, object: O) {
        nodes[self.partition.dispatch(&object.position())].insert(object)
    }

    fn insert(&mut self, object: O) {
        let mut tmp = NodeState::Empty;
        mem::swap(&mut tmp, &mut self.state);
        self.state = match tmp {
            NodeState::Empty => NodeState::Leaf(object),
            NodeState::Leaf(other) => {
                let mut nodes: Vec<_> = self.partition.subdivide()
                    .into_iter()
                    .map(|p| PureTree::empty(p))
                    .collect();
                self.dispatch(&mut nodes, object);
                self.dispatch(&mut nodes, other);
                NodeState::Branch(nodes)
            },
            NodeState::Branch(mut nodes) => {
                self.dispatch(&mut nodes, object);
                NodeState::Branch(nodes)
            }
        };
    }
}

impl<P, O> ObjectQuery for PureTree<P, O> {
    fn query_objects<R, F>(&self, recurse: &R, f: &mut F)
        where R: Fn(&PureTree<P, O>) -> bool,
              F: FnMut(&O),
    {
        match self.state {
            NodeState::Branch(ref nodes) =>
                if recurse(self) {
                    for node in nodes.iter() {
                        node.query_objects(recurse, f)
                    }
                },
            NodeState::Leaf(ref obj) => f(obj),
            _ => (),
        }
    }
}

impl<P, O> Node for PureTree<P, O> {
    type Partition = P;
    type Object = O;
    type Container = Vec<PureTree<P, O>>;

    fn state(&self) -> &NodeState<O, Vec<PureTree<P, O>>> {
        &self.state
    }

    fn partition(&self) -> &P {
        &self.partition
    }
}

/// An N-dimensional tree
///
/// This tree does not know the dimension of its point at compile time, as it is
/// not hard-coded and genericity over constants is unsupported in Rust.
pub struct Tree<P, O, D> {
    state: NodeState<O, Vec<Tree<P, O, D>>>,
    partition: P,
    data: D,
}

impl<P, O, D> Tree<P, O, D> {
    /// Construct an empty tree
    fn empty(partition: P, data: D) -> Tree<P, O, D> {
        Tree {
            state: NodeState::Empty,
            partition: partition,
            data: data,
        }
    }
}

impl<P, O, D: Clone> Tree<P, O, D> {
    /// Recompute the associated data
    fn recompute_data<S, C>(&mut self, default: D, single: &S, combine: &C)
        where S: Fn(&O) -> D,
              C: Fn(&D, &D) -> D,
    {
        self.data = match self.state {
            NodeState::Empty => default,
            NodeState::Leaf(ref obj) => single(obj),
            NodeState::Branch(ref mut nodes) => {
                for node in nodes.iter_mut() {
                    node.recompute_data(default.clone(), single, combine);
                }
                nodes.iter().fold(default.clone(), |current, node| combine(&current, &node.data))
            },
        };
    }
}

impl<P, O, D> Tree<P,  O, D>
    where O: Position,
          P: Partition<<O as Position>::Point>,
          D: Clone,
{
    fn dispatch(&self, nodes: &mut Vec<Tree<P, O, D>>, object: O, default: D) {
        nodes[self.partition.dispatch(&object.position())].insert(object, default)
    }

    /// Inserts a new object into the tree
    ///
    /// NOTE: this does not update the data correctly but merely places a
    /// default value in there.
    fn insert(&mut self, object: O, default: D) {
        let mut tmp = NodeState::Empty;
        mem::swap(&mut tmp, &mut self.state);
        self.state = match tmp {
            NodeState::Empty => NodeState::Leaf(object),
            NodeState::Leaf(other) => {
                let mut nodes: Vec<_> = self.partition.subdivide()
                    .into_iter()
                    .map(|p| Tree::empty(p, default.clone()))
                    .collect();
                self.dispatch(&mut nodes, object, default.clone());
                self.dispatch(&mut nodes, other, default.clone());
                NodeState::Branch(nodes)
            },
            NodeState::Branch(mut nodes) => {
                self.dispatch(&mut nodes, object, default.clone());
                NodeState::Branch(nodes)
            },
        };
    }

    /// Construct the tree from an iterator
    pub fn new<I, S, C>(objects: I, partition: P, default: D, single: &S, combine: &C) -> Tree<P, O, D>
        where I: Iterator<Item=O>,
              S: Fn(&O) -> D,
              C: Fn(&D, &D) -> D,
    {
        let mut objects = objects;
        let mut tree = Tree::empty(partition, default.clone());
        for object in objects {
            tree.insert(object, default.clone());
        }
        tree.recompute_data(default.clone(), single, combine);
        tree
    }
}

impl<P, O, D> Node for Tree<P, O, D> {
    type Partition = P;
    type Object = O;
    type Container = Vec<Tree<P, O, D>>;

    fn state(&self) -> &NodeState<O, Vec<Tree<P, O, D>>> {
        &self.state
    }

    fn partition(&self) -> &P {
        &self.partition
    }
}

impl<P, O, D> AssociatedData for Tree<P, O, D> {
    type Data = D;

    fn data(&self) -> &D {
        &self.data
    }
}

impl<P, O, D> DataQuery for Tree<P, O, D> {
    fn query_data<R, F>(&self, recurse: &R, f: &mut F)
        where R: Fn(&Tree<P, O, D>) -> bool,
              F: FnMut(&D),
    {
        match self.state {
            NodeState::Branch(ref nodes) if recurse(self) =>
                for node in nodes.iter() {
                    node.query_data(recurse, f)
                },
            _ => f(&self.data),
        }
    }
}

impl<P, O, D> ObjectQuery for Tree<P, O, D> {
    fn query_objects<R, F>(&self, recurse: &R, f: &mut F)
        where R: Fn(&Tree<P, O, D>) -> bool,
              F: FnMut(&O),
    {
        match self.state {
            NodeState::Branch(ref nodes) if recurse(self) =>
                for node in nodes.iter() {
                    node.query_objects(recurse, f)
                },
            NodeState::Leaf(ref obj) => f(obj),
            _ => (),
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Tree, PureTree};
    use tree::{NodeState, Node, ObjectQuery, Positioned};
    use partition::Ncube;
    use std::rand::distributions::{IndependentSample, Range};
    use std::rand::thread_rng;
    use std::iter::AdditiveIterator;
    use test::Bencher;
    use nalgebra::{Pnt2, FloatPnt, Vec2, Orig};
    use quickcheck::quickcheck;

    #[test]
    fn tree_insert_into_empty() {
        let mut n = Tree::empty(Ncube::new(Pnt2::new(0.0f32, 0.0), 10.0f32), ());
        n.insert(Positioned { object: (), position: Pnt2::new(1.0f32, 0.0) }, ());
        match n.state {
            NodeState::Leaf(_) => (),
            _ => panic!("node is no leaf")
        }
    }

    #[test]
    fn tree_branch_on_second_insert() {
        let mut n = Tree::empty(Ncube::new(Pnt2::new(0.0, 0.0), 10.0), ());
        n.insert(Positioned { object: 1i32, position: Pnt2::new(1.0, -2.0) }, ());
        n.insert(Positioned { object: 2, position: Pnt2::new(2.0, 1.0) }, ());
        match n.state {
            NodeState::Branch(nodes) => {
                for k in 1..3 {
                    assert!(nodes.iter().any(|node| match node.state {
                        NodeState::Leaf(ref entry) => entry.object == k,
                        _ => false,
                    }));
                }
            },
            _ => panic!("node is no branch"),
        }
    }

    #[test]
    fn tree_from_empty_vec() {
        let tree: Tree<Ncube<Pnt2<f64>, f64>, Positioned<u8, Pnt2<f64>>, ()> =
            Tree::new(
                vec![].into_iter(),
                Ncube::new(Pnt2::new(0.0, 0.0), 1.0),
                (), &|_| (), &|_, _| ()
            );
        match tree.state {
            NodeState::Empty => (),
            _ => panic!(),
        }
    }

    #[test]
    fn tree_from_iter_more_than_two_branches() {
        fn tree_from_iter_more_than_two_branches(data: Vec<(f64, f64)>) -> bool {
            let tree = Tree::new(
                data.iter()
                .map(|&(x, y)| Positioned {
                    object: (),
                    position: Pnt2::new(x, y),
                }),
                Ncube::new(Orig::orig(), 200.0),
                (), &|_| (), &|_, _| ()
            );
            (data.len() >= 2) == (
                match tree.state {
                    NodeState::Branch(_) => true,
                    _ => false,
                }
            )
        }
        quickcheck(tree_from_iter_more_than_two_branches as fn(data: Vec<(f64, f64)>) -> bool)
    }

    #[test]
    fn tree_from_iter_one_is_a_leaf() {
        fn tree_from_iter_one_is_a_leaf(data: Vec<(f64, f64)>) -> bool {
            let tree = Tree::new(
                data.iter()
                .map(|&(x, y)| Positioned { object: (), position: Pnt2::new(x, y) }),
                Ncube::new(Orig::orig(), 200.0),
                (), &|_| (), &|_, _| ()
            );
            (data.len() == 1) == (
                match tree.state {
                    NodeState::Leaf(_) => true,
                    _ => false,
                }
            )
        }
        quickcheck(tree_from_iter_one_is_a_leaf as fn(data: Vec<(f64, f64)>) -> bool)
    }

    #[bench]
    fn pure_tree_quad_new_1000(b: &mut Bencher) {
        let coord_dist = Range::new(-1.0f64, 1.0);
        let mut rng = thread_rng();
        let vec: Vec<_> = (0..1000).map(|_| Positioned {
            object: (),
            position: Pnt2::new(
                coord_dist.ind_sample(&mut rng),
                coord_dist.ind_sample(&mut rng)
            ),
        }).collect();
        b.iter(|| {
            PureTree::new(
                vec.iter().map(|a| a.clone()),
                Ncube::new(Orig::orig(), 2.0),
            )
        })
    }

    #[bench]
    fn tree_quad_with_center_of_mass_new_1000(b: &mut Bencher) {
        let coord_dist = Range::new(-1.0f64, 1.0);
        let mut rng = thread_rng();
        let vec: Vec<_> = (0..1000).map(|_| Positioned {
            object: 1.0,
            position: Pnt2::new(
                coord_dist.ind_sample(&mut rng),
                coord_dist.ind_sample(&mut rng)
            ),
        }).collect();
        b.iter(|| {
            Tree::new(
                vec.iter().map(|a| a.clone()),
                Ncube::new(Orig::orig(), 2.0),
                (Vec2::new(0.0f64, 0.0), 0.0f64),
                &|obj| (obj.position.to_vec() * obj.object, obj.object),
                &|&(mps, ms), &(mp, m)| (mps + mp, ms + m)
            )
        })
    }

    #[bench]
    fn pure_tree_query_objects(b: &mut Bencher) {
        let coord_dist = Range::new(-1.0f64, 1.0);
        let mut rng = thread_rng();
        let search_radius = 0.3;
        let tree = PureTree::new(
            (0..1000).map(|_| Positioned {
                object: (),
                position: Pnt2::new(
                    coord_dist.ind_sample(&mut rng),
                    coord_dist.ind_sample(&mut rng)
                ),
            }),
            Ncube::new(Orig::orig(), 200.0),
        );
        b.iter(|| {
            // Count the number of objects within the search radius 10000 times
            (0..10000)
                .map(|_| {
                    let mut i: i32 = 0;
                    tree.query_objects(
                        &|node| node.partition().center().dist(&Orig::orig()) < search_radius + node.partition().width() / 2.0,
                        &mut |other| if other.position.dist(&Orig::orig()) < search_radius {i += 1},
                    );
                    i
                })
                .sum()
        })
    }
}
<commit_msg>Update to latest nightly<commit_after>//! Dimension-unspecific tree implementations

use std::mem;
use tree::{NodeState, DataQuery, ObjectQuery, AssociatedData, Node, Position};
use partition::Partition;

/// A pure N-dimensional tree
pub struct PureTree<P, O> {
    state: NodeState<O, Vec<PureTree<P, O>>>,
    partition: P,
}

impl<P, O> PureTree<P, O>
    where P: Partition<<O as Position>::Point>,
          O: Position,
{
    fn empty(partition: P) -> PureTree<P, O> {
        PureTree {
            state: NodeState::Empty,
            partition: partition,
        }
    }
}

impl<P, O> PureTree<P, O>
    where O: Position,
          P: Partition<<O as Position>::Point>,
{
    /// Construct a tree without checking the geometry of the input data
    pub fn new<I: Iterator<Item=O>>(iter: I, partition: P) -> PureTree<P, O> {
        let mut tree = PureTree::empty(partition);
        for object in iter {
            tree.insert(object)
        }
        tree
    }

    fn dispatch(&self, nodes: &mut Vec<PureTree<P, O>>, object: O) {
        nodes[self.partition.dispatch(&object.position())].insert(object)
    }

    fn insert(&mut self, object: O) {
        let mut tmp = NodeState::Empty;
        mem::swap(&mut tmp, &mut self.state);
        self.state = match tmp {
            NodeState::Empty => NodeState::Leaf(object),
            NodeState::Leaf(other) => {
                let mut nodes: Vec<_> = self.partition.subdivide()
                    .into_iter()
                    .map(|p| PureTree::empty(p))
                    .collect();
                self.dispatch(&mut nodes, object);
                self.dispatch(&mut nodes, other);
                NodeState::Branch(nodes)
            },
            NodeState::Branch(mut nodes) => {
                self.dispatch(&mut nodes, object);
                NodeState::Branch(nodes)
            }
        };
    }
}

impl<P, O> ObjectQuery for PureTree<P, O> {
    fn query_objects<R, F>(&self, recurse: &R, f: &mut F)
        where R: Fn(&PureTree<P, O>) -> bool,
              F: FnMut(&O),
    {
        match self.state {
            NodeState::Branch(ref nodes) =>
                if recurse(self) {
                    for node in nodes.iter() {
                        node.query_objects(recurse, f)
                    }
                },
            NodeState::Leaf(ref obj) => f(obj),
            _ => (),
        }
    }
}

impl<P, O> Node for PureTree<P, O> {
    type Partition = P;
    type Object = O;
    type Container = Vec<PureTree<P, O>>;

    fn state(&self) -> &NodeState<O, Vec<PureTree<P, O>>> {
        &self.state
    }

    fn partition(&self) -> &P {
        &self.partition
    }
}

/// An N-dimensional tree
///
/// This tree does not know the dimension of its point at compile time, as it is
/// not hard-coded and genericity over constants is unsupported in Rust.
pub struct Tree<P, O, D> {
    state: NodeState<O, Vec<Tree<P, O, D>>>,
    partition: P,
    data: D,
}

impl<P, O, D> Tree<P, O, D> {
    /// Construct an empty tree
    fn empty(partition: P, data: D) -> Tree<P, O, D> {
        Tree {
            state: NodeState::Empty,
            partition: partition,
            data: data,
        }
    }
}

impl<P, O, D: Clone> Tree<P, O, D> {
    /// Recompute the associated data
    fn recompute_data<S, C>(&mut self, default: D, single: &S, combine: &C)
        where S: Fn(&O) -> D,
              C: Fn(&D, &D) -> D,
    {
        self.data = match self.state {
            NodeState::Empty => default,
            NodeState::Leaf(ref obj) => single(obj),
            NodeState::Branch(ref mut nodes) => {
                for node in nodes.iter_mut() {
                    node.recompute_data(default.clone(), single, combine);
                }
                nodes.iter().fold(default.clone(), |current, node| combine(&current, &node.data))
            },
        };
    }
}

impl<P, O, D> Tree<P,  O, D>
    where O: Position,
          P: Partition<<O as Position>::Point>,
          D: Clone,
{
    fn dispatch(&self, nodes: &mut Vec<Tree<P, O, D>>, object: O, default: D) {
        nodes[self.partition.dispatch(&object.position())].insert(object, default)
    }

    /// Inserts a new object into the tree
    ///
    /// NOTE: this does not update the data correctly but merely places a
    /// default value in there.
    fn insert(&mut self, object: O, default: D) {
        let mut tmp = NodeState::Empty;
        mem::swap(&mut tmp, &mut self.state);
        self.state = match tmp {
            NodeState::Empty => NodeState::Leaf(object),
            NodeState::Leaf(other) => {
                let mut nodes: Vec<_> = self.partition.subdivide()
                    .into_iter()
                    .map(|p| Tree::empty(p, default.clone()))
                    .collect();
                self.dispatch(&mut nodes, object, default.clone());
                self.dispatch(&mut nodes, other, default.clone());
                NodeState::Branch(nodes)
            },
            NodeState::Branch(mut nodes) => {
                self.dispatch(&mut nodes, object, default.clone());
                NodeState::Branch(nodes)
            },
        };
    }

    /// Construct the tree from an iterator
    pub fn new<I, S, C>(objects: I, partition: P, default: D, single: &S, combine: &C) -> Tree<P, O, D>
        where I: Iterator<Item=O>,
              S: Fn(&O) -> D,
              C: Fn(&D, &D) -> D,
    {
        let mut tree = Tree::empty(partition, default.clone());
        for object in objects {
            tree.insert(object, default.clone());
        }
        tree.recompute_data(default.clone(), single, combine);
        tree
    }
}

impl<P, O, D> Node for Tree<P, O, D> {
    type Partition = P;
    type Object = O;
    type Container = Vec<Tree<P, O, D>>;

    fn state(&self) -> &NodeState<O, Vec<Tree<P, O, D>>> {
        &self.state
    }

    fn partition(&self) -> &P {
        &self.partition
    }
}

impl<P, O, D> AssociatedData for Tree<P, O, D> {
    type Data = D;

    fn data(&self) -> &D {
        &self.data
    }
}

impl<P, O, D> DataQuery for Tree<P, O, D> {
    fn query_data<R, F>(&self, recurse: &R, f: &mut F)
        where R: Fn(&Tree<P, O, D>) -> bool,
              F: FnMut(&D),
    {
        match self.state {
            NodeState::Branch(ref nodes) if recurse(self) =>
                for node in nodes.iter() {
                    node.query_data(recurse, f)
                },
            _ => f(&self.data),
        }
    }
}

impl<P, O, D> ObjectQuery for Tree<P, O, D> {
    fn query_objects<R, F>(&self, recurse: &R, f: &mut F)
        where R: Fn(&Tree<P, O, D>) -> bool,
              F: FnMut(&O),
    {
        match self.state {
            NodeState::Branch(ref nodes) if recurse(self) =>
                for node in nodes.iter() {
                    node.query_objects(recurse, f)
                },
            NodeState::Leaf(ref obj) => f(obj),
            _ => (),
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Tree, PureTree};
    use tree::{NodeState, Node, ObjectQuery, Positioned};
    use partition::Ncube;
    use std::rand::distributions::{IndependentSample, Range};
    use std::rand::thread_rng;
    use std::iter::AdditiveIterator;
    use test::Bencher;
    use nalgebra::{Pnt2, FloatPnt, Vec2, Orig};
    use quickcheck::quickcheck;

    #[test]
    fn tree_insert_into_empty() {
        let mut n = Tree::empty(Ncube::new(Pnt2::new(0.0f32, 0.0), 10.0f32), ());
        n.insert(Positioned { object: (), position: Pnt2::new(1.0f32, 0.0) }, ());
        match n.state {
            NodeState::Leaf(_) => (),
            _ => panic!("node is no leaf")
        }
    }

    #[test]
    fn tree_branch_on_second_insert() {
        let mut n = Tree::empty(Ncube::new(Pnt2::new(0.0, 0.0), 10.0), ());
        n.insert(Positioned { object: 1i32, position: Pnt2::new(1.0, -2.0) }, ());
        n.insert(Positioned { object: 2, position: Pnt2::new(2.0, 1.0) }, ());
        match n.state {
            NodeState::Branch(nodes) => {
                for k in 1..3 {
                    assert!(nodes.iter().any(|node| match node.state {
                        NodeState::Leaf(ref entry) => entry.object == k,
                        _ => false,
                    }));
                }
            },
            _ => panic!("node is no branch"),
        }
    }

    #[test]
    fn tree_from_empty_vec() {
        let tree: Tree<Ncube<Pnt2<f64>, f64>, Positioned<u8, Pnt2<f64>>, ()> =
            Tree::new(
                vec![].into_iter(),
                Ncube::new(Pnt2::new(0.0, 0.0), 1.0),
                (), &|_| (), &|_, _| ()
            );
        match tree.state {
            NodeState::Empty => (),
            _ => panic!(),
        }
    }

    #[test]
    fn tree_from_iter_more_than_two_branches() {
        fn tree_from_iter_more_than_two_branches(data: Vec<(f64, f64)>) -> bool {
            let tree = Tree::new(
                data.iter()
                .map(|&(x, y)| Positioned {
                    object: (),
                    position: Pnt2::new(x, y),
                }),
                Ncube::new(Orig::orig(), 200.0),
                (), &|_| (), &|_, _| ()
            );
            (data.len() >= 2) == (
                match tree.state {
                    NodeState::Branch(_) => true,
                    _ => false,
                }
            )
        }
        quickcheck(tree_from_iter_more_than_two_branches as fn(data: Vec<(f64, f64)>) -> bool)
    }

    #[test]
    fn tree_from_iter_one_is_a_leaf() {
        fn tree_from_iter_one_is_a_leaf(data: Vec<(f64, f64)>) -> bool {
            let tree = Tree::new(
                data.iter()
                .map(|&(x, y)| Positioned { object: (), position: Pnt2::new(x, y) }),
                Ncube::new(Orig::orig(), 200.0),
                (), &|_| (), &|_, _| ()
            );
            (data.len() == 1) == (
                match tree.state {
                    NodeState::Leaf(_) => true,
                    _ => false,
                }
            )
        }
        quickcheck(tree_from_iter_one_is_a_leaf as fn(data: Vec<(f64, f64)>) -> bool)
    }

    #[bench]
    fn pure_tree_quad_new_1000(b: &mut Bencher) {
        let coord_dist = Range::new(-1.0f64, 1.0);
        let mut rng = thread_rng();
        let vec: Vec<_> = (0..1000).map(|_| Positioned {
            object: (),
            position: Pnt2::new(
                coord_dist.ind_sample(&mut rng),
                coord_dist.ind_sample(&mut rng)
            ),
        }).collect();
        b.iter(|| {
            PureTree::new(
                vec.iter().map(|a| a.clone()),
                Ncube::new(Orig::orig(), 2.0),
            )
        })
    }

    #[bench]
    fn tree_quad_with_center_of_mass_new_1000(b: &mut Bencher) {
        let coord_dist = Range::new(-1.0f64, 1.0);
        let mut rng = thread_rng();
        let vec: Vec<_> = (0..1000).map(|_| Positioned {
            object: 1.0,
            position: Pnt2::new(
                coord_dist.ind_sample(&mut rng),
                coord_dist.ind_sample(&mut rng)
            ),
        }).collect();
        b.iter(|| {
            Tree::new(
                vec.iter().map(|a| a.clone()),
                Ncube::new(Orig::orig(), 2.0),
                (Vec2::new(0.0f64, 0.0), 0.0f64),
                &|obj| (obj.position.to_vec() * obj.object, obj.object),
                &|&(mps, ms), &(mp, m)| (mps + mp, ms + m)
            )
        })
    }

    #[bench]
    fn pure_tree_query_objects(b: &mut Bencher) {
        let coord_dist = Range::new(-1.0f64, 1.0);
        let mut rng = thread_rng();
        let search_radius = 0.3;
        let tree = PureTree::new(
            (0..1000).map(|_| Positioned {
                object: (),
                position: Pnt2::new(
                    coord_dist.ind_sample(&mut rng),
                    coord_dist.ind_sample(&mut rng)
                ),
            }),
            Ncube::new(Orig::orig(), 200.0),
        );
        b.iter(|| {
            // Count the number of objects within the search radius 10000 times
            (0..10000)
                .map(|_| {
                    let mut i: i32 = 0;
                    tree.query_objects(
                        &|node| node.partition().center().dist(&Orig::orig()) < search_radius + node.partition().width() / 2.0,
                        &mut |other| if other.position.dist(&Orig::orig()) < search_radius {i += 1},
                    );
                    i
                })
                .sum()
        })
    }
}
<|endoftext|>


<commit_before>//
// FlightVars
// Copyright (c) 2015, 2016 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::fmt;
use std::io;
use std::str::FromStr;

use byteorder::{BigEndian, ReadBytesExt};
use hex::FromHex;

#[derive(Debug, PartialEq)]
pub struct OffsetAddr(u16);

impl FromHex for OffsetAddr {
    type Error = io::Error;
    fn from_hex(s: &str) -> Result<Self, Self::Error> {
        let error = || io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("invalid FSUIPC offset address in '{}'", s));
        let buf: Vec<u8> = try!(FromHex::from_hex(s).map_err(|_| error()));
        if buf.len() > 2 { Err(error()) }
        else {
            (&buf[..]).read_u16::<BigEndian>()
                .map(|v| OffsetAddr(v))
                .map_err(|_| error())
        }
    }
}

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

#[derive(Debug, PartialEq)]
pub enum OffsetLen { Ub, Sb, Uw, Sw, Ud, Sd }

impl fmt::Display for OffsetLen {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            OffsetLen::Ub => write!(f, "UB"),
            OffsetLen::Sb => write!(f, "SB"),
            OffsetLen::Uw => write!(f, "UW"),
            OffsetLen::Sw => write!(f, "SW"),
            OffsetLen::Ud => write!(f, "UD"),
            OffsetLen::Sd => write!(f, "SD"),
        }
    }
}

impl FromStr for OffsetLen {
    type Err = io::Error;
    fn from_str(s: &str) -> Result<OffsetLen, io::Error> {
        match s {
            "UB" => Ok(OffsetLen::Ub),
            "SB" => Ok(OffsetLen::Sb),
            "UW" => Ok(OffsetLen::Uw),
            "SW" => Ok(OffsetLen::Sw),
            "UD" => Ok(OffsetLen::Ud),
            "SD" => Ok(OffsetLen::Sd),
            _ => Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("invalid FSUIPC offset length in '{}'", s))),
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct Offset(OffsetAddr, OffsetLen);

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

impl FromStr for Offset {
    type Err = io::Error;
    fn from_str(s: &str) -> Result<Offset, io::Error> {
        let pair: Vec<&str> = s.split(":").collect();
        if pair.len() == 2 {
            let addr = try!(OffsetAddr::from_hex(pair[0]));
            let len = try!(OffsetLen::from_str(pair[1]));
            Ok(Offset(addr, len))
        } else {
            Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("invalid FSUIPC offset in '{}'", s)))
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Message {
    Begin { version: u16, client_id: String },
    WriteLvar { lvar: String, value: i64 },
    WriteOffset { offset: Offset, value: i64 },
    ObserveLvar { lvar: String }
}

impl Message {

    pub fn begin(version: u16, client_id: &str) -> Message {
        Message::Begin { version: version, client_id: client_id.to_string() }
    }

    pub fn write_lvar(lvar: &str, value: i64) -> Message {
        Message::WriteLvar { lvar: lvar.to_string(), value: value }
    }

    pub fn write_offset(offset: Offset, value: i64) -> Message {
        Message::WriteOffset { offset: offset, value: value }
    }

    pub fn obs_lvar(lvar: &str) -> Message {
        Message::ObserveLvar { lvar: lvar.to_string() }
    }
}

impl fmt::Display for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Message::Begin { version, ref client_id } =>
                write!(f, "BEGIN {} {}", version, client_id),
            &Message::WriteLvar { ref lvar, value} =>
                write!(f, "WRITE_LVAR {} {}", lvar, value),
            &Message::WriteOffset { ref offset, value } =>
                write!(f, "WRITE_OFFSET {} {}", offset, value),
            &Message::ObserveLvar { ref lvar } =>
                write!(f, "OBS_LVAR {}", lvar),
        }
    }
}

impl FromStr for Message {
    type Err = io::Error;
    fn from_str(s: &str) -> Result<Message, io::Error> {
        let deco = MessageParser::new(s);
        deco.parse()
    }
}

pub struct MessageParser<'a> {
    input: &'a str
}

impl<'a> MessageParser<'a> {
    pub fn new(input: &'a str) -> MessageParser {
        MessageParser { input: input }
    }

    pub fn parse(self) -> io::Result<Message> {
        let args: Vec<&str> = self.input.split_whitespace().collect();
        let cmd = args[0];
        let args = &args[1..];
        match &cmd.to_uppercase()[..] {
            "BEGIN" => self.parse_begin(&args),
            "WRITE_LVAR" => self.parse_write_lvar(&args),
            "WRITE_OFFSET" => self.parse_write_offset(&args),
            "OBS_LVAR" => self.parse_obs_lvar(&args),
            _ => Err(self.input_error()),
        }
    }

    fn parse_begin(self, args: &[&str]) -> io::Result<Message> {
        try!(self.require_argc(args, 2));
        let ver = try!(args[0].parse().map_err(|_| self.input_error()));
        Ok(Message::begin(ver, args[1]))
    }

    fn parse_write_lvar(self, args: &[&str]) -> io::Result<Message> {
        try!(self.require_argc(args, 2));
        let lvar = args[0];
        let value = try!(args[1].parse().map_err(|_| self.input_error()));
        Ok(Message::write_lvar(&lvar, value))
    }

    fn parse_write_offset(self, args: &[&str]) -> io::Result<Message> {
        try!(self.require_argc(args, 2));
        let offset = try!(args[0].parse());
        let value = try!(args[1].parse().map_err(|_| self.input_error()));
        Ok(Message::write_offset(offset, value))
    }

    fn parse_obs_lvar(self, args: &[&str]) -> io::Result<Message> {
        try!(self.require_argc(args, 1));
        Ok(Message::obs_lvar(args[0]))
    }

    fn require_argc(&self, args: &[&str], expected: usize) -> io::Result<()> {
        if args.len() == expected { Ok(()) }
        else { Err(self.input_error()) }
    }

    fn input_error(&self) -> io::Error {
        io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("invalid oacsp message in '{}'", self.input))
    }
}

#[cfg(test)]
mod tests {
    use std::str::FromStr;

    use super::*;

    #[test]
    fn should_display_begin_msg() {
        let msg = Message::begin(1, "arduino");
        let buf = format!("{}", msg);
        assert_eq!(buf, "BEGIN 1 arduino")
    }

    #[test]
    fn should_parse_begin_msg() {
        let buf = "BEGIN 1 arduino";
        let msg = Message::from_str(&buf).unwrap();
        assert_eq!(msg, Message::begin(1, "arduino"));
    }

    #[test]
    fn should_display_write_lvar_msg() {
        let msg = Message::write_lvar("foobar", 42);
        let buf = format!("{}", msg);
        assert_eq!(buf, "WRITE_LVAR foobar 42")
    }

    #[test]
    fn should_parse_write_lvar_msg() {
        let buf = "WRITE_LVAR foobar 42";
        let msg = Message::from_str(&buf).unwrap();
        assert_eq!(msg, Message::write_lvar("foobar", 42));
    }

    #[test]
    fn should_display_write_offset_msg() {
        let msg = Message::write_offset(Offset(OffsetAddr(0x1234), OffsetLen::Uw), 42);
        let buf = format!("{}", msg);
        assert_eq!(buf, "WRITE_OFFSET 1234:UW 42")
    }

    #[test]
    fn should_parse_write_offset_msg() {
        let buf = "WRITE_OFFSET 1234:UW 42";
        let msg = Message::from_str(&buf).unwrap();
        assert_eq!(msg, Message::write_offset(Offset(OffsetAddr(0x1234), OffsetLen::Uw), 42));
    }

    #[test]
    fn should_display_obs_lvar_msg() {
        let msg = Message::obs_lvar("foobar");
        let buf = format!("{}", msg);
        assert_eq!(buf, "OBS_LVAR foobar")
    }

    #[test]
    fn should_parse_obs_lvar_msg() {
        let buf = "OBS_LVAR foobar";
        let msg = Message::from_str(&buf).unwrap();
        assert_eq!(msg, Message::obs_lvar("foobar"));
    }
}
<commit_msg>Introduce  `ObserveOffset` message in `oacsp`<commit_after>//
// FlightVars
// Copyright (c) 2015, 2016 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::fmt;
use std::io;
use std::str::FromStr;

use byteorder::{BigEndian, ReadBytesExt};
use hex::FromHex;

#[derive(Debug, PartialEq)]
pub struct OffsetAddr(u16);

impl FromHex for OffsetAddr {
    type Error = io::Error;
    fn from_hex(s: &str) -> Result<Self, Self::Error> {
        let error = || io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("invalid FSUIPC offset address in '{}'", s));
        let buf: Vec<u8> = try!(FromHex::from_hex(s).map_err(|_| error()));
        if buf.len() > 2 { Err(error()) }
        else {
            (&buf[..]).read_u16::<BigEndian>()
                .map(|v| OffsetAddr(v))
                .map_err(|_| error())
        }
    }
}

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

#[derive(Debug, PartialEq)]
pub enum OffsetLen { Ub, Sb, Uw, Sw, Ud, Sd }

impl fmt::Display for OffsetLen {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            OffsetLen::Ub => write!(f, "UB"),
            OffsetLen::Sb => write!(f, "SB"),
            OffsetLen::Uw => write!(f, "UW"),
            OffsetLen::Sw => write!(f, "SW"),
            OffsetLen::Ud => write!(f, "UD"),
            OffsetLen::Sd => write!(f, "SD"),
        }
    }
}

impl FromStr for OffsetLen {
    type Err = io::Error;
    fn from_str(s: &str) -> Result<OffsetLen, io::Error> {
        match s {
            "UB" => Ok(OffsetLen::Ub),
            "SB" => Ok(OffsetLen::Sb),
            "UW" => Ok(OffsetLen::Uw),
            "SW" => Ok(OffsetLen::Sw),
            "UD" => Ok(OffsetLen::Ud),
            "SD" => Ok(OffsetLen::Sd),
            _ => Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("invalid FSUIPC offset length in '{}'", s))),
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct Offset(OffsetAddr, OffsetLen);

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

impl FromStr for Offset {
    type Err = io::Error;
    fn from_str(s: &str) -> Result<Offset, io::Error> {
        let pair: Vec<&str> = s.split(":").collect();
        if pair.len() == 2 {
            let addr = try!(OffsetAddr::from_hex(pair[0]));
            let len = try!(OffsetLen::from_str(pair[1]));
            Ok(Offset(addr, len))
        } else {
            Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("invalid FSUIPC offset in '{}'", s)))
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Message {
    Begin { version: u16, client_id: String },
    WriteLvar { lvar: String, value: i64 },
    WriteOffset { offset: Offset, value: i64 },
    ObserveLvar { lvar: String },
    ObserveOffset { offset: Offset }
}

impl Message {

    pub fn begin(version: u16, client_id: &str) -> Message {
        Message::Begin { version: version, client_id: client_id.to_string() }
    }

    pub fn write_lvar(lvar: &str, value: i64) -> Message {
        Message::WriteLvar { lvar: lvar.to_string(), value: value }
    }

    pub fn write_offset(offset: Offset, value: i64) -> Message {
        Message::WriteOffset { offset: offset, value: value }
    }

    pub fn obs_lvar(lvar: &str) -> Message {
        Message::ObserveLvar { lvar: lvar.to_string() }
    }

    pub fn obs_offset(offset: Offset) -> Message {
        Message::ObserveOffset { offset: offset }
    }
}

impl fmt::Display for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Message::Begin { version, ref client_id } =>
                write!(f, "BEGIN {} {}", version, client_id),
            &Message::WriteLvar { ref lvar, value} =>
                write!(f, "WRITE_LVAR {} {}", lvar, value),
            &Message::WriteOffset { ref offset, value } =>
                write!(f, "WRITE_OFFSET {} {}", offset, value),
            &Message::ObserveLvar { ref lvar } =>
                write!(f, "OBS_LVAR {}", lvar),
            &Message::ObserveOffset { ref offset } =>
                write!(f, "OBS_OFFSET {}", offset),
        }
    }
}

impl FromStr for Message {
    type Err = io::Error;
    fn from_str(s: &str) -> Result<Message, io::Error> {
        let deco = MessageParser::new(s);
        deco.parse()
    }
}

pub struct MessageParser<'a> {
    input: &'a str
}

impl<'a> MessageParser<'a> {
    pub fn new(input: &'a str) -> MessageParser {
        MessageParser { input: input }
    }

    pub fn parse(self) -> io::Result<Message> {
        let args: Vec<&str> = self.input.split_whitespace().collect();
        let cmd = args[0];
        let args = &args[1..];
        match &cmd.to_uppercase()[..] {
            "BEGIN" => self.parse_begin(&args),
            "WRITE_LVAR" => self.parse_write_lvar(&args),
            "WRITE_OFFSET" => self.parse_write_offset(&args),
            "OBS_LVAR" => self.parse_obs_lvar(&args),
            "OBS_OFFSET" => self.parse_obs_offset(&args),
            _ => Err(self.input_error()),
        }
    }

    fn parse_begin(self, args: &[&str]) -> io::Result<Message> {
        try!(self.require_argc(args, 2));
        let ver = try!(args[0].parse().map_err(|_| self.input_error()));
        Ok(Message::begin(ver, args[1]))
    }

    fn parse_write_lvar(self, args: &[&str]) -> io::Result<Message> {
        try!(self.require_argc(args, 2));
        let lvar = args[0];
        let value = try!(args[1].parse().map_err(|_| self.input_error()));
        Ok(Message::write_lvar(&lvar, value))
    }

    fn parse_write_offset(self, args: &[&str]) -> io::Result<Message> {
        try!(self.require_argc(args, 2));
        let offset = try!(args[0].parse());
        let value = try!(args[1].parse().map_err(|_| self.input_error()));
        Ok(Message::write_offset(offset, value))
    }

    fn parse_obs_lvar(self, args: &[&str]) -> io::Result<Message> {
        try!(self.require_argc(args, 1));
        Ok(Message::obs_lvar(args[0]))
    }

    fn parse_obs_offset(self, args: &[&str]) -> io::Result<Message> {
        try!(self.require_argc(args, 1));
        Ok(Message::obs_offset(try!(args[0].parse())))
    }

    fn require_argc(&self, args: &[&str], expected: usize) -> io::Result<()> {
        if args.len() == expected { Ok(()) }
        else { Err(self.input_error()) }
    }

    fn input_error(&self) -> io::Error {
        io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("invalid oacsp message in '{}'", self.input))
    }
}

#[cfg(test)]
mod tests {
    use std::str::FromStr;

    use super::*;

    #[test]
    fn should_display_begin_msg() {
        let msg = Message::begin(1, "arduino");
        let buf = format!("{}", msg);
        assert_eq!(buf, "BEGIN 1 arduino")
    }

    #[test]
    fn should_parse_begin_msg() {
        let buf = "BEGIN 1 arduino";
        let msg = Message::from_str(&buf).unwrap();
        assert_eq!(msg, Message::begin(1, "arduino"));
    }

    #[test]
    fn should_display_write_lvar_msg() {
        let msg = Message::write_lvar("foobar", 42);
        let buf = format!("{}", msg);
        assert_eq!(buf, "WRITE_LVAR foobar 42")
    }

    #[test]
    fn should_parse_write_lvar_msg() {
        let buf = "WRITE_LVAR foobar 42";
        let msg = Message::from_str(&buf).unwrap();
        assert_eq!(msg, Message::write_lvar("foobar", 42));
    }

    #[test]
    fn should_display_write_offset_msg() {
        let msg = Message::write_offset(Offset(OffsetAddr(0x1234), OffsetLen::Uw), 42);
        let buf = format!("{}", msg);
        assert_eq!(buf, "WRITE_OFFSET 1234:UW 42")
    }

    #[test]
    fn should_parse_write_offset_msg() {
        let buf = "WRITE_OFFSET 1234:UW 42";
        let msg = Message::from_str(&buf).unwrap();
        assert_eq!(msg, Message::write_offset(Offset(OffsetAddr(0x1234), OffsetLen::Uw), 42));
    }

    #[test]
    fn should_display_obs_lvar_msg() {
        let msg = Message::obs_lvar("foobar");
        let buf = format!("{}", msg);
        assert_eq!(buf, "OBS_LVAR foobar")
    }

    #[test]
    fn should_parse_obs_lvar_msg() {
        let buf = "OBS_LVAR foobar";
        let msg = Message::from_str(&buf).unwrap();
        assert_eq!(msg, Message::obs_lvar("foobar"));
    }

    #[test]
    fn should_display_obs_offset_msg() {
        let msg = Message::obs_offset(Offset(OffsetAddr(0x1234), OffsetLen::Uw));
        let buf = format!("{}", msg);
        assert_eq!(buf, "OBS_OFFSET 1234:UW")
    }

    #[test]
    fn should_parse_obs_offset_msg() {
        let buf = "OBS_OFFSET 1234:UW";
        let msg = Message::from_str(&buf).unwrap();
        assert_eq!(msg, Message::obs_offset(Offset(OffsetAddr(0x1234), OffsetLen::Uw)));
    }
}
<|endoftext|>


<commit_before>mod testdata;
use testdata::{
    newton,
    generate_data,
    NEWTON_ITER,
    SETLEN
};

use std::time::SystemTime;
use std::thread;
use std::thread::JoinHandle;
use std::iter::Map;
use std::slice::Chunks;
use std::sync::Arc;

const THREADS: usize = 4;

fn main() {
    let data = generate_data(SETLEN/10);
    println!("generiere {} testdaten", SETLEN/10);
    let earlier = SystemTime::now();
    let _new_data = map_data(data);
    let dur = match SystemTime::now().duration_since(earlier) {
        Ok(v) => v,
        Err(e) => {
            println!("messfehler: {}", e);
            return;
        }
    };
    println!("duration: {}.{} secs", dur.as_secs(), dur.subsec_nanos());
}

fn map_data(data: Vec<f64>) -> Vec<f64> {
    let chunklen = data.len() / THREADS + 1;
    data.chunks(chunklen)
        .map(|x: Chunks<&[f64]> | -> JoinHandle<Map<&[f64], Fn(&f64) -> f64>>{ //über slices
            //für jeden slice einen thread spawnen, der über den slice iteriert, und newton darauf anwendet.
            thread::spawn(move || x.map(|y| {
                newton(*y, NEWTON_ITER)
            })) //Rückgabewert: ThreadHandle<Map<f64>>
        })
        .map(|handle| handle.join().expect("failed to join"))
        .flat_map(|x| x)
        .collect()
}

/*fn map_data(data: Vec<f64>) -> Vec<f64> {
    let chunklen = data.len() / THREADS + 1;
    let chunks: Chunks<f64> = data.chunks(chunklen);
    chunks.map(|x: &[f64]| x);
    vec!()
}*/<commit_msg>implemented pmap2 properly<commit_after>mod testdata;
use testdata::{
    newton,
    generate_data,
    NEWTON_ITER,
    SETLEN
};

use std::time::SystemTime;
use std::thread;
use std::thread::JoinHandle;
use std::iter::Map;
use std::slice::Chunks;
use std::sync::Arc;
use std::boxed::Box;
use std::sync::Mutex;

const THREADS: usize = 4;

fn main() {
    let data = generate_data(SETLEN);
    println!("generiere {} testdaten", SETLEN);
    let earlier = SystemTime::now();
    let _new_data = map_data(data);
    let dur = match SystemTime::now().duration_since(earlier) {
        Ok(v) => v,
        Err(e) => {
            println!("messfehler: {}", e);
            return;
        }
    };
    println!("duration: {}.{} secs", dur.as_secs(), dur.subsec_nanos());
}

fn map_data(data: Vec<f64>) -> Vec<f64> {
    let mut handles:Vec<JoinHandle<Vec<f64>>> = Vec::new();
    let mut data: Vec<Arc<_>> = data.chunks(data.len()/THREADS + 1).
                                        map(|x| Arc::new(x.to_owned())).collect();
    println!("{}", data.len());
    for d in data {
        handles.push(thread::spawn(move || d.iter().map(|x| newton(*x, NEWTON_ITER)).collect()));
    }
    let mut ret = Vec::with_capacity(THREADS);
    for handle in handles {
        ret.push(handle.join().unwrap());
    }
    ret.into_iter().flat_map(|x| x).collect()
}
<|endoftext|>