<commit_before>//! The parser works based on the following grammar
//!
//! Equation ==> Term { "+" Term }
//!           |  Term { "-" Term }
//!
//! Term     ==> Function Product
//!           |  Product
//!
//! Product  ==> Factor { "*" Factor }
//!           |  Factor { "/" Factor }
//!
//! Factor   ==> "-" Factor
//!           |  Exponent { "^" Factor }
//!
//! Exponent ==> Number { "!" }
//!
//! Number   ==> "(" Equation ")"
//!           |  "|" Equation "|"
//!           |  Constant
//!           |  { Digit }
//!
//! Function ==> "sin" | "cos" | "tan" | "asin" | "acos" | "atan" | "sqrt" | "abs" | "exp"
//!           |  "ln" | "log"
//!
//! Constant ==> "pi" | "e" | "phi"
//!
//! Digit    ==> "0".."9"

use std::str::Chars;
use std::iter::Peekable;
use errors::{CalcrResult, CalcrError};
use ast::{Ast, AstFunc};
use ast::AstBranch::*;
use ast::AstVal::*;
use ast::AstFunc::*;
use ast::AstOp::*;
use ast::AstConst::*;

pub fn parse_equation(eq: String) -> CalcrResult<Ast> {
	let mut parser = Parser {
		pos: 0,
		iter: eq.chars().peekable(),
		paren_level: 0,
		abs_level: 0,
	};
	parser.parse_equation()
}

pub struct Parser<'a> {
    pos: usize,
    iter: Peekable<Chars<'a>>,
    paren_level: u32,
    abs_level: u32,
}

impl<'a> Parser<'a> {
    fn parse_equation(&mut self) -> CalcrResult<Ast> {
        let mut lhs = try!(self.parse_term());
        self.consume_whitespace();
        while self.peek_char() == Some('+') || self.peek_char() == Some('-') {
            let op_pos = self.pos;
            let op = if self.consume_char() == '+' {
                Plus
            } else {
                Minus
            };
            self.consume_whitespace();
            let rhs = try!(self.parse_term());
            lhs = Ast {
                val: Op(op),
                span: (op_pos, op_pos),
                branches: Binary(Box::new(lhs), Box::new(rhs)),
            };
            self.consume_whitespace();
        }
        if self.peek_char() == Some(')') && self.paren_level < 1 {
            Err(CalcrError {
                desc: format!("Missing opening parentheses"),
                span: (self.pos, self.pos),
            })
        } else if self.peek_char() == Some('|') && self.abs_level < 1 {
            Err(CalcrError {
                desc: format!("Missing opening abs delimiter"),
                span: (self.pos, self.pos),
            })
        } else {
            Ok(lhs)
        }
    }

    fn parse_term(&mut self) -> CalcrResult<Ast> {
        let begin_pos = self.pos;
        if let Some(func) = self.consume_function() {
            let end_pos = self.pos;
            self.consume_whitespace();
            let arg = try!(self.parse_product());
            Ok(Ast {
                val: Func(func),
                span: (begin_pos, end_pos),
                branches: Unary(Box::new(arg)),
            })
        } else {
            self.parse_product()
        }
    }

    fn parse_product(&mut self) -> CalcrResult<Ast> {
        let mut lhs = try!(self.parse_factor());
        self.consume_whitespace();
        while self.peek_char() == Some('*') || self.peek_char() == Some('/') {
            let op_pos = self.pos;
            let op = if self.consume_char() == '*' {
                Mult
            } else {
                Div
            };
            self.consume_whitespace();
            let rhs = try!(self.parse_factor());
            lhs = Ast {
                val: Op(op),
                span: (op_pos, op_pos),
                branches: Binary(Box::new(lhs), Box::new(rhs)),
            };
            self.consume_whitespace();
        }
        Ok(lhs)
    }

    fn parse_factor(&mut self) -> CalcrResult<Ast> {
        if self.peek_char() == Some('-') {
            let op_pos = self.pos;
            self.consume_char();
            let rhs = try!(self.parse_factor());
            Ok(Ast {
                val: Op(Neg),
                span: (op_pos, op_pos),
                branches: Unary(Box::new(rhs)),
            })
        } else {
            let lhs = try!(self.parse_exponent());
            if self.peek_char() == Some('^') {
                let op_pos = self.pos;
                self.consume_char();
                let rhs = try!(self.parse_factor());
                Ok(Ast {
                    val: Op(Pow),
                    span: (op_pos, op_pos),
                    branches: Binary(Box::new(lhs), Box::new(rhs)),
                })
            } else {
                Ok(lhs)
            }
        }
    }

    fn parse_exponent(&mut self) -> CalcrResult<Ast> {
        let mut out = try!(self.parse_number());
        self.consume_whitespace();

        // we don't parse the factorial signs (`!`) using recursion, since we need to put the
        // current `out` at the bottum of the tree at each step, so it is easier if we have access
        // to each node as we create them.
        while self.peek_char() == Some('!') {
            let op_pos = self.pos;
            self.consume_char();
            self.consume_whitespace();
            out = Ast {
                val: Op(Fact),
                span: (op_pos, op_pos),
                branches: Unary(Box::new(out)),
            };
        }
        Ok(out)
    }

    fn parse_number(&mut self) -> CalcrResult<Ast> {
        match self.peek_char() {
            Some('(') => {
                // store the current pos in case we need to report a paren error
                let pre_pos = self.pos;
                self.consume_char();
                self.consume_whitespace();
                self.paren_level += 1;
                let eq = try!(self.parse_equation());

                if self.eof() || self.consume_char() != ')' {
                    Err(CalcrError {
                        desc: "Missing closing parentheses".to_string(),
                        span: (pre_pos, pre_pos),
                    })
                } else {
                    self.paren_level -= 1;
                    Ok(eq)
                }
            },
            Some('|') => {
                // store the current pos in case we need to report an abs delim error
                let pre_pos = self.pos;
                self.consume_char();
                self.consume_whitespace();
                self.abs_level += 1;
                let eq = try!(self.parse_equation());

                if self.eof() || self.consume_char() != '|' {
                    Err(CalcrError {
                        desc: "Missing closing abs delimiter".to_string(),
                        span: (pre_pos, pre_pos),
                    })
                } else {
                    self.abs_level -= 1;
                    Ok(Ast {
                        val: Func(Abs),
                        span: (pre_pos, pre_pos),
                        branches: Unary(Box::new(eq)),
                    })
                }
            },
            Some(ch) if ch.is_alphabetic() => {
                let cnst_str = self.consume_while(|ch| ch.is_alphabetic());
                let cnst = match cnst_str.as_ref() {
                    "pi" => Pi,
                    "e" => E,
                    "phi" => Phi,
                    _ => return Err(CalcrError {
                        desc: format!("Invalid function or constant: {}", cnst_str),
                        span: (self.pos - cnst_str.len(), self.pos),
                    }),
                };
                Ok(Ast {
                    val: Const(cnst),
                    span: (self.pos - cnst_str.len(), self.pos),
                    branches: Leaf,
                })
            },
            Some(ch) if ch.is_numeric() => {
                let num_str = self.consume_while(|ch| ch.is_numeric() || ch == '.');
                if let Ok(num) = num_str.parse::<f64>() {
                    Ok(Ast {
                        val: Num(num),
                        span: (self.pos - num_str.len(), self.pos),
                        branches: Leaf,
                    })
                } else {
                    Err(CalcrError {
                        desc: format!("Invalid number: {}", num_str),
                        span: (self.pos - num_str.len(), self.pos),
                    })
                }
            },
            _ => Err(CalcrError {
                desc: format!("Expected number or constant"),
                span: (self.pos, self.pos),
            }),
        }
    }

    fn consume_function(&mut self) -> Option<AstFunc> {
        let pre_pos = self.pos;
        match self.consume_while(|ch| ch.is_alphabetic()).as_ref() {
            "sin" => Some(Sin),
            "cos" => Some(Cos),
            "tan" => Some(Tan),
            "asin" => Some(Asin),
            "acos" => Some(Acos),
            "atan" => Some(Atan),
            "sqrt" => Some(Sqrt),
            "abs" => Some(Abs),
            "exp" => Some(Exp),
            "ln" => Some(Ln),
            "log" => Some(Log),
            _ => {
                // no function found, so restore the previous position
                self.pos = pre_pos;
                None
            },
        }
    }

    /// Peeks at the next `char` and returns `Some` if one was found, or `None` if none are left
    fn peek_char(&mut self) -> Option<char> {
        self.iter.peek().map(|ch| *ch)
    }

    /// Consumes a `char` - thereby advanding `pos` - and returns it
    ///
    /// # Panics
    /// This function panics if there are no more chars to consume
    fn consume_char(&mut self) -> char {
        let ch = self.iter.next();
        self.pos += 1;
        ch.unwrap().to_lowercase().next().unwrap()
    }

    /// Consumes `char`s long as `pred` returns true and we are not eof
    ///
    /// The `char`s are returned as a `String`. Note that unlike `consume_char` this function will
    /// not panic.
    fn consume_while<F>(&mut self, pred: F) -> String where F: Fn(char) -> bool {
        let mut out = String::new();
        loop {
            match self.peek_char() {
                Some(ch) if pred(ch) => out.push(self.consume_char()),
                _ => break,
            }
        }
        out
    }

    /// Consumes any current whitespace
    fn consume_whitespace(&mut self) {
        self.consume_while(|ch| ch.is_whitespace());
    }

    /// Returns true if we are the end of input
    fn eof(&mut self) -> bool {
        self.iter.peek().is_none()
    }
}<commit_msg>Fix bug in parser when consuming functions<commit_after>//! The parser works based on the following grammar
//!
//! Equation ==> Term { "+" Term }
//!           |  Term { "-" Term }
//!
//! Term     ==> Function Product
//!           |  Product
//!
//! Product  ==> Factor { "*" Factor }
//!           |  Factor { "/" Factor }
//!
//! Factor   ==> "-" Factor
//!           |  Exponent { "^" Factor }
//!
//! Exponent ==> Number { "!" }
//!
//! Number   ==> "(" Equation ")"
//!           |  "|" Equation "|"
//!           |  Constant
//!           |  { Digit }
//!
//! Function ==> "sin" | "cos" | "tan" | "asin" | "acos" | "atan" | "sqrt" | "abs" | "exp"
//!           |  "ln" | "log"
//!
//! Constant ==> "pi" | "e" | "phi"
//!
//! Digit    ==> "0".."9"

