<commit_before>use syntax_definition::*;
use scope::*;
use onig::{self, Region};
use std::usize;

#[derive(Debug, Clone)]
pub struct ParseState {
    stack: Vec<StateLevel>,
    pub scope_stack: ScopeStack,
    first_line: bool,
}

#[derive(Debug, Clone)]
struct StateLevel {
    context: ContextPtr,
    prototype: Option<ContextPtr>,
    scopes_pushed: usize,
}

#[derive(Debug)]
struct RegexMatch {
    regions: Region,
    context: ContextPtr,
    pat_index: usize,
}

impl ParseState {
    pub fn new(syntax: &SyntaxDefinition) -> ParseState {
        let start_state = StateLevel {
            context: syntax.contexts["main"].clone(),
            prototype: None,
            scopes_pushed: 1,
        };
        let mut scope_stack = ScopeStack::new();
        scope_stack.push(syntax.scope);
        ParseState {
            stack: vec![start_state],
            scope_stack: scope_stack,
            first_line: true,
        }
    }

    pub fn parse_line(&mut self, line: &str) -> Vec<(usize, ScopeStackOp)> {
        assert!(self.stack.len() > 0,
                "Somehow main context was popped from the stack");
        let mut match_start = 0;
        let mut res = Vec::new();
        while self.parse_next_token(line, &mut match_start, &mut res) {
        }
        // apply operations to our scope to keep up
        // TODO do we even need to keep a scope stack in the parser state?
        for &(_, ref op) in res.iter() {
            self.scope_stack.apply(op);
        }
        return res;
    }

    fn parse_next_token(&mut self,
                        line: &str,
                        start: &mut usize,
                        ops: &mut Vec<(usize, ScopeStackOp)>)
                        -> bool {
        let cur_match = {
            let cur_level = &self.stack[self.stack.len() - 1];
            let mut min_start = usize::MAX;
            let mut cur_match: Option<RegexMatch> = None;
            for (pat_context_ptr, pat_index) in context_iter(cur_level.context.clone()) {
                let pat_context = pat_context_ptr.borrow();
                let match_pat = pat_context.match_at(pat_index);

                println!("{:?}", match_pat.regex_str);
                let regex = match_pat.regex.as_ref().unwrap(); // TODO handle backrefs
                let mut regions = Region::new();
                // TODO caching
                let matched = regex.search_with_options(line,
                                                        *start,
                                                        line.len(),
                                                        onig::SEARCH_OPTION_NONE,
                                                        Some(&mut regions));
                if let Some(match_start) = matched {
                    if match_start < min_start {
                        min_start = match_start;
                        cur_match = Some(RegexMatch {
                            regions: regions,
                            context: pat_context_ptr.clone(),
                            pat_index: pat_index,
                        });
                    }
                }
            }
            cur_match
        };

        if let Some(reg_match) = cur_match {
            let (_, match_end) = reg_match.regions.pos(0).unwrap();
            *start = match_end;
            self.exec_pattern(line, reg_match, ops);
            true
        } else {
            false
        }
    }

    fn exec_pattern(&mut self,
                    line: &str,
                    reg_match: RegexMatch,
                    ops: &mut Vec<(usize, ScopeStackOp)>) {
        let (match_start, match_end) = reg_match.regions.pos(0).unwrap();
        let context = reg_match.context.borrow();
        let pat = context.match_at(reg_match.pat_index);
        for s in pat.scope.iter() {
            ops.push((match_start, ScopeStackOp::Push(s.clone())));
        }
        if !pat.scope.is_empty() {
            ops.push((match_end, ScopeStackOp::Pop(pat.scope.len())));
        }
        // TODO apply capture scopes
        // TODO perform operation (with prototype)
        // TODO apply meta scopes
    }
}

#[cfg(test)]
mod tests {
    use package_set::PackageSet;
    use parser::*;
    use scope::*;
    fn debug_print_ops(line: &str,
                       scope_repo: &ScopeRepository,
                       ops: &Vec<(usize, ScopeStackOp)>) {
        println!("{}", line);
        for &(i, ref op) in ops.iter() {
            print!("{: <1$}", "", i);
            match op {
                &ScopeStackOp::Push(s) => {
                    println!("^ +{}", scope_repo.to_string(s));
                }
                &ScopeStackOp::Pop(count) => {
                    println!("^ pop {}", count);
                }
            }
        }
    }

    #[test]
    fn can_parse() {
        let mut ps = PackageSet::load_from_folder("testdata/Packages").unwrap();
        let mut state = {
            let syntax = ps.find_syntax_by_name("Ruby on Rails").unwrap();
            ParseState::new(syntax)
        };

        let line = "class Bob; 5; end";
        let ops = state.parse_line(line);
        debug_print_ops(line, &ps.scope_repo, &ops);

        let test_ops = vec![
            (0, ScopeStackOp::Push(ps.scope_repo.build("meta.class.ruby"))),
            // TODO missing captures
            (9, ScopeStackOp::Pop(1)),
            (9, ScopeStackOp::Push(ps.scope_repo.build("punctuation.separator.statement.ruby"))),
            (10, ScopeStackOp::Pop(1)),
        ];
        assert_eq!(&ops[0..test_ops.len()], &test_ops[..]);
        // assert!(false);
    }
}
<commit_msg>Parse and assign scopes to captures<commit_after>use syntax_definition::*;
use scope::*;
use onig::{self, Region};
use std::usize;

#[derive(Debug, Clone)]
pub struct ParseState {
    stack: Vec<StateLevel>,
    pub scope_stack: ScopeStack,
    first_line: bool,
}

#[derive(Debug, Clone)]
struct StateLevel {
    context: ContextPtr,
    prototype: Option<ContextPtr>,
    scopes_pushed: usize,
}

#[derive(Debug)]
struct RegexMatch {
    regions: Region,
    context: ContextPtr,
    pat_index: usize,
}

impl ParseState {
    pub fn new(syntax: &SyntaxDefinition) -> ParseState {
        let start_state = StateLevel {
            context: syntax.contexts["main"].clone(),
            prototype: None,
            scopes_pushed: 1,
        };
        let mut scope_stack = ScopeStack::new();
        scope_stack.push(syntax.scope);
        ParseState {
            stack: vec![start_state],
            scope_stack: scope_stack,
            first_line: true,
        }
    }

    pub fn parse_line(&mut self, line: &str) -> Vec<(usize, ScopeStackOp)> {
        assert!(self.stack.len() > 0,
                "Somehow main context was popped from the stack");
        let mut match_start = 0;
        let mut res = Vec::new();
        while self.parse_next_token(line, &mut match_start, &mut res) {
        }
        // apply operations to our scope to keep up
        // TODO do we even need to keep a scope stack in the parser state?
        for &(_, ref op) in res.iter() {
            self.scope_stack.apply(op);
        }
        return res;
    }

    fn parse_next_token(&mut self,
                        line: &str,
                        start: &mut usize,
                        ops: &mut Vec<(usize, ScopeStackOp)>)
                        -> bool {
        let cur_match = {
            let cur_level = &self.stack[self.stack.len() - 1];
            let mut min_start = usize::MAX;
            let mut cur_match: Option<RegexMatch> = None;
            for (pat_context_ptr, pat_index) in context_iter(cur_level.context.clone()) {
                let pat_context = pat_context_ptr.borrow();
                let match_pat = pat_context.match_at(pat_index);

                println!("{:?}", match_pat.regex_str);
                let regex = match_pat.regex.as_ref().unwrap(); // TODO handle backrefs
                let mut regions = Region::new();
                // TODO caching
                let matched = regex.search_with_options(line,
                                                        *start,
                                                        line.len(),
                                                        onig::SEARCH_OPTION_NONE,
                                                        Some(&mut regions));
                if let Some(match_start) = matched {
                    if match_start < min_start {
                        min_start = match_start;
                        cur_match = Some(RegexMatch {
                            regions: regions,
                            context: pat_context_ptr.clone(),
                            pat_index: pat_index,
                        });
                    }
                }
            }
            cur_match
        };

        if let Some(reg_match) = cur_match {
            let (_, match_end) = reg_match.regions.pos(0).unwrap();
            *start = match_end;
            self.exec_pattern(line, reg_match, ops);
            true
        } else {
            false
        }
    }

    fn exec_pattern(&mut self,
                    line: &str,
                    reg_match: RegexMatch,
                    ops: &mut Vec<(usize, ScopeStackOp)>) {
        let (match_start, match_end) = reg_match.regions.pos(0).unwrap();
        let context = reg_match.context.borrow();
        let pat = context.match_at(reg_match.pat_index);
        for s in pat.scope.iter() {
            ops.push((match_start, ScopeStackOp::Push(s.clone())));
        }
        if let Some(ref capture_map) = pat.captures {
            // captures could appear in an arbitrary order, have to produce ops in right order
            // ex: ((bob)|(hi))* could match hibob in wrong order, and outer has to push first
            // we don't have to handle a capture matching multiple times, Sublime doesn't
            let mut map: Vec<((usize, i32), ScopeStackOp)> = Vec::new();
            for (cap_index, scopes) in capture_map.iter() {
                if let Some((cap_start, cap_end)) = reg_match.regions.pos(*cap_index) {
                    for scope in scopes.iter() {
                        map.push(((cap_start, -((cap_end - cap_start) as i32)),
                                  ScopeStackOp::Push(scope.clone())));
                    }
                    map.push(((cap_end, -1000000), ScopeStackOp::Pop(scopes.len())));
                }
            }
            map.sort_by(|a, b| a.0.cmp(&b.0));
            for ((index, _), op) in map.into_iter() {
                ops.push((index, op));
            }
        }
        if !pat.scope.is_empty() {
            ops.push((match_end, ScopeStackOp::Pop(pat.scope.len())));
        }
        // TODO perform operation (with prototype)
        // TODO apply meta scopes
    }
}

#[cfg(test)]
mod tests {
    use package_set::PackageSet;
    use parser::*;
    use scope::*;
    fn debug_print_ops(line: &str,
                       scope_repo: &ScopeRepository,
                       ops: &Vec<(usize, ScopeStackOp)>) {
        println!("{}", line);
        for &(i, ref op) in ops.iter() {
            print!("{: <1$}", "", i);
            match op {
                &ScopeStackOp::Push(s) => {
                    println!("^ +{}", scope_repo.to_string(s));
                }
                &ScopeStackOp::Pop(count) => {
                    println!("^ pop {}", count);
                }
            }
        }
    }

    #[test]
    fn can_parse() {
        let mut ps = PackageSet::load_from_folder("testdata/Packages").unwrap();
        let mut state = {
            let syntax = ps.find_syntax_by_name("Ruby on Rails").unwrap();
            ParseState::new(syntax)
        };

        let line = "module Bob::Wow::Troll::Five; 5; end";
        let ops = state.parse_line(line);
        debug_print_ops(line, &ps.scope_repo, &ops);

        let test_ops = vec![
            (0, ScopeStackOp::Push(ps.scope_repo.build("meta.module.ruby"))),
            (0, ScopeStackOp::Push(ps.scope_repo.build("keyword.control.module.ruby"))),
            (6, ScopeStackOp::Pop(1)),
            (7, ScopeStackOp::Push(ps.scope_repo.build("entity.name.type.module.ruby"))),
            (7, ScopeStackOp::Push(ps.scope_repo.build("entity.other.inherited-class.module.first.ruby"))),
            (10, ScopeStackOp::Push(ps.scope_repo.build("punctuation.separator.inheritance.ruby"))),
            (12, ScopeStackOp::Pop(1)),
            (12, ScopeStackOp::Pop(1)),
        ];
        assert_eq!(&ops[0..test_ops.len()], &test_ops[..]);
        // assert!(false);
    }
}
<|endoftext|>


