<commit_before>use std::result:: { Result };
use std::collections:: { HashMap };
use std::default::Default;
use lcov_parser:: {
    LCOVParser, LCOVRecord, LineData, FunctionData as FunctionDataRecord,
    BranchData as BranchDataRecord,
    FunctionName, ParseError, FromFile
};
use branch:: { BranchUnit };
use test:: { Test, TestSum };
use file:: { File, CheckSum, FunctionData };

/// Read the trace file of LCOV
///
/// # Examples
///
/// ```
/// use lcov_merge::parse_file;
///
/// let files = parse_file("tests/fixtures/fixture1.info").unwrap();
/// assert_eq!(files.keys().count(), 3);
///
/// let fixture = files.get("/home/vagrant/shared/lcov-merge/tests/fixtures/fixture.c").unwrap();
///
/// assert_eq!(fixture.sum().get_line_count(&4), Some(&1));
/// assert_eq!(fixture.sum().get_line_count(&6), Some(&1));
/// assert_eq!(fixture.sum().get_line_count(&7), Some(&1));
/// assert_eq!(fixture.sum().get_line_count(&8), Some(&1));
/// assert_eq!(fixture.sum().get_line_count(&1), None);
///
/// assert_eq!(fixture.get_test(&"example".to_string()).unwrap().get_line_count(&4), Some(&1));
/// ```
pub fn parse_file(file: &str) -> Result<HashMap<String, File>, ParseError> {
    let mut parse = ReportParser::new();
    parse.parse(file)
}

struct ReportParser {
    test_name: Option<String>,
    source_name: Option<String>,
    tests: HashMap<String, Test>,
    sum: TestSum,
    checksum: CheckSum,
    func: FunctionData,
    files: HashMap<String, File>
}

impl ReportParser {
    fn new() -> Self {
        ReportParser {
            test_name: None,
            source_name: None,
            tests: HashMap::new(),
            sum: TestSum::new(),
            checksum: HashMap::new(),
            func: HashMap::new(),
            files: HashMap::new()
        }
    }
    fn parse(&mut self, file: &str) -> Result<HashMap<String, File>, ParseError> {
        let mut parser = try!(LCOVParser::from_file(file));

        loop {
            let result = try!(parser.next());

            if result.is_none() {
                break;
            }
            let record = result.unwrap();

            match record {
                LCOVRecord::TestName(ref name) => self.on_test_name(name),
                LCOVRecord::SourceFile(ref name) => self.on_source_file(name),
                LCOVRecord::Data(ref data) => self.on_data(data),
                LCOVRecord::FunctionName(ref func_name) => self.on_func_name(func_name),
                LCOVRecord::FunctionData(ref func_data) => self.on_func_data(func_data),
                LCOVRecord::BranchData(ref branch_data) => self.on_branch_data(branch_data),
                LCOVRecord::EndOfRecord => self.on_end_of_record(),
                _ => { continue; }
            };
        }
        Ok(self.files.clone())
    }
    fn on_test_name(&mut self, test_name: &Option<String>) {
        self.test_name = test_name.clone().or( Some(String::new()) );
    }
    fn on_source_file(&mut self, source_name: &String) {
        self.source_name = Some(source_name.clone());

        let current_test_name = self.test_name.as_ref().unwrap();

        if !self.tests.contains_key(current_test_name) {
            self.tests.insert(current_test_name.to_string(), Test::default());
        }
    }
    fn on_data(&mut self, data: &LineData) {
        self.sum += data;

        if self.test_name.is_some() {
            let test_name = self.test_name.clone().unwrap();
            let mut test = self.tests.get_mut(&test_name).unwrap();
            test.add_line_count(&data.line, &data.count);
        }

        if data.checksum.is_none() {
            return;
        }

        if !self.checksum.contains_key(&data.line) {
            let checksum_value = data.checksum.clone().unwrap();
            self.checksum.insert(data.line.clone(), checksum_value);
            return;
        }

        let checksum_value = data.checksum.clone().unwrap();
        let current_checksum = self.checksum.get(&data.line).unwrap();
        if current_checksum != &checksum_value {
            println!("{} {}", current_checksum, checksum_value);
        }
    }
    fn on_func_name(&mut self, func_name: &FunctionName) {
        let _ = self.func.entry(func_name.name.clone())
            .or_insert(func_name.line.clone());
    }
    fn on_func_data(&mut self, func_data: &FunctionDataRecord) {
        self.sum += func_data;

        if self.test_name.is_none() {
            return;
        }

        let test_name = self.test_name.clone().unwrap();
        let mut test = self.tests.get_mut(&test_name).unwrap();

        test.add_func_count(&func_data.name, &func_data.count);
    }
    fn on_branch_data(&mut self, branch_data: &BranchDataRecord) {
        let ref branch_unit = BranchUnit::new(branch_data.block.clone(), branch_data.branch.clone());

        self.sum += branch_data;

        if self.test_name.is_some() {
            let ref test_name = self.test_name.clone().unwrap();
            let mut test = self.tests.get_mut(test_name).unwrap();
            test.add_branch_count(
                &branch_data.line,
                branch_unit,
                &branch_data.taken
            );
        }
    }
    fn on_end_of_record(&mut self) {
        let source_name = self.source_name.clone().unwrap();

        self.files.insert(source_name, File::new(
            self.sum.clone(),
            self.tests.clone(),
            self.checksum.clone(),
            self.func.clone()
        ));
    }
}
<commit_msg>Remove add_method code<commit_after>use std::result:: { Result };
use std::collections:: { HashMap };
use std::default::Default;
use lcov_parser:: {
    LCOVParser, LCOVRecord, LineData, FunctionData as FunctionDataRecord,
    BranchData as BranchDataRecord,
    FunctionName, ParseError, FromFile
};
use branch:: { BranchUnit };
use test:: { Test, TestSum };
use file:: { File, CheckSum, FunctionData };

/// Read the trace file of LCOV
///
/// # Examples
///
/// ```
/// use lcov_merge::parse_file;
///
/// let files = parse_file("tests/fixtures/fixture1.info").unwrap();
/// assert_eq!(files.keys().count(), 3);
///
/// let fixture = files.get("/home/vagrant/shared/lcov-merge/tests/fixtures/fixture.c").unwrap();
///
/// assert_eq!(fixture.sum().get_line_count(&4), Some(&1));
/// assert_eq!(fixture.sum().get_line_count(&6), Some(&1));
/// assert_eq!(fixture.sum().get_line_count(&7), Some(&1));
/// assert_eq!(fixture.sum().get_line_count(&8), Some(&1));
/// assert_eq!(fixture.sum().get_line_count(&1), None);
///
/// assert_eq!(fixture.get_test(&"example".to_string()).unwrap().get_line_count(&4), Some(&1));
/// ```
pub fn parse_file(file: &str) -> Result<HashMap<String, File>, ParseError> {
    let mut parse = ReportParser::new();
    parse.parse(file)
}

struct ReportParser {
    test_name: Option<String>,
    source_name: Option<String>,
    tests: HashMap<String, Test>,
    sum: TestSum,
    checksum: CheckSum,
    func: FunctionData,
    files: HashMap<String, File>
}

impl ReportParser {
    fn new() -> Self {
        ReportParser {
            test_name: None,
            source_name: None,
            tests: HashMap::new(),
            sum: TestSum::new(),
            checksum: HashMap::new(),
            func: HashMap::new(),
            files: HashMap::new()
        }
    }
    fn parse(&mut self, file: &str) -> Result<HashMap<String, File>, ParseError> {
        let mut parser = try!(LCOVParser::from_file(file));

        loop {
            let result = try!(parser.next());

            if result.is_none() {
                break;
            }
            let record = result.unwrap();

            match record {
                LCOVRecord::TestName(ref name) => self.on_test_name(name),
                LCOVRecord::SourceFile(ref name) => self.on_source_file(name),
                LCOVRecord::Data(ref data) => self.on_data(data),
                LCOVRecord::FunctionName(ref func_name) => self.on_func_name(func_name),
                LCOVRecord::FunctionData(ref func_data) => self.on_func_data(func_data),
                LCOVRecord::BranchData(ref branch_data) => self.on_branch_data(branch_data),
                LCOVRecord::EndOfRecord => self.on_end_of_record(),
                _ => { continue; }
            };
        }
        Ok(self.files.clone())
    }
    fn on_test_name(&mut self, test_name: &Option<String>) {
        self.test_name = test_name.clone().or( Some(String::new()) );
    }
    fn on_source_file(&mut self, source_name: &String) {
        self.source_name = Some(source_name.clone());

        let current_test_name = self.test_name.as_ref().unwrap();

        if !self.tests.contains_key(current_test_name) {
            self.tests.insert(current_test_name.to_string(), Test::default());
        }
    }
    fn on_data(&mut self, data: &LineData) {
        self.sum += data;

        if self.test_name.is_some() {
            let test_name = self.test_name.clone().unwrap();
            let mut test = self.tests.get_mut(&test_name).unwrap();

            *test += data;
        }

        if data.checksum.is_none() {
            return;
        }

        if !self.checksum.contains_key(&data.line) {
            let checksum_value = data.checksum.clone().unwrap();
            self.checksum.insert(data.line.clone(), checksum_value);
            return;
        }

        let checksum_value = data.checksum.clone().unwrap();
        let current_checksum = self.checksum.get(&data.line).unwrap();
        if current_checksum != &checksum_value {
            println!("{} {}", current_checksum, checksum_value);
        }
    }
    fn on_func_name(&mut self, func_name: &FunctionName) {
        let _ = self.func.entry(func_name.name.clone())
            .or_insert(func_name.line.clone());
    }
    fn on_func_data(&mut self, func_data: &FunctionDataRecord) {
        self.sum += func_data;

        if self.test_name.is_none() {
            return;
        }

        let test_name = self.test_name.clone().unwrap();
        let mut test = self.tests.get_mut(&test_name).unwrap();

        *test += func_data;
    }
    fn on_branch_data(&mut self, branch_data: &BranchDataRecord) {
        self.sum += branch_data;

        if self.test_name.is_some() {
            let ref test_name = self.test_name.clone().unwrap();
            let mut test = self.tests.get_mut(test_name).unwrap();

            *test += branch_data;
        }
    }
    fn on_end_of_record(&mut self) {
        let source_name = self.source_name.clone().unwrap();

        self.files.insert(source_name, File::new(
            self.sum.clone(),
            self.tests.clone(),
            self.checksum.clone(),
            self.func.clone()
        ));
    }
}
<|endoftext|>