use std::str::Chars;
use std::iter::Peekable;
use errors::{CalcrResult, CalcrError};
use ast::{Ast, AstFunc};
use ast::AstBranch::*;
use ast::AstVal::*;
use ast::AstFunc::*;
use ast::AstOp::*;
use ast::AstConst::*;

pub fn parse_equation(eq: String) -> CalcrResult<Ast> {
	let mut parser = Parser {
		pos: 0,
		iter: eq.chars().peekable(),
		paren_level: 0,
		abs_level: 0,
	};
	parser.parse_equation()
}

pub struct Parser<'a> {
    pos: usize,
    iter: Peekable<Chars<'a>>,
    paren_level: u32,
    abs_level: u32,
}

impl<'a> Parser<'a> {
    fn parse_equation(&mut self) -> CalcrResult<Ast> {
        let mut lhs = try!(self.parse_term());
        self.consume_whitespace();
        while self.peek_char() == Some('+') || self.peek_char() == Some('-') {
            let op_pos = self.pos;
            let op = if self.consume_char() == '+' {
                Plus
            } else {
                Minus
            };
            self.consume_whitespace();
            let rhs = try!(self.parse_term());
            lhs = Ast {
                val: Op(op),
                span: (op_pos, op_pos),
                branches: Binary(Box::new(lhs), Box::new(rhs)),
            };
            self.consume_whitespace();
        }
        if self.peek_char() == Some(')') && self.paren_level < 1 {
            Err(CalcrError {
                desc: format!("Missing opening parentheses"),
                span: (self.pos, self.pos),
            })
        } else if self.peek_char() == Some('|') && self.abs_level < 1 {
            Err(CalcrError {
                desc: format!("Missing opening abs delimiter"),
                span: (self.pos, self.pos),
            })
        } else {
            Ok(lhs)
        }
    }

    fn parse_term(&mut self) -> CalcrResult<Ast> {
        let begin_pos = self.pos;
        if let Some(func) = self.consume_function() {
            let end_pos = self.pos;
            self.consume_whitespace();
            let arg = try!(self.parse_product());
            Ok(Ast {
                val: Func(func),
                span: (begin_pos, end_pos),
                branches: Unary(Box::new(arg)),
            })
        } else {
            self.parse_product()
        }
    }

    fn parse_product(&mut self) -> CalcrResult<Ast> {
        let mut lhs = try!(self.parse_factor());
        self.consume_whitespace();
        while self.peek_char() == Some('*') || self.peek_char() == Some('/') {
            let op_pos = self.pos;
            let op = if self.consume_char() == '*' {
                Mult
            } else {
                Div
            };
            self.consume_whitespace();
            let rhs = try!(self.parse_factor());
            lhs = Ast {
                val: Op(op),
                span: (op_pos, op_pos),
                branches: Binary(Box::new(lhs), Box::new(rhs)),
            };
            self.consume_whitespace();
        }
        Ok(lhs)
    }

    fn parse_factor(&mut self) -> CalcrResult<Ast> {
        if self.peek_char() == Some('-') {
            let op_pos = self.pos;
            self.consume_char();
            let rhs = try!(self.parse_factor());
            Ok(Ast {
                val: Op(Neg),
                span: (op_pos, op_pos),
                branches: Unary(Box::new(rhs)),
            })
        } else {
            let lhs = try!(self.parse_exponent());
            if self.peek_char() == Some('^') {
                let op_pos = self.pos;
                self.consume_char();
                let rhs = try!(self.parse_factor());
                Ok(Ast {
                    val: Op(Pow),
                    span: (op_pos, op_pos),
                    branches: Binary(Box::new(lhs), Box::new(rhs)),
                })
            } else {
                Ok(lhs)
            }
        }
    }

    fn parse_exponent(&mut self) -> CalcrResult<Ast> {
        let mut out = try!(self.parse_number());
        self.consume_whitespace();

        // we don't parse the factorial signs (`!`) using recursion, since we need to put the
        // current `out` at the bottum of the tree at each step, so it is easier if we have access
        // to each node as we create them.
        while self.peek_char() == Some('!') {
            let op_pos = self.pos;
            self.consume_char();
            self.consume_whitespace();
            out = Ast {
                val: Op(Fact),
                span: (op_pos, op_pos),
                branches: Unary(Box::new(out)),
            };
        }
        Ok(out)
    }

    fn parse_number(&mut self) -> CalcrResult<Ast> {
        match self.peek_char() {
            Some('(') => {
                // store the current pos in case we need to report a paren error
                let pre_pos = self.pos;
                self.consume_char();
                self.consume_whitespace();
                self.paren_level += 1;
                let eq = try!(self.parse_equation());

                if self.eof() || self.consume_char() != ')' {
                    Err(CalcrError {
                        desc: "Missing closing parentheses".to_string(),
                        span: (pre_pos, pre_pos),
                    })
                } else {
                    self.paren_level -= 1;
                    Ok(eq)
                }
            },
            Some('|') => {
                // store the current pos in case we need to report an abs delim error
                let pre_pos = self.pos;
                self.consume_char();
                self.consume_whitespace();
                self.abs_level += 1;
                let eq = try!(self.parse_equation());

                if self.eof() || self.consume_char() != '|' {
                    Err(CalcrError {
                        desc: "Missing closing abs delimiter".to_string(),
                        span: (pre_pos, pre_pos),
                    })
                } else {
                    self.abs_level -= 1;
                    Ok(Ast {
                        val: Func(Abs),
                        span: (pre_pos, pre_pos),
                        branches: Unary(Box::new(eq)),
                    })
                }
            },
            Some(ch) if ch.is_alphabetic() => {
                let cnst_str = self.consume_while(|ch| ch.is_alphabetic());
                let cnst = match cnst_str.as_ref() {
                    "pi" => Pi,
                    "e" => E,
                    "phi" => Phi,
                    _ => return Err(CalcrError {
                        desc: format!("Invalid function or constant: {}", cnst_str),
                        span: (self.pos - cnst_str.len(), self.pos),
                    }),
                };
                Ok(Ast {
                    val: Const(cnst),
                    span: (self.pos - cnst_str.len(), self.pos),
                    branches: Leaf,
                })
            },
            Some(ch) if ch.is_numeric() => {
                let num_str = self.consume_while(|ch| ch.is_numeric() || ch == '.');
                if let Ok(num) = num_str.parse::<f64>() {
                    Ok(Ast {
                        val: Num(num),
                        span: (self.pos - num_str.len(), self.pos),
                        branches: Leaf,
                    })
                } else {
                    Err(CalcrError {
                        desc: format!("Invalid number: {}", num_str),
                        span: (self.pos - num_str.len(), self.pos),
                    })
                }
            },
            _ => Err(CalcrError {
                desc: format!("Expected number or constant"),
                span: (self.pos, self.pos),
            }),
        }
    }

    fn consume_function(&mut self) -> Option<AstFunc> {
        let pre_pos = self.pos;
        let pre_iter = self.iter.clone();
        match self.consume_while(|ch| ch.is_alphabetic()).as_ref() {
            "sin" => Some(Sin),
            "cos" => Some(Cos),
            "tan" => Some(Tan),
            "asin" => Some(Asin),
            "acos" => Some(Acos),
            "atan" => Some(Atan),
            "sqrt" => Some(Sqrt),
            "abs" => Some(Abs),
            "exp" => Some(Exp),
            "ln" => Some(Ln),
            "log" => Some(Log),
            _ => {
                // no function found, so restore the previous position
                self.iter = pre_iter;
                self.pos = pre_pos;
                None
            },
        }
    }

    /// Peeks at the next `char` and returns `Some` if one was found, or `None` if none are left
    fn peek_char(&mut self) -> Option<char> {
        self.iter.peek().map(|ch| *ch)
    }

    /// Consumes a `char` - thereby advanding `pos` - and returns it
    ///
    /// # Panics
    /// This function panics if there are no more chars to consume
    fn consume_char(&mut self) -> char {
        let ch = self.iter.next();
        self.pos += 1;
        ch.unwrap().to_lowercase().next().unwrap()
    }

    /// Consumes `char`s long as `pred` returns true and we are not eof
    ///
    /// The `char`s are returned as a `String`. Note that unlike `consume_char` this function will
    /// not panic.
    fn consume_while<F>(&mut self, pred: F) -> String where F: Fn(char) -> bool {
        let mut out = String::new();
        loop {
            match self.peek_char() {
                Some(ch) if pred(ch) => out.push(self.consume_char()),
                _ => break,
            }
        }
        out
    }

    /// Consumes any current whitespace
    fn consume_whitespace(&mut self) {
        self.consume_while(|ch| ch.is_whitespace());
    }

    /// Returns true if we are the end of input
    fn eof(&mut self) -> bool {
        self.iter.peek().is_none()
    }
}<|endoftext|>


<commit_before>#[cfg(feature = "regex1")]
use regex::Regex;
use serde_json::{Value, Map, Number};
use url::percent_encoding::percent_decode;

use merge::merge;
use helpers::{create_array, push_item_to_array};

#[cfg(feature = "regex1")]
lazy_static! {
    static ref PARENT_REGEX: Regex = Regex::new(r"^([^\]\[]+)").unwrap();
    static ref CHILD_REGEX: Regex = Regex::new(r"(\[[^\]\[]*\])").unwrap();
}

type Object = Map<String, Value>;

#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum ParseErrorKind {
    DecodingError,
    Other
}

#[derive(Debug)]
pub struct ParseError {
    pub kind: ParseErrorKind,
    pub message: String
}

pub type ParseResult<T> = Result<T,ParseError>;