<commit_before>
use ast::ExprAst;
use ast::BoolNode;
use ast::CharNode;

#[allow(dead_code)]

#[deriving(Clone, Show)]
pub struct Parser {
    code: String,
    cur: uint,
    col: uint,
    line: uint
}

pub struct ParserError {
    line: uint,
    col: uint,
    desc: String
}

impl ParserError {
    pub fn new(line: uint, col: uint, desc: String) -> ParserError {
        ParserError {
            line: line,
            col: col,
            desc: desc
        }
    }
}

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

#[allow(dead_code)]
impl Parser {
    pub fn new() -> Parser {
        Parser{
            code: "".to_string(),
            line: 0,
            cur: 0,
            col: 0
        }
    }

    pub fn load(&mut self, code: String) -> ExprAst {
        self.code = code;
        self.line = 1;
        self.cur = 0;
        self.col = 1;
        self.skip_white();

        let cur = self.getc();
        if cur == '#' {
            let next = self.getc();
            match next {
                't' => return ExprAst::Bool(BoolNode::new(true)),
                'f' => return ExprAst::Bool(BoolNode::new(false)),
                '\\' => return self.read_char(),
                _ => panic!("error")
            }
        }
        ExprAst::Char(CharNode::new('a'))
    }

    //============= private methods =================

    fn is_delimiter(&self, ch: char) -> bool {
        if ch.is_whitespace() ||
            ch == '\"' || ch == '(' || ch == ')' ||  ch == ';' ||
            ch as u32 == 0 {
                true
            } else {
                false
            }
    }

    fn is_initial(&self, ch: char) -> bool {
        if ch.is_alphabetic() ||
            ch == '*' || ch == '/' ||
            ch == '+' || ch == '-' ||
            ch == '>' || ch == '<' ||
            ch == '=' || ch == '?' ||
            ch == '!' {
                true
            } else {
                false
            }
    }

    fn skip_white(&mut self) {
        while self.peekc().is_whitespace() {
            if self.peekc() == '\n' {
                self.line += 1;
            }
            self.cur += 1;
        }
    }

    fn peekc(&self) -> char {
        if self.cur < self.code.len() {
            self.code.char_at(self.cur)
        } else {
            0 as char
        }
    }

    fn getc(&mut self) -> char {
        if self.cur < self.code.len() {
            let res = self.code.char_at(self.cur);
            self.cur += 1;
            res
        } else {
            0 as char
        }
    }

    fn read_char(&mut self) -> ExprAst {
        ExprAst::Char(CharNode::new('a'))
    }

}
<commit_msg>more on parser<commit_after>use ast::ExprAst;
use ast::BoolNode;
use ast::CharNode;
use ast::IntNode;

#[allow(dead_code)]

#[deriving(Clone, Show)]
pub struct Parser {
    code: String,
    cur: uint,
    col: uint,
    line: uint
}

pub struct ParserError {
    line: uint,
    col: uint,
    desc: String
}

impl ParserError {
    pub fn new(line: uint, col: uint, desc: String) -> ParserError {
        ParserError {
            line: line,
            col: col,
            desc: desc
        }
    }
}

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

#[allow(dead_code)]
impl Parser {
    pub fn new() -> Parser {
        Parser{
            code: "".to_string(),
            line: 0,
            cur: 0,
            col: 0
        }
    }

    pub fn load(&mut self, code: String) -> ExprAst {
        self.code = code;
        self.line = 1;
        self.cur = 0;
        self.col = 1;
        self.skip_white();

        let mut cur = self.getc();
        if cur == '#' {
            let next = self.getc();
            match next {
                't' => return ExprAst::Bool(BoolNode::new(true)),
                'f' => return ExprAst::Bool(BoolNode::new(false)),
                '\\' => return self.read_char(),
                _ => panic!("error")
            }
        } else if self.is_digits(cur) || (cur == '-' && (self.is_digits(self.peekc()))) {
            let mut sign = 1i32;
            if cur == '-' {
                sign = -1;
            } else {
                self.unread();
            }
            let mut num = 0i32;
            loop {
                cur = self.getc();
                if !self.is_digits(cur) {
                    break;
                }
                num = (num * 10i32) + (cur as i32 - 0i32);
            }
            num *= sign;
            return ExprAst::Int(IntNode::new(num));
        }
        ExprAst::Char(CharNode::new('a'))
    }

    //============= private methods =================

    fn is_digits(&self, ch: char) -> bool {
        match ch {
            '0'...'9' => true,
            _ => false
        }
    }

    fn is_delimiter(&self, ch: char) -> bool {
        if ch.is_whitespace() ||
            ch == '\"' || ch == '(' || ch == ')' ||  ch == ';' ||
            ch as u32 == 0 {
                true
            } else {
                false
            }
    }

    fn is_initial(&self, ch: char) -> bool {
        if ch.is_alphabetic() ||
            ch == '*' || ch == '/' ||
            ch == '+' || ch == '-' ||
            ch == '>' || ch == '<' ||
            ch == '=' || ch == '?' ||
            ch == '!' {
                true
            } else {
                false
            }
    }

    fn skip_white(&mut self) {
        while self.peekc().is_whitespace() {
            if self.peekc() == '\n' {
                self.line += 1;
            }
            self.cur += 1;
        }
    }

    fn peekc(&self) -> char {
        if self.cur < self.code.len() {
            self.code.char_at(self.cur)
        } else {
            0 as char
        }
    }

    fn getc(&mut self) -> char {
        if self.cur < self.code.len() {
            let res = self.code.char_at(self.cur);
            self.cur += 1;
            res
        } else {
            0 as char
        }
    }

    fn unread(&mut self) {
        if self.cur == 0 {
            panic!("error current position");
        }
        self.cur -= 1;
    }

    fn read_char(&mut self) -> ExprAst {
        ExprAst::Char(CharNode::new('a'))
    }

}
<|endoftext|>


<commit_before>//! The puzzle's state and rules.

use std::collections::BTreeSet;
use std::rc::Rc;

use ::{Val,VarToken};

/// A collection of candidates.
#[derive(Clone,Debug,Eq,PartialEq)]
enum Candidates {
    None,                       // A variable with no candidates.
    Value(Val),                 // A variable set to its initial value.
    Set(Rc<BTreeSet<Val>>),     // A variable with a list of candidates.
}

/// The puzzle to be solved.
pub struct Puzzle {
    // The number of variables in the puzzle.
    num_vars: usize,

    // The list of candidates for each variable.
    candidates: Vec<Candidates>,
}

impl Puzzle {
    /// Allocate a new puzzle.
    ///
    /// # Examples
    ///
    /// ```
    /// puzzle_solver::Puzzle::new();
    /// ```
    pub fn new() -> Self {
        Puzzle {
            num_vars: 0,
            candidates: Vec::new(),
        }
    }

    /// Allocate a new puzzle variable, without inserting any
    /// candidates.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut puzzle = puzzle_solver::Puzzle::new();
    /// puzzle.new_var();
    /// ```
    pub fn new_var(&mut self) -> VarToken {
        let var = VarToken(self.num_vars);
        self.num_vars = self.num_vars + 1;
        self.candidates.push(Candidates::None);
        var
    }

    /// Set a variable to a known value.
    ///
    /// This is useful when the variable is given as part of the
    /// problem.  After this operation, any subsequent attempts to set
    /// the value will panic.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut magic_square = puzzle_solver::Puzzle::new();
    /// let mut vars = Vec::new();
    /// for _ in 0..9 {
    ///     vars.push(magic_square.new_var());
    /// }
    /// magic_square.set_value(vars[4], 5);
    /// ```
    pub fn set_value(&mut self, var: VarToken, value: Val) {
        let VarToken(idx) = var;

        if let Candidates::Value(val) = self.candidates[idx] {
            if val != value {
                panic!("attempt to set fixed variable");
            }
        }

        self.candidates[idx] = Candidates::Value(value);
    }

    /// Add candidates to a variable.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut send_more_money = puzzle_solver::Puzzle::new();
    /// for _ in 0..9 {
    ///     let var = send_more_money.new_var();
    ///     send_more_money.insert_candidates(var, &[0,1,2,3,4,5,6,7,8,9]);
    /// }
    /// ```
    pub fn insert_candidates(&mut self, var: VarToken, candidates: &[Val]) {
        let VarToken(idx) = var;

        match &self.candidates[idx] {
            &Candidates::Value(_) =>
                panic!("attempt to set fixed variable"),

            &Candidates::None => {
                self.candidates[idx] = Candidates::Set(Rc::new(BTreeSet::new()));
            },

            &Candidates::Set(_) => (),
        }

        // Why you dumb Rust?
        if let Candidates::Set(ref mut rc) = self.candidates[idx] {
            let cs = Rc::get_mut(rc).expect("unique");
            cs.extend(candidates);
        }
    }

    /// Remove candidates from a variable.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut send_more_money = puzzle_solver::Puzzle::new();
    /// let mut vars = Vec::new();
    /// for _ in 0..8 { // [s,e,n,d,m,o,r,y].
    ///     let var = send_more_money.new_var();
    ///     send_more_money.insert_candidates(var, &[0,1,2,3,4,5,6,7,8,9]);
    ///     vars.push(var);
    /// }
    ///
    /// let s = vars[0];
    /// let m = vars[4];
    /// send_more_money.remove_candidates(s, &[0]);
    /// send_more_money.remove_candidates(m, &[0]);
    /// ```
    pub fn remove_candidates(&mut self, var: VarToken, candidates: &[Val]) {
        let VarToken(idx) = var;

        match self.candidates[idx] {
            Candidates::Value(_) =>
                panic!("attempt to set fixed variable"),

            Candidates::None => (),

            Candidates::Set(ref mut rc) => {
                let cs = Rc::get_mut(rc).expect("unique");
                for c in candidates.iter() {
                    cs.remove(c);
                }
            },
        }
    }

    /// Set the variable's candidates to the intersection with the
    /// given list.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut send_more_money = puzzle_solver::Puzzle::new();
    /// let mut vars = Vec::new();
    /// for _ in 0..8 { // [s,e,n,d,m,o,r,y].
    ///     let var = send_more_money.new_var();
    ///     send_more_money.insert_candidates(var, &[0,1,2,3,4,5,6,7,8,9]);
    ///     vars.push(var);
    /// }
    ///
    /// let m = vars[4];
    /// send_more_money.intersect_candidates(m, &[0,1]);
    /// ```
    pub fn intersect_candidates(&mut self, var: VarToken, candidates: &[Val]) {
        let VarToken(idx) = var;

        match self.candidates[idx] {
            Candidates::Value(_) =>
                panic!("attempt to set fixed variable"),

            Candidates::None => (),

            Candidates::Set(ref mut rc) => {
                let cs = Rc::get_mut(rc).expect("unique");
                let mut set = BTreeSet::new();
                set.extend(candidates);
                *cs = cs.intersection(&set).cloned().collect();
            },
        }
    }
}
<commit_msg>Add convenience functions for creating puzzle variables.<commit_after>//! The puzzle's state and rules.