<commit_before>use parser::combinators::{Parser, ParseTo, Consumer, token};
use parser::lexer::{Token};
use parser::lexer::Token::{Identifier};
use ast::{Typ};
use ast::Typ::{F32, F64, I32, I64};

#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
pub enum ParseError {
    ExpectingTyp(String),
}

pub trait ParserConsumer<T,D> where D: Consumer<Result<T,ParseError>> {
    fn accept<P>(self, parser: P) where P: for<'a> ParseTo<&'a[Token<'a>],D>;
}

fn is_identifier<'a>(tok: Token<'a>) -> bool {
    match tok {
        Identifier(_) => true,
        _             => false,
    }
}

fn mk_typ<'a>(tok: Token<'a>) -> Result<Typ,ParseError> {
    match tok {
        Identifier("f32") => Ok(F32),
        Identifier("f64") => Ok(F64),
        Identifier("i32") => Ok(I32),
        Identifier("i64") => Ok(I64),
        _                 => Err(ParseError::ExpectingTyp(String::from(tok))),
    }
}

pub fn typ_parser<C,D>(consumer: C) where C: ParserConsumer<Typ,D>, D: Consumer<Result<Typ,ParseError>> {
    consumer.accept(token(is_identifier).map(mk_typ));
}

#[test]
fn test_typ() {
    use parser::combinators::MatchResult::{Matched,Failed};
    use parser::lexer::Token::{LParen};
    struct TestConsumer;
    impl ParserConsumer<Typ,Vec<Result<Typ,ParseError>>> for TestConsumer {
        fn accept<P>(self, mut parser: P) where P: for<'a> ParseTo<&'a[Token<'a>],Vec<Result<Typ,ParseError>>> {
            let mut results = Vec::new();
            assert_eq!(parser.push_to(&[Identifier("f32")], &mut results), Matched(None));
            assert_eq!(parser.done_to(&mut results), true);
            assert_eq!(results, [Ok(F32)]);
            results.clear();
            assert_eq!(parser.push_to(&[Identifier("f64")], &mut results), Matched(None));
            assert_eq!(parser.done_to(&mut results), true);
            assert_eq!(results, [Ok(F64)]);
            results.clear();
            assert_eq!(parser.push_to(&[Identifier("i32")], &mut results), Matched(None));
            assert_eq!(parser.done_to(&mut results), true);
            assert_eq!(results, [Ok(I32)]);
            results.clear();
            assert_eq!(parser.push_to(&[Identifier("i64")], &mut results), Matched(None));
            assert_eq!(parser.done_to(&mut results), true);
            assert_eq!(results, [Ok(I64)]);
            results.clear();
            assert_eq!(parser.push_to(&[LParen], &mut results), Failed(Some(&[LParen][..])));
            assert_eq!(parser.done_to(&mut results), false);
            assert_eq!(results, []);
            results.clear();
            assert_eq!(parser.push_to(&[Identifier("foo")], &mut results), Matched(None));
            assert_eq!(parser.done_to(&mut results), true);
            assert_eq!(results, [Err(ParseError::ExpectingTyp(String::from("foo")))]);
            results.clear();
        }
    }
    typ_parser(TestConsumer);
}
<commit_msg>Added var parser.<commit_after>use parser::combinators::{Parser, ParseTo, Consumer, token, tokens};
use parser::lexer::{Token};
use parser::lexer::Token::{Identifier};
use ast::{Typ, Var};
use ast::Typ::{F32, F64, I32, I64};

#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
pub enum ParseError {
    ExpectingTyp(String),
    ExpectingId(String),
}

pub trait ParserConsumer<T,D> where D: Consumer<Result<T,ParseError>> {
    fn accept<P>(self, parser: P) where P: for<'a> ParseTo<&'a[Token<'a>],D>;
}

fn is_identifier<'a>(tok: Token<'a>) -> bool {
    match tok {
        Identifier(_) => true,
        _             => false,
    }
}

fn is_param<'a>(tok: Token<'a>) -> bool {
    match tok {
        Identifier("param") => true,
        _                   => false,
    }
}

fn mk_typ<'a>(tok: Token<'a>) -> Result<Typ,ParseError> {
    match tok {
        Identifier("f32") => Ok(F32),
        Identifier("f64") => Ok(F64),
        Identifier("i32") => Ok(I32),
        Identifier("i64") => Ok(I64),
        _                 => Err(ParseError::ExpectingTyp(String::from(tok))),
    }
}

fn mk_id<'a>(tok: Token<'a>) -> Result<String,ParseError> {
    match tok {
        Identifier(x) => Ok(String::from(x)),
        _             => Err(ParseError::ExpectingId(String::from(tok))),
    }
}

fn mk_var<'a>(children: (Result<String,ParseError>, Result<Typ,ParseError>))-> Result<Var,ParseError> {
    Ok(Var { name: try!(children.0), typ: try!(children.1) })
}

pub fn var_parser<C,D>(consumer: C) where C: ParserConsumer<Var,D>, D: Consumer<Result<Var,ParseError>> {
    let typ = token(is_identifier).map(mk_typ);
    let id = token(is_identifier).map(mk_id);
    let param = token(is_param).ignore().and_then(id).zip(typ).map(mk_var);
    consumer.accept(param);
}

#[test]
fn test_var() {
    use parser::combinators::MatchResult::{Matched,Failed};
    use parser::lexer::Token::{LParen};
    struct TestConsumer;
    impl ParserConsumer<Var,Vec<Result<Var,ParseError>>> for TestConsumer {
        fn accept<P>(self, mut parser: P) where P: for<'a> ParseTo<&'a[Token<'a>],Vec<Result<Var,ParseError>>> {
            let mut results = Vec::new();
            assert_eq!(parser.done_to(&mut results), false);
            assert_eq!(results, []);
            results.clear();
            assert_eq!(parser.push_to(&[Identifier("param"),Identifier("$x"),Identifier("f32")], &mut results), Matched(None));
            assert_eq!(parser.done_to(&mut results), true);
            assert_eq!(results, [Ok(Var{ name: String::from("$x"), typ: F32 })]);
            results.clear();
            assert_eq!(parser.push_to(&[LParen], &mut results), Failed(Some(&[LParen][..])));
            assert_eq!(parser.done_to(&mut results), false);
            assert_eq!(results, []);
            results.clear();
            assert_eq!(parser.push_to(&[Identifier("param"),Identifier("$x"),Identifier("foo")], &mut results), Matched(None));
            assert_eq!(parser.done_to(&mut results), true);
            assert_eq!(results, [Err(ParseError::ExpectingTyp(String::from("foo")))]);
            results.clear();
        }
    }
    var_parser(TestConsumer);
}
<|endoftext|>


<commit_before>use middleware::Middleware;
use request::Request;
use response::Response;
use hyper::method::Method;

struct Route {
    method: Method,
    path: String,
    action: Box<Middleware>
}

pub trait HttpMethods {
    fn new_route<T: Middleware>(&mut self, Method, String, T);
    fn get<T: Middleware>(&mut self, path: String, action: T) {
        self.new_route(Method::Get, path, action);
    }

    fn post<T: Middleware>(&mut self, path: String, action: T) {
        self.new_route(Method::Post, path, action);
    }

    fn put<T: Middleware>(&mut self, path: String, action: T) {
        self.new_route(Method::Put, path, action);
    }

    fn delete<T: Middleware>(&mut self, path: String, action: T) {
        self.new_route(Method::Delete, path, action);
    }
}

pub struct Router {
    base: String,
    routes: Vec<Route>
}

impl Router {
    pub fn new(base: String) -> Router {
        Router {
            base: base,
            routes: vec![]
        }
    }

    pub fn serve<'m, 'r>(&'m self, req: Request<'m, 'r>, res: Response<'m>) {
        match self.match_route(req.method(), req.path().to_string()) {
            Some(route) => route.action.execute(req, res),
            None => panic!("Route not found.")
        };
    }

    fn match_route(&self, method: &Method, path: String) -> Option<&Route> {
        let mut matched_route = None;
        for route in self.routes.iter() {
            if route.method == *method && route.path == path.to_string() {
                matched_route = Some(route);
                break;
            }
        }
        matched_route
    }
}

impl HttpMethods for Router {
    fn new_route<T: Middleware>(&mut self, method: Method, path: String, action: T) {
        let route = Route {
            method: Method::Get,
            path: path,
            action: Box::new(action)
        };
        self.routes.push(route);
    }
}
<commit_msg>new method skeletons<commit_after>use middleware::Middleware;
use request::Request;
use response::Response;
use hyper::method::Method;

struct Route {
    method: Method,
    path: String,
    action: Box<Middleware>
}

pub trait HttpMethods {
    fn new_route<T: Middleware>(&mut self, Method, String, T);
    fn get<T: Middleware>(&mut self, path: String, action: T) {
        self.new_route(Method::Get, path, action);
    }

    fn post<T: Middleware>(&mut self, path: String, action: T) {
        self.new_route(Method::Post, path, action);
    }

    fn put<T: Middleware>(&mut self, path: String, action: T) {
        self.new_route(Method::Put, path, action);
    }

    fn delete<T: Middleware>(&mut self, path: String, action: T) {
        self.new_route(Method::Delete, path, action);
    }
}

pub struct Router {
    base: String,
    routes: Vec<Route>
}

impl Router {
    pub fn new(base: String) -> Router {
        Router {
            base: base,
            routes: vec![]
        }
    }

    pub fn serve<'m, 'r>(&'m self, req: Request<'m, 'r>, res: Response<'m>) {
        match self.match_route(req.method(), req.path().to_string()) {
            Some(route) => route.action.execute(req, res),
            None => panic!("Route not found.")
        };
    }

    fn match_route(&self, method: &Method, path: String) -> Option<&Route> {
        let mut matched_route = None;
        for route in self.routes.iter() {
            if route.method == *method && route.path == path.to_string() {
                matched_route = Some(route);
                break;
            }
        }
        matched_route
    }
}