pub fn decode_component(source: &str) -> Result<String,String> {
    let result = percent_decode(source.as_bytes()).decode_utf8_lossy().to_string();
    return Ok(result);
}

fn parse_pair(part: &str) -> (&str, Option<&str>) {
    let separator = part.find("]=")
                        .and_then(|pos| Some(pos+1))
                        .or_else(|| part.find("="));
    match separator {
        None => return (part, None),
        Some(pos) => {
            let key = &part[..pos];
            let val = &part[(pos + 1)..];
            return (key, Some(val));
        }
    }
}

fn parse_pairs(body: &str) -> Vec<(&str, Option<&str>)> {
    let mut pairs = vec![];
    for part in body.split("&") {
        pairs.push(parse_pair(part));
    }
    return pairs
}

#[cfg(feature = "regex1")]
fn parse_key(key: &str) -> ParseResult<Vec<String>> {
    let mut keys: Vec<String> = vec![];

    match PARENT_REGEX.captures(key) {
        Some(captures) => {
            match decode_component(captures.get(1).unwrap().as_str()) {
                Ok(decoded_key) => keys.push(decoded_key),
                Err(err_msg) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err_msg })
            }
        }
        None => ()
    };

    for captures in CHILD_REGEX.captures_iter(key) {
        match decode_component(captures.get(1).unwrap().as_str()) {
            Ok(decoded_key) => keys.push(decoded_key),
            Err(err_msg) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err_msg })
        }
    }

    Ok(keys)
}

#[cfg(not(feature = "regex1"))]
fn parse_key(key: &str) -> ParseResult<Vec<String>> {
    let mut keys: Vec<String> = vec![];

    match key.split(|c| c=='[' || c==']').next() {
        Some(parent) if !parent.is_empty() =>  {
            match decode_component(parent) {
                Ok(decoded_key) => keys.push(decoded_key),
                Err(err_msg) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err_msg })
            }
        }
        _ => ()
    }

    let mut prev_bracket = None;
    for (idx, ch) in key.char_indices() {
        match ch {
            '[' => prev_bracket = Some(idx),
            ']' => {
                if let Some(prev_idx) = prev_bracket {
                    prev_bracket = None;
                    let child = &key[prev_idx..=idx];
                    match decode_component(child) {
                        Ok(decoded_key) => keys.push(decoded_key),
                        Err(err_msg) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err_msg })
                    }
                }
            }
            _ => (),
        }
    }

    Ok(keys)
}

fn cleanup_key(key: &str) -> &str {
    if key.starts_with("[") && key.ends_with("]") {
        &key[1..(key.len()-1)]
    } else {
        key
    }
}

fn create_idx_merger(idx: u64, obj: Value) -> Value {
    let mut tree = Object::new();
    tree.insert("__idx".to_string(), Value::Number(Number::from(idx)));
    tree.insert("__object".to_string(), obj);
    return Value::Object(tree)
}

fn create_object_with_key(key: String, obj: Value) -> Value {
    let mut tree = Object::new();
    tree.insert(key, obj);
    return Value::Object(tree)
}

fn apply_object(keys: &[String], val: Value) -> Value {

    if keys.len() > 0 {
        let key = keys.get(0).unwrap();
        if key == "[]" {
            let mut new_array = create_array();
            let item = apply_object(&keys[1..], val);
            push_item_to_array(&mut new_array, item);
            return new_array;
        } else {
            let key = cleanup_key(key);
            let array_index = key.parse();

            match array_index {
                Ok(idx) => {
                    let result = apply_object(&keys[1..], val);
                    let item = create_idx_merger(idx, result);
                    return item;
                },
                Err(_) => {
                    return create_object_with_key(key.to_string(), apply_object(&keys[1..], val));
                }
            }
        }

    } else {
        return val;
    }
}

pub fn parse(params: &str) -> ParseResult<Value> {
    let tree = Object::new();
    let mut obj = Value::Object(tree);
    let decoded_params = match decode_component(params) {
        Ok(val) => val,
        Err(err) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err })
    };
    let pairs = parse_pairs(&decoded_params);
    for &(key, value) in pairs.iter() {
        let parse_key_res = try!(parse_key(key));
        let key_chain = &parse_key_res[0..];
        let decoded_value = match value {
            None => Value::Null,
            Some(val) => match decode_component(val) {
                Ok(decoded_value) => Value::String(decoded_value),
                Err(err) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err })
            }
        };
        let partial = apply_object(key_chain, decoded_value);
        merge(&mut obj, &partial);
    }

    Ok(obj)
}

#[cfg(test)]
mod tests {
    use parse;
    use super::parse_pair;
    use serde_json::{Value, to_string};

    fn eq_str(value: Value, string: &str) {
        assert_eq!(&to_string(&value).unwrap(), string)
    }

    #[test]
    fn test_parse_pair() {
        assert_eq!(parse_pair("foo=1"), ("foo", Some("1")));
        assert_eq!(parse_pair("empty="), ("empty", Some("")));
        assert_eq!(parse_pair("noval"), ("noval", None));
    }