use std::collections::BTreeSet;
use std::rc::Rc;

use ::{Val,VarToken};

/// A collection of candidates.
#[derive(Clone,Debug,Eq,PartialEq)]
enum Candidates {
    None,                       // A variable with no candidates.
    Value(Val),                 // A variable set to its initial value.
    Set(Rc<BTreeSet<Val>>),     // A variable with a list of candidates.
}

/// The puzzle to be solved.
pub struct Puzzle {
    // The number of variables in the puzzle.
    num_vars: usize,

    // The list of candidates for each variable.
    candidates: Vec<Candidates>,
}

impl Puzzle {
    /// Allocate a new puzzle.
    ///
    /// # Examples
    ///
    /// ```
    /// puzzle_solver::Puzzle::new();
    /// ```
    pub fn new() -> Self {
        Puzzle {
            num_vars: 0,
            candidates: Vec::new(),
        }
    }

    /// Allocate a new puzzle variable, without inserting any
    /// candidates.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut puzzle = puzzle_solver::Puzzle::new();
    /// puzzle.new_var();
    /// ```
    pub fn new_var(&mut self) -> VarToken {
        let var = VarToken(self.num_vars);
        self.num_vars = self.num_vars + 1;
        self.candidates.push(Candidates::None);
        var
    }

    /// Allocate a new puzzle variable, initialising it with potential
    /// candidates.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut send_more_money = puzzle_solver::Puzzle::new();
    /// send_more_money.new_var_with_candidates(&[0,1,2,3,4,5,6,7,8,9]);
    /// ```
    pub fn new_var_with_candidates(&mut self, candidates: &[Val]) -> VarToken {
        let var = self.new_var();
        self.insert_candidates(var, candidates);
        var
    }

    /// Allocate a 1d vector of puzzle variables, each initialised to
    /// have the same set of potential candidates.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut send_more_money = puzzle_solver::Puzzle::new();
    /// send_more_money.new_vars_with_candidates_1d(8, &[0,1,2,3,4,5,6,7,8,9]);
    /// ```
    pub fn new_vars_with_candidates_1d(&mut self, n: usize, candidates: &[Val])
            -> Vec<VarToken> {
        let mut vars = Vec::with_capacity(n);
        for _ in 0..n {
            vars.push(self.new_var_with_candidates(candidates));
        }
        vars
    }

    /// Allocate a 2d array of puzzle variables, each initialised to
    /// have the same set of potential candidates.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut magic_square = puzzle_solver::Puzzle::new();
    /// magic_square.new_vars_with_candidates_2d(3, 3, &[1,2,3,4,5,6,7,8,9]);
    /// ```
    pub fn new_vars_with_candidates_2d(self: &mut Puzzle,
            width: usize, height: usize, candidates: &[Val])
            -> Vec<Vec<VarToken>> {
        let mut vars = Vec::with_capacity(height);
        for _ in 0..height {
            vars.push(self.new_vars_with_candidates_1d(width, candidates));
        }
        vars
    }

    /// Set a variable to a known value.
    ///
    /// This is useful when the variable is given as part of the
    /// problem.  After this operation, any subsequent attempts to set
    /// the value will panic.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut magic_square = puzzle_solver::Puzzle::new();
    /// let vars = magic_square.new_vars_with_candidates_2d(3, 3,
    ///         &[1,2,3,4,5,6,7,8,9]);
    ///
    /// magic_square.set_value(vars[1][1], 5);
    /// ```
    pub fn set_value(&mut self, var: VarToken, value: Val) {
        let VarToken(idx) = var;

        if let Candidates::Value(val) = self.candidates[idx] {
            if val != value {
                panic!("attempt to set fixed variable");
            }
        }

        self.candidates[idx] = Candidates::Value(value);
    }

    /// Add candidates to a variable.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut send_more_money = puzzle_solver::Puzzle::new();
    /// for _ in 0..9 {
    ///     let var = send_more_money.new_var();
    ///     send_more_money.insert_candidates(var, &[0,1,2,3,4,5,6,7,8,9]);
    /// }
    /// ```
    pub fn insert_candidates(&mut self, var: VarToken, candidates: &[Val]) {
        let VarToken(idx) = var;

        match &self.candidates[idx] {
            &Candidates::Value(_) =>
                panic!("attempt to set fixed variable"),

            &Candidates::None => {
                self.candidates[idx] = Candidates::Set(Rc::new(BTreeSet::new()));
            },

            &Candidates::Set(_) => (),
        }

        // Why you dumb Rust?
        if let Candidates::Set(ref mut rc) = self.candidates[idx] {
            let cs = Rc::get_mut(rc).expect("unique");
            cs.extend(candidates);
        }
    }

    /// Remove candidates from a variable.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut send_more_money = puzzle_solver::Puzzle::new();
    /// let vars = send_more_money.new_vars_with_candidates_1d(8,
    ///         &[0,1,2,3,4,5,6,7,8,9]);
    ///
    /// let s = vars[0];
    /// let m = vars[4];
    /// send_more_money.remove_candidates(s, &[0]);
    /// send_more_money.remove_candidates(m, &[0]);
    /// ```
    pub fn remove_candidates(&mut self, var: VarToken, candidates: &[Val]) {
        let VarToken(idx) = var;

        match self.candidates[idx] {
            Candidates::Value(_) =>
                panic!("attempt to set fixed variable"),

            Candidates::None => (),

            Candidates::Set(ref mut rc) => {
                let cs = Rc::get_mut(rc).expect("unique");
                for c in candidates.iter() {
                    cs.remove(c);
                }
            },
        }
    }

    /// Set the variable's candidates to the intersection with the
    /// given list.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut send_more_money = puzzle_solver::Puzzle::new();
    /// let vars = send_more_money.new_vars_with_candidates_1d(8,
    ///         &[0,1,2,3,4,5,6,7,8,9]);
    ///
    /// let m = vars[4];
    /// send_more_money.intersect_candidates(m, &[0,1]);
    /// ```
    pub fn intersect_candidates(&mut self, var: VarToken, candidates: &[Val]) {
        let VarToken(idx) = var;

        match self.candidates[idx] {
            Candidates::Value(_) =>
                panic!("attempt to set fixed variable"),

            Candidates::None => (),

            Candidates::Set(ref mut rc) => {
                let cs = Rc::get_mut(rc).expect("unique");
                let mut set = BTreeSet::new();
                set.extend(candidates);
                *cs = cs.intersection(&set).cloned().collect();
            },
        }
    }
}
<|endoftext|>


<commit_before>/// Reader will read the entries from stdin or command output
/// And send the entries to controller, the controller will save it into model.

extern crate libc;

use std::process::{Command, Stdio, Child};
use std::sync::{Arc, RwLock};
use std::io::{stdin, BufRead, BufReader};
use std::error::Error;
use util::eventbox::EventBox;
use event::Event;
use item::Item;
use getopts;
use regex::Regex;

const READER_EVENT_DURATION: u64 = 30;

pub struct Reader {
    cmd: String, // command to invoke
    eb: Arc<EventBox<Event>>,         // eventbox
    pub eb_req: Arc<EventBox<Event>>,
    items: Arc<RwLock<Vec<Item>>>, // all items
    use_ansi_color: bool,
    default_arg: String,
    transform_fields: Vec<FieldRange>,
    matching_fields: Vec<FieldRange>,
    delimiter: Regex,
    replace_str: String,
}

impl Reader {

    pub fn new(cmd: String, eb: Arc<EventBox<Event>>, items: Arc<RwLock<Vec<Item>>>) -> Self {
        Reader{cmd: cmd,
               eb: eb,
               eb_req: Arc::new(EventBox::new()),
               items: items,
               use_ansi_color: false,
               default_arg: String::new(),
               transform_fields: Vec::new(),
               matching_fields: Vec::new(),
               delimiter: Regex::new(r".*?\t").unwrap(),
               replace_str: "{}".to_string(),
        }
    }

    // invoke find comand.
    fn get_command_output(&self, arg: &str) -> Result<(Option<Child>, Box<BufRead>), Box<Error>> {
        let mut command = try!(Command::new("sh")
                           .arg("-c")
                           .arg(self.cmd.replace(&self.replace_str, arg))
                           .stdout(Stdio::piped())
                           .stderr(Stdio::null())
                           .spawn());
        let stdout = try!(command.stdout.take().ok_or("command output: unwrap failed".to_owned()));
        Ok((Some(command), Box::new(BufReader::new(stdout))))
    }

    pub fn parse_options(&mut self, options: &getopts::Matches) {
        if options.opt_present("ansi") {
            self.use_ansi_color = true;
        }

        if let Some(cmd) = options.opt_str("c") {
            self.cmd = cmd.clone();
        }

        if let Some(query) = options.opt_str("q") {
            self.default_arg = query.to_string();
        }

        if let Some(delimiter) = options.opt_str("d") {
            self.delimiter = Regex::new(&(".*?".to_string() + &delimiter))
                .unwrap_or(Regex::new(r".*?\t").unwrap());
        }

        if let Some(transform_fields) = options.opt_str("with-nth") {
            self.transform_fields = transform_fields.split(',')
                .map(|string| {
                    parse_range(string)
                })
                .filter(|range| range.is_some())
                .map(|range| range.unwrap())
                .collect();
        }

        if let Some(matching_fields) = options.opt_str("nth") {
            self.matching_fields = matching_fields.split(',')
                .map(|string| {
                    parse_range(string)
                })
                .filter(|range| range.is_some())
                .map(|range| range.unwrap())
                .collect();
        }

        if let Some(replace_str) = options.opt_str("I") {
            self.replace_str = replace_str.clone();
        }
    }

    pub fn run(&mut self) {
        // check if the input is TTY
        let istty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
        let mut arg = self.default_arg.clone();

        loop {
            let (command, read): (Option<Child>, Box<BufRead>) = if istty {
                self.get_command_output(&arg).expect("command not found")
            } else {
                (None, Box::new(BufReader::new(stdin())))
            };

            self.read_items(read);
            command.map(|mut x| {
                let _ = x.kill();
                let _ = x.wait();
            });

            for (e, val) in self.eb_req.wait() {
                match e {
                    Event::EvReaderResetQuery => {
                        let mut items = self.items.write().unwrap();
                        items.clear();
                        arg = *val.downcast::<String>().unwrap();
                        self.eb.set(Event::EvReaderSync, Box::new(true));
                        let _ = self.eb_req.wait_for(Event::EvModelAck);
                    }
                    _ => {}
                }
            }
        }
    }

    fn read_items(&self, mut source: Box<BufRead>) {
        loop {
            let mut input = String::new();
            match source.read_line(&mut input) {
                Ok(n) => {
                    if n <= 0 { break; }

                    if input.ends_with("\n") {
                        input.pop();
                        if input.ends_with("\r") {
                            input.pop();
                        }
                    }
                    let mut items = self.items.write().unwrap();
                    items.push(Item::new(input,
                                         self.use_ansi_color,
                                         &self.transform_fields,
                                         &self.matching_fields,
                                         &self.delimiter));
                }
                Err(_err) => {} // String not UTF8 or other error, skip.
            }
            self.eb.set_throttle(Event::EvReaderNewItem, Box::new(true), READER_EVENT_DURATION);
            if self.eb_req.peek(Event::EvReaderResetQuery) {
                break;
            }
        }
        self.eb.set_throttle(Event::EvReaderNewItem, Box::new(false), READER_EVENT_DURATION);
    }
}

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum FieldRange {
    Single(i64),
    LeftInf(i64),
    RightInf(i64),
    Both(i64, i64),
}