impl HttpMethods for Router {
    fn new_route<T: Middleware>(&mut self, method: Method, path: String, action: T) {
        let route = Route {
            method: method,
            path: path,
            action: Box::new(action)
        };
        self.routes.push(route);
    }
}
<|endoftext|>


<commit_before>use mozprofile::prefreader::PrefReaderError;
use mozprofile::profile::Profile;
use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::convert::From;
use std::env;
use std::error::Error;
use std::fmt;
use std::io::{Result as IoResult, Error as IoError, ErrorKind};
use std::path::{Path, PathBuf};
use std::process;
use std::process::{Command, Stdio};

pub trait Runner {
    fn start(&mut self) -> Result<(), RunnerError>;

    fn args(&mut self) -> &mut Vec<String>;

    fn build_command(&self, &mut Command);

    fn envs(&mut self) -> &mut HashMap<String, String>;

    fn is_running(&self) -> bool;

    fn stop(&mut self) -> IoResult<Option<process::ExitStatus>>;
}

#[derive(Debug)]
pub enum RunnerError {
    Io(IoError),
    PrefReader(PrefReaderError),
}

impl fmt::Display for RunnerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.description().fmt(f)
    }
}

impl Error for RunnerError {
    fn description(&self) -> &str {
        match *self {
            RunnerError::Io(ref err) => {
                match err.kind() {
                    ErrorKind::NotFound => "no such file or directory",
                    _ => err.description(),
                }
            }
            RunnerError::PrefReader(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        Some(match *self {
            RunnerError::Io(ref err) => err as &Error,
            RunnerError::PrefReader(ref err) => err as &Error,
        })
    }
}

impl From<IoError> for RunnerError {
    fn from(value: IoError) -> RunnerError {
        RunnerError::Io(value)
    }
}

impl From<PrefReaderError> for RunnerError {
    fn from(value: PrefReaderError) -> RunnerError {
        RunnerError::PrefReader(value)
    }
}

pub struct FirefoxRunner {
    pub binary: PathBuf,
    args: Vec<String>,
    envs: HashMap<String, String>,
    process: Option<process::Child>,
    pub ret_code: Option<process::ExitStatus>,
    pub profile: Profile
}

impl FirefoxRunner {
    pub fn new(binary: &Path, profile: Option<Profile>) -> IoResult<FirefoxRunner> {
        let prof = match profile {
            Some(p) => p,
            None => try!(Profile::new(None))
        };

        let mut envs = HashMap::new();
        envs.insert("MOZ_NO_REMOTE".to_string(), "1".to_string());
        envs.insert("NO_EM_RESTART".to_string(), "1".to_string());

        Ok(FirefoxRunner {
            binary: binary.to_path_buf(),
            process: None,
            ret_code: None,
            args: Vec::new(),
            envs: envs,
            profile: prof
        })
    }
}

impl Runner for FirefoxRunner {
    fn start(&mut self) -> Result<(), RunnerError> {
        let mut cmd = Command::new(&self.binary);
        self.build_command(&mut cmd);

        debug!("Command {:?}", cmd);

        let prefs = try!(self.profile.user_prefs());
        try!(prefs.write());

        let process = try!(cmd.spawn());
        self.process = Some(process);
        Ok(())
    }

    fn args(&mut self) -> &mut Vec<String> {
        &mut self.args
    }

    fn build_command(&self, command: &mut Command) {
        command
            .args(&self.args[..])
            .envs(&self.envs);

        if !self.args.iter().any(|x| is_profile_arg(x)) {
            command.arg("-profile").arg(&self.profile.path);
        }
        command.stdout(Stdio::inherit())
            .stderr(Stdio::inherit());
    }

    fn envs(&mut self) -> &mut HashMap<String, String> {
        &mut self.envs
    }

    fn is_running(&self) -> bool {
        self.process.is_some() && self.ret_code.is_none()
    }

    fn stop(&mut self) -> IoResult<Option<process::ExitStatus>> {
        if let Some(p) = self.process.as_mut() {
            try!(p.kill());
            let status = try!(p.wait());
            self.ret_code = Some(status);
        };
        Ok(self.ret_code)
    }
}

fn parse_arg_name(arg: &str) -> Option<&str> {
    let mut start = 0;
    let mut end = 0;

    for (i, c) in arg.chars().enumerate() {
        if i == 0 {
            if !platform::arg_prefix_char(c) {
                break;
            }
        } else if i == 1 {
            if name_end_char(c) {
                break;
            } else if c != '-' {
                start = i;
                end = start + 1;
            } else {
                start = i + 1;
                end = start;
            }
        } else {
            end += 1;
            if name_end_char(c) {
                end -= 1;
                break;
            }
        }
    }

    if start > 0 && end > start {
        Some(&arg[start..end])
    } else {
        None
    }
}

fn name_end_char(c: char) -> bool {
    c == ' ' || c == '='
}

/// Check if an argument string affects the Firefox profile
///
/// Returns a boolean indicating whether a given string
/// contains one of the `-P`, `-Profile` or `-ProfileManager`
/// arguments, respecting the various platform-specific conventions.
pub fn is_profile_arg(arg: &str) -> bool {
    if let Some(name) = parse_arg_name(arg) {
        name.eq_ignore_ascii_case("profile") ||
            name.eq_ignore_ascii_case("p") ||
            name.eq_ignore_ascii_case("profilemanager")
    } else {
        false
    }
}

fn find_binary(name: &str) -> Option<PathBuf> {
    env::var("PATH")
        .ok()
        .and_then(|path_env| {
            for mut path in env::split_paths(&*path_env) {
                path.push(name);
                if path.exists() {
                    return Some(path)
                }
            }
            None
        })
}

#[cfg(target_os = "linux")]
pub mod platform {
    use super::find_binary;
    use std::path::PathBuf;

    pub fn firefox_default_path() -> Option<PathBuf> {
        find_binary("firefox")
    }

    pub fn arg_prefix_char(c: char) -> bool {
        c == '-'
    }
}

#[cfg(target_os = "macos")]
pub mod platform {
    use super::find_binary;
    use std::env;
    use std::path::PathBuf;

    pub fn firefox_default_path() -> Option<PathBuf> {
        if let Some(path) = find_binary("firefox-bin") {
            return Some(path)
        }
        let home = env::home_dir();
        for &(prefix_home, trial_path) in [
            (false, "/Applications/Firefox.app/Contents/MacOS/firefox-bin"),
            (true, "Applications/Firefox.app/Contents/MacOS/firefox-bin")].iter() {
            let path = match (home.as_ref(), prefix_home) {
                (Some(ref home_dir), true) => home_dir.join(trial_path),
                (None, true) => continue,
                (_, false) => PathBuf::from(trial_path)
            };
            if path.exists() {
                return Some(path)
            }
        }
        None
    }

    pub fn arg_prefix_char(c: char) -> bool {
        c == '-'
    }
}

#[cfg(target_os = "windows")]
pub mod platform {
    use super::find_binary;
    use std::io::Error;
    use std::path::PathBuf;
    use winreg::RegKey;
    use winreg::enums::*;

    pub fn firefox_default_path() -> Option<PathBuf> {
        let opt_path = firefox_registry_path().unwrap_or(None);
        if let Some(path) = opt_path {
            if path.exists() {
                return Some(path)
            }
        };
        find_binary("firefox.exe")
    }

    fn firefox_registry_path() -> Result<Option<PathBuf>, Error> {
        let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
        for subtree_key in ["SOFTWARE", "SOFTWARE\\WOW6432Node"].iter() {
            let subtree = try!(hklm.open_subkey_with_flags(subtree_key, KEY_READ));
            let mozilla_org = match subtree.open_subkey_with_flags("mozilla.org\\Mozilla", KEY_READ) {
                Ok(val) => val,
                Err(_) => continue
            };
            let current_version: String = try!(mozilla_org.get_value("CurrentVersion"));
            let mozilla = try!(subtree.open_subkey_with_flags("Mozilla", KEY_READ));
            for key_res in mozilla.enum_keys() {
                let key = try!(key_res);
                let section_data = try!(mozilla.open_subkey_with_flags(&key, KEY_READ));
                let version: Result<String, _> = section_data.get_value("GeckoVer");
                if let Ok(ver) = version {
                    if ver == current_version {
                        let mut bin_key = key.to_owned();
                        bin_key.push_str("\\bin");
                        if let Ok(bin_subtree) = mozilla.open_subkey_with_flags(bin_key, KEY_READ) {
                            let path: Result<String, _> = bin_subtree.get_value("PathToExe");
                            if let Ok(path) = path {
                                return Ok(Some(PathBuf::from(path)))
                            }
                        }
                    }
                }
            }
        }
        Ok(None)
    }

    pub fn arg_prefix_char(c: char) -> bool {
        c == '/' || c == '-'
    }
}

#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
pub mod platform {
    use std::path::PathBuf;

    pub fn firefox_default_path() -> Option<PathBuf> {
        None
    }

    pub fn arg_prefix_char(c: char) -> bool {
        c == '-'
    }
}

#[cfg(test)]
mod tests {
    use super::{parse_arg_name, is_profile_arg};

    fn parse(arg: &str, name: Option<&str>) {
        let result = parse_arg_name(arg);
        assert_eq!(result, name);
    }

    #[test]
    fn test_parse_arg_name() {
        parse("-p", Some("p"));
        parse("--p", Some("p"));
        parse("--profile foo", Some("profile"));
        parse("--profile", Some("profile"));
        parse("--", None);
        parse("", None);
        parse("-=", None);
        parse("--=", None);
        parse("-- foo", None);
        parse("foo", None);
        parse("/ foo", None);
        parse("/- foo", None);
        parse("/=foo", None);
        parse("foo", None);
        parse("-profile", Some("profile"));
        parse("-profile=foo", Some("profile"));
        parse("-profile = foo", Some("profile"));
        parse("-profile abc", Some("profile"));
    }

    #[cfg(target_os = "windows")]
    #[test]
    fn test_parse_arg_name_windows() {
        parse("/profile", Some("profile"));
    }

    #[cfg(not(target_os = "windows"))]
    #[test]
    fn test_parse_arg_name_non_windows() {
        parse("/profile", None);
    }

    #[test]
    fn test_is_profile_arg() {
        assert!(is_profile_arg("--profile"));
        assert!(is_profile_arg("-p"));
        assert!(is_profile_arg("-PROFILEMANAGER"));
        assert!(is_profile_arg("-ProfileMANAGER"));
        assert!(!is_profile_arg("-- profile"));
        assert!(!is_profile_arg("-profiled"));
        assert!(!is_profile_arg("-p1"));
        assert!(is_profile_arg("-p test"));
        assert!(is_profile_arg("-profile /foo"));
    }
}
<commit_msg>Use info level for logging executed command and arguments (#13)<commit_after>use mozprofile::prefreader::PrefReaderError;
use mozprofile::profile::Profile;
use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::convert::From;
use std::env;
use std::error::Error;
use std::fmt;
use std::io::{Result as IoResult, Error as IoError, ErrorKind};
use std::path::{Path, PathBuf};
use std::process;
use std::process::{Command, Stdio};

pub trait Runner {
    fn start(&mut self) -> Result<(), RunnerError>;

    fn args(&mut self) -> &mut Vec<String>;

    fn build_command(&self, &mut Command);

    fn envs(&mut self) -> &mut HashMap<String, String>;

    fn is_running(&self) -> bool;

    fn stop(&mut self) -> IoResult<Option<process::ExitStatus>>;
}

#[derive(Debug)]
pub enum RunnerError {
    Io(IoError),
    PrefReader(PrefReaderError),
}

impl fmt::Display for RunnerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.description().fmt(f)
    }
}

impl Error for RunnerError {
    fn description(&self) -> &str {
        match *self {
            RunnerError::Io(ref err) => {
                match err.kind() {
                    ErrorKind::NotFound => "no such file or directory",
                    _ => err.description(),
                }
            }
            RunnerError::PrefReader(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        Some(match *self {
            RunnerError::Io(ref err) => err as &Error,
            RunnerError::PrefReader(ref err) => err as &Error,
        })
    }
}

impl From<IoError> for RunnerError {
    fn from(value: IoError) -> RunnerError {
        RunnerError::Io(value)
    }
}

impl From<PrefReaderError> for RunnerError {
    fn from(value: PrefReaderError) -> RunnerError {
        RunnerError::PrefReader(value)
    }
}

pub struct FirefoxRunner {
    pub binary: PathBuf,
    args: Vec<String>,
    envs: HashMap<String, String>,
    process: Option<process::Child>,
    pub ret_code: Option<process::ExitStatus>,
    pub profile: Profile
}

impl FirefoxRunner {
    pub fn new(binary: &Path, profile: Option<Profile>) -> IoResult<FirefoxRunner> {
        let prof = match profile {
            Some(p) => p,
            None => try!(Profile::new(None))
        };

        let mut envs = HashMap::new();
        envs.insert("MOZ_NO_REMOTE".to_string(), "1".to_string());
        envs.insert("NO_EM_RESTART".to_string(), "1".to_string());

        Ok(FirefoxRunner {
            binary: binary.to_path_buf(),
            process: None,
            ret_code: None,
            args: Vec::new(),
            envs: envs,
            profile: prof
        })
    }
}

impl Runner for FirefoxRunner {
    fn start(&mut self) -> Result<(), RunnerError> {
        let mut cmd = Command::new(&self.binary);
        self.build_command(&mut cmd);

        let prefs = try!(self.profile.user_prefs());
        try!(prefs.write());

        info!("Running command: {:?}", cmd);
        let process = try!(cmd.spawn());
        self.process = Some(process);
        Ok(())
    }

    fn args(&mut self) -> &mut Vec<String> {
        &mut self.args
    }

    fn build_command(&self, command: &mut Command) {
        command
            .args(&self.args[..])
            .envs(&self.envs);

        if !self.args.iter().any(|x| is_profile_arg(x)) {
            command.arg("-profile").arg(&self.profile.path);
        }
        command.stdout(Stdio::inherit())
            .stderr(Stdio::inherit());
    }

    fn envs(&mut self) -> &mut HashMap<String, String> {
        &mut self.envs
    }

    fn is_running(&self) -> bool {
        self.process.is_some() && self.ret_code.is_none()
    }

    fn stop(&mut self) -> IoResult<Option<process::ExitStatus>> {
        if let Some(p) = self.process.as_mut() {
            try!(p.kill());
            let status = try!(p.wait());
            self.ret_code = Some(status);
        };
        Ok(self.ret_code)
    }
}

fn parse_arg_name(arg: &str) -> Option<&str> {
    let mut start = 0;
    let mut end = 0;

    for (i, c) in arg.chars().enumerate() {
        if i == 0 {
            if !platform::arg_prefix_char(c) {
                break;
            }
        } else if i == 1 {
            if name_end_char(c) {
                break;
            } else if c != '-' {
                start = i;
                end = start + 1;
            } else {
                start = i + 1;
                end = start;
            }
        } else {
            end += 1;
            if name_end_char(c) {
                end -= 1;
                break;
            }
        }
    }

    if start > 0 && end > start {
        Some(&arg[start..end])
    } else {
        None
    }
}

fn name_end_char(c: char) -> bool {
    c == ' ' || c == '='
}

/// Check if an argument string affects the Firefox profile
///
/// Returns a boolean indicating whether a given string
/// contains one of the `-P`, `-Profile` or `-ProfileManager`
/// arguments, respecting the various platform-specific conventions.
pub fn is_profile_arg(arg: &str) -> bool {
    if let Some(name) = parse_arg_name(arg) {
        name.eq_ignore_ascii_case("profile") ||
            name.eq_ignore_ascii_case("p") ||
            name.eq_ignore_ascii_case("profilemanager")
    } else {
        false
    }
}

fn find_binary(name: &str) -> Option<PathBuf> {
    env::var("PATH")
        .ok()
        .and_then(|path_env| {
            for mut path in env::split_paths(&*path_env) {
                path.push(name);
                if path.exists() {
                    return Some(path)
                }
            }
            None
        })
}

#[cfg(target_os = "linux")]
pub mod platform {
    use super::find_binary;
    use std::path::PathBuf;

    pub fn firefox_default_path() -> Option<PathBuf> {
        find_binary("firefox")
    }

    pub fn arg_prefix_char(c: char) -> bool {
        c == '-'
    }
}

#[cfg(target_os = "macos")]
pub mod platform {
    use super::find_binary;
    use std::env;
    use std::path::PathBuf;

    pub fn firefox_default_path() -> Option<PathBuf> {
        if let Some(path) = find_binary("firefox-bin") {
            return Some(path)
        }
        let home = env::home_dir();
        for &(prefix_home, trial_path) in [
            (false, "/Applications/Firefox.app/Contents/MacOS/firefox-bin"),
            (true, "Applications/Firefox.app/Contents/MacOS/firefox-bin")].iter() {
            let path = match (home.as_ref(), prefix_home) {
                (Some(ref home_dir), true) => home_dir.join(trial_path),
                (None, true) => continue,
                (_, false) => PathBuf::from(trial_path)
            };
            if path.exists() {
                return Some(path)
            }
        }
        None
    }

    pub fn arg_prefix_char(c: char) -> bool {
        c == '-'
    }
}

#[cfg(target_os = "windows")]
pub mod platform {
    use super::find_binary;
    use std::io::Error;
    use std::path::PathBuf;
    use winreg::RegKey;
    use winreg::enums::*;

    pub fn firefox_default_path() -> Option<PathBuf> {
        let opt_path = firefox_registry_path().unwrap_or(None);
        if let Some(path) = opt_path {
            if path.exists() {
                return Some(path)
            }
        };
        find_binary("firefox.exe")
    }

    fn firefox_registry_path() -> Result<Option<PathBuf>, Error> {
        let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
        for subtree_key in ["SOFTWARE", "SOFTWARE\\WOW6432Node"].iter() {
            let subtree = try!(hklm.open_subkey_with_flags(subtree_key, KEY_READ));
            let mozilla_org = match subtree.open_subkey_with_flags("mozilla.org\\Mozilla", KEY_READ) {
                Ok(val) => val,
                Err(_) => continue
            };
            let current_version: String = try!(mozilla_org.get_value("CurrentVersion"));
            let mozilla = try!(subtree.open_subkey_with_flags("Mozilla", KEY_READ));
            for key_res in mozilla.enum_keys() {
                let key = try!(key_res);
                let section_data = try!(mozilla.open_subkey_with_flags(&key, KEY_READ));
                let version: Result<String, _> = section_data.get_value("GeckoVer");
                if let Ok(ver) = version {
                    if ver == current_version {
                        let mut bin_key = key.to_owned();
                        bin_key.push_str("\\bin");
                        if let Ok(bin_subtree) = mozilla.open_subkey_with_flags(bin_key, KEY_READ) {
                            let path: Result<String, _> = bin_subtree.get_value("PathToExe");
                            if let Ok(path) = path {
                                return Ok(Some(PathBuf::from(path)))
                            }
                        }
                    }
                }
            }
        }
        Ok(None)
    }

    pub fn arg_prefix_char(c: char) -> bool {
        c == '/' || c == '-'
    }
}

#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
pub mod platform {
    use std::path::PathBuf;

    pub fn firefox_default_path() -> Option<PathBuf> {
        None
    }

    pub fn arg_prefix_char(c: char) -> bool {
        c == '-'
    }
}

#[cfg(test)]
mod tests {
    use super::{parse_arg_name, is_profile_arg};

    fn parse(arg: &str, name: Option<&str>) {
        let result = parse_arg_name(arg);
        assert_eq!(result, name);
    }

    #[test]
    fn test_parse_arg_name() {
        parse("-p", Some("p"));
        parse("--p", Some("p"));
        parse("--profile foo", Some("profile"));
        parse("--profile", Some("profile"));
        parse("--", None);
        parse("", None);
        parse("-=", None);
        parse("--=", None);
        parse("-- foo", None);
        parse("foo", None);
        parse("/ foo", None);
        parse("/- foo", None);
        parse("/=foo", None);
        parse("foo", None);
        parse("-profile", Some("profile"));
        parse("-profile=foo", Some("profile"));
        parse("-profile = foo", Some("profile"));
        parse("-profile abc", Some("profile"));
    }

    #[cfg(target_os = "windows")]
    #[test]
    fn test_parse_arg_name_windows() {
        parse("/profile", Some("profile"));
    }

    #[cfg(not(target_os = "windows"))]
    #[test]
    fn test_parse_arg_name_non_windows() {
        parse("/profile", None);
    }

    #[test]
    fn test_is_profile_arg() {
        assert!(is_profile_arg("--profile"));
        assert!(is_profile_arg("-p"));
        assert!(is_profile_arg("-PROFILEMANAGER"));
        assert!(is_profile_arg("-ProfileMANAGER"));
        assert!(!is_profile_arg("-- profile"));
        assert!(!is_profile_arg("-profiled"));
        assert!(!is_profile_arg("-p1"));
        assert!(is_profile_arg("-p test"));
        assert!(is_profile_arg("-profile /foo"));
    }
}
<|endoftext|>


<commit_before>#![doc = include_str!("core_arch_docs.md")]
#![allow(improper_ctypes_definitions)]
#![allow(dead_code)]
#![allow(unused_features)]
#![deny(rust_2018_idioms)]
#![feature(
    custom_inner_attributes,
    link_llvm_intrinsics,
    platform_intrinsics,
    repr_simd,
    simd_ffi,
    proc_macro_hygiene,
    stmt_expr_attributes,
    core_intrinsics,
    no_core,
    rustc_attrs,
    stdsimd,
    staged_api,
    doc_cfg,
    tbm_target_feature,
    sse4a_target_feature,
    arm_target_feature,
    aarch64_target_feature,
    cmpxchg16b_target_feature,
    avx512_target_feature,
    mips_target_feature,
    powerpc_target_feature,
    wasm_target_feature,
    abi_unadjusted,
    adx_target_feature,
    rtm_target_feature,
    f16c_target_feature,
    allow_internal_unstable,
    decl_macro,
    bench_black_box,
    asm_const
)]
#![cfg_attr(test, feature(test, abi_vectorcall))]
#![deny(clippy::missing_inline_in_public_items)]
#![allow(
    clippy::inline_always,
    clippy::too_many_arguments,
    clippy::cast_sign_loss,
    clippy::cast_lossless,
    clippy::cast_possible_wrap,
    clippy::cast_possible_truncation,
    clippy::cast_precision_loss,
    clippy::shadow_reuse,
    clippy::cognitive_complexity,
    clippy::similar_names,
    clippy::many_single_char_names
)]
#![cfg_attr(test, allow(unused_imports))]
#![no_std]
#![unstable(feature = "stdsimd", issue = "27731")]
#![doc(
    test(attr(deny(warnings))),
    test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
)]