    #[test]
    fn it_parses_simple_string() {
        eq_str(parse("0=foo").unwrap(), r#"{"0":"foo"}"#);
        eq_str(parse("a[<=>]==23").unwrap(), r#"{"a":{"<=>":"=23"}}"#);
        eq_str(parse(" foo = bar = baz ").unwrap(), r#"{" foo ":" bar = baz "}"#);
    }

    #[test]
    fn it_parses_nested_string() {
        eq_str(parse("a[b][c][d][e][f][g][h]=i").unwrap(),
            r#"{"a":{"b":{"c":{"d":{"e":{"f":{"g":{"h":"i"}}}}}}}}"#);
    }

    #[test]
    fn it_parses_simple_array() {
        eq_str(parse("a=b&a=c&a=d&a=e").unwrap(),
            r#"{"a":["b","c","d","e"]}"#);
    }

    #[test]
    fn it_parses_explicit_array() {
        eq_str(parse("a[]=b&a[]=c&a[]=d").unwrap(),
            r#"{"a":["b","c","d"]}"#);
    }

    #[test]
    fn it_parses_nested_array() {
        eq_str(parse("a[b][]=c&a[b][]=d").unwrap(),
            r#"{"a":{"b":["c","d"]}}"#);
    }

    #[test]
    fn it_allows_to_specify_array_indexes() {
        eq_str(parse("a[0][]=c&a[1][]=d").unwrap(),
            r#"{"a":[["c"],["d"]]}"#);
    }

    #[test]
    fn it_transforms_arrays_to_object() {
        eq_str(parse("foo[0]=bar&foo[bad]=baz").unwrap(),
            r#"{"foo":{"0":"bar","bad":"baz"}}"#);

        eq_str(parse("foo[0][a]=a&foo[0][b]=b&foo[1][a]=aa&foo[1][b]=bb").unwrap(),
            r#"{"foo":[{"a":"a","b":"b"},{"a":"aa","b":"bb"}]}"#);
    }

    #[test]
    fn it_transforms_standalone_keys() {
        eq_str(parse("foo=bar&baz").unwrap(),
            r#"{"baz":null,"foo":"bar"}"#);
    }

    #[test]
    fn it_doesnt_produce_empty_keys() {
        eq_str(parse("_r=1&").unwrap(),
            r#"{"_r":"1"}"#);
    }

    #[test]
    fn it_supports_encoded_strings() {
        eq_str(parse("a[b%20c]=c%20d").unwrap(),
            r#"{"a":{"b c":"c d"}}"#);
    }

    #[test]
    fn it_parses_explicit_encoded_array() {
        eq_str(parse("a%5B%5D=b&a%5B%5D=c&a%5B%5D=d").unwrap(),
            r#"{"a":["b","c","d"]}"#);
    }
}
<commit_msg>feat(parser): Use Value::default to determine default value<commit_after>#[cfg(feature = "regex1")]
use regex::Regex;
use serde_json::{Value, Map, Number};
use url::percent_encoding::percent_decode;

use merge::merge;
use helpers::{create_array, push_item_to_array};

#[cfg(feature = "regex1")]
lazy_static! {
    static ref PARENT_REGEX: Regex = Regex::new(r"^([^\]\[]+)").unwrap();
    static ref CHILD_REGEX: Regex = Regex::new(r"(\[[^\]\[]*\])").unwrap();
}

type Object = Map<String, Value>;

#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum ParseErrorKind {
    DecodingError,
    Other
}

#[derive(Debug)]
pub struct ParseError {
    pub kind: ParseErrorKind,
    pub message: String
}

pub type ParseResult<T> = Result<T,ParseError>;

pub fn decode_component(source: &str) -> Result<String,String> {
    let result = percent_decode(source.as_bytes()).decode_utf8_lossy().to_string();
    return Ok(result);
}

fn parse_pair(part: &str) -> (&str, Option<&str>) {
    let separator = part.find("]=")
                        .and_then(|pos| Some(pos+1))
                        .or_else(|| part.find("="));
    match separator {
        None => return (part, None),
        Some(pos) => {
            let key = &part[..pos];
            let val = &part[(pos + 1)..];
            return (key, Some(val));
        }
    }
}

fn parse_pairs(body: &str) -> Vec<(&str, Option<&str>)> {
    let mut pairs = vec![];
    for part in body.split("&") {
        pairs.push(parse_pair(part));
    }
    return pairs
}

#[cfg(feature = "regex1")]
fn parse_key(key: &str) -> ParseResult<Vec<String>> {
    let mut keys: Vec<String> = vec![];

    match PARENT_REGEX.captures(key) {
        Some(captures) => {
            match decode_component(captures.get(1).unwrap().as_str()) {
                Ok(decoded_key) => keys.push(decoded_key),
                Err(err_msg) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err_msg })
            }
        }
        None => ()
    };

    for captures in CHILD_REGEX.captures_iter(key) {
        match decode_component(captures.get(1).unwrap().as_str()) {
            Ok(decoded_key) => keys.push(decoded_key),
            Err(err_msg) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err_msg })
        }
    }

    Ok(keys)
}

#[cfg(not(feature = "regex1"))]
fn parse_key(key: &str) -> ParseResult<Vec<String>> {
    let mut keys: Vec<String> = vec![];

    match key.split(|c| c=='[' || c==']').next() {
        Some(parent) if !parent.is_empty() =>  {
            match decode_component(parent) {
                Ok(decoded_key) => keys.push(decoded_key),
                Err(err_msg) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err_msg })
            }
        }
        _ => ()
    }

    let mut prev_bracket = None;
    for (idx, ch) in key.char_indices() {
        match ch {
            '[' => prev_bracket = Some(idx),
            ']' => {
                if let Some(prev_idx) = prev_bracket {
                    prev_bracket = None;
                    let child = &key[prev_idx..=idx];
                    match decode_component(child) {
                        Ok(decoded_key) => keys.push(decoded_key),
                        Err(err_msg) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err_msg })
                    }
                }
            }
            _ => (),
        }
    }

    Ok(keys)
}

fn cleanup_key(key: &str) -> &str {
    if key.starts_with("[") && key.ends_with("]") {
        &key[1..(key.len()-1)]
    } else {
        key
    }
}

fn create_idx_merger(idx: u64, obj: Value) -> Value {
    let mut tree = Object::new();
    tree.insert("__idx".to_string(), Value::Number(Number::from(idx)));
    tree.insert("__object".to_string(), obj);
    return Value::Object(tree)
}

fn create_object_with_key(key: String, obj: Value) -> Value {
    let mut tree = Object::new();
    tree.insert(key, obj);
    return Value::Object(tree)
}

fn apply_object(keys: &[String], val: Value) -> Value {

    if keys.len() > 0 {
        let key = keys.get(0).unwrap();
        if key == "[]" {
            let mut new_array = create_array();
            let item = apply_object(&keys[1..], val);
            push_item_to_array(&mut new_array, item);
            return new_array;
        } else {
            let key = cleanup_key(key);
            let array_index = key.parse();

            match array_index {
                Ok(idx) => {
                    let result = apply_object(&keys[1..], val);
                    let item = create_idx_merger(idx, result);
                    return item;
                },
                Err(_) => {
                    return create_object_with_key(key.to_string(), apply_object(&keys[1..], val));
                }
            }
        }

    } else {
        return val;
    }
}

pub fn parse(params: &str) -> ParseResult<Value> {
    let tree = Object::new();
    let mut obj = Value::Object(tree);
    let decoded_params = match decode_component(params) {
        Ok(val) => val,
        Err(err) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err })
    };
    let pairs = parse_pairs(&decoded_params);
    for &(key, value) in pairs.iter() {
        let parse_key_res = try!(parse_key(key));
        let key_chain = &parse_key_res[0..];
        let decoded_value = match value {
            None => Value::default(),
            Some(val) => match decode_component(val) {
                Ok(decoded_value) => Value::String(decoded_value),
                Err(err) => return Err(ParseError{ kind: ParseErrorKind::DecodingError, message: err })
            }
        };
        let partial = apply_object(key_chain, decoded_value);
        merge(&mut obj, &partial);
    }

    Ok(obj)
}

#[cfg(test)]
mod tests {
    use parse;
    use super::parse_pair;
    use serde_json::{Value, to_string};

    fn eq_str(value: Value, string: &str) {
        assert_eq!(&to_string(&value).unwrap(), string)
    }

    #[test]
    fn test_parse_pair() {
        assert_eq!(parse_pair("foo=1"), ("foo", Some("1")));
        assert_eq!(parse_pair("empty="), ("empty", Some("")));
        assert_eq!(parse_pair("noval"), ("noval", None));
    }

    #[test]
    fn it_parses_simple_string() {
        eq_str(parse("0=foo").unwrap(), r#"{"0":"foo"}"#);
        eq_str(parse("a[<=>]==23").unwrap(), r#"{"a":{"<=>":"=23"}}"#);
        eq_str(parse(" foo = bar = baz ").unwrap(), r#"{" foo ":" bar = baz "}"#);
    }

    #[test]
    fn it_parses_nested_string() {
        eq_str(parse("a[b][c][d][e][f][g][h]=i").unwrap(),
            r#"{"a":{"b":{"c":{"d":{"e":{"f":{"g":{"h":"i"}}}}}}}}"#);
    }

    #[test]
    fn it_parses_simple_array() {
        eq_str(parse("a=b&a=c&a=d&a=e").unwrap(),
            r#"{"a":["b","c","d","e"]}"#);
    }

    #[test]
    fn it_parses_explicit_array() {
        eq_str(parse("a[]=b&a[]=c&a[]=d").unwrap(),
            r#"{"a":["b","c","d"]}"#);
    }

    #[test]
    fn it_parses_nested_array() {
        eq_str(parse("a[b][]=c&a[b][]=d").unwrap(),
            r#"{"a":{"b":["c","d"]}}"#);
    }

    #[test]
    fn it_allows_to_specify_array_indexes() {
        eq_str(parse("a[0][]=c&a[1][]=d").unwrap(),
            r#"{"a":[["c"],["d"]]}"#);
    }

    #[test]
    fn it_transforms_arrays_to_object() {
        eq_str(parse("foo[0]=bar&foo[bad]=baz").unwrap(),
            r#"{"foo":{"0":"bar","bad":"baz"}}"#);

        eq_str(parse("foo[0][a]=a&foo[0][b]=b&foo[1][a]=aa&foo[1][b]=bb").unwrap(),
            r#"{"foo":[{"a":"a","b":"b"},{"a":"aa","b":"bb"}]}"#);
    }

    #[test]
    fn it_transforms_standalone_keys() {
        eq_str(parse("foo=bar&baz").unwrap(),
            r#"{"baz":null,"foo":"bar"}"#);
    }

    #[test]
    fn it_doesnt_produce_empty_keys() {
        eq_str(parse("_r=1&").unwrap(),
            r#"{"_r":"1"}"#);
    }

    #[test]
    fn it_supports_encoded_strings() {
        eq_str(parse("a[b%20c]=c%20d").unwrap(),
            r#"{"a":{"b c":"c d"}}"#);
    }

    #[test]
    fn it_parses_explicit_encoded_array() {
        eq_str(parse("a%5B%5D=b&a%5B%5D=c&a%5B%5D=d").unwrap(),
            r#"{"a":["b","c","d"]}"#);
    }
}
<|endoftext|>


<commit_before>use eventual::{self, Async};
use std::borrow::Cow;
use std::sync::{mpsc, Mutex, Arc, MutexGuard};
use std::thread;
use std::io::{Read, Seek};
use vorbis;

use audio_decrypt::AudioDecrypt;
use audio_backend::Sink;
use metadata::{FileFormat, Track, TrackRef};
use session::{Bitrate, Session};
use mixer::AudioFilter;
use util::{self, ReadSeek, SpotifyId, Subfile};
pub use spirc::PlayStatus;

#[cfg(not(feature = "with-tremor"))]
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
    decoder.time_seek(ms as f64 / 1000f64)
}

#[cfg(not(feature = "with-tremor"))]
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
    decoder.time_tell().map(|t| (t * 1000f64) as i64)
}

#[cfg(feature = "with-tremor")]
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
    decoder.time_seek(ms)
}

#[cfg(feature = "with-tremor")]
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
    decoder.time_tell()
}

pub type PlayerObserver = Box<Fn(&PlayerState) + Send>;

#[derive(Clone)]
pub struct Player {
    state: Arc<Mutex<PlayerState>>,
    observers: Arc<Mutex<Vec<PlayerObserver>>>,

    commands: mpsc::Sender<PlayerCommand>,
}

#[derive(Clone)]
pub struct PlayerState {
    pub status: PlayStatus,
    pub position_ms: u32,
    pub position_measured_at: i64,
    pub track: Option<SpotifyId>,

    pub end_of_track: bool,
}

struct PlayerInternal {
    state: Arc<Mutex<PlayerState>>,
    observers: Arc<Mutex<Vec<PlayerObserver>>>,

    session: Session,
    commands: mpsc::Receiver<PlayerCommand>,
}

#[derive(Debug)]
enum PlayerCommand {
    Load(SpotifyId, bool, u32),
    Play,
    Pause,
    Stop,
    Seek(u32),
    SeekAt(u32, i64),
}

impl Player {
    pub fn new<F>(session: Session, stream_editor: Option<Box<AudioFilter + Send>>, sink_builder: F) -> Player
        where F: FnOnce() -> Box<Sink> + Send + 'static {
        let (cmd_tx, cmd_rx) = mpsc::channel();

        let state = Arc::new(Mutex::new(PlayerState {
            status: PlayStatus::kPlayStatusStop,
            position_ms: 0,
            position_measured_at: 0,
            track: None,
            end_of_track: false,
        }));

        let observers = Arc::new(Mutex::new(Vec::new()));

        let internal = PlayerInternal {
            session: session,
            commands: cmd_rx,
            state: state.clone(),
            observers: observers.clone(),
        };

        thread::spawn(move || internal.run(sink_builder(), stream_editor));

        Player {
            commands: cmd_tx,
            state: state,
            observers: observers,
        }
    }

    fn command(&self, cmd: PlayerCommand) {
        self.commands.send(cmd).unwrap();
    }

    pub fn load(&self, track: SpotifyId, start_playing: bool, position_ms: u32) {
        self.command(PlayerCommand::Load(track, start_playing, position_ms));
    }

    pub fn play(&self) {
        self.command(PlayerCommand::Play)
    }

    pub fn pause(&self) {
        self.command(PlayerCommand::Pause)
    }

    pub fn stop(&self) {
        self.command(PlayerCommand::Stop)
    }

    pub fn seek(&self, position_ms: u32) {
        self.command(PlayerCommand::Seek(position_ms));
    }

    pub fn seek_at(&self, position_ms: u32, measured_at: i64) {
        self.command(PlayerCommand::SeekAt(position_ms, measured_at));
    }

    pub fn state(&self) -> PlayerState {
        self.state.lock().unwrap().clone()
    }

    pub fn add_observer(&self, observer: PlayerObserver) {
        self.observers.lock().unwrap().push(observer);
    }
}

fn find_available_alternative<'a>(session: &Session, track: &'a Track) -> Option<Cow<'a, Track>> {
    if track.available {
        Some(Cow::Borrowed(track))
    } else {
        let alternatives = track.alternatives
            .iter()
            .map(|alt_id| {
                session.metadata::<Track>(*alt_id)
            })
        .collect::<Vec<TrackRef>>();

        eventual::sequence(alternatives.into_iter()).iter().find(|alt| alt.available).map(Cow::Owned)
    }
}

fn load_track(session: &Session, track_id: SpotifyId) -> Option<vorbis::Decoder<Subfile<AudioDecrypt<Box<ReadSeek>>>>> {
    let track = session.metadata::<Track>(track_id).await().unwrap();

    info!("Loading track \"{}\"", track.name);

    let track = match find_available_alternative(session, &track) {
        Some(track) => track,
        None => {
            warn!("Track \"{}\" is not available", track.name);
            return None;
        }
    };

    let format = match session.config().bitrate {
        Bitrate::Bitrate96 => FileFormat::OGG_VORBIS_96,
        Bitrate::Bitrate160 => FileFormat::OGG_VORBIS_160,
        Bitrate::Bitrate320 => FileFormat::OGG_VORBIS_320,
    };

    let file_id = match track.files.get(&format) {
        Some(&file_id) => file_id,
        None => {
            warn!("Track \"{}\" is not available in format {:?}", track.name, format);
            return None;
        }
    };

    let key = session.audio_key(track.id, file_id).await().unwrap();

    let audio_file = Subfile::new(AudioDecrypt::new(key, session.audio_file(file_id)), 0xa7);
    let decoder = vorbis::Decoder::new(audio_file).unwrap();

    Some(decoder)
}

fn run_onstart(session: &Session) {
    match session.config().onstart {
        Some(ref program) => util::run_program(program),
        None => {},
    };
}

fn run_onstop(session: &Session) {
    match session.config().onstop {
        Some(ref program) => util::run_program(program),
        None => {},
    };
}

impl PlayerInternal {
    fn run(self, mut sink: Box<Sink>, stream_editor: Option<Box<AudioFilter + Send>>) {
        let mut decoder = None;

        loop {
            let playing = self.state.lock().unwrap().status == PlayStatus::kPlayStatusPlay;
            let cmd = if playing {
                self.commands.try_recv().ok()
            } else {
                Some(self.commands.recv().unwrap())
            };

            match cmd {
                Some(PlayerCommand::Load(track_id, play, position)) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            sink.stop().unwrap();
                            run_onstop(&self.session);
                        }
                        state.end_of_track = false;
                        state.status = PlayStatus::kPlayStatusPause;
                        state.position_ms = position;
                        state.position_measured_at = util::now_ms();
                        state.track = Some(track_id);
                        true
                    });
                    drop(decoder);

                    decoder = match load_track(&self.session, track_id) {
                        Some(mut decoder) => {
                            match vorbis_time_seek_ms(&mut decoder, position as i64) {
                                Ok(_) => (),
                                Err(err) => error!("Vorbis error: {:?}", err),
                            }

                            self.update(|state| {
                                state.status = if play {
                                    run_onstart(&self.session);
                                    sink.start().unwrap();
                                    PlayStatus::kPlayStatusPlay
                                } else {
                                    PlayStatus::kPlayStatusPause
                                };
                                state.position_ms = position;
                                state.position_measured_at = util::now_ms();

                                true
                            });

                            info!("Load Done");
                            Some(decoder)
                        }

                        None => {
                            self.update(|state| {
                                state.status = PlayStatus::kPlayStatusStop;
                                state.end_of_track = true;
                                true
                            });

                            None
                        }
                    }

                }
                Some(PlayerCommand::Seek(position)) => {
                    match vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64) {
                        Ok(_) => (),
                        Err(err) => error!("Vorbis error: {:?}", err),
                    }
                    self.update(|state| {
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();

                        true
                    });
                }
                Some(PlayerCommand::SeekAt(position, measured_at)) => {
                    let position = (util::now_ms() - measured_at + position as i64) as u32;

                    match vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64) {
                        Ok(_) => (),
                        Err(err) => error!("Vorbis error: {:?}", err),
                    }
                    self.update(|state| {
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();

                        true
                    });
                }
                Some(PlayerCommand::Play) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPlay;
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    run_onstart(&self.session);
                    sink.start().unwrap();
                }
                Some(PlayerCommand::Pause) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPause;
                        state.position_ms = decoder.as_mut().map(|d| vorbis_time_tell_ms(d).unwrap()).unwrap_or(0) as u32;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.stop().unwrap();
                    run_onstop(&self.session);
                }
                Some(PlayerCommand::Stop) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            state.status = PlayStatus::kPlayStatusPause;
                        }
                        state.position_ms = 0;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.stop().unwrap();
                    run_onstop(&self.session);
                    decoder = None;
                }
                None => (),
            }

            if self.state.lock().unwrap().status == PlayStatus::kPlayStatusPlay {
                let packet = decoder.as_mut().unwrap().packets().next();

                match packet {
                    Some(Ok(packet)) => {
                        let mut buffer = packet.data.to_vec();

                        if let Some(ref editor) = stream_editor {
                            editor.modify_stream(&mut buffer)
                        };
                        sink.write(&buffer).unwrap();

                        self.update(|state| {
                            state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                            state.position_measured_at = util::now_ms();

                            false
                        });
                    }
                    Some(Err(vorbis::VorbisError::Hole)) => (),
                    Some(Err(e)) => panic!("Vorbis error {:?}", e),
                    None => {
                        self.update(|state| {
                            state.status = PlayStatus::kPlayStatusStop;
                            state.end_of_track = true;
                            true
                        });

                        sink.stop().unwrap();
                        run_onstop(&self.session);
                        decoder = None;
                    }
                }
            }
        }
    }