// range: "start..end", end is excluded.
// "0", "0..", "..10", "1..10", etc.
fn parse_range(range: &str) -> Option<FieldRange> {
    use self::FieldRange::*;
    let range_string: Vec<&str> = range.split("..").collect();
    if range_string.len() <= 0 || range_string.len() > 2 {
        return None;
    }

    let start = range_string.get(0).and_then(|x| x.parse::<i64>().ok());
    let end = range_string.get(1).and_then(|x| x.parse::<i64>().ok());

    if range_string.len() == 1 {
        return if start.is_none() {None} else {Some(Single(start.unwrap()))};
    }

    if start.is_none() && end.is_none() {
        Some(RightInf(0))
    } else if end.is_none() {
        // 1..
        Some(RightInf(start.unwrap()))
    } else if start.is_none() {
        // ..1
        Some(LeftInf(end.unwrap()))
    } else {
        Some(Both(start.unwrap(), end.unwrap()))
    }
}

#[cfg(test)]
mod test {
    use super::FieldRange::*;
    #[test]
    fn test_parse_range() {
        assert_eq!(super::parse_range("1"), Some(Single(1)));
        assert_eq!(super::parse_range("-1"), Some(Single(-1)));

        assert_eq!(super::parse_range("1.."), Some(RightInf(1)));
        assert_eq!(super::parse_range("-1.."), Some(RightInf(-1)));

        assert_eq!(super::parse_range("..1"), Some(LeftInf(1)));
        assert_eq!(super::parse_range("..-1"), Some(LeftInf(-1)));

        assert_eq!(super::parse_range("1..3"), Some(Both(1, 3)));
        assert_eq!(super::parse_range("-1..-3"), Some(Both(-1, -3)));

        assert_eq!(super::parse_range(".."), Some(RightInf(0)));
        assert_eq!(super::parse_range("a.."), None);
        assert_eq!(super::parse_range("..b"), None);
        assert_eq!(super::parse_range("a..b"), None);
    }
}
<commit_msg>[reader] fix range to pass test<commit_after>/// Reader will read the entries from stdin or command output
/// And send the entries to controller, the controller will save it into model.

extern crate libc;

use std::process::{Command, Stdio, Child};
use std::sync::{Arc, RwLock};
use std::io::{stdin, BufRead, BufReader};
use std::error::Error;
use util::eventbox::EventBox;
use event::Event;
use item::Item;
use getopts;
use regex::Regex;

const READER_EVENT_DURATION: u64 = 30;

pub struct Reader {
    cmd: String, // command to invoke
    eb: Arc<EventBox<Event>>,         // eventbox
    pub eb_req: Arc<EventBox<Event>>,
    items: Arc<RwLock<Vec<Item>>>, // all items
    use_ansi_color: bool,
    default_arg: String,
    transform_fields: Vec<FieldRange>,
    matching_fields: Vec<FieldRange>,
    delimiter: Regex,
    replace_str: String,
}

impl Reader {

    pub fn new(cmd: String, eb: Arc<EventBox<Event>>, items: Arc<RwLock<Vec<Item>>>) -> Self {
        Reader{cmd: cmd,
               eb: eb,
               eb_req: Arc::new(EventBox::new()),
               items: items,
               use_ansi_color: false,
               default_arg: String::new(),
               transform_fields: Vec::new(),
               matching_fields: Vec::new(),
               delimiter: Regex::new(r".*?\t").unwrap(),
               replace_str: "{}".to_string(),
        }
    }

    // invoke find comand.
    fn get_command_output(&self, arg: &str) -> Result<(Option<Child>, Box<BufRead>), Box<Error>> {
        let mut command = try!(Command::new("sh")
                           .arg("-c")
                           .arg(self.cmd.replace(&self.replace_str, arg))
                           .stdout(Stdio::piped())
                           .stderr(Stdio::null())
                           .spawn());
        let stdout = try!(command.stdout.take().ok_or("command output: unwrap failed".to_owned()));
        Ok((Some(command), Box::new(BufReader::new(stdout))))
    }

    pub fn parse_options(&mut self, options: &getopts::Matches) {
        if options.opt_present("ansi") {
            self.use_ansi_color = true;
        }

        if let Some(cmd) = options.opt_str("c") {
            self.cmd = cmd.clone();
        }

        if let Some(query) = options.opt_str("q") {
            self.default_arg = query.to_string();
        }

        if let Some(delimiter) = options.opt_str("d") {
            self.delimiter = Regex::new(&(".*?".to_string() + &delimiter))
                .unwrap_or(Regex::new(r".*?\t").unwrap());
        }

        if let Some(transform_fields) = options.opt_str("with-nth") {
            self.transform_fields = transform_fields.split(',')
                .map(|string| {
                    parse_range(string)
                })
                .filter(|range| range.is_some())
                .map(|range| range.unwrap())
                .collect();
        }

        if let Some(matching_fields) = options.opt_str("nth") {
            self.matching_fields = matching_fields.split(',')
                .map(|string| {
                    parse_range(string)
                })
                .filter(|range| range.is_some())
                .map(|range| range.unwrap())
                .collect();
        }

        if let Some(replace_str) = options.opt_str("I") {
            self.replace_str = replace_str.clone();
        }
    }

    pub fn run(&mut self) {
        // check if the input is TTY
        let istty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
        let mut arg = self.default_arg.clone();

        loop {
            let (command, read): (Option<Child>, Box<BufRead>) = if istty {
                self.get_command_output(&arg).expect("command not found")
            } else {
                (None, Box::new(BufReader::new(stdin())))
            };

            self.read_items(read);
            command.map(|mut x| {
                let _ = x.kill();
                let _ = x.wait();
            });

            for (e, val) in self.eb_req.wait() {
                match e {
                    Event::EvReaderResetQuery => {
                        let mut items = self.items.write().unwrap();
                        items.clear();
                        arg = *val.downcast::<String>().unwrap();
                        self.eb.set(Event::EvReaderSync, Box::new(true));
                        let _ = self.eb_req.wait_for(Event::EvModelAck);
                    }
                    _ => {}
                }
            }
        }
    }

    fn read_items(&self, mut source: Box<BufRead>) {
        loop {
            let mut input = String::new();
            match source.read_line(&mut input) {
                Ok(n) => {
                    if n <= 0 { break; }

                    if input.ends_with("\n") {
                        input.pop();
                        if input.ends_with("\r") {
                            input.pop();
                        }
                    }
                    let mut items = self.items.write().unwrap();
                    items.push(Item::new(input,
                                         self.use_ansi_color,
                                         &self.transform_fields,
                                         &self.matching_fields,
                                         &self.delimiter));
                }
                Err(_err) => {} // String not UTF8 or other error, skip.
            }
            self.eb.set_throttle(Event::EvReaderNewItem, Box::new(true), READER_EVENT_DURATION);
            if self.eb_req.peek(Event::EvReaderResetQuery) {
                break;
            }
        }
        self.eb.set_throttle(Event::EvReaderNewItem, Box::new(false), READER_EVENT_DURATION);
    }
}

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum FieldRange {
    Single(i64),
    LeftInf(i64),
    RightInf(i64),
    Both(i64, i64),
}

// range: "start..end", end is excluded.
// "0", "0..", "..10", "1..10", etc.
fn parse_range(range: &str) -> Option<FieldRange> {
    use self::FieldRange::*;

    if range == ".." {
        return Some(RightInf(0));
    }

    let range_string: Vec<&str> = range.split("..").collect();
    if range_string.len() <= 0 || range_string.len() > 2 {
        return None;
    }

    let start = range_string.get(0).and_then(|x| x.parse::<i64>().ok());
    let end = range_string.get(1).and_then(|x| x.parse::<i64>().ok());

    if range_string.len() == 1 {
        return if start.is_none() {None} else {Some(Single(start.unwrap()))};
    }

    if start.is_none() && end.is_none() {
        None
    } else if end.is_none() {
        // 1..
        Some(RightInf(start.unwrap()))
    } else if start.is_none() {
        // ..1
        Some(LeftInf(end.unwrap()))
    } else {
        Some(Both(start.unwrap(), end.unwrap()))
    }
}

#[cfg(test)]
mod test {
    use super::FieldRange::*;
    #[test]
    fn test_parse_range() {
        assert_eq!(super::parse_range("1"), Some(Single(1)));
        assert_eq!(super::parse_range("-1"), Some(Single(-1)));

        assert_eq!(super::parse_range("1.."), Some(RightInf(1)));
        assert_eq!(super::parse_range("-1.."), Some(RightInf(-1)));

        assert_eq!(super::parse_range("..1"), Some(LeftInf(1)));
        assert_eq!(super::parse_range("..-1"), Some(LeftInf(-1)));

        assert_eq!(super::parse_range("1..3"), Some(Both(1, 3)));
        assert_eq!(super::parse_range("-1..-3"), Some(Both(-1, -3)));

        assert_eq!(super::parse_range(".."), Some(RightInf(0)));
        assert_eq!(super::parse_range("a.."), None);
        assert_eq!(super::parse_range("..b"), None);
        assert_eq!(super::parse_range("a..b"), None);
    }
}
<|endoftext|>


<commit_before>//============================================================================
//
//  A Tagged Image File Format (TIFF) Library for Rust
//
//  Based on the TIFF 6.0 specification:
//
//      https://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
//
//  Copyright (c) 2014 by Gavin Baker <gavinb@antonym.org>
//  Published under the MIT License
//
//============================================================================

use std::io::{Result, Error, ErrorKind, Read, Seek, SeekFrom};
use std::path::Path;
use std::fs::File;

use byteorder::{ReadBytesExt, WriteBytesExt, ByteOrder, BigEndian, LittleEndian};

use {TIFFByteOrder, HeaderMagic, TIFFHeader, IFD, IFDEntry, decode_tag, decode_tag_type, SeekableReader};

pub struct TIFFReader;

impl TIFFReader {

    pub fn load(&self, filename: &str) -> Result<Box<TIFFHeader>> {

        let filepath = Path::new(filename);
        let mut reader = File::open(&filepath).unwrap();

        self.read(&mut reader)
    }

    pub fn read(&self, reader: &mut SeekableReader) -> Result<Box<TIFFHeader>> {

        let byte_order = self.read_byte_order(reader).unwrap();

        let magic = match byte_order {
            TIFFByteOrder::LittleEndian => self.read_magic::<LittleEndian>(reader),
            TIFFByteOrder::BigEndian => self.read_magic::<BigEndian>(reader),
        };

        Err(Error::new(ErrorKind::Other, "Not implemented"))
    }

    pub fn read_byte_order(&self, reader: &mut SeekableReader) -> Result<TIFFByteOrder> {

        // Bytes 0-1: "II" or "MM"
        // Read and validate ByteOrder

        let byte_order_field = try!(reader.read_u16::<LittleEndian>());
        let byte_order: TIFFByteOrder;

        if byte_order_field == TIFFByteOrder::LittleEndian as u16 {
            byte_order = TIFFByteOrder::LittleEndian;
        } else if byte_order_field == TIFFByteOrder::BigEndian as u16 {
            byte_order = TIFFByteOrder::BigEndian;
        } else {
            return Err(Error::new(ErrorKind::Other,
                                  format!("Invalid byte order in header: {:04x}", byte_order_field)));
        }
        println!("byte_order {:?}", byte_order);

        Ok(byte_order)
    }