#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
#[macro_use]
extern crate std_detect;
#[path = "mod.rs"]
mod core_arch;

pub mod arch {
    pub use crate::core_arch::arch::*;
    pub use core::arch::asm;
}

#[allow(unused_imports)]
use core::{convert, ffi, hint, intrinsics, marker, mem, ops, ptr, sync};
<commit_msg>Remove feature gates for stabilized features<commit_after>#![doc = include_str!("core_arch_docs.md")]
#![allow(improper_ctypes_definitions)]
#![allow(dead_code)]
#![allow(unused_features)]
#![deny(rust_2018_idioms)]
#![feature(
    custom_inner_attributes,
    link_llvm_intrinsics,
    platform_intrinsics,
    repr_simd,
    simd_ffi,
    proc_macro_hygiene,
    stmt_expr_attributes,
    core_intrinsics,
    no_core,
    rustc_attrs,
    stdsimd,
    staged_api,
    doc_cfg,
    tbm_target_feature,
    sse4a_target_feature,
    arm_target_feature,
    cmpxchg16b_target_feature,
    avx512_target_feature,
    mips_target_feature,
    powerpc_target_feature,
    wasm_target_feature,
    abi_unadjusted,
    rtm_target_feature,
    f16c_target_feature,
    allow_internal_unstable,
    decl_macro,
    bench_black_box,
    asm_const
)]
#![cfg_attr(test, feature(test, abi_vectorcall))]
#![deny(clippy::missing_inline_in_public_items)]
#![allow(
    clippy::inline_always,
    clippy::too_many_arguments,
    clippy::cast_sign_loss,
    clippy::cast_lossless,
    clippy::cast_possible_wrap,
    clippy::cast_possible_truncation,
    clippy::cast_precision_loss,
    clippy::shadow_reuse,
    clippy::cognitive_complexity,
    clippy::similar_names,
    clippy::many_single_char_names
)]
#![cfg_attr(test, allow(unused_imports))]
#![no_std]
#![unstable(feature = "stdsimd", issue = "27731")]
#![doc(
    test(attr(deny(warnings))),
    test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
)]