    fn update<F>(&self, f: F)
        where F: FnOnce(&mut MutexGuard<PlayerState>) -> bool
    {
        let mut guard = self.state.lock().unwrap();
        let update = f(&mut guard);

        let observers = self.observers.lock().unwrap();
        if update {
            let state = guard.clone();
            drop(guard);

            for observer in observers.iter() {
                observer(&state);
            }
        }
    }
}

impl PlayerState {
    pub fn status(&self) -> PlayStatus {
        self.status
    }

    pub fn position(&self) -> (u32, i64) {
        (self.position_ms, self.position_measured_at)
    }

    pub fn end_of_track(&self) -> bool {
        self.end_of_track
    }
}
<commit_msg>Avoid copying the data array in the player<commit_after>use eventual::{self, Async};
use std::borrow::Cow;
use std::sync::{mpsc, Mutex, Arc, MutexGuard};
use std::thread;
use std::io::{Read, Seek};
use vorbis;

use audio_decrypt::AudioDecrypt;
use audio_backend::Sink;
use metadata::{FileFormat, Track, TrackRef};
use session::{Bitrate, Session};
use mixer::AudioFilter;
use util::{self, ReadSeek, SpotifyId, Subfile};
pub use spirc::PlayStatus;

#[cfg(not(feature = "with-tremor"))]
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
    decoder.time_seek(ms as f64 / 1000f64)
}

#[cfg(not(feature = "with-tremor"))]
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
    decoder.time_tell().map(|t| (t * 1000f64) as i64)
}

#[cfg(feature = "with-tremor")]
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
    decoder.time_seek(ms)
}

#[cfg(feature = "with-tremor")]
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
    decoder.time_tell()
}

pub type PlayerObserver = Box<Fn(&PlayerState) + Send>;

#[derive(Clone)]
pub struct Player {
    state: Arc<Mutex<PlayerState>>,
    observers: Arc<Mutex<Vec<PlayerObserver>>>,

    commands: mpsc::Sender<PlayerCommand>,
}

#[derive(Clone)]
pub struct PlayerState {
    pub status: PlayStatus,
    pub position_ms: u32,
    pub position_measured_at: i64,
    pub track: Option<SpotifyId>,

    pub end_of_track: bool,
}

struct PlayerInternal {
    state: Arc<Mutex<PlayerState>>,
    observers: Arc<Mutex<Vec<PlayerObserver>>>,

    session: Session,
    commands: mpsc::Receiver<PlayerCommand>,
}

#[derive(Debug)]
enum PlayerCommand {
    Load(SpotifyId, bool, u32),
    Play,
    Pause,
    Stop,
    Seek(u32),
    SeekAt(u32, i64),
}

impl Player {
    pub fn new<F>(session: Session, stream_editor: Option<Box<AudioFilter + Send>>, sink_builder: F) -> Player
        where F: FnOnce() -> Box<Sink> + Send + 'static {
        let (cmd_tx, cmd_rx) = mpsc::channel();

        let state = Arc::new(Mutex::new(PlayerState {
            status: PlayStatus::kPlayStatusStop,
            position_ms: 0,
            position_measured_at: 0,
            track: None,
            end_of_track: false,
        }));

        let observers = Arc::new(Mutex::new(Vec::new()));

        let internal = PlayerInternal {
            session: session,
            commands: cmd_rx,
            state: state.clone(),
            observers: observers.clone(),
        };

        thread::spawn(move || internal.run(sink_builder(), stream_editor));

        Player {
            commands: cmd_tx,
            state: state,
            observers: observers,
        }
    }

    fn command(&self, cmd: PlayerCommand) {
        self.commands.send(cmd).unwrap();
    }

    pub fn load(&self, track: SpotifyId, start_playing: bool, position_ms: u32) {
        self.command(PlayerCommand::Load(track, start_playing, position_ms));
    }

    pub fn play(&self) {
        self.command(PlayerCommand::Play)
    }

    pub fn pause(&self) {
        self.command(PlayerCommand::Pause)
    }

    pub fn stop(&self) {
        self.command(PlayerCommand::Stop)
    }

    pub fn seek(&self, position_ms: u32) {
        self.command(PlayerCommand::Seek(position_ms));
    }

    pub fn seek_at(&self, position_ms: u32, measured_at: i64) {
        self.command(PlayerCommand::SeekAt(position_ms, measured_at));
    }

    pub fn state(&self) -> PlayerState {
        self.state.lock().unwrap().clone()
    }

    pub fn add_observer(&self, observer: PlayerObserver) {
        self.observers.lock().unwrap().push(observer);
    }
}