    pub fn read_magic<Endian: ByteOrder>(&self, reader: &mut SeekableReader) -> Result<HeaderMagic> {

        // Read and validate HeaderMagic
        // Bytes 2-3: 42

        let magic_field = try!(reader.read_u16::<Endian>());

        let magic: HeaderMagic;

        if magic_field == HeaderMagic::LittleEndian as u16 {
            Ok(HeaderMagic::LittleEndian)
        }
        else if magic_field == HeaderMagic::BigEndian as u16 {
            Ok(HeaderMagic::BigEndian)
        } else {
            Err(Error::new(ErrorKind::Other, "Invalid magic number in header"))
        }
    }

    pub fn read_<Endian: ByteOrder>(&self, reader: &mut SeekableReader) -> Result<Box<TIFFHeader>> {

        // @todo Ensure file is >= min size

        // Read offset to first IFD

        let ifd_offset_field = try!(reader.read_u32::<Endian>());

        // Assemble validated header

        let header = Box::new(TIFFHeader {
            byte_order: TIFFByteOrder::LittleEndian,
            magic: HeaderMagic::LittleEndian,
            ifd_offset: ifd_offset_field,
        });

        try!(reader.seek(SeekFrom::Start(ifd_offset_field as u64)));
        println!("IFD offset: {:?}", ifd_offset_field);

        try!(self.read_IFD(reader));

        Ok(header)
    }

    #[allow(non_snake_case)]
    fn read_IFD(&self, reader: &mut SeekableReader) -> Result<Box<IFD>> {

        let entry_count = try!(reader.read_u16::<LittleEndian>());

        println!("IFD entry count: {}", entry_count);

        let mut ifd = Box::new(IFD { count: entry_count, entries: Vec::with_capacity(entry_count as usize) });

        println!("IFD entry count: {}", entry_count);

        for entry_number in 0..entry_count as usize {
            ifd.entries.push(*self.read_tag(entry_number, reader).unwrap());
        }

        Ok(ifd)
    }

    fn read_tag(&self, entry_number: usize, reader: &mut SeekableReader) -> Result<Box<IFDEntry>> {

        let tag_value = try!(reader.read_u16::<LittleEndian>());
        let typ_value = try!(reader.read_u16::<LittleEndian>());
        let count_value = try!(reader.read_u32::<LittleEndian>());
        let value_offset_value = try!(reader.read_u32::<LittleEndian>());

        let tag_msg = format!("Invalid tag {:x}", tag_value);
        let tag = decode_tag(tag_value).expect(&tag_msg);

        let typ_msg = format!("Invalid tag type {:x}", typ_value);
        let typ = decode_tag_type(typ_value).expect(&typ_msg);

        let e0 = Box::new(IFDEntry {
            tag: tag,
            typ: typ,
            count: count_value,
            value_offset: value_offset_value,
        });

        println!("IFD[{:?}] {:?} {:?} {:x} {}", entry_number, e0.tag, e0.typ, e0.count, e0.value_offset);
        Ok(e0)
    }
}
<commit_msg>Minor tweaks in reader to parameterise over endianness<commit_after>//============================================================================
//
//  A Tagged Image File Format (TIFF) Library for Rust
//
//  Based on the TIFF 6.0 specification:
//
//      https://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
//
//  Copyright (c) 2014 by Gavin Baker <gavinb@antonym.org>
//  Published under the MIT License
//
//============================================================================

use std::io::{Result, Error, ErrorKind, Read, Seek, SeekFrom};
use std::path::Path;
use std::fs::File;

use byteorder::{ReadBytesExt, WriteBytesExt, ByteOrder, BigEndian, LittleEndian};

use {TIFFByteOrder, HeaderMagic, TIFFHeader, IFD, IFDEntry, decode_tag, decode_tag_type, SeekableReader};

pub struct TIFFReader;

impl TIFFReader {

    pub fn load(&self, filename: &str) -> Result<Box<TIFFHeader>> {

        let filepath = Path::new(filename);
        let mut reader = File::open(&filepath).unwrap();

        self.read(&mut reader)
    }

    pub fn read(&self, reader: &mut SeekableReader) -> Result<Box<TIFFHeader>> {

        let byte_order = self.read_byte_order(reader);

        let magic = match byte_order {
            Ok(TIFFByteOrder::LittleEndian) => self.read_magic::<LittleEndian>(reader),
            Ok(TIFFByteOrder::BigEndian) => self.read_magic::<BigEndian>(reader),
            Err(e) => Err(e)
        };

        self.read_::<LittleEndian>(reader)
    }

    pub fn read_byte_order(&self, reader: &mut SeekableReader) -> Result<TIFFByteOrder> {

        // Bytes 0-1: "II" or "MM"
        // Read and validate ByteOrder

        let byte_order_field = try!(reader.read_u16::<LittleEndian>());
        let byte_order: TIFFByteOrder;

        if byte_order_field == TIFFByteOrder::LittleEndian as u16 {
            byte_order = TIFFByteOrder::LittleEndian;
        } else if byte_order_field == TIFFByteOrder::BigEndian as u16 {
            byte_order = TIFFByteOrder::BigEndian;
        } else {
            return Err(Error::new(ErrorKind::Other,
                                  format!("Invalid byte order in header: {:04x}", byte_order_field)));
        }
        println!("byte_order {:?}", byte_order);

        Ok(byte_order)
    }

    pub fn read_magic<Endian: ByteOrder>(&self, reader: &mut SeekableReader) -> Result<HeaderMagic> {

        // Read and validate HeaderMagic
        // Bytes 2-3: 42

        let magic_field = try!(reader.read_u16::<Endian>());

        let magic: HeaderMagic;

        if magic_field == HeaderMagic::LittleEndian as u16 {
            Ok(HeaderMagic::LittleEndian)
        }
        else if magic_field == HeaderMagic::BigEndian as u16 {
            Ok(HeaderMagic::BigEndian)
        } else {
            Err(Error::new(ErrorKind::Other, "Invalid magic number in header"))
        }
    }

    pub fn read_<Endian: ByteOrder>(&self, reader: &mut SeekableReader) -> Result<Box<TIFFHeader>> {

        // @todo Ensure file is >= min size

        // Read offset to first IFD

        let ifd_offset_field = try!(reader.read_u32::<Endian>());

        // Assemble validated header

        let header = Box::new(TIFFHeader {
            byte_order: TIFFByteOrder::LittleEndian,
            magic: HeaderMagic::LittleEndian,
            ifd_offset: ifd_offset_field,
        });

        try!(reader.seek(SeekFrom::Start(ifd_offset_field as u64)));
        println!("IFD offset: {:?}", ifd_offset_field);

        try!(self.read_IFD::<Endian>(reader));

        Ok(header)
    }

    #[allow(non_snake_case)]
    fn read_IFD<Endian: ByteOrder>(&self, reader: &mut SeekableReader) -> Result<Box<IFD>> {

        let entry_count = try!(reader.read_u16::<Endian>());

        println!("IFD entry count: {}", entry_count);

        let mut ifd = Box::new(IFD { count: entry_count, entries: Vec::with_capacity(entry_count as usize) });

        println!("IFD entry count: {}", entry_count);

        for entry_number in 0..entry_count as usize {
            ifd.entries.push(*self.read_tag::<Endian>(entry_number, reader).unwrap());
        }

        Ok(ifd)
    }

    fn read_tag<Endian: ByteOrder>(&self, entry_number: usize, reader: &mut SeekableReader) -> Result<Box<IFDEntry>> {

        let tag_value = try!(reader.read_u16::<Endian>());
        let typ_value = try!(reader.read_u16::<Endian>());
        let count_value = try!(reader.read_u32::<Endian>());
        let value_offset_value = try!(reader.read_u32::<Endian>());

        let tag_msg = format!("Invalid tag {:x}", tag_value);
        let tag = decode_tag(tag_value).expect(&tag_msg);

        let typ_msg = format!("Invalid tag type {:x}", typ_value);
        let typ = decode_tag_type(typ_value).expect(&typ_msg);

        let e0 = Box::new(IFDEntry {
            tag: tag,
            typ: typ,
            count: count_value,
            value_offset: value_offset_value,
        });

        println!("IFD[{:?}] {:?} {:?} {:x} {}", entry_number, e0.tag, e0.typ, e0.count, e0.value_offset);
        Ok(e0)
    }
}
<|endoftext|>


<commit_before>// 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/.

//! Structs and methods for searching for tweets.
//!
//! Since there are several optional parameters for searches, egg-mode handles it with a builder
//! pattern. To begin, call `search` with your requested search term. Additional parameters can be
//! added onto the `SearchBuilder` struct that is returned. When you're ready to load the first
//! page of results, hand your tokens to `call`.
//!
//! ```rust,no_run
//! # extern crate egg_mode; extern crate tokio; extern crate futures;
//! # use egg_mode::Token;
//! use tokio::runtime::current_thread::block_on_all;
//! # fn main() {
//! # let token: Token = unimplemented!();
//! use egg_mode::search::{self, ResultType};
//!
//! let search = block_on_all(search::search("rustlang")
//!                                  .result_type(ResultType::Recent)
//!                                  .call(&token))
//!                  .unwrap();
//!
//! for tweet in &search.statuses {
//!     println!("(@{}) {}", tweet.user.as_ref().unwrap().screen_name, tweet.text);
//! }
//! # }
//! ```
//!
//! Once you have your `SearchResult`, you can navigate the search results by calling `older` and
//! `newer` to get the next and previous pages, respsectively. In addition, you can see your
//! original query in the search result struct as well, so you can categorize multiple searches by
//! their query. While this is given as a regular field, note that modifying `query` will not
//! change what is searched for when you call `older` or `newer`; the `SearchResult` keeps its
//! search arguments in a separate private field.
//!
//! The search parameter given in the initial call to `search` has several options itself. A full
//! reference is available in [Twitter's Search API documentation][search-doc]. This listing by
//! itself does not include the search by Place ID, as mentioned on [a separate Tweets by Place
//! page][search-place]. A future version of egg-mode might break these options into further
//! methods on `SearchBuilder`.
//!
//! The lifetime parameter on `SearchBuilder`, `SearchFuture`, and `SearchResult` correspond to the
//! text given as the search query and (if applicable) to the `lang` method of `SearchBuilder`. As
//! these types use `Cow<'a, str>` internally, you can hand these types owned Strings to give them
//! a `'static` lifetime, if necessary.
//!
//! [search-doc]: https://dev.twitter.com/rest/public/search
//! [search-place]: https://dev.twitter.com/rest/public/search-by-place

use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt;

use futures::{Future, Poll, Async};
use serde::{Deserialize, Deserializer};

use auth;
use error;
use links;
use tweet::Tweet;
use common::*;

///Begin setting up a tweet search with the given query.
pub fn search<'a, S: Into<Cow<'a, str>>>(query: S) -> SearchBuilder<'a> {
    SearchBuilder {
        query: query.into(),
        lang: None,
        result_type: None,
        count: None,
        until: None,
        geocode: None,
        since_id: None,
        max_id: None,
    }
}