#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
#[macro_use]
extern crate std_detect;
#[path = "mod.rs"]
mod core_arch;

pub mod arch {
    pub use crate::core_arch::arch::*;
    pub use core::arch::asm;
}

#[allow(unused_imports)]
use core::{convert, ffi, hint, intrinsics, marker, mem, ops, ptr, sync};
<|endoftext|>


<commit_before>use std;
use std::cmp;
use std::io::stdout;
use std::io::Write;
use std::thread;
use std::time;

use termion;
use termion::clear;
use termion::cursor;
use termion::input::MouseTerminal;
use termion::raw::IntoRawMode;
use termion::raw::RawTerminal;

use core::Core;
use update::Update;
use view::View;

pub struct Screen {
    pub stdout: MouseTerminal<RawTerminal<std::io::Stdout>>,
    pub size: (u16, u16),
}

impl Screen {
    pub fn new() -> Screen {
        let mut stdout = MouseTerminal::from(stdout().into_raw_mode().unwrap());
        write!(stdout, "{}", clear::All).unwrap();
        stdout.flush().unwrap();
        Screen {
            size: termion::terminal_size().unwrap(),
            stdout: stdout,
        }
    }

    // TODO: handle lines that are longer than terminal width.
    // Should we wrap them or truncate them?
    pub fn redraw(&mut self, _update: &Update) {
        unimplemented!();
        // write!(self.stdout, "{}", termion::clear::All).unwrap();
        // write!(self.stdout, "{}", cursor::Up(self.size.1)).unwrap();
        //
        // let nb_lines = cmp::min(update.lines.len(), self.size.1 as usize);
        // if nb_lines > 0 {
        // for line in update.lines.iter().take(nb_lines - 1) {
        // write!(self.stdout, "{}", cursor::Left(self.size.0)).unwrap();
        //
        // if let Some(selection) = line.selection {
        // let start = selection.0 as usize;
        // let end = selection.1 as usize;
        // let mut str_before = String::new();
        // for c in line.text.chars().take(start) {
        // str_before.push(c);
        // }
        // let mut str_selection = String::new();
        // for c in line.text.chars().skip(start).take(end) {
        // str_selection.push(c);
        // }
        // let mut str_after = String::new();
        // for c in line.text.chars().skip(end) {
        // str_after.push(c);
        // }
        // write!(self.stdout, "{}{}{}{}{}{}",
        // termion::style::Reset,
        // str_before,
        // termion::color::Bg(color::Red),
        // str_selection,
        // termion::style::Reset,
        // str_after).unwrap();
        // } else {
        // self.stdout.write_all(line.text.as_bytes()).unwrap();
        // }
        // }
        //
        // If the last line has a trailing \n, we need to remove it
        // let mut last_line = update.lines[nb_lines - 1].text.clone();
        // match last_line.pop() {
        // Some('\n') | None => {
        // },
        // Some(c) => {
        // last_line.push(c);
        // }
        // }
        // write!(self.stdout, "{}", cursor::Left(self.size.0)).unwrap();
        // self.stdout.write_all(last_line.as_bytes()).unwrap();
        // }
        //
        // let cursor_line_idx = update.scroll_to.0 - update.first_line;
        // let cursor_line = update.lines[cursor_line_idx as usize].text.clone();
        // let mut cols =  0;
        // for c in cursor_line.chars().take(update.scroll_to.1 as usize) {
        // if c == '\t' {
        // cols += 4;
        // } else {
        // cols += 1;
        // }
        // }
        // self.scroll(cols + 1, cursor_line_idx + 1);
        //
    }

    pub fn draw(&mut self, view: &View) {
        write!(self.stdout, "{}", termion::clear::All).unwrap();
        write!(self.stdout, "{}", cursor::Up(self.size.1)).unwrap();

        let range = 0..(cmp::min(view.lines.len(), self.size.1 as usize));
        for (lineno, line) in range.zip(view.lines.iter()) {
            write!(self.stdout, "{}", line.text.clone().unwrap()).unwrap();
            self.scroll(0, lineno as u64);
        }
    }

    pub fn scroll(&mut self, col: u64, line: u64) {
        write!(self.stdout, "{}", cursor::Goto((col + 1) as u16, (line + 1) as u16)).unwrap();
        self.stdout.flush().unwrap();
    }

    pub fn init(&mut self) {
        write!(self.stdout, "{}", termion::clear::All).unwrap();
        write!(self.stdout, "{}", cursor::Up(self.size.1)).unwrap();
        self.stdout.flush().unwrap();
    }

    pub fn update(&mut self, core: &mut Core) {
        // TODO: check if terminal size changed. If so, send a `render_line` command to the backend,
        // and a `scroll` command for future updates.
        if let Ok(msg) = core.update_rx.try_recv() {
            let msg_list = msg.as_array().unwrap();
            let (method, params) = (msg_list[0].as_str().unwrap(),
                                    msg_list[1].as_object().unwrap());
            if method == "update" {
                let update = Update::from_value(params.get("update").unwrap());
                core.update(&update);

                let view = core.view();
                self.draw(&view);
            } else if method == "scroll_to" {
                let (col, line) = (params.get("col").unwrap().as_u64().unwrap(),
                                   params.get("line").unwrap().as_u64().unwrap());
                self.scroll(col, line);
            } else if method == "set_style" {
                // TODO: ???
            } else {
                info!("Unknown request from backend {:?}", method);
            }
        } else {
            thread::sleep(time::Duration::from_millis(10));
        }
    }
}
<commit_msg>Removes dead code from screen module<commit_after>use std;
use std::cmp;
use std::io::stdout;
use std::io::Write;
use std::thread;
use std::time;