fn find_available_alternative<'a>(session: &Session, track: &'a Track) -> Option<Cow<'a, Track>> {
    if track.available {
        Some(Cow::Borrowed(track))
    } else {
        let alternatives = track.alternatives
            .iter()
            .map(|alt_id| {
                session.metadata::<Track>(*alt_id)
            })
        .collect::<Vec<TrackRef>>();

        eventual::sequence(alternatives.into_iter()).iter().find(|alt| alt.available).map(Cow::Owned)
    }
}

fn load_track(session: &Session, track_id: SpotifyId) -> Option<vorbis::Decoder<Subfile<AudioDecrypt<Box<ReadSeek>>>>> {
    let track = session.metadata::<Track>(track_id).await().unwrap();

    info!("Loading track \"{}\"", track.name);

    let track = match find_available_alternative(session, &track) {
        Some(track) => track,
        None => {
            warn!("Track \"{}\" is not available", track.name);
            return None;
        }
    };

    let format = match session.config().bitrate {
        Bitrate::Bitrate96 => FileFormat::OGG_VORBIS_96,
        Bitrate::Bitrate160 => FileFormat::OGG_VORBIS_160,
        Bitrate::Bitrate320 => FileFormat::OGG_VORBIS_320,
    };

    let file_id = match track.files.get(&format) {
        Some(&file_id) => file_id,
        None => {
            warn!("Track \"{}\" is not available in format {:?}", track.name, format);
            return None;
        }
    };

    let key = session.audio_key(track.id, file_id).await().unwrap();

    let audio_file = Subfile::new(AudioDecrypt::new(key, session.audio_file(file_id)), 0xa7);
    let decoder = vorbis::Decoder::new(audio_file).unwrap();

    Some(decoder)
}

fn run_onstart(session: &Session) {
    match session.config().onstart {
        Some(ref program) => util::run_program(program),
        None => {},
    };
}

fn run_onstop(session: &Session) {
    match session.config().onstop {
        Some(ref program) => util::run_program(program),
        None => {},
    };
}

impl PlayerInternal {
    fn run(self, mut sink: Box<Sink>, stream_editor: Option<Box<AudioFilter + Send>>) {
        let mut decoder = None;

        loop {
            let playing = self.state.lock().unwrap().status == PlayStatus::kPlayStatusPlay;
            let cmd = if playing {
                self.commands.try_recv().ok()
            } else {
                Some(self.commands.recv().unwrap())
            };

            match cmd {
                Some(PlayerCommand::Load(track_id, play, position)) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            sink.stop().unwrap();
                            run_onstop(&self.session);
                        }
                        state.end_of_track = false;
                        state.status = PlayStatus::kPlayStatusPause;
                        state.position_ms = position;
                        state.position_measured_at = util::now_ms();
                        state.track = Some(track_id);
                        true
                    });
                    drop(decoder);

                    decoder = match load_track(&self.session, track_id) {
                        Some(mut decoder) => {
                            match vorbis_time_seek_ms(&mut decoder, position as i64) {
                                Ok(_) => (),
                                Err(err) => error!("Vorbis error: {:?}", err),
                            }

                            self.update(|state| {
                                state.status = if play {
                                    run_onstart(&self.session);
                                    sink.start().unwrap();
                                    PlayStatus::kPlayStatusPlay
                                } else {
                                    PlayStatus::kPlayStatusPause
                                };
                                state.position_ms = position;
                                state.position_measured_at = util::now_ms();

                                true
                            });

                            info!("Load Done");
                            Some(decoder)
                        }

                        None => {
                            self.update(|state| {
                                state.status = PlayStatus::kPlayStatusStop;
                                state.end_of_track = true;
                                true
                            });

                            None
                        }
                    }

                }
                Some(PlayerCommand::Seek(position)) => {
                    match vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64) {
                        Ok(_) => (),
                        Err(err) => error!("Vorbis error: {:?}", err),
                    }
                    self.update(|state| {
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();

                        true
                    });
                }
                Some(PlayerCommand::SeekAt(position, measured_at)) => {
                    let position = (util::now_ms() - measured_at + position as i64) as u32;

                    match vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64) {
                        Ok(_) => (),
                        Err(err) => error!("Vorbis error: {:?}", err),
                    }
                    self.update(|state| {
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();

                        true
                    });
                }
                Some(PlayerCommand::Play) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPlay;
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    run_onstart(&self.session);
                    sink.start().unwrap();
                }
                Some(PlayerCommand::Pause) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPause;
                        state.position_ms = decoder.as_mut().map(|d| vorbis_time_tell_ms(d).unwrap()).unwrap_or(0) as u32;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.stop().unwrap();
                    run_onstop(&self.session);
                }
                Some(PlayerCommand::Stop) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            state.status = PlayStatus::kPlayStatusPause;
                        }
                        state.position_ms = 0;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.stop().unwrap();
                    run_onstop(&self.session);
                    decoder = None;
                }
                None => (),
            }

            if self.state.lock().unwrap().status == PlayStatus::kPlayStatusPlay {
                let packet = decoder.as_mut().unwrap().packets().next();

                match packet {
                    Some(Ok(mut packet)) => {
                        if let Some(ref editor) = stream_editor {
                            editor.modify_stream(&mut packet.data)
                        };
                        sink.write(&packet.data).unwrap();

                        self.update(|state| {
                            state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                            state.position_measured_at = util::now_ms();

                            false
                        });
                    }
                    Some(Err(vorbis::VorbisError::Hole)) => (),
                    Some(Err(e)) => panic!("Vorbis error {:?}", e),
                    None => {
                        self.update(|state| {
                            state.status = PlayStatus::kPlayStatusStop;
                            state.end_of_track = true;
                            true
                        });

                        sink.stop().unwrap();
                        run_onstop(&self.session);
                        decoder = None;
                    }
                }
            }
        }
    }

    fn update<F>(&self, f: F)
        where F: FnOnce(&mut MutexGuard<PlayerState>) -> bool
    {
        let mut guard = self.state.lock().unwrap();
        let update = f(&mut guard);

        let observers = self.observers.lock().unwrap();
        if update {
            let state = guard.clone();
            drop(guard);

            for observer in observers.iter() {
                observer(&state);
            }
        }
    }
}

impl PlayerState {
    pub fn status(&self) -> PlayStatus {
        self.status
    }

    pub fn position(&self) -> (u32, i64) {
        (self.position_ms, self.position_measured_at)
    }