///Represents what kind of tweets should be included in search results.
#[derive(Debug, Copy, Clone)]
pub enum ResultType {
    ///Return only the most recent tweets in the response.
    Recent,
    ///Return only the most popular tweets in the response.
    Popular,
    ///Include both popular and real-time results in the response.
    Mixed,
}

///Display impl that turns the variants into strings that can be used as search parameters.
impl fmt::Display for ResultType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ResultType::Recent => write!(f, "recent"),
            ResultType::Popular => write!(f, "popular"),
            ResultType::Mixed => write!(f, "mixed"),
        }
    }
}

///Represents a radius around a given location to return search results for.
pub enum Distance {
    ///A radius given in miles.
    Miles(f32),
    ///A radius given in kilometers.
    Kilometers(f32),
}

///Represents a tweet search query before being sent.
#[must_use = "SearchBuilder is lazy and won't do anything unless `call`ed"]
pub struct SearchBuilder<'a> {
    ///The text to search for.
    query: Cow<'a, str>,
    lang: Option<Cow<'a, str>>,
    result_type: Option<ResultType>,
    count: Option<u32>,
    until: Option<(u32, u32, u32)>,
    geocode: Option<(f32, f32, Distance)>,
    since_id: Option<u64>,
    max_id: Option<u64>,
}

impl<'a> SearchBuilder<'a> {
    ///Restrict search results to those that have been machine-parsed as the given two-letter
    ///language code.
    pub fn lang<S: Into<Cow<'a, str>>>(self, lang: S) -> Self {
        SearchBuilder {
            lang: Some(lang.into()),
            ..self
        }
    }

    ///Specify the type of search results to include. The default is `Recent`.
    pub fn result_type(self, result_type: ResultType) -> Self {
        SearchBuilder {
            result_type: Some(result_type),
            ..self
        }
    }

    ///Set the number of tweets to return per-page, up to a maximum of 100. The default is 15.
    pub fn count(self, count: u32) -> Self {
        SearchBuilder {
            count: Some(count),
            ..self
        }
    }

    ///Returns tweets created before the given date. Keep in mind that search is limited to the
    ///last 7 days of results, so giving a date here that's older than a week will return no
    ///results.
    pub fn until(self, year: u32, month: u32, day: u32) -> Self {
        SearchBuilder {
            until: Some((year, month, day)),
            ..self
        }
    }

    ///Restricts results to users located within the given radius of the given coordinate. This is
    ///preferably populated from location-tagged tweets, but can be filled in from the user's
    ///profile as a fallback.
    pub fn geocode(self, latitude: f32, longitude: f32, radius: Distance) -> Self {
        SearchBuilder {
            geocode: Some((latitude, longitude, radius)),
            ..self
        }
    }

    ///Restricts results to those with higher IDs than (i.e. that were posted after) the given
    ///tweet ID.
    pub fn since_tweet(self, since_id: u64) -> Self {
        SearchBuilder {
            since_id: Some(since_id),
            ..self
        }
    }

    ///Restricts results to those with IDs no higher than (i.e. were posted earlier than) the given
    ///tweet ID. Will include the given tweet in search results.
    pub fn max_tweet(self, max_id: u64) -> Self {
        SearchBuilder {
            max_id: Some(max_id),
            ..self
        }
    }

    ///Finalize the search terms and return the first page of responses.
    pub fn call(self, token: &auth::Token) -> SearchFuture<'a> {
        let mut params = HashMap::new();

        add_param(&mut params, "q", self.query);

        if let Some(lang) = self.lang {
            add_param(&mut params, "lang", lang);
        }

        if let Some(result_type) = self.result_type {
            add_param(&mut params, "result_type", result_type.to_string());
        }

        if let Some(count) = self.count {
            add_param(&mut params, "count", count.to_string());
        }

        if let Some((year, month, day)) = self.until {
            add_param(&mut params, "until", format!("{}-{}-{}", year, month, day));
        }

        if let Some((lat, lon, radius)) = self.geocode {
            match radius {
                Distance::Miles(r) => add_param(&mut params, "geocode", format!("{:.6},{:.6},{}mi", lat, lon, r)),
                Distance::Kilometers(r) => add_param(&mut params, "geocode", format!("{:.6},{:.6},{}km", lat, lon, r)),
            };
        }

        if let Some(since_id) = self.since_id {
            add_param(&mut params, "since_id", since_id.to_string());
        }

        if let Some(max_id) = self.max_id {
            add_param(&mut params, "max_id", max_id.to_string());
        }

        let req = auth::get(links::statuses::SEARCH, token, Some(&params));

        SearchFuture {
            loader: make_parsed_future(req),
            params: Some(params),
        }
    }
}

/// `Future` that represents a search query in progress.
///
/// When this future resolves, it will either contain a `SearchResult` or the error that was
/// encountered while loading or parsing the response.
#[must_use = "futures do nothing unless polled"]
pub struct SearchFuture<'a> {
    loader: FutureResponse<SearchResult<'a>>,
    params: Option<ParamList<'a>>,
}

impl<'a> Future for SearchFuture<'a> {
    type Item = Response<SearchResult<'a>>;
    type Error = error::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut resp = match self.loader.poll() {
            Ok(Async::Ready(resp)) => resp,
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            Err(e) => return Err(e),
        };

        resp.params = self.params.take();
        Ok(Async::Ready(resp))
    }
}

#[derive(Debug, Deserialize)]
struct RawSearch<'a> {
    #[serde(borrow)]
    search_metadata: RawSearchMetaData<'a>,
    statuses: Vec<Tweet>
}

#[derive(Debug, Deserialize)]
struct RawSearchMetaData<'a> {
    completed_in: f64,
    count: u64,
    max_id: u64,
    next_results: &'a str,
    query: &'a str,
    refresh_url: &'a str,
    since_id: u64,
}

impl<'de> Deserialize<'de> for SearchResult<'static> {
    fn deserialize<D>(deser: D) -> Result<SearchResult<'static>, D::Error> where D: Deserializer<'de> {
        let raw = RawSearch::deserialize(deser)?;
        Ok(SearchResult {
            statuses: raw.statuses,
            query: raw.search_metadata.query.into(),
            max_id: raw.search_metadata.max_id,
            since_id: raw.search_metadata.since_id,
            params: None
        })
    }
}

///Represents a page of search results, along with metadata to request the next or previous page.
#[derive(Debug)]
pub struct SearchResult<'a> {
    ///The list of statuses in this page of results.
    pub statuses: Vec<Tweet>,
    ///The query used to generate this page of results. Note that changing this will not affect the
    ///`next_page` method.
    pub query: String,
    ///Last tweet id in this page of results. This id can be used in `SearchBuilder::since_tweet`
    pub max_id: u64,
    ///First tweet id in this page of results. This id can be used in `SearchBuilder::since_tweet`
    pub since_id: u64,
    params: Option<ParamList<'a>>,
}

impl<'a> SearchResult<'a> {
    ///Load the next page of search results for the same query.
    pub fn older(&self, token: &auth::Token) -> SearchFuture<'a> {
        let mut params = self.params.as_ref().cloned().unwrap_or_default();
        params.remove("since_id");

        if let Some(min_id) = self.statuses.iter().map(|t| t.id).min() {
            add_param(&mut params, "max_id", (min_id - 1).to_string());
        } else {
            params.remove("max_id");
        }

        let req = auth::get(links::statuses::SEARCH, token, Some(&params));

        SearchFuture {
            loader: make_parsed_future(req),
            params: Some(params),
        }
    }

    ///Load the previous page of search results for the same query.
    pub fn newer(&self, token: &auth::Token) -> SearchFuture<'a> {
        let mut params = self.params.as_ref().cloned().unwrap_or_default();
        params.remove("max_id");

        if let Some(max_id) = self.statuses.iter().map(|t| t.id).max() {
            add_param(&mut params, "since_id", max_id.to_string());
        } else {
            params.remove("since_id");
        }

        let req = auth::get(links::statuses::SEARCH, token, Some(&params));

        SearchFuture {
            loader: make_parsed_future(req),
            params: Some(params),
        }
    }
}
<commit_msg>fix RawSearchMetaData definition<commit_after>// 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/.

//! Structs and methods for searching for tweets.
//!
//! Since there are several optional parameters for searches, egg-mode handles it with a builder
//! pattern. To begin, call `search` with your requested search term. Additional parameters can be
//! added onto the `SearchBuilder` struct that is returned. When you're ready to load the first
//! page of results, hand your tokens to `call`.
//!
//! ```rust,no_run
//! # extern crate egg_mode; extern crate tokio; extern crate futures;
//! # use egg_mode::Token;
//! use tokio::runtime::current_thread::block_on_all;
//! # fn main() {
//! # let token: Token = unimplemented!();
//! use egg_mode::search::{self, ResultType};
//!
//! let search = block_on_all(search::search("rustlang")
//!                                  .result_type(ResultType::Recent)
//!                                  .call(&token))
//!                  .unwrap();
//!
//! for tweet in &search.statuses {
//!     println!("(@{}) {}", tweet.user.as_ref().unwrap().screen_name, tweet.text);
//! }
//! # }
//! ```
//!
//! Once you have your `SearchResult`, you can navigate the search results by calling `older` and
//! `newer` to get the next and previous pages, respsectively. In addition, you can see your
//! original query in the search result struct as well, so you can categorize multiple searches by
//! their query. While this is given as a regular field, note that modifying `query` will not
//! change what is searched for when you call `older` or `newer`; the `SearchResult` keeps its
//! search arguments in a separate private field.
//!
//! The search parameter given in the initial call to `search` has several options itself. A full
//! reference is available in [Twitter's Search API documentation][search-doc]. This listing by
//! itself does not include the search by Place ID, as mentioned on [a separate Tweets by Place
//! page][search-place]. A future version of egg-mode might break these options into further
//! methods on `SearchBuilder`.
//!
//! The lifetime parameter on `SearchBuilder`, `SearchFuture`, and `SearchResult` correspond to the
//! text given as the search query and (if applicable) to the `lang` method of `SearchBuilder`. As
//! these types use `Cow<'a, str>` internally, you can hand these types owned Strings to give them
//! a `'static` lifetime, if necessary.
//!
//! [search-doc]: https://dev.twitter.com/rest/public/search
//! [search-place]: https://dev.twitter.com/rest/public/search-by-place

use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt;

use futures::{Future, Poll, Async};
use serde::{Deserialize, Deserializer};

use auth;
use error;
use links;
use tweet::Tweet;
use common::*;

///Begin setting up a tweet search with the given query.
pub fn search<'a, S: Into<Cow<'a, str>>>(query: S) -> SearchBuilder<'a> {
    SearchBuilder {
        query: query.into(),
        lang: None,
        result_type: None,
        count: None,
        until: None,
        geocode: None,
        since_id: None,
        max_id: None,
    }
}

///Represents what kind of tweets should be included in search results.
#[derive(Debug, Copy, Clone)]
pub enum ResultType {
    ///Return only the most recent tweets in the response.
    Recent,
    ///Return only the most popular tweets in the response.
    Popular,
    ///Include both popular and real-time results in the response.
    Mixed,
}

///Display impl that turns the variants into strings that can be used as search parameters.
impl fmt::Display for ResultType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ResultType::Recent => write!(f, "recent"),
            ResultType::Popular => write!(f, "popular"),
            ResultType::Mixed => write!(f, "mixed"),
        }
    }
}

///Represents a radius around a given location to return search results for.
pub enum Distance {
    ///A radius given in miles.
    Miles(f32),
    ///A radius given in kilometers.
    Kilometers(f32),
}