use termion;
use termion::clear;
use termion::cursor;
use termion::input::MouseTerminal;
use termion::raw::IntoRawMode;
use termion::raw::RawTerminal;

use core::Core;
use update::Update;
use view::View;

pub struct Screen {
    pub stdout: MouseTerminal<RawTerminal<std::io::Stdout>>,
    pub size: (u16, u16),
}

impl Screen {
    pub fn new() -> Screen {
        let mut stdout = MouseTerminal::from(stdout().into_raw_mode().unwrap());
        write!(stdout, "{}", clear::All).unwrap();
        stdout.flush().unwrap();
        Screen {
            size: termion::terminal_size().unwrap(),
            stdout: stdout,
        }
    }

    pub fn draw(&mut self, view: &View) {
        write!(self.stdout, "{}", termion::clear::All).unwrap();
        write!(self.stdout, "{}", cursor::Up(self.size.1)).unwrap();

        let range = 0..(cmp::min(view.lines.len(), self.size.1 as usize));
        for (lineno, line) in range.zip(view.lines.iter()) {
            write!(self.stdout, "{}", line.text.clone().unwrap()).unwrap();
            self.scroll(0, lineno as u64);
        }
    }

    pub fn scroll(&mut self, col: u64, line: u64) {
        write!(self.stdout, "{}", cursor::Goto((col + 1) as u16, (line + 1) as u16)).unwrap();
        self.stdout.flush().unwrap();
    }

    pub fn init(&mut self) {
        write!(self.stdout, "{}", termion::clear::All).unwrap();
        write!(self.stdout, "{}", cursor::Up(self.size.1)).unwrap();
        self.stdout.flush().unwrap();
    }

    pub fn update(&mut self, core: &mut Core) {
        // TODO: check if terminal size changed. If so, send a `render_line` command to the backend,
        // and a `scroll` command for future updates.
        if let Ok(msg) = core.update_rx.try_recv() {
            let msg_list = msg.as_array().unwrap();
            let (method, params) = (msg_list[0].as_str().unwrap(),
                                    msg_list[1].as_object().unwrap());
            if method == "update" {
                let update = Update::from_value(params.get("update").unwrap());
                core.update(&update);

                let view = core.view();
                self.draw(&view);
            } else if method == "scroll_to" {
                let (col, line) = (params.get("col").unwrap().as_u64().unwrap(),
                                   params.get("line").unwrap().as_u64().unwrap());
                self.scroll(col, line);
            } else if method == "set_style" {
                // TODO: ???
            } else {
                info!("Unknown request from backend {:?}", method);
            }
        } else {
            thread::sleep(time::Duration::from_millis(10));
        }
    }
}
<|endoftext|>


<commit_before>//! Write benchmark information to the output repository

use errors::{Result, ResultExt};

use std::fs::{self, read_dir, File, OpenOptions};
use std::io::{BufRead, BufReader, Read, Write};
use std::path::PathBuf;
use std::process::Command;
use std::str;
use std::collections::HashSet;

use serde_json;
use collector::CommitData;
use rust_sysroot::git::Commit as GitCommit;
use execute::Benchmark;

pub struct Repo {
    path: PathBuf,
    use_remote: bool,
    retries: Vec<String>,
}

impl Repo {
    fn git(&self, args: &[&str]) -> Result<()> {
        let mut command = Command::new("git");
        command.current_dir(&self.path);
        info!("git {:?}", args);
        command.args(args);
        let status = command
            .status()
            .chain_err(|| format!("could not spawn git {:?}", args))?;
        if !status.success() {
            bail!(
                "command `git {:?}` failed in `{}`",
                args,
                self.path.display()
            );
        }
        Ok(())
    }

    pub fn open(path: PathBuf, use_remote: bool) -> Result<Self> {
        let mut result = Repo {
            path: path,
            use_remote,
            retries: vec![],
        };

        if !result.retries_file().exists() {
            // try not to nuke random repositories.
            bail!("`{}` file not present", result.retries_file().display());
        }

        if result.use_remote {
            result.git(&["fetch"])?;
            result.git(&["reset", "--hard", "@{upstream}"])?;
        }

        fs::create_dir_all(result.times()).chain_err(|| "can't create `times/`")?;
        result.load_retries()?;

        Ok(result)
    }

    pub fn success(&self, data: &CommitData) -> Result<()> {
        self.add_commit_data(data)?;
        self.commit_and_push(&format!("{} - success", data.commit.sha))?;
        Ok(())
    }

    pub fn find_missing_commits<'a>(
        &self,
        commits: &'a [GitCommit],
        benchmarks: &[Benchmark],
        triple: &str,
    ) -> Result<Vec<&'a GitCommit>> {
        let mut have = HashSet::new();
        let path = self.times();
        for entry in read_dir(path)? {
            let entry = entry?;
            let filename = entry.file_name().to_string_lossy().to_string();
            let sha =
                &filename[filename.find("00:00").unwrap() + 6..filename.find("-x86").unwrap()];
            have.insert(sha.to_string());
        }

        if let Ok(file) = File::open(self.broken_commits_file()) {
            let file = BufReader::new(file);
            for line in file.lines() {
                let line = line?;
                let sha = &line[..line.find(":").unwrap()];
                have.insert(sha.to_string());
            }
        }

        let missing = commits
            .iter()
            .filter(|c| {
                !have.contains(&c.sha) || {
                    self.load_commit_data(c, triple)
                        .ok()
                        .map(|data| {
                            benchmarks
                                .iter()
                                .any(|b| data.benchmarks.keys().find(|k| **k == b.name).is_none())
                        })
                        .unwrap_or(true)
                }
            })
            .collect::<Vec<_>>();

        Ok(missing)
    }

    fn commit_and_push(&self, message: &str) -> Result<()> {
        self.write_retries()?;
        self.git(&["add", "retries", "times"])?;
        if let Ok(_) = self.git(&["diff-index", "--quiet", "--cached", "HEAD"]) {
            self.git(&["commit", "-m", message])?;
            if self.use_remote {
                self.git(&["push"])?;
            }
        } else {
            println!("nothing to commit...");
        }
        Ok(())
    }

    pub fn load_commit_data(&self, commit: &GitCommit, triple: &str) -> Result<CommitData> {
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date.to_rfc3339(),
            commit.sha,
            triple
        ));
        info!("loading file {}", filepath.display());
        let mut file = File::open(&filepath)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        let data = serde_json::from_str(&contents)?;
        Ok(data)
    }

    pub fn add_commit_data(&self, data: &CommitData) -> Result<()> {
        let commit = &data.commit;
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date,
            commit.sha,
            data.triple
        ));
        info!("creating file {}", filepath.display());
        let mut file = File::create(&filepath)?;
        serde_json::to_writer(&mut file, &data)?;
        Ok(())
    }

    fn load_retries(&mut self) -> Result<()> {
        let mut retries = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(self.retries_file())
            .chain_err(|| {
                format!("can't create `{}`", self.retries_file().display())
            })?;
        let mut retries_s = String::new();
        retries.read_to_string(&mut retries_s)?;
        self.retries = retries_s
            .split('\n')
            .map(|line| line.trim())
            .filter(|line| !line.is_empty())
            .map(|line| if line.len() == 40 {
                Ok(line.to_owned())
            } else {
                bail!("bad retry hash `{}`", line)
            })
            .collect::<Result<_>>()?;
        info!("loaded retries: {:?}", self.retries);
        Ok(())
    }

    fn write_retries(&self) -> Result<()> {
        info!("writing retries");
        let mut retries = OpenOptions::new()
            .write(true)
            .truncate(true)
            .open(self.retries_file())
            .chain_err(|| "can't create `retries`")?;
        for retry in self.retries.iter() {
            writeln!(retries, "{}", retry)?;
        }
        Ok(())
    }

    pub fn next_retry(&mut self) -> Option<String> {
        if self.retries.len() == 0 {
            None
        } else {
            Some(self.retries.remove(0))
        }
    }

    fn broken_commits_file(&self) -> PathBuf {
        self.path.join("broken-commits-log")
    }

    fn retries_file(&self) -> PathBuf {
        self.path.join("retries")
    }

    pub fn times(&self) -> PathBuf {
        self.path.join("times")
    }
}
<commit_msg>Error return code is when index is dirty.<commit_after>//! Write benchmark information to the output repository

use errors::{Result, ResultExt};

use std::fs::{self, read_dir, File, OpenOptions};
use std::io::{BufRead, BufReader, Read, Write};
use std::path::PathBuf;
use std::process::Command;
use std::str;
use std::collections::HashSet;

use serde_json;
use collector::CommitData;
use rust_sysroot::git::Commit as GitCommit;
use execute::Benchmark;

pub struct Repo {
    path: PathBuf,
    use_remote: bool,
    retries: Vec<String>,
}

impl Repo {
    fn git(&self, args: &[&str]) -> Result<()> {
        let mut command = Command::new("git");
        command.current_dir(&self.path);
        info!("git {:?}", args);
        command.args(args);
        let status = command
            .status()
            .chain_err(|| format!("could not spawn git {:?}", args))?;
        if !status.success() {
            bail!(
                "command `git {:?}` failed in `{}`",
                args,
                self.path.display()
            );
        }
        Ok(())
    }

    pub fn open(path: PathBuf, use_remote: bool) -> Result<Self> {
        let mut result = Repo {
            path: path,
            use_remote,
            retries: vec![],
        };

        if !result.retries_file().exists() {
            // try not to nuke random repositories.
            bail!("`{}` file not present", result.retries_file().display());
        }

        if result.use_remote {
            result.git(&["fetch"])?;
            result.git(&["reset", "--hard", "@{upstream}"])?;
        }

        fs::create_dir_all(result.times()).chain_err(|| "can't create `times/`")?;
        result.load_retries()?;

        Ok(result)
    }

    pub fn success(&self, data: &CommitData) -> Result<()> {
        self.add_commit_data(data)?;
        self.commit_and_push(&format!("{} - success", data.commit.sha))?;
        Ok(())
    }