    pub fn end_of_track(&self) -> bool {
        self.end_of_track
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::{File, read_dir};
use std::io::Read;
use std::string::string;
use serde::de::Deserialize;
use serde_protobuf::descriptor::Descriptors;
use serde_protobuf::de::Deserializer;
use serde_value::Value;
use protobuf::{CodedInputStream, parse_from_reader};

pub fn process_single(read: &mut Read) {
    for mut fdset_file, mut named_message in discover_fdsets() {
        let proto = parse_from_reader(&mut fdset_file).unwrap();
        let descriptors = Descriptors::from_proto(&proto);
        let byte_is = CodedInputStream::new(read);

        let mut deserializer = Deserializer::for_named_message(&descriptors, ".com.example.dog.Dog", byte_is).unwrap();
        let value = Value::deserialize(&mut deserializer).unwrap();
        println!("{:?}", value);
    }
}

pub fn process_stream(read: &mut Read) {
    let mut stream = CodedInputStream::new(read);

    loop {
        match stream.eof() {
            Err(e) => panic!(e),
            Ok(true) => break,
            Ok(false) => break,
            //todo: actually do deserialization here
        }
    }
}

fn discover_fdsets() -> Vec<(File, String)> {
    let mut fdset_files = Vec::new();

    let mut home = env::home_dir().expect("Could not find $HOME");
    home.push(".pq");
    let paths = read_dir(home.as_path()).unwrap();

    for p in paths {
        let mut named_messages = Vec::new();
        let path = match p {
            Ok(p) => p.path(),
            Err(_) => continue,
        };
        match path.extension() {
            Some(x) => {
                if x != "fdset" {
                    if x == "names" {
                        let mut f = File::open(path).unwrap();
                        for l in f.lines() {
                            named_messages.push(l);
                        }
                    }
                    continue;
                }
            },
            None => continue,
        }
        fdset_files.push((File::open(path.as_path()).unwrap(),
                          named_messages.first());
    }
    return fdset_files;
}
<commit_msg>Revert "Try to maintain message names per fdset"<commit_after>use std::env;
use std::fs::{File, read_dir};
use std::io::Read;
use serde::de::Deserialize;
use serde_protobuf::descriptor::Descriptors;
use serde_protobuf::de::Deserializer;
use serde_value::Value;
use protobuf::{CodedInputStream, parse_from_reader};

pub fn process_single(read: &mut Read) {
    for mut fdset_file in discover_fdsets() {
        let proto = parse_from_reader(&mut fdset_file).unwrap();
        let descriptors = Descriptors::from_proto(&proto);
        let byte_is = CodedInputStream::new(read);

        let mut deserializer = Deserializer::for_named_message(&descriptors, ".com.example.dog.Dog", byte_is).unwrap();
        let value = Value::deserialize(&mut deserializer).unwrap();
        println!("{:?}", value);
    }
}

pub fn process_stream(read: &mut Read) {
    let mut stream = CodedInputStream::new(read);

    loop {
        match stream.eof() {
            Err(e) => panic!(e),
            Ok(true) => break,
            Ok(false) => break,
            //todo: actually do deserialization here
        }
    }
}

fn discover_fdsets() -> Vec<File> {
    let mut fdset_files = Vec::new();

    let mut home = env::home_dir().expect("Could not find $HOME");
    home.push(".pq");
    let paths = read_dir(home.as_path()).unwrap();

    for p in paths {
        let path = match p {
            Ok(p) => p.path(),
            Err(_) => continue,
        };
        match path.extension() {
            Some(x) => {
                if x != "fdset" {
                    continue;
                }
            },
            None => continue,
        }
        fdset_files.push(File::open(path.as_path()).unwrap());
    }
    return fdset_files;
}
<|endoftext|>


<commit_before>use std;
use std::io::prelude::*;
use std::io::{Error, ErrorKind};
use std::net::TcpStream;

/// Reads bytes from the TCP stream until CRLF is found or the given limit is
/// reached.
pub fn read_line(stream: &TcpStream, limit: usize) -> std::io::Result<String> {
  let mut result = String::with_capacity(limit);

  for byte in stream.take(limit as u64).bytes() {
    let raw = try!(byte);
    let chr = raw as char;

    result.push(chr);

    if chr == '\n' {
      break;
    }
  }

  if result.ends_with("\r\n") {
    // .truncate() panics if the new length is not at char boundary. Since we
    // know the string ends with \r\n, that won't happen.
    let new_len = result.len() - 2;
    result.truncate(new_len);

    // Return the result.
    Ok(result)
  } else if result.len() == limit {
    // The line did not fit in the given limit.
    Err(Error::new(ErrorKind::Other, "Line too long."))
  } else {
    // The line ending was invalid or missing.
    Err(Error::new(ErrorKind::Other, "The line must end in CRLF sequence."))
  }
}

/// Reads four bytes from the stream and combines them together to form a 32 bit
/// unsigned integer.
pub fn read_u32(stream: &TcpStream) -> std::io::Result<u32> {
  let mut buf: Vec<u8> = vec![];
  let read = try!(stream.take(4).read_to_end(&mut buf));

  if read < 4 {
    return Err(Error::new(ErrorKind::Other, "Unexpected end of stream."));
  }

  Ok(buf.iter().enumerate().fold(0, |result, (i, value)| {
    result | ((*value as u32) << (3 - i) * 8)
  }))
}

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

  #[test]
  fn test_readline_basic() {
    let stream = create_tcp_stream("foo\r\n".as_bytes());
    assert_eq!(read_line(&stream, 255).unwrap(), "foo");
  }

  #[test]
  fn test_readline_empty_line() {
    let stream = create_tcp_stream("\r\n".as_bytes());
    assert_eq!(read_line(&stream, 255).unwrap(), "");
  }

  #[test]
  fn test_readline_multiple_lines_reads_only_first() {
    let stream = create_tcp_stream("bar\r\nfoo\r\n".as_bytes());
    assert_eq!(read_line(&stream, 255).unwrap(), "bar");
    assert_eq!(read_line(&stream, 255).unwrap(), "foo");
  }

  #[test]
  fn test_readline_line_too_long() {
    let stream = create_tcp_stream("barbazfoo\r\n".as_bytes());
    assert!(read_line(&stream, 5).is_err());
  }

  #[test]
  fn test_readline_line_at_limit() {
    let stream = create_tcp_stream("123\r\n".as_bytes());
    assert_eq!(read_line(&stream, 5).unwrap(), "123");
  }

  #[test]
  fn test_readline_no_cr_before_lf() {
    let stream = create_tcp_stream("barbazfoo\n".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_no_crlf() {
    let stream = create_tcp_stream("barbazfoo".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_no_lf() {
    let stream = create_tcp_stream("barb\razfoo".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_empty() {
    let stream = create_tcp_stream("".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_only_lf() {
    let stream = create_tcp_stream("\n".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_read_u32_basic() {
    let stream = create_tcp_stream(&[0x29, 0xb7, 0xf4, 0xaa, 0xff, 0xff]);
    assert_eq!(read_u32(&stream).unwrap(), 0x29b7f4aa);
  }

  #[test]
  fn test_read_u32_basic_zeroes() {
    let stream = create_tcp_stream(&[0x29, 0x00, 0xf4, 0xaa, 0xff, 0xff]);
    assert_eq!(read_u32(&stream).unwrap(), 0x2900f4aa);
  }

  #[test]
  fn test_read_u32_too_little_data() {
    let stream = create_tcp_stream(&[0x29, 0xb7, 0xf4]);
    assert!(read_u32(&stream).is_err());
  }
}
<commit_msg>Add read_bytes() method for reading a specific number of bytes from a stream.<commit_after>use std;
use std::io::prelude::*;
use std::io::{Error, ErrorKind};
use std::net::TcpStream;

/// Reads bytes from the TCP stream until CRLF is found or the given limit is
/// reached.
pub fn read_line(stream: &TcpStream, limit: usize) -> std::io::Result<String> {
  let mut result = String::with_capacity(limit);

  for byte in stream.take(limit as u64).bytes() {
    let raw = try!(byte);
    let chr = raw as char;

    result.push(chr);

    if chr == '\n' {
      break;
    }
  }

  if result.ends_with("\r\n") {
    // .truncate() panics if the new length is not at char boundary. Since we
    // know the string ends with \r\n, that won't happen.
    let new_len = result.len() - 2;
    result.truncate(new_len);

    // Return the result.
    Ok(result)
  } else if result.len() == limit {
    // The line did not fit in the given limit.
    Err(Error::new(ErrorKind::Other, "Line too long."))
  } else {
    // The line ending was invalid or missing.
    Err(Error::new(ErrorKind::Other, "The line must end in CRLF sequence."))
  }
}

/// Reads the given number of bytes from the stream into a Vec<u8> or returns
/// an error if the exact number of bytes cannot be read.
pub fn read_bytes(stream: &TcpStream, amount: usize) -> std::io::Result<Vec<u8>> {
  let mut buf: Vec<u8> = vec![];
  let read = try!(stream.take(amount as u64).read_to_end(&mut buf));

  if read < amount {
    Err(Error::new(ErrorKind::Other, "Unexpected end of stream."))
  } else {
    Ok(buf)
  }
}

/// Reads four bytes from the stream and combines them together to form a 32 bit
/// unsigned integer.
pub fn read_u32(stream: &TcpStream) -> std::io::Result<u32> {
  let mut buf = try!(read_bytes(stream, 4));

  Ok(buf.iter().enumerate().fold(0, |result, (i, value)| {
    result | ((*value as u32) << (3 - i) * 8)
  }))
}

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

  #[test]
  fn test_readline_basic() {
    let stream = create_tcp_stream("foo\r\n".as_bytes());
    assert_eq!(read_line(&stream, 255).unwrap(), "foo");
  }

  #[test]
  fn test_readline_empty_line() {
    let stream = create_tcp_stream("\r\n".as_bytes());
    assert_eq!(read_line(&stream, 255).unwrap(), "");
  }

  #[test]
  fn test_readline_multiple_lines_reads_only_first() {
    let stream = create_tcp_stream("bar\r\nfoo\r\n".as_bytes());
    assert_eq!(read_line(&stream, 255).unwrap(), "bar");
    assert_eq!(read_line(&stream, 255).unwrap(), "foo");
  }

  #[test]
  fn test_readline_line_too_long() {
    let stream = create_tcp_stream("barbazfoo\r\n".as_bytes());
    assert!(read_line(&stream, 5).is_err());
  }

  #[test]
  fn test_readline_line_at_limit() {
    let stream = create_tcp_stream("123\r\n".as_bytes());
    assert_eq!(read_line(&stream, 5).unwrap(), "123");
  }

  #[test]
  fn test_readline_no_cr_before_lf() {
    let stream = create_tcp_stream("barbazfoo\n".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_no_crlf() {
    let stream = create_tcp_stream("barbazfoo".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_no_lf() {
    let stream = create_tcp_stream("barb\razfoo".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_empty() {
    let stream = create_tcp_stream("".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_only_lf() {
    let stream = create_tcp_stream("\n".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_read_u32_basic() {
    let stream = create_tcp_stream(&[0x29, 0xb7, 0xf4, 0xaa, 0xff, 0xff]);
    assert_eq!(read_u32(&stream).unwrap(), 0x29b7f4aa);
  }

  #[test]
  fn test_read_u32_basic_zeroes() {
    let stream = create_tcp_stream(&[0x29, 0x00, 0xf4, 0xaa, 0xff, 0xff]);
    assert_eq!(read_u32(&stream).unwrap(), 0x2900f4aa);
  }

  #[test]
  fn test_read_u32_too_little_data() {
    let stream = create_tcp_stream(&[0x29, 0xb7, 0xf4]);
    assert!(read_u32(&stream).is_err());
  }

  #[test]
  fn test_read_bytes_basic() {
    let stream = create_tcp_stream(&[1,2,3,4,5,6]);
    assert_eq!(read_bytes(&stream, 2).unwrap(), [1,2]);
    assert_eq!(read_bytes(&stream, 3).unwrap(), [3,4,5]);
    assert_eq!(read_bytes(&stream, 1).unwrap(), [6]);
  }

  #[test]
  fn test_read_bytes_too_little_data() {
    let stream = create_tcp_stream(&[1,2,3,4,5,6]);
    assert!(read_bytes(&stream, 10).is_err())
  }
}
<|endoftext|>


<commit_before>use pom::{Input, DataInput};
use std::cmp;
use std::fs::File;
use std::io::{Result, Read, Error, ErrorKind};
use std::path::Path;

use super::{Document, Object, ObjectId};
use super::parser;
use xref::XrefEntry;
use object_stream::ObjectStream;

impl Document {
	/// Load PDF document from specified file path.
	pub fn load<P: AsRef<Path>>(path: P) -> Result<Document> {
		let mut file = File::open(path)?;
		let mut buffer = Vec::with_capacity(file.metadata()?.len() as usize);
		file.read_to_end(&mut buffer)?;

		let mut reader = Reader {
			buffer: buffer,
			document: Document::new(),
		};

		reader.read()?;
		Ok(reader.document)
	}
}

pub struct Reader {
	buffer: Vec<u8>,
	document: Document,
}

impl Reader {
	/// Read whole document.
	fn read(&mut self) -> Result<()> {
		let mut input = DataInput::new(&self.buffer);
		// The document structure can be expressed in PEG as:
		//   document <- header indirect_object* xref trailer xref_start
		let version = parser::header().parse(&mut input)
			.map_err(|_|Error::new(ErrorKind::InvalidData, "Not a valid PDF file (header)."))?;

		let xref_start = Self::get_xref_start(&self.buffer, &mut input)?;
		input.jump_to(xref_start);

		let (mut xref, mut trailer) = parser::xref_and_trailer(&self).parse(&mut input)
			.map_err(|_|Error::new(ErrorKind::InvalidData, "Not a valid PDF file (xref_and_trailer)."))?;

		// Read previous Xrefs of linearized or incremental updated document.
		let mut prev_xref_start = trailer.remove("Prev");
		while let Some(prev) = prev_xref_start.and_then(|offset|offset.as_i64()) {
			input.jump_to(prev as usize);
			let (prev_xref, mut prev_trailer) = parser::xref_and_trailer(&self).parse(&mut input)
				.map_err(|_|Error::new(ErrorKind::InvalidData, "Not a valid PDF file (prev xref_and_trailer)."))?;
			xref.extend(prev_xref);
			prev_xref_start = prev_trailer.remove("Prev");
		}

		self.document.version = version;
		self.document.max_id = xref.size - 1;
		self.document.trailer = trailer;
		self.document.reference_table = xref;

		for entry in self.document.reference_table.entries.values().filter(|entry|entry.is_normal()) {
			match *entry {
				XrefEntry::Normal{offset, ..} => {
					let (object_id, mut object) = self.read_object(offset as usize)?;

					match object {
						Object::Stream(ref mut stream) => if stream.dict.type_is("ObjStm") {
							self.document.streams.insert(object_id.0, ObjectStream::new(stream));
						},
						_ => {}
					}

					self.document.objects.insert(object_id, object);
				},
				_ => {},
			};
		}

		Ok(())
	}

	/// Get object offset by object id.
	fn get_offset(&self, id: ObjectId) -> Option<u32> {
		if let Some(entry) = self.document.reference_table.get(id.0) {
			match *entry {
				XrefEntry::Normal{offset, generation} => {
					if id.1 == generation { Some(offset) } else { None }
				},
				_ => None,
			}
		} else {
			None
		}
	}

	pub fn get_object(&self, id: ObjectId) -> Option<Object> {
		if let Some(offset) = self.get_offset(id) {
			if let Ok((_, obj)) = self.read_object(offset as usize) {
				return Some(obj);
			}
		}
		return None;
	}

	fn read_object(&self, offset: usize) -> Result<(ObjectId, Object)> {
		let mut input = DataInput::new(&self.buffer);
		input.jump_to(offset);
		parser::indirect_object(self).parse(&mut input)
			.map_err(|err|Error::new(ErrorKind::InvalidData, format!("Not a valid PDF file (read object at {}).\n{:?}", offset, err)))
	}

	fn get_xref_start(buffer: &[u8], input: &mut Input<u8>) -> Result<usize> {
		let seek_pos = buffer.len() - cmp::min(buffer.len(), 512);
		Self::search_substring(buffer, b"%%EOF", seek_pos)
			.and_then(|eof_pos| Self::search_substring(buffer, b"startxref", eof_pos - 25))
			.and_then(|xref_pos| {
				input.jump_to(xref_pos);
				match parser::xref_start().parse(input) {
					Ok(startxref) => Some(startxref as usize),
					_ => None,
				}
			})
			.ok_or(Error::new(ErrorKind::InvalidData, "Not a valid PDF file (xref_start)."))
	}

	fn search_substring(buffer: &[u8], pattern: &[u8], start_pos: usize) -> Option<usize> {
		let mut seek_pos = start_pos;
		let mut index = 0;

		while seek_pos < buffer.len() && index < pattern.len() {
			if buffer[seek_pos] == pattern[index] {
				index += 1;
			} else if index > 0 {
				seek_pos -= index;
				index = 0;
			}
			seek_pos += 1;

			if index == pattern.len() {
				return Some(seek_pos - index);
			}
		}

		return None;
	}
}

#[test]
fn load_document() {
	let mut doc = Document::load("assets/example.pdf").unwrap();
	assert_eq!(doc.version, "1.5");
	doc.save("test_2_load.pdf").unwrap();
}
<commit_msg>Read xref stream in hybrid-reference file<commit_after>use pom::{Input, DataInput};
use std::cmp;
use std::fs::File;
use std::io::{Result, Read, Error, ErrorKind};
use std::path::Path;

use super::{Document, Object, ObjectId};
use super::parser;
use xref::XrefEntry;
use object_stream::ObjectStream;

impl Document {
	/// Load PDF document from specified file path.
	pub fn load<P: AsRef<Path>>(path: P) -> Result<Document> {
		let mut file = File::open(path)?;
		let mut buffer = Vec::with_capacity(file.metadata()?.len() as usize);
		file.read_to_end(&mut buffer)?;

		let mut reader = Reader {
			buffer: buffer,
			document: Document::new(),
		};

		reader.read()?;
		Ok(reader.document)
	}
}

pub struct Reader {
	buffer: Vec<u8>,
	document: Document,
}

impl Reader {
	/// Read whole document.
	fn read(&mut self) -> Result<()> {
		let mut input = DataInput::new(&self.buffer);
		// The document structure can be expressed in PEG as:
		//   document <- header indirect_object* xref trailer xref_start
		let version = parser::header().parse(&mut input)
			.map_err(|_|Error::new(ErrorKind::InvalidData, "Not a valid PDF file (header)."))?;

		let xref_start = Self::get_xref_start(&self.buffer, &mut input)?;
		input.jump_to(xref_start);

		let (mut xref, mut trailer) = parser::xref_and_trailer(&self).parse(&mut input)
			.map_err(|_|Error::new(ErrorKind::InvalidData, "Not a valid PDF file (xref_and_trailer)."))?;

		// Read previous Xrefs of linearized or incremental updated document.
		let mut prev_xref_start = trailer.remove("Prev");
		while let Some(prev) = prev_xref_start.and_then(|offset|offset.as_i64()) {
			input.jump_to(prev as usize);
			let (prev_xref, mut prev_trailer) = parser::xref_and_trailer(&self).parse(&mut input)
				.map_err(|_|Error::new(ErrorKind::InvalidData, "Not a valid PDF file (prev xref_and_trailer)."))?;
			xref.extend(prev_xref);

			// Read xref stream in hybrid-reference file
			let prev_xref_stream_start = trailer.remove("XRefStm");
			if let Some(prev) = prev_xref_stream_start.and_then(|offset|offset.as_i64()) {
				input.jump_to(prev as usize);
				let (prev_xref, _) = parser::xref_and_trailer(&self).parse(&mut input)
					.map_err(|_|Error::new(ErrorKind::InvalidData, "Not a valid PDF file (prev xref_and_trailer)."))?;
				xref.extend(prev_xref);
			}

			prev_xref_start = prev_trailer.remove("Prev");
		}

		self.document.version = version;
		self.document.max_id = xref.size - 1;
		self.document.trailer = trailer;
		self.document.reference_table = xref;

		for entry in self.document.reference_table.entries.values().filter(|entry|entry.is_normal()) {
			match *entry {
				XrefEntry::Normal{offset, ..} => {
					let (object_id, mut object) = self.read_object(offset as usize)?;

					match object {
						Object::Stream(ref mut stream) => if stream.dict.type_is("ObjStm") {
							self.document.streams.insert(object_id.0, ObjectStream::new(stream));
						},
						_ => {}
					}

					self.document.objects.insert(object_id, object);
				},
				_ => {},
			};
		}

		Ok(())
	}

	/// Get object offset by object id.
	fn get_offset(&self, id: ObjectId) -> Option<u32> {
		if let Some(entry) = self.document.reference_table.get(id.0) {
			match *entry {
				XrefEntry::Normal{offset, generation} => {
					if id.1 == generation { Some(offset) } else { None }
				},
				_ => None,
			}
		} else {
			None
		}
	}

	pub fn get_object(&self, id: ObjectId) -> Option<Object> {
		if let Some(offset) = self.get_offset(id) {
			if let Ok((_, obj)) = self.read_object(offset as usize) {
				return Some(obj);
			}
		}
		return None;
	}

	fn read_object(&self, offset: usize) -> Result<(ObjectId, Object)> {
		let mut input = DataInput::new(&self.buffer);
		input.jump_to(offset);
		parser::indirect_object(self).parse(&mut input)
			.map_err(|err|Error::new(ErrorKind::InvalidData, format!("Not a valid PDF file (read object at {}).\n{:?}", offset, err)))
	}

	fn get_xref_start(buffer: &[u8], input: &mut Input<u8>) -> Result<usize> {
		let seek_pos = buffer.len() - cmp::min(buffer.len(), 512);
		Self::search_substring(buffer, b"%%EOF", seek_pos)
			.and_then(|eof_pos| Self::search_substring(buffer, b"startxref", eof_pos - 25))
			.and_then(|xref_pos| {
				input.jump_to(xref_pos);
				match parser::xref_start().parse(input) {
					Ok(startxref) => Some(startxref as usize),
					_ => None,
				}
			})
			.ok_or(Error::new(ErrorKind::InvalidData, "Not a valid PDF file (xref_start)."))
	}

	fn search_substring(buffer: &[u8], pattern: &[u8], start_pos: usize) -> Option<usize> {
		let mut seek_pos = start_pos;
		let mut index = 0;

		while seek_pos < buffer.len() && index < pattern.len() {
			if buffer[seek_pos] == pattern[index] {
				index += 1;
			} else if index > 0 {
				seek_pos -= index;
				index = 0;
			}
			seek_pos += 1;

			if index == pattern.len() {
				return Some(seek_pos - index);
			}
		}

		return None;
	}
}

#[test]
fn load_document() {
	let mut doc = Document::load("assets/example.pdf").unwrap();
	assert_eq!(doc.version, "1.5");
	doc.save("test_2_load.pdf").unwrap();
}
<|endoftext|>