///Represents a tweet search query before being sent.
#[must_use = "SearchBuilder is lazy and won't do anything unless `call`ed"]
pub struct SearchBuilder<'a> {
    ///The text to search for.
    query: Cow<'a, str>,
    lang: Option<Cow<'a, str>>,
    result_type: Option<ResultType>,
    count: Option<u32>,
    until: Option<(u32, u32, u32)>,
    geocode: Option<(f32, f32, Distance)>,
    since_id: Option<u64>,
    max_id: Option<u64>,
}

impl<'a> SearchBuilder<'a> {
    ///Restrict search results to those that have been machine-parsed as the given two-letter
    ///language code.
    pub fn lang<S: Into<Cow<'a, str>>>(self, lang: S) -> Self {
        SearchBuilder {
            lang: Some(lang.into()),
            ..self
        }
    }

    ///Specify the type of search results to include. The default is `Recent`.
    pub fn result_type(self, result_type: ResultType) -> Self {
        SearchBuilder {
            result_type: Some(result_type),
            ..self
        }
    }

    ///Set the number of tweets to return per-page, up to a maximum of 100. The default is 15.
    pub fn count(self, count: u32) -> Self {
        SearchBuilder {
            count: Some(count),
            ..self
        }
    }

    ///Returns tweets created before the given date. Keep in mind that search is limited to the
    ///last 7 days of results, so giving a date here that's older than a week will return no
    ///results.
    pub fn until(self, year: u32, month: u32, day: u32) -> Self {
        SearchBuilder {
            until: Some((year, month, day)),
            ..self
        }
    }

    ///Restricts results to users located within the given radius of the given coordinate. This is
    ///preferably populated from location-tagged tweets, but can be filled in from the user's
    ///profile as a fallback.
    pub fn geocode(self, latitude: f32, longitude: f32, radius: Distance) -> Self {
        SearchBuilder {
            geocode: Some((latitude, longitude, radius)),
            ..self
        }
    }

    ///Restricts results to those with higher IDs than (i.e. that were posted after) the given
    ///tweet ID.
    pub fn since_tweet(self, since_id: u64) -> Self {
        SearchBuilder {
            since_id: Some(since_id),
            ..self
        }
    }

    ///Restricts results to those with IDs no higher than (i.e. were posted earlier than) the given
    ///tweet ID. Will include the given tweet in search results.
    pub fn max_tweet(self, max_id: u64) -> Self {
        SearchBuilder {
            max_id: Some(max_id),
            ..self
        }
    }

    ///Finalize the search terms and return the first page of responses.
    pub fn call(self, token: &auth::Token) -> SearchFuture<'a> {
        let mut params = HashMap::new();

        add_param(&mut params, "q", self.query);

        if let Some(lang) = self.lang {
            add_param(&mut params, "lang", lang);
        }

        if let Some(result_type) = self.result_type {
            add_param(&mut params, "result_type", result_type.to_string());
        }

        if let Some(count) = self.count {
            add_param(&mut params, "count", count.to_string());
        }

        if let Some((year, month, day)) = self.until {
            add_param(&mut params, "until", format!("{}-{}-{}", year, month, day));
        }

        if let Some((lat, lon, radius)) = self.geocode {
            match radius {
                Distance::Miles(r) => add_param(&mut params, "geocode", format!("{:.6},{:.6},{}mi", lat, lon, r)),
                Distance::Kilometers(r) => add_param(&mut params, "geocode", format!("{:.6},{:.6},{}km", lat, lon, r)),
            };
        }

        if let Some(since_id) = self.since_id {
            add_param(&mut params, "since_id", since_id.to_string());
        }

        if let Some(max_id) = self.max_id {
            add_param(&mut params, "max_id", max_id.to_string());
        }

        let req = auth::get(links::statuses::SEARCH, token, Some(&params));

        SearchFuture {
            loader: make_parsed_future(req),
            params: Some(params),
        }
    }
}

/// `Future` that represents a search query in progress.
///
/// When this future resolves, it will either contain a `SearchResult` or the error that was
/// encountered while loading or parsing the response.
#[must_use = "futures do nothing unless polled"]
pub struct SearchFuture<'a> {
    loader: FutureResponse<SearchResult<'a>>,
    params: Option<ParamList<'a>>,
}

impl<'a> Future for SearchFuture<'a> {
    type Item = Response<SearchResult<'a>>;
    type Error = error::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut resp = match self.loader.poll() {
            Ok(Async::Ready(resp)) => resp,
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            Err(e) => return Err(e),
        };

        resp.params = self.params.take();
        Ok(Async::Ready(resp))
    }
}

#[derive(Debug, Deserialize)]
struct RawSearch<'a> {
    #[serde(borrow)]
    search_metadata: RawSearchMetaData<'a>,
    statuses: Vec<Tweet>
}

#[derive(Debug, Deserialize)]
struct RawSearchMetaData<'a> {
    completed_in: f64,
    max_id: u64,
    /// absent if no more results to retrieve
    next_results: Option<&'a str>,
    query: &'a str,
    /// absent if no results
    refresh_url: Option<&'a str>,
    count: u64,
    since_id: u64,
}

impl<'de> Deserialize<'de> for SearchResult<'static> {
    fn deserialize<D>(deser: D) -> Result<SearchResult<'static>, D::Error> where D: Deserializer<'de> {
        let raw = RawSearch::deserialize(deser)?;
        Ok(SearchResult {
            statuses: raw.statuses,
            query: raw.search_metadata.query.into(),
            max_id: raw.search_metadata.max_id,
            since_id: raw.search_metadata.since_id,
            params: None
        })
    }
}

///Represents a page of search results, along with metadata to request the next or previous page.
#[derive(Debug)]
pub struct SearchResult<'a> {
    ///The list of statuses in this page of results.
    pub statuses: Vec<Tweet>,
    ///The query used to generate this page of results. Note that changing this will not affect the
    ///`next_page` method.
    pub query: String,
    ///Last tweet id in this page of results. This id can be used in `SearchBuilder::since_tweet`
    pub max_id: u64,
    ///First tweet id in this page of results. This id can be used in `SearchBuilder::since_tweet`
    pub since_id: u64,
    params: Option<ParamList<'a>>,
}

impl<'a> SearchResult<'a> {
    ///Load the next page of search results for the same query.
    pub fn older(&self, token: &auth::Token) -> SearchFuture<'a> {
        let mut params = self.params.as_ref().cloned().unwrap_or_default();
        params.remove("since_id");

        if let Some(min_id) = self.statuses.iter().map(|t| t.id).min() {
            add_param(&mut params, "max_id", (min_id - 1).to_string());
        } else {
            params.remove("max_id");
        }

        let req = auth::get(links::statuses::SEARCH, token, Some(&params));

        SearchFuture {
            loader: make_parsed_future(req),
            params: Some(params),
        }
    }

    ///Load the previous page of search results for the same query.
    pub fn newer(&self, token: &auth::Token) -> SearchFuture<'a> {
        let mut params = self.params.as_ref().cloned().unwrap_or_default();
        params.remove("max_id");

        if let Some(max_id) = self.statuses.iter().map(|t| t.id).max() {
            add_param(&mut params, "since_id", max_id.to_string());
        } else {
            params.remove("since_id");
        }

        let req = auth::get(links::statuses::SEARCH, token, Some(&params));

        SearchFuture {
            loader: make_parsed_future(req),
            params: Some(params),
        }
    }
}
<|endoftext|>


<commit_before>// Detect AES in ECB mode
// In this file (8.txt) are a bunch of hex-encoded ciphertexts.

// One of them has been encrypted with ECB.

// Detect it.

// Remember that the problem with ECB is that it is stateless and
// deterministic; the same 16 byte plaintext block will always
// produce the same 16 byte ciphertext.

#![feature(old_io)]
#![feature(old_path)]

use std::collections::HashSet;

#[cfg(not(test))]
use std::env;
#[cfg(not(test))]
use std::old_io::BufferedReader;
#[cfg(not(test))]
use std::old_io::File;

fn main() {

	println!("Finding ECB...");

	if env::args().count() < 2 {
		panic!("Must pass a file to detect")
	}

	let arg = match env::args().nth(1) {
		Some(s) => s,
		None => panic!("No input argument given")
	};

	let path = Path::new(arg);
	let mut file = BufferedReader::new(File::open(&path));
	let lines: Vec<_> = file.lines()
		.map(|x| x.unwrap().trim().to_string())
		.collect();

	let mut block_set = HashSet::new();
	for line in lines {
		block_set.clear();
		let blocks = line.len() / 32;
		let mut found = false;
		for index in 0..blocks - 1 {
			let block = line[index * 32..(index + 1) * 32].to_string();
			if block_set.contains(&(block)) {
				println!("duplicate block: {:?}", block);
				found = true;
			} else {
				block_set.insert(block);
			}
		}
		if found {
			println!("in line: {:?}", line);
		}
	}
}<commit_msg>Update challenge 8 to latest Rust and refactor a bit<commit_after>// Detect AES in ECB mode
// In this file (8.txt) are a bunch of hex-encoded ciphertexts.

// One of them has been encrypted with ECB.

// Detect it.

// Remember that the problem with ECB is that it is stateless and
// deterministic; the same 16 byte plaintext block will always
// produce the same 16 byte ciphertext.

use std::collections::HashSet;

#[cfg(not(test))]
use std::env;
#[cfg(not(test))]
use std::io::BufReader;
#[cfg(not(test))]
use std::fs::File;
#[cfg(not(test))]
use std::path::Path;
#[cfg(not(test))]
use std::io::prelude::*;

#[cfg(not(test))]
fn main() {

	println!("Finding ECB...");

	if env::args().count() < 2 {
		panic!("Must pass a file to detect")
	}

	let arg = match env::args().nth(1) {
		Some(s) => s,
		None => panic!("No input argument given")
	};

	let path = Path::new(&arg);
	let file = BufReader::new(File::open(&path).unwrap());
	let lines: Vec<String> = file.lines()
		.map(|x| x.unwrap().trim().to_string())
		.collect();

	for line in lines {
		let duplicates = detect_ecb_in_line(&line);
		if duplicates.len() > 0 {
			for block in duplicates {
				println!("duplicate block: {:?}", block);
			}
			println!("in line: {:?}", line);
		}
	}
}

fn detect_ecb_in_line(line: &str) -> Vec<String> {
	let blocks = line.len() / 32;
	let mut block_set = HashSet::new();
	let mut duplicates = vec!();
	for index in 0..blocks - 1 {
		let block = line[index * 32..(index + 1) * 32].to_string();
		if block_set.contains(&block) {
			duplicates.push(block);
		} else {
			block_set.insert(block);
		}
	}
	duplicates
}

#[cfg(test)]
mod set1challenge8 {

	#[test]
	fn detect_ecb_in_line() {
		let line = "d880619740a8a19b7840a8a31c810a3d08649af70dc06f4fd5d2d69c744cd283e2dd052f6b641dbf9d11b0348542bb5708649af70dc06f4fd5d2d69c744cd2839475c9dfdbc1d46597949d9c7e82bf5a08649af70dc06f4fd5d2d69c744cd28397a93eab8d6aecd566489154789a6b0308649af70dc06f4fd5d2d69c744cd283d403180c98c8f6db1f2a3f9c4040deb0ab51b29933f2c123c58386b06fba186a";
		let duplicates = super::detect_ecb_in_line(&line);
		assert_eq!(duplicates.len(), 3);
		assert_eq!(duplicates[0], "08649af70dc06f4fd5d2d69c744cd283");
		assert_eq!(duplicates[1], "08649af70dc06f4fd5d2d69c744cd283");
		assert_eq!(duplicates[2], "08649af70dc06f4fd5d2d69c744cd283");
	}