    pub fn find_missing_commits<'a>(
        &self,
        commits: &'a [GitCommit],
        benchmarks: &[Benchmark],
        triple: &str,
    ) -> Result<Vec<&'a GitCommit>> {
        let mut have = HashSet::new();
        let path = self.times();
        for entry in read_dir(path)? {
            let entry = entry?;
            let filename = entry.file_name().to_string_lossy().to_string();
            let sha =
                &filename[filename.find("00:00").unwrap() + 6..filename.find("-x86").unwrap()];
            have.insert(sha.to_string());
        }

        if let Ok(file) = File::open(self.broken_commits_file()) {
            let file = BufReader::new(file);
            for line in file.lines() {
                let line = line?;
                let sha = &line[..line.find(":").unwrap()];
                have.insert(sha.to_string());
            }
        }

        let missing = commits
            .iter()
            .filter(|c| {
                !have.contains(&c.sha) || {
                    self.load_commit_data(c, triple)
                        .ok()
                        .map(|data| {
                            benchmarks
                                .iter()
                                .any(|b| data.benchmarks.keys().find(|k| **k == b.name).is_none())
                        })
                        .unwrap_or(true)
                }
            })
            .collect::<Vec<_>>();

        Ok(missing)
    }

    fn commit_and_push(&self, message: &str) -> Result<()> {
        self.write_retries()?;
        self.git(&["add", "retries", "times"])?;

        // dirty index
        if let Err(_) = self.git(&["diff-index", "--quiet", "--cached", "HEAD"]) {
            self.git(&["commit", "-m", message])?;
            if self.use_remote {
                self.git(&["push"])?;
            }
        } else {
            println!("nothing to commit...");
        }
        Ok(())
    }

    pub fn load_commit_data(&self, commit: &GitCommit, triple: &str) -> Result<CommitData> {
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date.to_rfc3339(),
            commit.sha,
            triple
        ));
        info!("loading file {}", filepath.display());
        let mut file = File::open(&filepath)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        let data = serde_json::from_str(&contents)?;
        Ok(data)
    }

    pub fn add_commit_data(&self, data: &CommitData) -> Result<()> {
        let commit = &data.commit;
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date,
            commit.sha,
            data.triple
        ));
        info!("creating file {}", filepath.display());
        let mut file = File::create(&filepath)?;
        serde_json::to_writer(&mut file, &data)?;
        Ok(())
    }

    fn load_retries(&mut self) -> Result<()> {
        let mut retries = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(self.retries_file())
            .chain_err(|| {
                format!("can't create `{}`", self.retries_file().display())
            })?;
        let mut retries_s = String::new();
        retries.read_to_string(&mut retries_s)?;
        self.retries = retries_s
            .split('\n')
            .map(|line| line.trim())
            .filter(|line| !line.is_empty())
            .map(|line| if line.len() == 40 {
                Ok(line.to_owned())
            } else {
                bail!("bad retry hash `{}`", line)
            })
            .collect::<Result<_>>()?;
        info!("loaded retries: {:?}", self.retries);
        Ok(())
    }

    fn write_retries(&self) -> Result<()> {
        info!("writing retries");
        let mut retries = OpenOptions::new()
            .write(true)
            .truncate(true)
            .open(self.retries_file())
            .chain_err(|| "can't create `retries`")?;
        for retry in self.retries.iter() {
            writeln!(retries, "{}", retry)?;
        }
        Ok(())
    }

    pub fn next_retry(&mut self) -> Option<String> {
        if self.retries.len() == 0 {
            None
        } else {
            Some(self.retries.remove(0))
        }
    }

    fn broken_commits_file(&self) -> PathBuf {
        self.path.join("broken-commits-log")
    }

    fn retries_file(&self) -> PathBuf {
        self.path.join("retries")
    }

    pub fn times(&self) -> PathBuf {
        self.path.join("times")
    }
}
<|endoftext|>


<commit_before>//! Licensed under the Apache License, Version 2.0
//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license
//! http://opensource.org/licenses/MIT, at your
//! option. This file may not be copied, modified, or distributed
//! except according to those terms.

use std::num::Saturating;

/// Alternate elements from two iterators until both
/// are run out
///
/// Iterator element type is `A` if `I: Iterator<A>`
#[deriving(Clone)]
pub struct Interleave<I, J> {
    a: I,
    b: J,
    flag: bool,
}

impl<I, J> Interleave<I, J> {
    ///
    pub fn new(a: I, b: J) -> Interleave<I, J> {
        Interleave{a: a, b: b, flag: false}
    }
}

impl<A, I: Iterator<A>, J: Iterator<A>> Iterator<A> for Interleave<I, J> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        self.flag = !self.flag;
        if self.flag {
            match self.a.next() {
                None => self.b.next(),
                r => r,
            }
        } else {
            match self.b.next() {
                None => self.a.next(),
                r => r,
            }
        }
    }
}

/// Clonable iterator adaptor to map elementwise
/// from `Iterator<A>` to `Iterator<B>`
///
/// Created with `.static_map(..)` on an iterator
///
/// Iterator element type is `B`
pub struct FnMap<A, B, I> {
    map: fn(A) -> B,
    iter: I,
}

impl<A, B, I> FnMap<A, B, I>
{
    pub fn new(iter: I, map: fn(A) -> B) -> FnMap<A, B, I> {
        FnMap{iter: iter, map: map}
    }
}

impl<A, B, I: Iterator<A>> Iterator<B> for FnMap<A, B, I>
{
    #[inline]
    fn next(&mut self) -> Option<B> {
        self.iter.next().map(|a| (self.map)(a))
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

impl<A, B, I: DoubleEndedIterator<A>> DoubleEndedIterator<B>
for FnMap<A, B, I>
{
    #[inline]
    fn next_back(&mut self) -> Option<B> {
        self.iter.next_back().map(|a| (self.map)(a))
    }
}

impl<A, B, I: Clone> Clone for FnMap<A, B, I>
{
    fn clone(&self) -> FnMap<A, B, I> {
        FnMap::new(self.iter.clone(), self.map)
    }
}

/// An iterator adaptor that allows putting back a single
/// item to the front of the iterator.
///
/// Iterator element type is `A`
#[deriving(Clone)]
pub struct PutBack<A, I> {
    top: Option<A>,
    iter: I
}

impl<A, I> PutBack<A, I> {
    /// Iterator element type is `A`
    #[inline]
    pub fn new(it: I) -> PutBack<A, I> {
        PutBack{top: None, iter: it}
    }

    /// Put back a single value to the front of the iterator.
    ///
    /// If a value is already in the put back slot, it is overwritten.
    #[inline]
    pub fn put_back(&mut self, x: A) {
        self.top = Some(x)
    }
}

impl<A, I: Iterator<A>> Iterator<A> for PutBack<A, I> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        match self.top.take() {
            None => self.iter.next(),
            top => top,
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        let (lo, hi) = self.iter.size_hint();
        match self.top {
            Some(_) => (lo.saturating_add(1), hi.and_then(|x| x.checked_add(&1))),
            None => (lo, hi)
        }
    }
}

/// An iterator adaptor that iterates over the cartesian product of
/// the element sets of two iterators `I` and `J`.
///
/// Iterator element type is `(A, B)` if `I: Iterator<A>` and `J: Iterator<B>`
#[deriving(Clone)]
pub struct Product<A, I, J> {
    a: I,
    a_cur: Option<A>,
    b: J,
    b_orig: J,
}

impl<A: Clone, B, I: Iterator<A>, J: Clone + Iterator<B>>
    Product<A, I, J>
{
    /// Create a new cartesian product iterator
    ///
    /// Iterator element type is `(A, B)` if `I: Iterator<A>` and `J: Iterator<B>`
    pub fn new(i: I, j: J) -> Product<A, I, J>
    {
        let mut i = i;
        Product{a_cur: i.next(), a: i, b: j.clone(), b_orig: j}
    }
}

impl<A: Clone, I: Iterator<A>, B, J: Clone + Iterator<B>>
Iterator<(A, B)> for Product<A, I, J>
{
    fn next(&mut self) -> Option<(A, B)>
    {
        let elt_b = match self.b.next() {
            None => {
                self.b = self.b_orig.clone();
                match self.b.next() {
                    None => return None,
                    Some(x) => {
                        self.a_cur = self.a.next();
                        x
                    }
                }
            }
            Some(x) => x
        };
        match self.a_cur {
            None => None,
            Some(ref a) => {
                Some((a.clone(), elt_b))
            }
        }
    }

    fn size_hint(&self) -> (uint, Option<uint>)
    {
        let (a, ah) = self.a.size_hint();
        let (b, bh) = self.b.size_hint();
        let (bo, boh) = self.b_orig.size_hint();

        // Compute a * bo + b for both lower and upper bound
        let low = a.checked_mul(&bo)
                    .and_then(|x| x.checked_add(&b))
                    .unwrap_or(::std::uint::MAX);
        let high = ah.and_then(|x| boh.and_then(|y| x.checked_mul(&y)))
                     .and_then(|x| bh.and_then(|y| x.checked_add(&y)));
        (low, high)
    }
}

<commit_msg>Fix FnMap doc<commit_after>//! Licensed under the Apache License, Version 2.0
//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license
//! http://opensource.org/licenses/MIT, at your
//! option. This file may not be copied, modified, or distributed
//! except according to those terms.

use std::num::Saturating;

/// Alternate elements from two iterators until both
/// are run out
///
/// Iterator element type is `A` if `I: Iterator<A>`
#[deriving(Clone)]
pub struct Interleave<I, J> {
    a: I,
    b: J,
    flag: bool,
}

impl<I, J> Interleave<I, J> {
    ///
    pub fn new(a: I, b: J) -> Interleave<I, J> {
        Interleave{a: a, b: b, flag: false}
    }
}

impl<A, I: Iterator<A>, J: Iterator<A>> Iterator<A> for Interleave<I, J> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        self.flag = !self.flag;
        if self.flag {
            match self.a.next() {
                None => self.b.next(),
                r => r,
            }
        } else {
            match self.b.next() {
                None => self.a.next(),
                r => r,
            }
        }
    }
}

/// Clonable iterator adaptor to map elementwise
/// from `Iterator<A>` to `Iterator<B>`
///
/// Created with `.fn_map(..)` on an iterator
///
/// Iterator element type is `B`
pub struct FnMap<A, B, I> {
    map: fn(A) -> B,
    iter: I,
}

impl<A, B, I> FnMap<A, B, I>
{
    pub fn new(iter: I, map: fn(A) -> B) -> FnMap<A, B, I> {
        FnMap{iter: iter, map: map}
    }
}

impl<A, B, I: Iterator<A>> Iterator<B> for FnMap<A, B, I>
{
    #[inline]
    fn next(&mut self) -> Option<B> {
        self.iter.next().map(|a| (self.map)(a))
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

impl<A, B, I: DoubleEndedIterator<A>> DoubleEndedIterator<B>
for FnMap<A, B, I>
{
    #[inline]
    fn next_back(&mut self) -> Option<B> {
        self.iter.next_back().map(|a| (self.map)(a))
    }
}

impl<A, B, I: Clone> Clone for FnMap<A, B, I>
{
    fn clone(&self) -> FnMap<A, B, I> {
        FnMap::new(self.iter.clone(), self.map)
    }
}

/// An iterator adaptor that allows putting back a single
/// item to the front of the iterator.
///
/// Iterator element type is `A`
#[deriving(Clone)]
pub struct PutBack<A, I> {
    top: Option<A>,
    iter: I
}

impl<A, I> PutBack<A, I> {
    /// Iterator element type is `A`
    #[inline]
    pub fn new(it: I) -> PutBack<A, I> {
        PutBack{top: None, iter: it}
    }

    /// Put back a single value to the front of the iterator.
    ///
    /// If a value is already in the put back slot, it is overwritten.
    #[inline]
    pub fn put_back(&mut self, x: A) {
        self.top = Some(x)
    }
}

impl<A, I: Iterator<A>> Iterator<A> for PutBack<A, I> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        match self.top.take() {
            None => self.iter.next(),
            top => top,
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        let (lo, hi) = self.iter.size_hint();
        match self.top {
            Some(_) => (lo.saturating_add(1), hi.and_then(|x| x.checked_add(&1))),
            None => (lo, hi)
        }
    }
}

/// An iterator adaptor that iterates over the cartesian product of
/// the element sets of two iterators `I` and `J`.
///
/// Iterator element type is `(A, B)` if `I: Iterator<A>` and `J: Iterator<B>`
#[deriving(Clone)]
pub struct Product<A, I, J> {
    a: I,
    a_cur: Option<A>,
    b: J,
    b_orig: J,
}

impl<A: Clone, B, I: Iterator<A>, J: Clone + Iterator<B>>
    Product<A, I, J>
{
    /// Create a new cartesian product iterator
    ///
    /// Iterator element type is `(A, B)` if `I: Iterator<A>` and `J: Iterator<B>`
    pub fn new(i: I, j: J) -> Product<A, I, J>
    {
        let mut i = i;
        Product{a_cur: i.next(), a: i, b: j.clone(), b_orig: j}
    }
}

impl<A: Clone, I: Iterator<A>, B, J: Clone + Iterator<B>>
Iterator<(A, B)> for Product<A, I, J>
{
    fn next(&mut self) -> Option<(A, B)>
    {
        let elt_b = match self.b.next() {
            None => {
                self.b = self.b_orig.clone();
                match self.b.next() {
                    None => return None,
                    Some(x) => {
                        self.a_cur = self.a.next();
                        x
                    }
                }
            }
            Some(x) => x
        };
        match self.a_cur {
            None => None,
            Some(ref a) => {
                Some((a.clone(), elt_b))
            }
        }
    }

    fn size_hint(&self) -> (uint, Option<uint>)
    {
        let (a, ah) = self.a.size_hint();
        let (b, bh) = self.b.size_hint();
        let (bo, boh) = self.b_orig.size_hint();

        // Compute a * bo + b for both lower and upper bound
        let low = a.checked_mul(&bo)
                    .and_then(|x| x.checked_add(&b))
                    .unwrap_or(::std::uint::MAX);
        let high = ah.and_then(|x| boh.and_then(|y| x.checked_mul(&y)))
                     .and_then(|x| bh.and_then(|y| x.checked_add(&y)));
        (low, high)
    }
}

<|endoftext|>


<commit_before>use env_logger;
use std::path::Path;
use lmdb::{EnvBuilder, DbFlags};

// general action that works exactly
// as expected, no issues
pub fn action1() {
    env_logger::init().unwrap();
    debug!("checkpoint 1.A");
    let num : u8 = {
        match get_vec() {
            Ok(val) => {
                let val2 = val[0];
                val2
            },
            Err(_)  => {
                0
            }
        }
    };
    debug!("checkpoint 1.B");
    debug!("num = {}", num);

}

fn get_vec() -> Result<Vec<u8>,()> {
    Ok(vec![1,2,3])
}

pub fn action2() {
    let path = Path::new("lmdb_data");
    let env = Box::new(EnvBuilder::new().open(path, 0o777).unwrap());

    debug!("checkpoint 2.A");
    let num : u8 = {
        let db_handle = env.get_default_db(DbFlags::empty()).unwrap();
        let reader = env.get_reader().unwrap();
        let db_ref = reader.bind(&db_handle);
        match db_ref.get::<Vec<u8>>(&"log/0") {
            Ok(val) => {
                let val2 = val[0];
                val2
            },
            Err(_)  => {
                0
            }
        }
    };
    debug!("checkpoint 2.B");
    println!("num = {}", num);
}
<commit_msg>#! Fix segfault<commit_after>use env_logger;
use std::path::Path;
use lmdb::{EnvBuilder, DbFlags};

// general action that works exactly
// as expected, no issues
pub fn action1() {
    env_logger::init().unwrap();
    debug!("checkpoint 1.A");
    let num : u8 = {
        match get_vec() {
            Ok(val) => {
                let val2 = val[0];
                val2
            },
            Err(_)  => {
                0
            }
        }
    };
    debug!("checkpoint 1.B");
    debug!("num = {}", num);

}

fn get_vec() -> Result<Vec<u8>,()> {
    Ok(vec![1,2,3])
}

pub fn action2() {
    let path = Path::new("lmdb_data");
    let env = Box::new(EnvBuilder::new().open(path, 0o777).unwrap());

    debug!("checkpoint 2.A");
    let num : u8 = {
        let db_handle = env.get_default_db(DbFlags::empty()).unwrap();
        let reader = env.get_reader().unwrap();
        let db_ref = reader.bind(&db_handle);
        match db_ref.get::<&[u8]>(&"log/0") {
            Ok(val) => {
                let val2 = val[0];
                val2
            },
            Err(_)  => {
                0
            }
        }
    };
    debug!("checkpoint 2.B");
    println!("num = {}", num);
}
<|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/. */

use dom::bindings::error::Fallible;
use dom::bindings::error::Error::DataClone;
use dom::bindings::global::GlobalRef;

use js::glue::JS_STRUCTURED_CLONE_VERSION;
use js::jsapi::JSContext;
use js::jsapi::{JS_WriteStructuredClone, JS_ClearPendingException};
use js::jsapi::JS_ReadStructuredClone;
use js::jsval::{JSVal, UndefinedValue};

use libc::size_t;
use std::ptr;

pub struct StructuredCloneData {
    data: *mut u64,
    nbytes: size_t,
}

impl StructuredCloneData {
    pub fn write(cx: *mut JSContext, message: JSVal)
                 -> Fallible<StructuredCloneData> {
        let mut data = ptr::null_mut();
        let mut nbytes = 0;
        let result = unsafe {
            JS_WriteStructuredClone(cx, message, &mut data, &mut nbytes,
                                    ptr::null(), ptr::null_mut())
        };
        if result == 0 {
            unsafe { JS_ClearPendingException(cx); }
            return Err(DataClone);
        }
        Ok(StructuredCloneData {
            data: data,
            nbytes: nbytes,
        })
    }

    pub fn read(self, global: GlobalRef) -> JSVal {
        let mut message = UndefinedValue();
        unsafe {
            assert!(JS_ReadStructuredClone(
                global.get_cx(), self.data as *const u64, self.nbytes,
                JS_STRUCTURED_CLONE_VERSION, &mut message,
                ptr::null(), ptr::null_mut()) != 0);
        }
        message
    }
}
<commit_msg>Document structuredclone.rs.<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/. */

//! This module implements structured cloning, as defined by [HTML]
//! (https://html.spec.whatwg.org/multipage/#safe-passing-of-structured-data).

#![deny(missing_docs)]

use dom::bindings::error::Fallible;
use dom::bindings::error::Error::DataClone;
use dom::bindings::global::GlobalRef;

use js::glue::JS_STRUCTURED_CLONE_VERSION;
use js::jsapi::JSContext;
use js::jsapi::{JS_WriteStructuredClone, JS_ClearPendingException};
use js::jsapi::JS_ReadStructuredClone;
use js::jsval::{JSVal, UndefinedValue};

use libc::size_t;
use std::ptr;

/// A buffer for a structured clone.
pub struct StructuredCloneData {
    data: *mut u64,
    nbytes: size_t,
}

impl StructuredCloneData {
    /// Writes a structured clone. Returns a `DataClone` error if that fails.
    pub fn write(cx: *mut JSContext, message: JSVal)
                 -> Fallible<StructuredCloneData> {
        let mut data = ptr::null_mut();
        let mut nbytes = 0;
        let result = unsafe {
            JS_WriteStructuredClone(cx, message, &mut data, &mut nbytes,
                                    ptr::null(), ptr::null_mut())
        };
        if result == 0 {
            unsafe { JS_ClearPendingException(cx); }
            return Err(DataClone);
        }
        Ok(StructuredCloneData {
            data: data,
            nbytes: nbytes,
        })
    }

    /// Reads a structured clone.
    ///
    /// Panics if `JS_ReadStructuredClone` fails.
    pub fn read(self, global: GlobalRef) -> JSVal {
        let mut message = UndefinedValue();
        unsafe {
            assert!(JS_ReadStructuredClone(
                global.get_cx(), self.data as *const u64, self.nbytes,
                JS_STRUCTURED_CLONE_VERSION, &mut message,
                ptr::null(), ptr::null_mut()) != 0);
        }
        message
    }
}
<|endoftext|>