	#[test]
	fn dont_detect_ecb_in_line() {
		let line = "b148a13d9a04ba6ef17afb0e25a6c91a454ec0eded513a567a9824dd3cd16770f4c1dae48854c2cf557139640c1cd121cac974f74f7001aa4927f6bdb4e0fa73676855df520e2af6ac785a420e43e829fa4e77e5de386d58404d42aa57bf56467f98322275df9f1a72fbb03fa8ea8b84356bbcd7159c59ef283a1aec240ef5d25df6e2aaaea36826beb03b0826d4abc8f22837812dafe6c9623517471fc653b9";
		let duplicates = super::detect_ecb_in_line(&line);
		assert_eq!(duplicates.len(), 0);

	}
}<|endoftext|>


<commit_before>#![feature(phase)]
#![feature(globs)]
#![feature(macro_rules)]

#[phase(plugin)]
extern crate deuterium_plugin;
extern crate deuterium_orm;
extern crate time;
extern crate deuterium;

extern crate postgres;
extern crate r2d2;
extern crate r2d2_postgres;
extern crate test;

use test::Bencher;

use deuterium::*;
use deuterium_orm::*;
use std::sync::Arc;
use time::Timespec;

use postgres::NoSsl;
use postgres::PostgresConnection;
use r2d2_postgres::PostgresPoolManager;

macro_rules! assert_sql(
    ($query:expr, $s:expr) => (
        assert_eq!($query.to_final_sql().as_slice(), $s)
    )
)

deuterium_model! jedi {
    #[primary_key="id"]
    pub struct Jedi {
        id: i32,
        name: String,
        force_level: i32,
        light_side: bool,
        created_at: Timespec,
        updated_at: Timespec
    }
}

impl Jedi {
    pub fn ordered() -> SelectQuery<(), LimitMany, Jedi> {
        Jedi::table().select_all().order_by(&Jedi::created_at_f())
    }
}

fn setup_tables(cn: &PostgresConnection) {
   cn.batch_execute(r#"
        DROP TABLE IF EXISTS jedi CASCADE;
        CREATE TABLE jedi (
            id          serial PRIMARY KEY,
            name        varchar(40) NOT NULL,
            force_level integer,
            light_side  boolean,
            created_at  timestamptz DEFAULT CURRENT_TIMESTAMP,
            updated_at  timestamptz DEFAULT CURRENT_TIMESTAMP
        );

        INSERT INTO jedi (name, force_level, light_side) VALUES
            ('Luke Skywalker', 100, true),
            ('Mace Windu', 90, true),
            ('Obi-Wan Kenoby', 99, true),
            ('Kit Fisto', 70, true),
            ('Count Dooku', 99, false),
            ('Darth Maul', 70, false),
            ('Anakin Skywalker', 100, false);

    "#).unwrap();
}

fn setup_pg() -> adapter::postgres::PostgresPool {
    let manager = PostgresPoolManager::new("postgres://panferov@localhost/jedi", NoSsl);
    let config = r2d2::Config {
        pool_size: 5,
        test_on_check_out: true,
        ..std::default::Default::default()
    };

    let handler = r2d2::NoopErrorHandler;
    r2d2::Pool::new(config, manager, handler).unwrap()
}

#[test]
fn test_it() {
    let pool = setup_pg();
    let cn = pool.get().unwrap();

    setup_tables(&*cn);

    Jedi::ordered().where_(Jedi::name_f().is("Luke Skywalker".to_string())).query_list(&*cn, &[]);
    Jedi::ordered().where_(Jedi::name_f().is("Anakin Skywalker".to_string())).first().query(&*cn, &[]).unwrap();
}

const BENCH_SIZE: uint = 1000;

#[bench]
fn bench_list_query(b: &mut Bencher) {
    let pool = setup_pg();
    let cn = pool.get().unwrap();

    setup_tables(&*cn);

    b.iter(|| {
        for i in range(0, BENCH_SIZE) {
            Jedi::ordered().where_(Jedi::name_f().is("Luke Skywalker".to_string())).query_list(&*cn, &[]);
        }
    })
}<commit_msg>test: fix warn<commit_after>#![feature(phase)]
#![feature(globs)]
#![feature(macro_rules)]

#[phase(plugin)]
extern crate deuterium_plugin;
extern crate deuterium_orm;
extern crate time;
extern crate deuterium;

extern crate postgres;
extern crate r2d2;
extern crate r2d2_postgres;
extern crate test;

use test::Bencher;

use deuterium::*;
use deuterium_orm::*;
use std::sync::Arc;
use time::Timespec;

use postgres::NoSsl;
use postgres::PostgresConnection;
use r2d2_postgres::PostgresPoolManager;

macro_rules! assert_sql(
    ($query:expr, $s:expr) => (
        assert_eq!($query.to_final_sql().as_slice(), $s)
    )
)

deuterium_model! jedi {
    #[primary_key="id"]
    pub struct Jedi {
        id: i32,
        name: String,
        force_level: i32,
        light_side: bool,
        created_at: Timespec,
        updated_at: Timespec
    }
}

impl Jedi {
    pub fn ordered() -> SelectQuery<(), LimitMany, Jedi> {
        Jedi::table().select_all().order_by(&Jedi::created_at_f())
    }
}

fn setup_tables(cn: &PostgresConnection) {
   cn.batch_execute(r#"
        DROP TABLE IF EXISTS jedi CASCADE;
        CREATE TABLE jedi (
            id          serial PRIMARY KEY,
            name        varchar(40) NOT NULL,
            force_level integer,
            light_side  boolean,
            created_at  timestamptz DEFAULT CURRENT_TIMESTAMP,
            updated_at  timestamptz DEFAULT CURRENT_TIMESTAMP
        );

        INSERT INTO jedi (name, force_level, light_side) VALUES
            ('Luke Skywalker', 100, true),
            ('Mace Windu', 90, true),
            ('Obi-Wan Kenoby', 99, true),
            ('Kit Fisto', 70, true),
            ('Count Dooku', 99, false),
            ('Darth Maul', 70, false),
            ('Anakin Skywalker', 100, false);

    "#).unwrap();
}

fn setup_pg() -> adapter::postgres::PostgresPool {
    let manager = PostgresPoolManager::new("postgres://panferov@localhost/jedi", NoSsl);
    let config = r2d2::Config {
        pool_size: 5,
        test_on_check_out: true,
        ..std::default::Default::default()
    };

    let handler = r2d2::NoopErrorHandler;
    r2d2::Pool::new(config, manager, handler).unwrap()
}

#[test]
fn test_it() {
    let pool = setup_pg();
    let cn = pool.get().unwrap();

    setup_tables(&*cn);

    Jedi::ordered().where_(Jedi::name_f().is("Luke Skywalker".to_string())).query_list(&*cn, &[]);
    Jedi::ordered().where_(Jedi::name_f().is("Anakin Skywalker".to_string())).first().query(&*cn, &[]).unwrap();
}

const BENCH_SIZE: uint = 1000;

#[bench]
fn bench_list_query(b: &mut Bencher) {
    let pool = setup_pg();
    let cn = pool.get().unwrap();

    setup_tables(&*cn);

    b.iter(|| {
        for _ in range(0, BENCH_SIZE) {
            Jedi::ordered().where_(Jedi::name_f().is("Luke Skywalker".to_string())).query_list(&*cn, &[]);
        }
    })
}<|endoftext|>


<commit_before>#![feature(integer_atomics)]

extern crate neb;

mod chunk;
mod types;
mod server;
mod cell;
mod transaction;

#[macro_use]
extern crate log;
extern crate env_logger;
extern crate rand;
extern crate uuid;
#[macro_use]
extern crate lazy_static;

use neb::ram::schema::Field;

pub fn default_fields () -> Field {
    Field {
        type_id: 0,
        name: String::from("*"),
        nullable: false,
        is_array: false,
        sub: Some(vec![
            Field {
                type_id: 6,
                name: String::from("id"),
                nullable:false,
                is_array:false,
                sub: None,
            },
            Field {
                type_id: 20,
                name: String::from("name"),
                nullable:false,
                is_array:false,
                sub: None,
            },
            Field {
                type_id: 10,
                name: String::from("score"),
                nullable:false,
                is_array:false,
                sub: None,
            }
        ])
    }
}<commit_msg>remove uuid in test<commit_after>#![feature(integer_atomics)]

extern crate neb;

mod chunk;
mod types;
mod server;
mod cell;
mod transaction;

#[macro_use]
extern crate log;
extern crate env_logger;
extern crate rand;
#[macro_use]
extern crate lazy_static;

use neb::ram::schema::Field;

pub fn default_fields () -> Field {
    Field {
        type_id: 0,
        name: String::from("*"),
        nullable: false,
        is_array: false,
        sub: Some(vec![
            Field {
                type_id: 6,
                name: String::from("id"),
                nullable:false,
                is_array:false,
                sub: None,
            },
            Field {
                type_id: 20,
                name: String::from("name"),
                nullable:false,
                is_array:false,
                sub: None,
            },
            Field {
                type_id: 10,
                name: String::from("score"),
                nullable:false,
                is_array:false,
                sub: None,
            }
        ])
    }
}<|endoftext|>


<commit_before>// Copyright 2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use libc::c_void;

use ffi::{self, gpointer, GCallback};
use translate::ToGlibPtr;

pub unsafe fn connect(receiver: gpointer, signal_name: &str, trampoline: GCallback,
                      closure: *mut Box<Fn()>) -> u64 {
    let handle = ffi::g_signal_connect_data(receiver, signal_name.borrow_to_glib().0,
        trampoline, closure as gpointer, destroy_closure, 0) as u64;
    assert!(handle > 0);
    handle
}

extern "C" fn destroy_closure(ptr: *mut c_void, _: *mut c_void) {
    unsafe {
        let ptr = ptr as *mut Box<Fn()>;
        // destroy
        //Box::from_raw(ptr);
        // from_raw API stability workaround
        let _: Box<Box<Fn()>> = ::std::mem::transmute(ptr);
    }
}
<commit_msg>Signals: remind the reader that the closure should be Fn + 'static<commit_after>// Copyright 2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use libc::c_void;

use ffi::{self, gpointer, GCallback};
use translate::ToGlibPtr;

pub unsafe fn connect(receiver: gpointer, signal_name: &str, trampoline: GCallback,
                      closure: *mut Box<Fn() + 'static>) -> u64 {
    let handle = ffi::g_signal_connect_data(receiver, signal_name.borrow_to_glib().0,
        trampoline, closure as gpointer, destroy_closure, 0) as u64;
    assert!(handle > 0);
    handle
}

extern "C" fn destroy_closure(ptr: *mut c_void, _: *mut c_void) {
    unsafe {
        let ptr = ptr as *mut Box<Fn()>;
        // destroy
        //Box::from_raw(ptr);
        // from_raw API stability workaround
        let _: Box<Box<Fn()>> = ::std::mem::transmute(ptr);
    }
}
<|endoftext|>