<commit_before>use crate::cargo::rust_flags;
use crate::config::Config;
use crate::errors::RunError;
use crate::event_log::*;
use crate::statemachine::*;
use nix::errno::Errno;
use nix::sys::signal::Signal;
use nix::sys::wait::*;
use nix::unistd::Pid;
use nix::Error as NixErr;
use procfs::process::Process;
use std::collections::{HashMap, HashSet};
use tracing::{debug, info, trace};

pub fn create_state_machine<'a>(
    test: Pid,
    traces: &'a mut TraceMap,
    config: &'a Config,
    event_log: &'a Option<EventLog>,
) -> (TestState, LinuxData<'a>) {
    let mut data = LinuxData::new(traces, config, event_log);
    data.parent = test;
    (TestState::start_state(), data)
}

pub type UpdateContext = (TestState, TracerAction<ProcessInfo>);

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct ProcessInfo {
    pub(crate) pid: Pid,
    pub(crate) signal: Option<Signal>,
}

impl ProcessInfo {
    fn new(pid: Pid, signal: Option<Signal>) -> Self {
        Self { pid, signal }
    }
}

impl From<Pid> for ProcessInfo {
    fn from(pid: Pid) -> Self {
        ProcessInfo::new(pid, None)
    }
}

impl From<&Pid> for ProcessInfo {
    fn from(pid: &Pid) -> Self {
        ProcessInfo::new(*pid, None)
    }
}

/// Handle to linux process state
pub struct LinuxData<'a> {
    /// Recent results from waitpid to be handled by statemachine
    wait_queue: Vec<WaitStatus>,
    /// Current Pid to process
    current: Pid,
    /// Parent PID of test process
    parent: Pid,
    /// Map of addresses to breakpoints
    breakpoints: HashMap<u64, Breakpoint>,
    /// Instrumentation points in code with associated coverage data
    traces: &'a mut TraceMap,
    /// Program config
    config: &'a Config,
    /// Thread count. Hopefully getting rid of in future
    thread_count: isize,
    /// Optional event log to update as the test progresses
    event_log: &'a Option<EventLog>,
    /// Breakpoint offset
    offset: u64,
}

fn get_offset(pid: Pid, config: &Config) -> u64 {
    if rust_flags(config).contains("dynamic-no-pic") {
        0
    } else if let Ok(proc) = Process::new(pid.as_raw()) {
        if let Ok(maps) = proc.maps() {
            if let Some(first) = maps.first() {
                info!("map: {:?}", first);
                first.address.0
            } else {
                0
            }
        } else {
            0
        }
    } else {
        0
    }
}

impl<'a> StateData for LinuxData<'a> {
    fn start(&mut self) -> Result<Option<TestState>, RunError> {
        match waitpid(self.current, Some(WaitPidFlag::WNOHANG)) {
            Ok(WaitStatus::StillAlive) => Ok(None),
            Ok(sig @ WaitStatus::Stopped(_, Signal::SIGTRAP)) => {
                if let WaitStatus::Stopped(child, _) = sig {
                    self.current = child;
                }
                trace!("Caught inferior transitioning to Initialise state");
                Ok(Some(TestState::Initialise))
            }
            Ok(_) => Err(RunError::TestRuntime(
                "Unexpected signal when starting test".to_string(),
            )),
            Err(e) => Err(RunError::TestRuntime(format!(
                "Error when starting test: {}",
                e
            ))),
        }
    }

    fn init(&mut self) -> Result<TestState, RunError> {
        trace_children(self.current)?;
        let offset = get_offset(self.current, self.config);
        self.offset = offset;
        trace!("Address offset: 0x{:x}", offset);
        for trace in self.traces.all_traces() {
            for addr in &trace.address {
                match Breakpoint::new(self.current, *addr + offset) {
                    Ok(bp) => {
                        let _ = self.breakpoints.insert(*addr + offset, bp);
                    }
                    Err(e) if e == NixErr::Sys(Errno::EIO) => {
                        return Err(RunError::TestRuntime(
                            "ERROR: Tarpaulin cannot find code addresses \
                             check that pie is disabled for your linker. \
                             If linking with gcc try adding -C link-args=-no-pie \
                             to your rust flags"
                                .to_string(),
                        ));
                    }
                    Err(NixErr::UnsupportedOperation) => {
                        debug!("Instrumentation address clash, ignoring 0x{:x}", addr);
                    }
                    Err(_) => {
                        return Err(RunError::TestRuntime(
                            "Failed to instrument test executable".to_string(),
                        ));
                    }
                }
            }
        }

        if continue_exec(self.parent, None).is_ok() {
            trace!("Initialised inferior, transitioning to wait state");
            Ok(TestState::wait_state())
        } else {
            Err(RunError::TestRuntime(
                "Test didn't launch correctly".to_string(),
            ))
        }
    }

    fn wait(&mut self) -> Result<Option<TestState>, RunError> {
        let mut result = Ok(None);
        let mut running = true;
        while running {
            let wait = waitpid(
                Pid::from_raw(-1),
                Some(WaitPidFlag::WNOHANG | WaitPidFlag::__WALL),
            );
            match wait {
                Ok(WaitStatus::StillAlive) => {
                    running = false;
                }
                Ok(WaitStatus::Exited(_, _)) => {
                    self.wait_queue.push(wait.unwrap());
                    result = Ok(Some(TestState::Stopped));
                    running = false;
                }
                Ok(WaitStatus::PtraceEvent(_, _, _)) => {
                    self.wait_queue.push(wait.unwrap());
                    result = Ok(Some(TestState::Stopped));
                    running = false;
                }
                Ok(s) => {
                    self.wait_queue.push(s);
                    result = Ok(Some(TestState::Stopped));
                }
                Err(e) => {
                    running = false;
                    result = Err(RunError::TestRuntime(format!(
                        "An error occurred while waiting for response from test: {}",
                        e
                    )))
                }
            }
        }
        if !self.wait_queue.is_empty() {
            trace!("Result queue is {:?}", self.wait_queue);
        }
        result
    }

    fn stop(&mut self) -> Result<TestState, RunError> {
        let mut actions = Vec::new();
        let mut pcs = HashSet::new();
        let mut result = Ok(TestState::wait_state());
        let pending = self.wait_queue.clone();
        self.wait_queue.clear();
        for status in &pending {
            if let Some(log) = self.event_log.as_ref() {
                let event = TraceEvent::new_from_wait(&status);
                log.push_trace(event);
            }
            let state = match status {
                WaitStatus::PtraceEvent(c, s, e) => match self.handle_ptrace_event(*c, *s, *e) {
                    Ok(s) => Ok(s),
                    Err(e) => Err(RunError::TestRuntime(format!(
                        "Error occurred when handling ptrace event: {}",
                        e
                    ))),
                },
                WaitStatus::Stopped(c, Signal::SIGTRAP) => {
                    self.current = *c;
                    match self.collect_coverage_data(&mut pcs) {
                        Ok(s) => Ok(s),
                        Err(e) => Err(RunError::TestRuntime(format!(
                            "Error when collecting coverage: {}",
                            e
                        ))),
                    }
                }
                WaitStatus::Stopped(child, Signal::SIGSTOP) => Ok((
                    TestState::wait_state(),
                    TracerAction::Continue(child.into()),
                )),
                WaitStatus::Stopped(_, Signal::SIGSEGV) => Err(RunError::TestRuntime(
                    "A segfault occurred while executing tests".to_string(),
                )),
                WaitStatus::Stopped(child, Signal::SIGILL) => {
                    let pc = current_instruction_pointer(*child).unwrap_or_else(|_| 1) - 1;
                    trace!("SIGILL raised. Child program counter is: 0x{:x}", pc);
                    Err(RunError::TestRuntime(format!(
                        "Error running test - SIGILL raised in {}",
                        child
                    )))
                }
                WaitStatus::Stopped(c, s) => {
                    let sig = if self.config.forward_signals {
                        Some(*s)
                    } else {
                        None
                    };
                    let info = ProcessInfo::new(*c, sig);
                    Ok((TestState::wait_state(), TracerAction::TryContinue(info)))
                }
                WaitStatus::Signaled(c, s, f) => {
                    if let Ok(s) = self.handle_signaled(c, s, *f) {
                        Ok(s)
                    } else {
                        Err(RunError::TestRuntime(
                            "Attempting to handle tarpaulin being signaled".to_string(),
                        ))
                    }
                }
                WaitStatus::Exited(child, ec) => {
                    for ref mut value in self.breakpoints.values_mut() {
                        value.thread_killed(*child);
                    }
                    trace!("Exited {:?} parent {:?}", child, self.parent);
                    if child == &self.parent {
                        Ok((TestState::End(*ec), TracerAction::Nothing))
                    } else {
                        // Process may have already been destroyed. This is just incase
                        Ok((
                            TestState::wait_state(),
                            TracerAction::TryContinue(self.parent.into()),
                        ))
                    }
                }
                _ => Err(RunError::TestRuntime(
                    "An unexpected signal has been caught by tarpaulin!".to_string(),
                )),
            };
            match state {
                Ok((TestState::Waiting { .. }, action)) => {
                    actions.push(action);
                }
                Ok((state, action)) => {
                    result = Ok(state);
                    actions.push(action);
                }
                Err(e) => result = Err(e),
            }
        }
        let mut continued = false;
        for a in &actions {
            if let Some(log) = self.event_log.as_ref() {
                let event = TraceEvent::new_from_action(&a);
                log.push_trace(event);
            }
            match a {
                TracerAction::TryContinue(t) => {
                    continued = true;
                    let _ = continue_exec(t.pid, t.signal);
                }
                TracerAction::Continue(t) => {
                    continued = true;
                    continue_exec(t.pid, t.signal)?;
                }
                TracerAction::Step(t) => {
                    continued = true;
                    single_step(t.pid)?;
                }
                TracerAction::Detach(t) => {
                    continued = true;
                    detach_child(t.pid)?;
                }
                _ => {}
            }
        }
        if !continued {
            trace!("No action suggested to continue tracee. Attempting a continue");
            let _ = continue_exec(self.parent, None);
        }
        result
    }
}

impl<'a> LinuxData<'a> {
    pub fn new(
        traces: &'a mut TraceMap,
        config: &'a Config,
        event_log: &'a Option<EventLog>,
    ) -> LinuxData<'a> {
        LinuxData {
            wait_queue: Vec::new(),
            current: Pid::from_raw(0),
            parent: Pid::from_raw(0),
            breakpoints: HashMap::new(),
            traces,
            config,
            event_log,
            thread_count: 0,
            offset: 0,
        }
    }

    fn handle_ptrace_event(
        &mut self,
        child: Pid,
        sig: Signal,
        event: i32,
    ) -> Result<(TestState, TracerAction<ProcessInfo>), RunError> {
        use nix::libc::*;

        if sig == Signal::SIGTRAP {
            match event {
                PTRACE_EVENT_CLONE => match get_event_data(child) {
                    Ok(t) => {
                        trace!("New thread spawned {}", t);
                        self.thread_count += 1;
                        Ok((
                            TestState::wait_state(),
                            TracerAction::Continue(child.into()),
                        ))
                    }
                    Err(e) => {
                        trace!("Error in clone event {:?}", e);
                        Err(RunError::TestRuntime(
                            "Error occurred upon test executable thread creation".to_string(),
                        ))
                    }
                },
                PTRACE_EVENT_FORK | PTRACE_EVENT_VFORK => {
                    trace!("Caught fork event");
                    Ok((
                        TestState::wait_state(),
                        TracerAction::Continue(child.into()),
                    ))
                }
                PTRACE_EVENT_EXEC => {
                    trace!("Child execed other process - detaching ptrace");
                    Ok((TestState::wait_state(), TracerAction::Detach(child.into())))
                }
                PTRACE_EVENT_EXIT => {
                    trace!("Child exiting");
                    self.thread_count -= 1;
                    Ok((
                        TestState::wait_state(),
                        TracerAction::TryContinue(child.into()),
                    ))
                }
                _ => Err(RunError::TestRuntime(format!(
                    "Unrecognised ptrace event {}",
                    event
                ))),
            }
        } else {
            trace!("Unexpected signal with ptrace event {}", event);
            trace!("Signal: {:?}", sig);
            Err(RunError::TestRuntime("Unexpected signal".to_string()))
        }
    }

    fn collect_coverage_data(
        &mut self,
        visited_pcs: &mut HashSet<u64>,
    ) -> Result<UpdateContext, RunError> {
        let mut action = None;
        if let Ok(rip) = current_instruction_pointer(self.current) {
            let rip = (rip - 1) as u64;
            trace!("Hit address 0x{:x}", rip);
            if self.breakpoints.contains_key(&rip) {
                let bp = &mut self.breakpoints.get_mut(&rip).unwrap();
                let updated = if visited_pcs.contains(&rip) {
                    let _ = bp.jump_to(self.current);
                    (true, TracerAction::Continue(self.current.into()))
                } else {
                    let enable = self.config.count;
                    // Don't reenable if multithreaded as can't yet sort out segfault issue
                    if let Ok(x) = bp.process(self.current, enable) {
                        x
                    } else {
                        // So failed to process a breakpoint.. Still continue to avoid
                        // stalling
                        (false, TracerAction::Continue(self.current.into()))
                    }
                };
                if updated.0 {
                    self.traces.increment_hit(rip - self.offset);
                }
                action = Some(updated.1);
            }
        }
        let action = action.unwrap_or_else(|| TracerAction::Continue(self.current.into()));
        Ok((TestState::wait_state(), action))
    }

    fn handle_signaled(
        &mut self,
        pid: &Pid,
        sig: &Signal,
        flag: bool,
    ) -> Result<UpdateContext, RunError> {
        match (sig, flag) {
            (Signal::SIGTRAP, true) => {
                Ok((TestState::wait_state(), TracerAction::Continue(pid.into())))
            }
            _ => Err(RunError::StateMachine("Unexpected stop".to_string())),
        }
    }
}
<commit_msg>Get executable name prepare for new init<commit_after>use crate::cargo::rust_flags;
use crate::config::Config;
use crate::errors::RunError;
use crate::event_log::*;
use crate::statemachine::*;
use nix::errno::Errno;
use nix::sys::signal::Signal;
use nix::sys::wait::*;
use nix::unistd::Pid;
use nix::Error as NixErr;
use procfs::process::Process;
use std::collections::{HashMap, HashSet};
use tracing::{debug, info, trace};

pub fn create_state_machine<'a>(
    test: Pid,
    traces: &'a mut TraceMap,
    config: &'a Config,
    event_log: &'a Option<EventLog>,
) -> (TestState, LinuxData<'a>) {
    let mut data = LinuxData::new(traces, config, event_log);
    data.parent = test;
    (TestState::start_state(), data)
}

pub type UpdateContext = (TestState, TracerAction<ProcessInfo>);

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct ProcessInfo {
    pub(crate) pid: Pid,
    pub(crate) signal: Option<Signal>,
}

impl ProcessInfo {
    fn new(pid: Pid, signal: Option<Signal>) -> Self {
        Self { pid, signal }
    }
}

impl From<Pid> for ProcessInfo {
    fn from(pid: Pid) -> Self {
        ProcessInfo::new(pid, None)
    }
}

impl From<&Pid> for ProcessInfo {
    fn from(pid: &Pid) -> Self {
        ProcessInfo::new(*pid, None)
    }
}

/// Handle to linux process state
pub struct LinuxData<'a> {
    /// Recent results from waitpid to be handled by statemachine
    wait_queue: Vec<WaitStatus>,
    /// Current Pid to process
    current: Pid,
    /// Parent PID of test process
    parent: Pid,
    /// Map of addresses to breakpoints
    breakpoints: HashMap<u64, Breakpoint>,
    /// Instrumentation points in code with associated coverage data
    traces: &'a mut TraceMap,
    /// Program config
    config: &'a Config,
    /// Thread count. Hopefully getting rid of in future
    thread_count: isize,
    /// Optional event log to update as the test progresses
    event_log: &'a Option<EventLog>,
    /// Breakpoint offset
    offset: u64,
}

fn get_offset(pid: Pid, config: &Config) -> u64 {
    if rust_flags(config).contains("dynamic-no-pic") {
        0
    } else if let Ok(proc) = Process::new(pid.as_raw()) {
        if let Ok(maps) = proc.maps() {
            if let Some(first) = maps.first() {
                first.address.0
            } else {
                0
            }
        } else {
            0
        }
    } else {
        0
    }
}

impl<'a> StateData for LinuxData<'a> {
    fn start(&mut self) -> Result<Option<TestState>, RunError> {
        match waitpid(self.current, Some(WaitPidFlag::WNOHANG)) {
            Ok(WaitStatus::StillAlive) => Ok(None),
            Ok(sig @ WaitStatus::Stopped(_, Signal::SIGTRAP)) => {
                if let WaitStatus::Stopped(child, _) = sig {
                    self.current = child;
                }
                trace!("Caught inferior transitioning to Initialise state");
                Ok(Some(TestState::Initialise))
            }
            Ok(_) => Err(RunError::TestRuntime(
                "Unexpected signal when starting test".to_string(),
            )),
            Err(e) => Err(RunError::TestRuntime(format!(
                "Error when starting test: {}",
                e
            ))),
        }
    }

    fn init(&mut self) -> Result<TestState, RunError> {
        self.init_process(self.current)?;

        if continue_exec(self.parent, None).is_ok() {
            trace!("Initialised inferior, transitioning to wait state");
            Ok(TestState::wait_state())
        } else {
            Err(RunError::TestRuntime(
                "Test didn't launch correctly".to_string(),
            ))
        }
    }

    fn wait(&mut self) -> Result<Option<TestState>, RunError> {
        let mut result = Ok(None);
        let mut running = true;
        while running {
            let wait = waitpid(
                Pid::from_raw(-1),
                Some(WaitPidFlag::WNOHANG | WaitPidFlag::__WALL),
            );
            match wait {
                Ok(WaitStatus::StillAlive) => {
                    running = false;
                }
                Ok(WaitStatus::Exited(_, _)) => {
                    self.wait_queue.push(wait.unwrap());
                    result = Ok(Some(TestState::Stopped));
                    running = false;
                }
                Ok(WaitStatus::PtraceEvent(_, _, _)) => {
                    self.wait_queue.push(wait.unwrap());
                    result = Ok(Some(TestState::Stopped));
                    running = false;
                }
                Ok(s) => {
                    self.wait_queue.push(s);
                    result = Ok(Some(TestState::Stopped));
                }
                Err(e) => {
                    running = false;
                    result = Err(RunError::TestRuntime(format!(
                        "An error occurred while waiting for response from test: {}",
                        e
                    )))
                }
            }
        }
        if !self.wait_queue.is_empty() {
            trace!("Result queue is {:?}", self.wait_queue);
        }
        result
    }

    fn stop(&mut self) -> Result<TestState, RunError> {
        let mut actions = Vec::new();
        let mut pcs = HashSet::new();
        let mut result = Ok(TestState::wait_state());
        let pending = self.wait_queue.clone();
        self.wait_queue.clear();
        for status in &pending {
            if let Some(log) = self.event_log.as_ref() {
                let event = TraceEvent::new_from_wait(&status);
                log.push_trace(event);
            }
            let state = match status {
                WaitStatus::PtraceEvent(c, s, e) => match self.handle_ptrace_event(*c, *s, *e) {
                    Ok(s) => Ok(s),
                    Err(e) => Err(RunError::TestRuntime(format!(
                        "Error occurred when handling ptrace event: {}",
                        e
                    ))),
                },
                WaitStatus::Stopped(c, Signal::SIGTRAP) => {
                    self.current = *c;
                    match self.collect_coverage_data(&mut pcs) {
                        Ok(s) => Ok(s),
                        Err(e) => Err(RunError::TestRuntime(format!(
                            "Error when collecting coverage: {}",
                            e
                        ))),
                    }
                }
                WaitStatus::Stopped(child, Signal::SIGSTOP) => Ok((
                    TestState::wait_state(),
                    TracerAction::Continue(child.into()),
                )),
                WaitStatus::Stopped(_, Signal::SIGSEGV) => Err(RunError::TestRuntime(
                    "A segfault occurred while executing tests".to_string(),
                )),
                WaitStatus::Stopped(child, Signal::SIGILL) => {
                    let pc = current_instruction_pointer(*child).unwrap_or_else(|_| 1) - 1;
                    trace!("SIGILL raised. Child program counter is: 0x{:x}", pc);
                    Err(RunError::TestRuntime(format!(
                        "Error running test - SIGILL raised in {}",
                        child
                    )))
                }
                WaitStatus::Stopped(c, s) => {
                    let sig = if self.config.forward_signals {
                        Some(*s)
                    } else {
                        None
                    };
                    let info = ProcessInfo::new(*c, sig);
                    Ok((TestState::wait_state(), TracerAction::TryContinue(info)))
                }
                WaitStatus::Signaled(c, s, f) => {
                    if let Ok(s) = self.handle_signaled(c, s, *f) {
                        Ok(s)
                    } else {
                        Err(RunError::TestRuntime(
                            "Attempting to handle tarpaulin being signaled".to_string(),
                        ))
                    }
                }
                WaitStatus::Exited(child, ec) => {
                    for ref mut value in self.breakpoints.values_mut() {
                        value.thread_killed(*child);
                    }
                    trace!("Exited {:?} parent {:?}", child, self.parent);
                    if child == &self.parent {
                        Ok((TestState::End(*ec), TracerAction::Nothing))
                    } else {
                        // Process may have already been destroyed. This is just incase
                        Ok((
                            TestState::wait_state(),
                            TracerAction::TryContinue(self.parent.into()),
                        ))
                    }
                }
                _ => Err(RunError::TestRuntime(
                    "An unexpected signal has been caught by tarpaulin!".to_string(),
                )),
            };
            match state {
                Ok((TestState::Waiting { .. }, action)) => {
                    actions.push(action);
                }
                Ok((state, action)) => {
                    result = Ok(state);
                    actions.push(action);
                }
                Err(e) => result = Err(e),
            }
        }
        let mut continued = false;
        for a in &actions {
            if let Some(log) = self.event_log.as_ref() {
                let event = TraceEvent::new_from_action(&a);
                log.push_trace(event);
            }
            match a {
                TracerAction::TryContinue(t) => {
                    continued = true;
                    let _ = continue_exec(t.pid, t.signal);
                }
                TracerAction::Continue(t) => {
                    continued = true;
                    continue_exec(t.pid, t.signal)?;
                }
                TracerAction::Step(t) => {
                    continued = true;
                    single_step(t.pid)?;
                }
                TracerAction::Detach(t) => {
                    continued = true;
                    detach_child(t.pid)?;
                }
                _ => {}
            }
        }
        if !continued {
            trace!("No action suggested to continue tracee. Attempting a continue");
            let _ = continue_exec(self.parent, None);
        }
        result
    }
}

impl<'a> LinuxData<'a> {
    pub fn new(
        traces: &'a mut TraceMap,
        config: &'a Config,
        event_log: &'a Option<EventLog>,
    ) -> LinuxData<'a> {
        LinuxData {
            wait_queue: Vec::new(),
            current: Pid::from_raw(0),
            parent: Pid::from_raw(0),
            breakpoints: HashMap::new(),
            traces,
            config,
            event_log,
            thread_count: 0,
            offset: 0,
        }
    }

    fn init_process(&mut self, pid: Pid) -> Result<TracerAction<ProcessInfo>, RunError> {
        trace_children(pid)?;
        let offset = get_offset(pid, self.config);
        self.offset = offset;
        trace!("Address offset: 0x{:x}", offset);
        for trace in self.traces.all_traces() {
            for addr in &trace.address {
                match Breakpoint::new(self.current, *addr + offset) {
                    Ok(bp) => {
                        let _ = self.breakpoints.insert(*addr + offset, bp);
                    }
                    Err(e) if e == NixErr::Sys(Errno::EIO) => {
                        return Err(RunError::TestRuntime(
                            "ERROR: Tarpaulin cannot find code addresses \
                             check that pie is disabled for your linker. \
                             If linking with gcc try adding -C link-args=-no-pie \
                             to your rust flags"
                                .to_string(),
                        ));
                    }
                    Err(NixErr::UnsupportedOperation) => {
                        debug!("Instrumentation address clash, ignoring 0x{:x}", addr);
                    }
                    Err(_) => {
                        return Err(RunError::TestRuntime(
                            "Failed to instrument test executable".to_string(),
                        ));
                    }
                }
            }
        }
        Ok(TracerAction::Continue(pid.into()))
    }

    fn handle_exec(
        &mut self,
        pid: Pid,
    ) -> Result<(TestState, TracerAction<ProcessInfo>), RunError> {
        trace!("Child execed other process");
        if let Ok(proc) = Process::new(pid.into()) {
            info!("{:?}", proc.exe());
        }
        Ok((TestState::wait_state(), TracerAction::Detach(pid.into())))
    }

    fn handle_ptrace_event(
        &mut self,
        child: Pid,
        sig: Signal,
        event: i32,
    ) -> Result<(TestState, TracerAction<ProcessInfo>), RunError> {
        use nix::libc::*;

        if sig == Signal::SIGTRAP {
            match event {
                PTRACE_EVENT_CLONE => match get_event_data(child) {
                    Ok(t) => {
                        trace!("New thread spawned {}", t);
                        self.thread_count += 1;
                        Ok((
                            TestState::wait_state(),
                            TracerAction::Continue(child.into()),
                        ))
                    }
                    Err(e) => {
                        trace!("Error in clone event {:?}", e);
                        Err(RunError::TestRuntime(
                            "Error occurred upon test executable thread creation".to_string(),
                        ))
                    }
                },
                PTRACE_EVENT_FORK | PTRACE_EVENT_VFORK => {
                    trace!("Caught fork event");
                    Ok((
                        TestState::wait_state(),
                        TracerAction::Continue(child.into()),
                    ))
                }
                PTRACE_EVENT_EXEC => self.handle_exec(child),
                PTRACE_EVENT_EXIT => {
                    trace!("Child exiting");
                    self.thread_count -= 1;
                    Ok((
                        TestState::wait_state(),
                        TracerAction::TryContinue(child.into()),
                    ))
                }
                _ => Err(RunError::TestRuntime(format!(
                    "Unrecognised ptrace event {}",
                    event
                ))),
            }
        } else {
            trace!("Unexpected signal with ptrace event {}", event);
            trace!("Signal: {:?}", sig);
            Err(RunError::TestRuntime("Unexpected signal".to_string()))
        }
    }

    fn collect_coverage_data(
        &mut self,
        visited_pcs: &mut HashSet<u64>,
    ) -> Result<UpdateContext, RunError> {
        let mut action = None;
        if let Ok(rip) = current_instruction_pointer(self.current) {
            let rip = (rip - 1) as u64;
            trace!("Hit address 0x{:x}", rip);
            if self.breakpoints.contains_key(&rip) {
                let bp = &mut self.breakpoints.get_mut(&rip).unwrap();
                let updated = if visited_pcs.contains(&rip) {
                    let _ = bp.jump_to(self.current);
                    (true, TracerAction::Continue(self.current.into()))
                } else {
                    let enable = self.config.count;
                    // Don't reenable if multithreaded as can't yet sort out segfault issue
                    if let Ok(x) = bp.process(self.current, enable) {
                        x
                    } else {
                        // So failed to process a breakpoint.. Still continue to avoid
                        // stalling
                        (false, TracerAction::Continue(self.current.into()))
                    }
                };
                if updated.0 {
                    self.traces.increment_hit(rip - self.offset);
                }
                action = Some(updated.1);
            }
        }
        let action = action.unwrap_or_else(|| TracerAction::Continue(self.current.into()));
        Ok((TestState::wait_state(), action))
    }

    fn handle_signaled(
        &mut self,
        pid: &Pid,
        sig: &Signal,
        flag: bool,
    ) -> Result<UpdateContext, RunError> {
        match (sig, flag) {
            (Signal::SIGTRAP, true) => {
                Ok((TestState::wait_state(), TracerAction::Continue(pid.into())))
            }
            _ => Err(RunError::StateMachine("Unexpected stop".to_string())),
        }
    }
}
<|endoftext|>


<commit_before>use codec::CodecTrait;
use codec_pandoc::{decode_pandoc, encode_node, PandocCodec};
use test_props::{article, proptest::prelude::*, Freedom};
use test_utils::assert_json_eq;

proptest! {
    #[test]
    fn test(input in article(
        Freedom::Min,
        PandocCodec::spec().unsupported_types,
        PandocCodec::spec().unsupported_properties,
    )) {
        let pandoc = encode_node(&input, None).unwrap();
        let output = decode_pandoc(pandoc).unwrap();
        assert_json_eq!(input, output);
    }
}
<commit_msg>test(Pandoc codec): Use RPNG `rpng_content: true` in tests<commit_after>use codec::{CodecTrait, EncodeOptions};
use codec_pandoc::{decode_pandoc, encode_node, PandocCodec};
use test_props::{article, proptest::prelude::*, Freedom};
use test_utils::assert_json_eq;

proptest! {
    #[test]
    fn test(input in article(
        Freedom::Min,
        PandocCodec::spec().unsupported_types,
        PandocCodec::spec().unsupported_properties,
    )) {
        let pandoc = encode_node(&input, Some(EncodeOptions{
            rpng_content: true,
            ..Default::default()
        })).unwrap();
        let output = decode_pandoc(pandoc).unwrap();
        assert_json_eq!(input, output);
    }
}
<|endoftext|>


<commit_before>

// -*- rust -*-
use std;
import std::deque;

#[test]
fn test_simple() {
    let d: deque::t[int] = deque::create[int]();
    assert (d.size() == 0u);
    d.add_front(17);
    d.add_front(42);
    d.add_back(137);
    assert (d.size() == 3u);
    d.add_back(137);
    assert (d.size() == 4u);
    log d.peek_front();
    assert (d.peek_front() == 42);
    log d.peek_back();
    assert (d.peek_back() == 137);
    let i: int = d.pop_front();
    log i;
    assert (i == 42);
    i = d.pop_back();
    log i;
    assert (i == 137);
    i = d.pop_back();
    log i;
    assert (i == 137);
    i = d.pop_back();
    log i;
    assert (i == 17);
    assert (d.size() == 0u);
    d.add_back(3);
    assert (d.size() == 1u);
    d.add_front(2);
    assert (d.size() == 2u);
    d.add_back(4);
    assert (d.size() == 3u);
    d.add_front(1);
    assert (d.size() == 4u);
    log d.get(0);
    log d.get(1);
    log d.get(2);
    log d.get(3);
    assert (d.get(0) == 1);
    assert (d.get(1) == 2);
    assert (d.get(2) == 3);
    assert (d.get(3) == 4);
}

fn test_boxes(a: @int, b: @int, c: @int, d: @int) {
    let deq: deque::t[@int] = deque::create[@int]();
    assert (deq.size() == 0u);
    deq.add_front(a);
    deq.add_front(b);
    deq.add_back(c);
    assert (deq.size() == 3u);
    deq.add_back(d);
    assert (deq.size() == 4u);
    assert (deq.peek_front() == b);
    assert (deq.peek_back() == d);
    assert (deq.pop_front() == b);
    assert (deq.pop_back() == d);
    assert (deq.pop_back() == c);
    assert (deq.pop_back() == a);
    assert (deq.size() == 0u);
    deq.add_back(c);
    assert (deq.size() == 1u);
    deq.add_front(b);
    assert (deq.size() == 2u);
    deq.add_back(d);
    assert (deq.size() == 3u);
    deq.add_front(a);
    assert (deq.size() == 4u);
    assert (deq.get(0) == a);
    assert (deq.get(1) == b);
    assert (deq.get(2) == c);
    assert (deq.get(3) == d);
}

type eqfn[T] = fn(&T, &T) -> bool ;

fn test_parameterized[@T](e: eqfn[T], a: &T, b: &T, c: &T, d: &T) {
    let deq: deque::t[T] = deque::create[T]();
    assert (deq.size() == 0u);
    deq.add_front(a);
    deq.add_front(b);
    deq.add_back(c);
    assert (deq.size() == 3u);
    deq.add_back(d);
    assert (deq.size() == 4u);
    assert (e(deq.peek_front(), b));
    assert (e(deq.peek_back(), d));
    assert (e(deq.pop_front(), b));
    assert (e(deq.pop_back(), d));
    assert (e(deq.pop_back(), c));
    assert (e(deq.pop_back(), a));
    assert (deq.size() == 0u);
    deq.add_back(c);
    assert (deq.size() == 1u);
    deq.add_front(b);
    assert (deq.size() == 2u);
    deq.add_back(d);
    assert (deq.size() == 3u);
    deq.add_front(a);
    assert (deq.size() == 4u);
    assert (e(deq.get(0), a));
    assert (e(deq.get(1), b));
    assert (e(deq.get(2), c));
    assert (e(deq.get(3), d));
}

tag taggy { one(int); two(int, int); three(int, int, int); }

tag taggypar[@T] { onepar(int); twopar(int, int); threepar(int, int, int); }

type reccy = {x: int, y: int, t: taggy};

#[test]
fn test() {
    fn inteq(a: &int, b: &int) -> bool { ret a == b; }
    fn intboxeq(a: &@int, b: &@int) -> bool { ret a == b; }
    fn taggyeq(a: &taggy, b: &taggy) -> bool {
        alt a {
          one(a1) { alt b { one(b1) { ret a1 == b1; } _ { ret false; } } }
          two(a1, a2) {
            alt b {
              two(b1, b2) { ret a1 == b1 && a2 == b2; }
              _ { ret false; }
            }
          }
          three(a1, a2, a3) {
            alt b {
              three(b1, b2, b3) { ret a1 == b1 && a2 == b2 && a3 == b3; }
              _ { ret false; }
            }
          }
        }
    }
    fn taggypareq[@T](a: &taggypar[T], b: &taggypar[T]) -> bool {
        alt a {
          onepar[T](a1) {
            alt b { onepar[T](b1) { ret a1 == b1; } _ { ret false; } }
          }
          twopar[T](a1, a2) {
            alt b {
              twopar[T](b1, b2) { ret a1 == b1 && a2 == b2; }
              _ { ret false; }
            }
          }
          threepar[T](a1, a2, a3) {
            alt b {
              threepar[T](b1, b2, b3) {
                ret a1 == b1 && a2 == b2 && a3 == b3;
              }
              _ { ret false; }
            }
          }
        }
    }
    fn reccyeq(a: &reccy, b: &reccy) -> bool {
        ret a.x == b.x && a.y == b.y && taggyeq(a.t, b.t);
    }
    log "*** test boxes";
    test_boxes(@5, @72, @64, @175);
    log "*** end test boxes";
    log "test parameterized: int";
    let eq1: eqfn[int] = inteq;
    test_parameterized[int](eq1, 5, 72, 64, 175);
    log "*** test parameterized: @int";
    let eq2: eqfn[@int] = intboxeq;
    test_parameterized[@int](eq2, @5, @72, @64, @175);
    log "*** end test parameterized @int";
    log "test parameterized: taggy";
    let eq3: eqfn[taggy] = taggyeq;
    test_parameterized[taggy](eq3, one(1), two(1, 2), three(1, 2, 3),
                              two(17, 42));
    /*
     * FIXME: Segfault.  Also appears to be caused only after upcall_grow_task

    log "*** test parameterized: taggypar[int]";
    let eqfn[taggypar[int]] eq4 = taggypareq[int];
    test_parameterized[taggypar[int]](eq4,
                                      onepar[int](1),
                                      twopar[int](1, 2),
                                      threepar[int](1, 2, 3),
                                      twopar[int](17, 42));
    log "*** end test parameterized: taggypar[int]";

     */

    log "*** test parameterized: reccy";
    let reccy1: reccy = {x: 1, y: 2, t: one(1)};
    let reccy2: reccy = {x: 345, y: 2, t: two(1, 2)};
    let reccy3: reccy = {x: 1, y: 777, t: three(1, 2, 3)};
    let reccy4: reccy = {x: 19, y: 252, t: two(17, 42)};
    let eq5: eqfn[reccy] = reccyeq;
    test_parameterized[reccy](eq5, reccy1, reccy2, reccy3, reccy4);
    log "*** end test parameterized: reccy";
    log "*** done";
}<commit_msg>Remove an obsolete FIXME in stdtest/deque.rs. Closes #140.<commit_after>

// -*- rust -*-
use std;
import std::deque;

#[test]
fn test_simple() {
    let d: deque::t[int] = deque::create[int]();
    assert (d.size() == 0u);
    d.add_front(17);
    d.add_front(42);
    d.add_back(137);
    assert (d.size() == 3u);
    d.add_back(137);
    assert (d.size() == 4u);
    log d.peek_front();
    assert (d.peek_front() == 42);
    log d.peek_back();
    assert (d.peek_back() == 137);
    let i: int = d.pop_front();
    log i;
    assert (i == 42);
    i = d.pop_back();
    log i;
    assert (i == 137);
    i = d.pop_back();
    log i;
    assert (i == 137);
    i = d.pop_back();
    log i;
    assert (i == 17);
    assert (d.size() == 0u);
    d.add_back(3);
    assert (d.size() == 1u);
    d.add_front(2);
    assert (d.size() == 2u);
    d.add_back(4);
    assert (d.size() == 3u);
    d.add_front(1);
    assert (d.size() == 4u);
    log d.get(0);
    log d.get(1);
    log d.get(2);
    log d.get(3);
    assert (d.get(0) == 1);
    assert (d.get(1) == 2);
    assert (d.get(2) == 3);
    assert (d.get(3) == 4);
}

fn test_boxes(a: @int, b: @int, c: @int, d: @int) {
    let deq: deque::t[@int] = deque::create[@int]();
    assert (deq.size() == 0u);
    deq.add_front(a);
    deq.add_front(b);
    deq.add_back(c);
    assert (deq.size() == 3u);
    deq.add_back(d);
    assert (deq.size() == 4u);
    assert (deq.peek_front() == b);
    assert (deq.peek_back() == d);
    assert (deq.pop_front() == b);
    assert (deq.pop_back() == d);
    assert (deq.pop_back() == c);
    assert (deq.pop_back() == a);
    assert (deq.size() == 0u);
    deq.add_back(c);
    assert (deq.size() == 1u);
    deq.add_front(b);
    assert (deq.size() == 2u);
    deq.add_back(d);
    assert (deq.size() == 3u);
    deq.add_front(a);
    assert (deq.size() == 4u);
    assert (deq.get(0) == a);
    assert (deq.get(1) == b);
    assert (deq.get(2) == c);
    assert (deq.get(3) == d);
}

type eqfn[T] = fn(&T, &T) -> bool ;

fn test_parameterized[@T](e: eqfn[T], a: &T, b: &T, c: &T, d: &T) {
    let deq: deque::t[T] = deque::create[T]();
    assert (deq.size() == 0u);
    deq.add_front(a);
    deq.add_front(b);
    deq.add_back(c);
    assert (deq.size() == 3u);
    deq.add_back(d);
    assert (deq.size() == 4u);
    assert (e(deq.peek_front(), b));
    assert (e(deq.peek_back(), d));
    assert (e(deq.pop_front(), b));
    assert (e(deq.pop_back(), d));
    assert (e(deq.pop_back(), c));
    assert (e(deq.pop_back(), a));
    assert (deq.size() == 0u);
    deq.add_back(c);
    assert (deq.size() == 1u);
    deq.add_front(b);
    assert (deq.size() == 2u);
    deq.add_back(d);
    assert (deq.size() == 3u);
    deq.add_front(a);
    assert (deq.size() == 4u);
    assert (e(deq.get(0), a));
    assert (e(deq.get(1), b));
    assert (e(deq.get(2), c));
    assert (e(deq.get(3), d));
}

tag taggy { one(int); two(int, int); three(int, int, int); }

tag taggypar[@T] { onepar(int); twopar(int, int); threepar(int, int, int); }

type reccy = {x: int, y: int, t: taggy};

#[test]
fn test() {
    fn inteq(a: &int, b: &int) -> bool { ret a == b; }
    fn intboxeq(a: &@int, b: &@int) -> bool { ret a == b; }
    fn taggyeq(a: &taggy, b: &taggy) -> bool {
        alt a {
          one(a1) { alt b { one(b1) { ret a1 == b1; } _ { ret false; } } }
          two(a1, a2) {
            alt b {
              two(b1, b2) { ret a1 == b1 && a2 == b2; }
              _ { ret false; }
            }
          }
          three(a1, a2, a3) {
            alt b {
              three(b1, b2, b3) { ret a1 == b1 && a2 == b2 && a3 == b3; }
              _ { ret false; }
            }
          }
        }
    }
    fn taggypareq[@T](a: &taggypar[T], b: &taggypar[T]) -> bool {
        alt a {
          onepar[T](a1) {
            alt b { onepar[T](b1) { ret a1 == b1; } _ { ret false; } }
          }
          twopar[T](a1, a2) {
            alt b {
              twopar[T](b1, b2) { ret a1 == b1 && a2 == b2; }
              _ { ret false; }
            }
          }
          threepar[T](a1, a2, a3) {
            alt b {
              threepar[T](b1, b2, b3) {
                ret a1 == b1 && a2 == b2 && a3 == b3;
              }
              _ { ret false; }
            }
          }
        }
    }
    fn reccyeq(a: &reccy, b: &reccy) -> bool {
        ret a.x == b.x && a.y == b.y && taggyeq(a.t, b.t);
    }
    log "*** test boxes";
    test_boxes(@5, @72, @64, @175);
    log "*** end test boxes";
    log "test parameterized: int";
    let eq1: eqfn[int] = inteq;
    test_parameterized[int](eq1, 5, 72, 64, 175);
    log "*** test parameterized: @int";
    let eq2: eqfn[@int] = intboxeq;
    test_parameterized[@int](eq2, @5, @72, @64, @175);
    log "*** end test parameterized @int";
    log "test parameterized: taggy";
    let eq3: eqfn[taggy] = taggyeq;
    test_parameterized[taggy](eq3, one(1), two(1, 2), three(1, 2, 3),
                              two(17, 42));

    log "*** test parameterized: taggypar[int]";
    let eq4: eqfn[taggypar[int]] = taggypareq[int];
    test_parameterized[taggypar[int]](eq4,
                                      onepar[int](1),
                                      twopar[int](1, 2),
                                      threepar[int](1, 2, 3),
                                      twopar[int](17, 42));
    log "*** end test parameterized: taggypar[int]";

    log "*** test parameterized: reccy";
    let reccy1: reccy = {x: 1, y: 2, t: one(1)};
    let reccy2: reccy = {x: 345, y: 2, t: two(1, 2)};
    let reccy3: reccy = {x: 1, y: 777, t: three(1, 2, 3)};
    let reccy4: reccy = {x: 19, y: 252, t: two(17, 42)};
    let eq5: eqfn[reccy] = reccyeq;
    test_parameterized[reccy](eq5, reccy1, reccy2, reccy3, reccy4);
    log "*** end test parameterized: reccy";
    log "*** done";
}
<|endoftext|>


<commit_before>#![crate_type = "lib"]
#![crate_name = "coinaddress"]

//! Functions for validating the base58 hash checksums, including specifically
//! the bitcoin and litecoin addresses.

extern crate num;
extern crate rustc;
extern crate test;

use num::bigint::BigUint;
use num::Zero;
use std::num::{from_uint, from_int};
use rustc::util::sha2::{Sha256, Digest};

#[deriving(PartialEq, Show)]
pub enum ValidationError {
    /// Given address is too short to be valid
    TooShort,
    /// Encoding is not a valid base58
    InvalidEncoding,
    /// Computed hash does not match the embedded one
    HashMismatch,

    // currency specific
    /// This address is not a bitcoin address (testnet or real).
    /// May happen when attempting to validate btc address
    NotBitcoin,
    /// This address is not a litecoin address.
    /// May happen when attempting to validate ltc address
    NotLitecoin,
}

static BASE58_CHARS: &'static str = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

fn decode_base58(bc: &str) -> Option<BigUint> {
    let mut res: BigUint = Zero::zero();
    let b58: BigUint = from_int(58).unwrap();

    for c in bc.chars() {
        match BASE58_CHARS.find(c) {
            None => {
                return None
            },
            Some(x) => {
                res = res * b58 + from_uint(x).unwrap();
            }
        }
    }
    Some(res)
}

fn bigint_to_bytes(n: BigUint) -> Vec<u8> {
    let mut res: Vec<u8> = Vec::new();
    let mut tmp = n;
    let b256: BigUint = from_int(256).unwrap();

    while !tmp.is_zero() {
        res.insert(0, (tmp % b256).to_u8().unwrap());
        tmp = tmp / b256;
    }

    if res.len() == 0 {
        return vec!(0);
    }

    res
}

fn pad_to(v: Vec<u8>, len: uint) -> Vec<u8> {
    let mut tmp: Vec<u8> = v;
    while tmp.len() < len {
        tmp.insert(0, 0)
    }
    tmp
}

fn double_sha256(chunk: &[u8]) -> Vec<u8> {
    let mut hash = Sha256::new();
    hash.input(chunk);
    let mut hash2 = Sha256::new();
    hash2.input(hash.result_bytes().as_slice());
    hash2.result_bytes()
}

/// Validate provided generic base58 hash.
/// Returns the hash version/type if correct and an error otherwise.
pub fn validate_base58_hash(addr: &str) -> Result<uint, ValidationError> {
    if addr.len() == 0 {
        return Err(ValidationError::TooShort);
    }

    let big = match decode_base58(addr) {
        None => return Err(ValidationError::InvalidEncoding),
        Some(x) => x
    };
    let bytes = bigint_to_bytes(big);
    let padded = pad_to(bytes, 25);

    let hash = double_sha256(padded.slice(0, padded.len() - 4));
    let short_hash = hash.slice(0, 4);
    let known = padded.slice(padded.len()-4, padded.len());
    if short_hash.as_slice() == known {
        Ok(padded[0].to_uint().unwrap())
    } else {
        Err(ValidationError::HashMismatch)
    }
}

/// Validate bitcoin address checksum.
/// Returns the hash version/type if correct and an error otherwise.
pub fn validate_btc_address(addr: &str) -> Result<uint, ValidationError> {
    match validate_base58_hash(addr) {
        Ok(0) => Ok(0),      // real address
        Ok(5) => Ok(5),      // script hash
        Ok(111) => Ok(111),  // testnet address
        Ok(_) => Err(ValidationError::NotBitcoin),
        Err(x) => Err(x)
    }
}

/// Validate litecoin address checksum.
/// Returns the hash version/type if correct and an error otherwise.
pub fn validate_ltc_address(addr: &str) -> Result<uint, ValidationError> {
    match validate_base58_hash(addr) {
        Ok(48) => Ok(48),      // real address
        Ok(111) => Ok(111),    // testnet address
        Ok(_) => Err(ValidationError::NotLitecoin),
        Err(x) => Err(x)
    }
}

#[test]
fn test_decoding() {
    use std::num::from_str_radix;

    assert_eq!(decode_base58("1"), from_int(0));
    assert_eq!(decode_base58("1AaZz"), from_int(0x1C8485));
    assert_eq!(decode_base58("AO"), None);
    assert_eq!(decode_base58("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"), from_str_radix("65A16059864A2FDBC7C99A4723A8395BC6F188EBC046B2FF", 16));
}

#[test]
fn test_to_bytes() {
    assert_eq!(bigint_to_bytes(Zero::zero()), vec!(0));
    assert_eq!(bigint_to_bytes(from_int(1).unwrap()), vec!(1));
    assert_eq!(bigint_to_bytes(from_int(256).unwrap()), vec!(1, 0));
}

#[test]
fn test_validate_hash() {
    assert_eq!(validate_base58_hash("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem"), Ok(0));
    assert_eq!(validate_base58_hash("mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn"), Ok(111));
    assert_eq!(validate_base58_hash("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYheX"), Err(ValidationError::HashMismatch));
    assert_eq!(validate_base58_hash("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYh  "), Err(ValidationError::InvalidEncoding));
    assert_eq!(validate_base58_hash("1"), Err(ValidationError::HashMismatch));
    assert_eq!(validate_base58_hash(""), Err(ValidationError::TooShort));
}

#[test]
fn test_validate_btc_address() {
    assert_eq!(validate_btc_address("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem"), Ok(0));
    assert_eq!(validate_btc_address("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX"), Ok(5));
    assert_eq!(validate_btc_address("mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn"), Ok(111));
    assert_eq!(validate_btc_address("LRELGDJyeCPRDXz4Dh1kWorMN9hTBB7CEz"), Err(ValidationError::NotBitcoin));
}

#[test]
fn test_validate_ltc_address() {
    assert_eq!(validate_ltc_address("LRELGDJyeCPRDXz4Dh1kWorMN9hTBB7CEz"), Ok(48));
    assert_eq!(validate_ltc_address("muen9zszN6rVwXaFw48xh6YkdUSjJcfzek"), Ok(111));
    assert_eq!(validate_ltc_address("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem"), Err(ValidationError::NotLitecoin));
}

#[bench]
fn bench_validate_hash(b: &mut test::Bencher) {
    b.iter(|| {
        validate_base58_hash("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem")
    })
}
<commit_msg>Enum is now copyable<commit_after>#![crate_type = "lib"]
#![crate_name = "coinaddress"]

//! Functions for validating the base58 hash checksums, including specifically
//! the bitcoin and litecoin addresses.

extern crate num;
extern crate rustc;
extern crate test;

use num::bigint::BigUint;
use num::Zero;
use std::num::{from_uint, from_int};
use rustc::util::sha2::{Sha256, Digest};

#[deriving(PartialEq, Show, Copy)]
pub enum ValidationError {
    /// Given address is too short to be valid
    TooShort,
    /// Encoding is not a valid base58
    InvalidEncoding,
    /// Computed hash does not match the embedded one
    HashMismatch,

    // currency specific
    /// This address is not a bitcoin address (testnet or real).
    /// May happen when attempting to validate btc address
    NotBitcoin,
    /// This address is not a litecoin address.
    /// May happen when attempting to validate ltc address
    NotLitecoin,
}

static BASE58_CHARS: &'static str = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

fn decode_base58(bc: &str) -> Option<BigUint> {
    let mut res: BigUint = Zero::zero();
    let b58: BigUint = from_int(58).unwrap();

    for c in bc.chars() {
        match BASE58_CHARS.find(c) {
            None => {
                return None
            },
            Some(x) => {
                res = res * b58 + from_uint(x).unwrap();
            }
        }
    }
    Some(res)
}

fn bigint_to_bytes(n: BigUint) -> Vec<u8> {
    let mut res: Vec<u8> = Vec::new();
    let mut tmp = n;
    let b256: BigUint = from_int(256).unwrap();

    while !tmp.is_zero() {
        res.insert(0, (tmp % b256).to_u8().unwrap());
        tmp = tmp / b256;
    }

    if res.len() == 0 {
        return vec!(0);
    }

    res
}

fn pad_to(v: Vec<u8>, len: uint) -> Vec<u8> {
    let mut tmp: Vec<u8> = v;
    while tmp.len() < len {
        tmp.insert(0, 0)
    }
    tmp
}

fn double_sha256(chunk: &[u8]) -> Vec<u8> {
    let mut hash = Sha256::new();
    hash.input(chunk);
    let mut hash2 = Sha256::new();
    hash2.input(hash.result_bytes().as_slice());
    hash2.result_bytes()
}

/// Validate provided generic base58 hash.
/// Returns the hash version/type if correct and an error otherwise.
pub fn validate_base58_hash(addr: &str) -> Result<uint, ValidationError> {
    if addr.len() == 0 {
        return Err(ValidationError::TooShort);
    }

    let big = match decode_base58(addr) {
        None => return Err(ValidationError::InvalidEncoding),
        Some(x) => x
    };
    let bytes = bigint_to_bytes(big);
    let padded = pad_to(bytes, 25);

    let hash = double_sha256(padded.slice(0, padded.len() - 4));
    let short_hash = hash.slice(0, 4);
    let known = padded.slice(padded.len()-4, padded.len());
    if short_hash.as_slice() == known {
        Ok(padded[0].to_uint().unwrap())
    } else {
        Err(ValidationError::HashMismatch)
    }
}

/// Validate bitcoin address checksum.
/// Returns the hash version/type if correct and an error otherwise.
pub fn validate_btc_address(addr: &str) -> Result<uint, ValidationError> {
    match validate_base58_hash(addr) {
        Ok(0) => Ok(0),      // real address
        Ok(5) => Ok(5),      // script hash
        Ok(111) => Ok(111),  // testnet address
        Ok(_) => Err(ValidationError::NotBitcoin),
        Err(x) => Err(x)
    }
}

/// Validate litecoin address checksum.
/// Returns the hash version/type if correct and an error otherwise.
pub fn validate_ltc_address(addr: &str) -> Result<uint, ValidationError> {
    match validate_base58_hash(addr) {
        Ok(48) => Ok(48),      // real address
        Ok(111) => Ok(111),    // testnet address
        Ok(_) => Err(ValidationError::NotLitecoin),
        Err(x) => Err(x)
    }
}

#[test]
fn test_decoding() {
    use std::num::from_str_radix;

    assert_eq!(decode_base58("1"), from_int(0));
    assert_eq!(decode_base58("1AaZz"), from_int(0x1C8485));
    assert_eq!(decode_base58("AO"), None);
    assert_eq!(decode_base58("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"), from_str_radix("65A16059864A2FDBC7C99A4723A8395BC6F188EBC046B2FF", 16));
}

#[test]
fn test_to_bytes() {
    assert_eq!(bigint_to_bytes(Zero::zero()), vec!(0));
    assert_eq!(bigint_to_bytes(from_int(1).unwrap()), vec!(1));
    assert_eq!(bigint_to_bytes(from_int(256).unwrap()), vec!(1, 0));
}

#[test]
fn test_validate_hash() {
    assert_eq!(validate_base58_hash("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem"), Ok(0));
    assert_eq!(validate_base58_hash("mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn"), Ok(111));
    assert_eq!(validate_base58_hash("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYheX"), Err(ValidationError::HashMismatch));
    assert_eq!(validate_base58_hash("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYh  "), Err(ValidationError::InvalidEncoding));
    assert_eq!(validate_base58_hash("1"), Err(ValidationError::HashMismatch));
    assert_eq!(validate_base58_hash(""), Err(ValidationError::TooShort));
}

#[test]
fn test_validate_btc_address() {
    assert_eq!(validate_btc_address("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem"), Ok(0));
    assert_eq!(validate_btc_address("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX"), Ok(5));
    assert_eq!(validate_btc_address("mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn"), Ok(111));
    assert_eq!(validate_btc_address("LRELGDJyeCPRDXz4Dh1kWorMN9hTBB7CEz"), Err(ValidationError::NotBitcoin));
}

#[test]
fn test_validate_ltc_address() {
    assert_eq!(validate_ltc_address("LRELGDJyeCPRDXz4Dh1kWorMN9hTBB7CEz"), Ok(48));
    assert_eq!(validate_ltc_address("muen9zszN6rVwXaFw48xh6YkdUSjJcfzek"), Ok(111));
    assert_eq!(validate_ltc_address("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem"), Err(ValidationError::NotLitecoin));
}

#[bench]
fn bench_validate_hash(b: &mut test::Bencher) {
    b.iter(|| {
        validate_base58_hash("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem")
    })
}
<|endoftext|>


<commit_before>/* includes the generated code from PEG
	- ${PROJECT_DIR}/targetbuild/ruwm-*out/
*/

use config_parser::*;

pub mod config_grammar {
	include!(concat!(env!("OUT_DIR"), "/config_grammar.rs"));
}

#[cfg(test)]
#[test]
fn test_parser() {

  let mut variables = Variables::new();

	match config_grammar::content("bindsym LeftGui+1 workspace 1

bindsym $super+$rand exec 'termite --config $HOME/.config/termite/config'
   bindsym RightGui+2 workspace 2

set $ws0 '0:emp'
bindsym RightGui+3 workspace $ws0
bindsym Hello+3 workspace 5

bindsym $super+$left focus left
bindsym $super+Ctrl focus down
bindsym $super+$up focus up
bindsym $super+$right focus right
bindsym $super+1 workspace $ws0

exec --no-startup-id 'nm-applet'

set $left h

", &mut variables){
		Ok(r) => println!("Parsed as: {:?}", r),
		Err(e) => println!("Parse error: {}", e),
	}
}
<commit_msg>some prototyping of error handling<commit_after>/* includes the generated code from PEG
	- ${PROJECT_DIR}/targetbuild/ruwm-*out/
*/

use config_parser::*;

pub mod config_grammar {
	include!(concat!(env!("OUT_DIR"), "/config_grammar.rs"));
}

#[cfg(test)]
#[test]
fn test_parser() {

  let mut variables = Variables::new();

	match config_grammar::content("bindsym LeftGui+1 workspace 1

bindsym $super+$rand exec 'termite --config $HOME/.config/termite/config'
   bindsym RightGui+2 workspace 2
# This is a comment
set $ws0 '0:emp'
bindsym RightGui+3 workspace $ws0
bindsym Hello+3 workspace 5

bindsym $super+$left focus left
bindsym $super+Ctrl focus down
bindsym $super+$up focus up
bindsym $super+$right focus right
bindsym $super+1 workspace $ws0

exec --no-startup-id 'nm-applet'

set $left h

", &mut variables){
		Ok(r) => println!("Parsed as: {:?}", r),
		Err(e) => println!("Parse error: {}", e),
	}
}
<|endoftext|>


<commit_before>//! Support for creating futures that represent timeouts.
//!
//! This module contains the `Timeout` type which is a future that will resolve
//! at a particular point in the future.

use std::io;
use std::time::{Duration, Instant};

use futures::{Future, Poll, Async};

use reactor::{Remote, Handle};
use reactor::timeout_token::TimeoutToken;

/// A future representing the notification that a timeout has occurred.
///
/// Timeouts are created through the `Timeout::new` or
/// `Timeout::new_at` methods indicating when a timeout should fire at.
/// Note that timeouts are not intended for high resolution timers, but rather
/// they will likely fire some granularity after the exact instant that they're
/// otherwise indicated to fire at.
pub struct Timeout {
    token: TimeoutToken,
    when: Instant,
    handle: Remote,
}

impl Timeout {
    /// Creates a new timeout which will fire at `dur` time into the future.
    ///
    /// This function will return a future that will resolve to the actual
    /// timeout object. The timeout object itself is then a future which will be
    /// set to fire at the specified point in the future.
    pub fn new(dur: Duration, handle: &Handle) -> io::Result<Timeout> {
        Timeout::new_at(Instant::now() + dur, handle)
    }

    /// Creates a new timeout which will fire at the time specified by `at`.
    ///
    /// This function will return a future that will resolve to the actual
    /// timeout object. The timeout object itself is then a future which will be
    /// set to fire at the specified point in the future.
    pub fn new_at(at: Instant, handle: &Handle) -> io::Result<Timeout> {
        Ok(Timeout {
            token: try!(TimeoutToken::new(at, &handle)),
            when: at,
            handle: handle.remote().clone(),
        })
    }
}

impl Future for Timeout {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(), io::Error> {
        // TODO: is this fast enough?
        let now = Instant::now();
        if self.when <= now {
            Ok(Async::Ready(()))
        } else {
            self.token.update_timeout(&self.handle);
            Ok(Async::NotReady)
        }
    }
}

impl Drop for Timeout {
    fn drop(&mut self) {
        self.token.cancel_timeout(&self.handle);
    }
}
<commit_msg>Add a method to reset Timeout.<commit_after>//! Support for creating futures that represent timeouts.
//!
//! This module contains the `Timeout` type which is a future that will resolve
//! at a particular point in the future.

use std::io;
use std::time::{Duration, Instant};

use futures::{Future, Poll, Async};

use reactor::{Remote, Handle};
use reactor::timeout_token::TimeoutToken;

/// A future representing the notification that a timeout has occurred.
///
/// Timeouts are created through the `Timeout::new` or
/// `Timeout::new_at` methods indicating when a timeout should fire at.
/// Note that timeouts are not intended for high resolution timers, but rather
/// they will likely fire some granularity after the exact instant that they're
/// otherwise indicated to fire at.
pub struct Timeout {
    token: TimeoutToken,
    when: Instant,
    handle: Remote,
}

impl Timeout {
    /// Creates a new timeout which will fire at `dur` time into the future.
    ///
    /// This function will return a future that will resolve to the actual
    /// timeout object. The timeout object itself is then a future which will be
    /// set to fire at the specified point in the future.
    pub fn new(dur: Duration, handle: &Handle) -> io::Result<Timeout> {
        Timeout::new_at(Instant::now() + dur, handle)
    }

    /// Creates a new timeout which will fire at the time specified by `at`.
    ///
    /// This function will return a future that will resolve to the actual
    /// timeout object. The timeout object itself is then a future which will be
    /// set to fire at the specified point in the future.
    pub fn new_at(at: Instant, handle: &Handle) -> io::Result<Timeout> {
        Ok(Timeout {
            token: try!(TimeoutToken::new(at, &handle)),
            when: at,
            handle: handle.remote().clone(),
        })
    }

    /// Resets this timeout to an new timeout which will fire at the time
    /// specified by `at`.
    pub fn reset(&mut self, at: Instant) {
        self.when = at;
        self.token.reset_timeout(self.when, &self.handle);
    }
}

impl Future for Timeout {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(), io::Error> {
        // TODO: is this fast enough?
        let now = Instant::now();
        if self.when <= now {
            Ok(Async::Ready(()))
        } else {
            self.token.update_timeout(&self.handle);
            Ok(Async::NotReady)
        }
    }
}

impl Drop for Timeout {
    fn drop(&mut self) {
        self.token.cancel_timeout(&self.handle);
    }
}
<|endoftext|>


<commit_before>use std::collections;
use std::rc;

use protobuf;

use error;
use value;

pub mod descriptor;

pub struct ProtobufValues<'a> {
    descriptors: descriptor::Descriptors,
    name: String,
    context: Context<'a>,
}

struct Context<'a> {
    input: protobuf::CodedInputStream<'a>,
}

impl<'a> ProtobufValues<'a> {
    pub fn new(descriptors: descriptor::Descriptors,
               name: String,
               input: protobuf::CodedInputStream<'a>)
               -> ProtobufValues<'a> {
        ProtobufValues {
            descriptors: descriptors,
            name: name,
            context: Context { input: input },
        }
    }

    fn try_next(&mut self) -> error::Result<value::Value> {
        match self.descriptors.messages_by_name.get(&self.name) {
            Some(message) => {
                self.context.read_message(&self.descriptors,
                                          &message.upgrade().unwrap())
            }
            None => {
                let msg = format!("Message type not found: {}", self.name);
                Err(error::Error::General(msg))
            }
        }
    }
}

impl<'a> Context<'a> {
    fn read_message(&mut self,
                    descriptors: &descriptor::Descriptors,
                    message: &descriptor::MessageDescriptor)
                    -> error::Result<value::Value> {
        let mut result = collections::BTreeMap::new();
        let mut repeateds = collections::HashMap::new();

        while !try!(self.input.eof()) {
            let (field_number, wire_type) = try!(self.input.read_tag_unpack());
            let number = field_number as i32;

            // Only handle known fields for now
            if let Some(field) = message.fields_by_number.get(&number) {
                use protobuf::descriptor::FieldDescriptorProto_Label;
                let field = &field.upgrade().unwrap();
                if field.proto_label ==
                   FieldDescriptorProto_Label::LABEL_REPEATED {
                    let mut values = repeateds.entry(field.name.clone())
                                              .or_insert_with(|| Vec::new());

                    try!(self.read_repeated_field(descriptors,
                                                  field,
                                                  wire_type,
                                                  &mut values));
                } else {
                    let value = try!(self.read_single_field(descriptors,
                                                            field,
                                                            wire_type));
                    result.insert(field.name.clone(), value);
                }
            } else {
                use protobuf::stream::wire_format::WireType;
                match wire_type {
                    WireType::WireTypeStartGroup => {
                        loop {
                            let (_, wire_type) = try!(self.input.read_tag_unpack());
                            if wire_type == WireType::WireTypeEndGroup {
                                break;
                            }
                            try!(self.input.skip_field(wire_type));
                        }
                    },
                    _ => try!(self.input.skip_field(wire_type)),
                }
            }
        }

        for (key, values) in repeateds.into_iter() {
            result.insert(key, value::Value::Sequence(values));
        }

        Ok(value::Value::Map(result))
    }

    fn read_single_field(&mut self,
                         descriptors: &descriptor::Descriptors,
                         field: &descriptor::FieldDescriptor,
                         wire_type: protobuf::stream::wire_format::WireType)
                         -> error::Result<value::Value> {
        use protobuf::descriptor::FieldDescriptorProto_Type::*;
        use protobuf::stream::wire_format::WireType::*;
        use protobuf::rt::unexpected_wire_type;

        let bad_wire_type = || {
            Err(error::Error::from(unexpected_wire_type(wire_type)))
        };

        match field.proto_type {
            TYPE_DOUBLE => {
                match wire_type {
                    WireTypeFixed64 => {
                        Ok(value::Value::F64(try!(self.input.read_double())))
                    }
                    _ => bad_wire_type(),
                }
            }
            TYPE_FLOAT => {
                match wire_type {
                    WireTypeFixed32 => {
                        Ok(value::Value::F32(try!(self.input.read_float())))
                    }
                    _ => bad_wire_type(),
                }
            }
            TYPE_INT64 => {
                match wire_type {
                    WireTypeVarint => {
                        Ok(value::Value::I64(try!(self.input.read_int64())))
                    }
                    _ => bad_wire_type(),
                }
            }
            TYPE_UINT64 => {
                match wire_type {
                    WireTypeVarint => {
                        Ok(value::Value::U64(try!(self.input.read_uint64())))
                    }
                    _ => bad_wire_type(),
                }
            }
            TYPE_INT32 => {
                match wire_type {
                    WireTypeVarint => {
                        Ok(value::Value::I32(try!(self.input.read_int32())))
                    }
                    _ => bad_wire_type(),
                }
            }
            TYPE_FIXED64 => {
                match wire_type {
                    WireTypeFixed64 => {
                        Ok(value::Value::U64(try!(self.input.read_fixed64())))
                    }
                    _ => bad_wire_type(),
                }
            }
            TYPE_FIXED32 => {
                match wire_type {
                    WireTypeFixed32 => {
                        Ok(value::Value::U32(try!(self.input.read_fixed32())))
                    }
                    _ => bad_wire_type(),
                }
            }
            TYPE_BOOL => {
                match wire_type {
                    WireTypeVarint => {
                        Ok(value::Value::Bool(try!(self.input.read_bool())))
                    }
                    _ => bad_wire_type(),
                }
            }
            TYPE_STRING => {
                match wire_type {
                    WireTypeLengthDelimited => {
                        Ok(value::Value::String(try!(self.input.read_string())))
                    }
                    _ => bad_wire_type(),
                }
            }
            TYPE_GROUP => unimplemented!(),
            TYPE_MESSAGE => {
                match wire_type {
                    WireTypeLengthDelimited => unimplemented!(),
                    _ => bad_wire_type(),
                }
            }
            TYPE_BYTES => {
                match wire_type {
                    WireTypeLengthDelimited => unimplemented!(),
                    _ => bad_wire_type(),
                }
            }
            TYPE_UINT32 => {
                match wire_type {
                    WireTypeVarint => {
                        Ok(value::Value::U32(try!(self.input.read_uint32())))
                    }
                    _ => bad_wire_type(),
                }
            }
            TYPE_ENUM => {
                match wire_type {
                    WireTypeVarint => unimplemented!(),
                    _ => bad_wire_type(),
                }
            }
            TYPE_SFIXED32 => {
                match wire_type {
                    WireTypeFixed32 => {
                        Ok(value::Value::I32(try!(self.input.read_sfixed32())))
                    }
                    _ => bad_wire_type(),
                }
            }
            TYPE_SFIXED64 => {
                match wire_type {
                    WireTypeFixed64 => {
                        Ok(value::Value::I64(try!(self.input.read_sfixed64())))
                    }
                    _ => bad_wire_type(),
                }
            }
            TYPE_SINT32 => {
                match wire_type {
                    WireTypeVarint => {
                        Ok(value::Value::I32(try!(self.input.read_sint32())))
                    }
                    _ => bad_wire_type(),
                }
            }
            TYPE_SINT64 => {
                match wire_type {
                    WireTypeVarint => {
                        Ok(value::Value::I64(try!(self.input.read_sint64())))
                    }
                    _ => bad_wire_type(),
                }
            }
        }
    }

    fn read_repeated_field(&mut self,
                           descriptors: &descriptor::Descriptors,
                           field: &descriptor::FieldDescriptor,
                           wire_type: protobuf::stream::wire_format::WireType,
                           values: &mut Vec<value::Value>)
                           -> error::Result<()> {
        Ok(())
    }
}

impl<'a> Iterator for ProtobufValues<'a> {
    type Item = error::Result<value::Value>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.context.input.eof() {
            Ok(false) => Some(self.try_next()),
            Ok(true) => None,
            Err(e) => Some(Err(error::Error::from(e))),
        }
    }
}
<commit_msg>Start working on repeated fields<commit_after>use std::collections;
use std::rc;

use protobuf;

use error;
use value;

pub mod descriptor;

pub struct ProtobufValues<'a> {
    descriptors: descriptor::Descriptors,
    name: String,
    context: Context<'a>,
}

struct Context<'a> {
    input: protobuf::CodedInputStream<'a>,
}

impl<'a> ProtobufValues<'a> {
    pub fn new(descriptors: descriptor::Descriptors,
               name: String,
               input: protobuf::CodedInputStream<'a>)
               -> ProtobufValues<'a> {
        ProtobufValues {
            descriptors: descriptors,
            name: name,
            context: Context { input: input },
        }
    }

    fn try_next(&mut self) -> error::Result<value::Value> {
        match self.descriptors.messages_by_name.get(&self.name) {
            Some(message) => {
                self.context.read_message(&self.descriptors,
                                          &message.upgrade().unwrap())
            }
            None => {
                let msg = format!("Message type not found: {}", self.name);
                Err(error::Error::General(msg))
            }
        }
    }
}

impl<'a> Context<'a> {
    fn read_message(&mut self,
                    descriptors: &descriptor::Descriptors,
                    message: &descriptor::MessageDescriptor)
                    -> error::Result<value::Value> {
        let mut result = collections::BTreeMap::new();
        let mut repeateds = collections::HashMap::new();

        while !try!(self.input.eof()) {
            let (field_number, wire_type) = try!(self.input.read_tag_unpack());
            let number = field_number as i32;

            // Only handle known fields for now
            if let Some(field) = message.fields_by_number.get(&number) {
                use protobuf::descriptor::FieldDescriptorProto_Label::*;

                let field = &field.upgrade().unwrap();
                if field.proto_label == LABEL_REPEATED {
                    let mut values = repeateds.entry(field.name.clone())
                                              .or_insert_with(|| Vec::new());

                    try!(self.read_repeated_field(descriptors,
                                                  field,
                                                  wire_type,
                                                  &mut values));
                } else {
                    let value = try!(self.read_single_field(descriptors,
                                                            field,
                                                            wire_type));
                    result.insert(field.name.clone(), value);
                }
            } else {
                use protobuf::stream::wire_format::WireType;
                match wire_type {
                    WireType::WireTypeStartGroup => {
                        loop {
                            let (_, wire_type) = try!(self.input
                                                          .read_tag_unpack());
                            if wire_type == WireType::WireTypeEndGroup {
                                break;
                            }
                            try!(self.input.skip_field(wire_type));
                        }
                    }
                    _ => try!(self.input.skip_field(wire_type)),
                }
            }
        }

        for (key, values) in repeateds.into_iter() {
            result.insert(key, value::Value::Sequence(values));
        }

        Ok(value::Value::Map(result))
    }

    fn read_single_field(&mut self,
                         descriptors: &descriptor::Descriptors,
                         field: &descriptor::FieldDescriptor,
                         wire_type: protobuf::stream::wire_format::WireType)
                         -> error::Result<value::Value> {
        use protobuf::descriptor::FieldDescriptorProto_Type::*;
        use protobuf::stream::wire_format::WireType::*;
        use protobuf::rt::unexpected_wire_type;
        use value::Value::*;

        macro_rules! wrap {
            ($wire_type:pat => $wrapper:expr, $read:expr) => {
                match wire_type {
                    $wire_type => {
                        Ok($wrapper(try!($read)))
                    }
                    _ => Err(error::Error::from(unexpected_wire_type(wire_type))),
                }
            }
        };

        match field.proto_type {
            TYPE_DOUBLE => {
                wrap!(WireTypeFixed64 => F64, self.input.read_double())
            }
            TYPE_FLOAT => {
                wrap!(WireTypeFixed32 => F32, self.input.read_float())
            }
            TYPE_INT64 => wrap!(WireTypeVarint => I64, self.input.read_int64()),
            TYPE_UINT64 => {
                wrap!(WireTypeVarint => U64, self.input.read_uint64())
            }
            TYPE_INT32 => wrap!(WireTypeVarint => I32, self.input.read_int32()),
            TYPE_FIXED64 => {
                wrap!(WireTypeFixed64 => U64, self.input.read_fixed64())
            }
            TYPE_FIXED32 => {
                wrap!(WireTypeFixed32 => U32, self.input.read_fixed32())
            }
            TYPE_BOOL => wrap!(WireTypeVarint => Bool, self.input.read_bool()),
            TYPE_STRING =>
                wrap!(WireTypeLengthDelimited => String, self.input.read_string()),
            TYPE_GROUP => unimplemented!(),
            TYPE_MESSAGE => {
                match wire_type {
                    WireTypeLengthDelimited => {
                        if let Some(message) =
                               descriptors.messages_by_name
                                          .get(&field.proto_type_name) {
                            let message = message.upgrade().unwrap();
                            let len = try!(self.input.read_raw_varint32());
                            let old_limit = try!(self.input.push_limit(len));
                            let result = try!(self.read_message(descriptors,
                                                                &message));
                            self.input.pop_limit(old_limit);
                            Ok(result)
                        } else {
                            Err(error::Error::General(format!("Missing type in schema: {}", field.proto_type_name)))
                        }
                    }
                    _ => {
                        Err(error::Error::from(unexpected_wire_type(wire_type)))
                    }
                }
            }
            TYPE_BYTES => {
                wrap!(WireTypeLengthDelimited => Bytes, self.input.read_bytes())
            }
            TYPE_UINT32 => {
                wrap!(WireTypeVarint => U32, self.input.read_uint32())
            }
            TYPE_ENUM => {
                match wire_type {
                    WireTypeVarint => unimplemented!(),
                    _ => {
                        Err(error::Error::from(unexpected_wire_type(wire_type)))
                    }
                }
            }
            TYPE_SFIXED32 => {
                wrap!(WireTypeFixed32 => I32, self.input.read_sfixed32())
            }
            TYPE_SFIXED64 => {
                wrap!(WireTypeFixed64 => I64, self.input.read_sfixed64())
            }
            TYPE_SINT32 => {
                wrap!(WireTypeVarint => I32, self.input.read_sint32())
            }
            TYPE_SINT64 => {
                wrap!(WireTypeVarint => I64, self.input.read_sint64())
            }
        }
    }

    fn read_repeated_field(&mut self,
                           descriptors: &descriptor::Descriptors,
                           field: &descriptor::FieldDescriptor,
                           wire_type: protobuf::stream::wire_format::WireType,
                           values: &mut Vec<value::Value>)
                           -> error::Result<()> {
        use protobuf::descriptor::FieldDescriptorProto_Type::*;
        use protobuf::stream::wire_format::WireType::*;
        use protobuf::rt::unexpected_wire_type;
        use value::Value::*;

        let mut i = &mut self.input;

        macro_rules! packable {
            ($wire_type:pat => $wrapper:expr, $read:expr) => {
                packable!($wire_type => 1, $wrapper, $read)
            };
            ($wire_type:pat => $size:expr, $wrapper:expr, $read:expr) => {
                match wire_type {
                    WireTypeLengthDelimited => {
                        let len = try!(i.read_raw_varint32());
                        values.reserve((len / $size) as usize);

                        let old_limit = try!(i.push_limit(len));
                        while !try!(i.eof()) {
                            values.push($wrapper(try!($read)));
                        }
                        i.pop_limit(old_limit);
                    }
                    $wire_type => {
                        values.push($wrapper(try!($read)));
                    }
                    _ => return Err(error::Error::from(unexpected_wire_type(wire_type))),
                }
            }
        };

        macro_rules! scalar {
            ($wire_type:pat => $wrapper:expr, $read:expr) => {
                match wire_type {
                    $wire_type => {
                        values.push($wrapper(try!($read)));
                    }
                    _ => return Err(error::Error::from(unexpected_wire_type(wire_type))),
                }
            }
        };

        match field.proto_type {
            TYPE_DOUBLE => {
                packable!(WireTypeFixed64 => 8, F64, i.read_double())
            }
            TYPE_FLOAT => packable!(WireTypeFixed32 => 4, F32, i.read_float()),
            TYPE_INT64 => packable!(WireTypeVarint => I64, i.read_int64()),
            TYPE_UINT64 => packable!(WireTypeVarint => U64, i.read_uint64()),
            TYPE_INT32 => packable!(WireTypeVarint => I32, i.read_int32()),
            TYPE_FIXED64 => packable!(WireTypeFixed64 => U64, i.read_fixed64()),
            TYPE_FIXED32 => packable!(WireTypeFixed32 => U32, i.read_fixed32()),
            TYPE_BOOL => packable!(WireTypeVarint => Bool, i.read_bool()),
            TYPE_STRING => {
                scalar!(WireTypeLengthDelimited => String, i.read_string())
            }
            TYPE_GROUP => unimplemented!(),
            TYPE_MESSAGE => {
                match wire_type {
                    WireTypeLengthDelimited => unimplemented!(),
                    _ => unimplemented!(),
                }
            }
            TYPE_BYTES => {
                match wire_type {
                    WireTypeLengthDelimited => unimplemented!(),
                    _ => unimplemented!(),
                }
            }
            TYPE_UINT32 => packable!(WireTypeVarint => U32, i.read_uint32()),
            TYPE_ENUM => {
                match wire_type {
                    WireTypeVarint => unimplemented!(),
                    _ => unimplemented!(),
                }
            }
            TYPE_SFIXED32 => {
                packable!(WireTypeFixed32 => 4, I32, i.read_sfixed32())
            }
            TYPE_SFIXED64 => {
                packable!(WireTypeFixed64 => 8, I64, i.read_sfixed64())
            }
            TYPE_SINT32 => packable!(WireTypeVarint => 4, I32, i.read_sint32()),
            TYPE_SINT64 => packable!(WireTypeVarint => 8, I64, i.read_sint64()),
        }

        Ok(())
    }
}

impl<'a> Iterator for ProtobufValues<'a> {
    type Item = error::Result<value::Value>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.context.input.eof() {
            Ok(false) => Some(self.try_next()),
            Ok(true) => None,
            Err(e) => Some(Err(error::Error::from(e))),
        }
    }
}
<|endoftext|>


<commit_before>//! This file tests for the DOC_MARKDOWN lint

#![feature(plugin)]
#![plugin(clippy)]
#![allow(dead_code)]
#![warn(doc_markdown)]

/// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
/// Markdown is _weird_. I mean _really weird_.  This \_ is ok. So is `_`. But not Foo::some_fun
/// which should be reported only once despite being __doubly bad__.
/// Here be ::a::global:path.
/// That's not code ~NotInCodeBlock~.
/// be_sure_we_got_to_the_end_of_it
fn foo_bar() {
}

/// That one tests multiline ticks.
/// ```rust
/// foo_bar FOO_BAR
/// _foo bar_
/// ```
///
/// ~~~rust
/// foo_bar FOO_BAR
/// _foo bar_
/// ~~~
/// be_sure_we_got_to_the_end_of_it
fn multiline_codeblock() {
}

/// This _is a test for
/// multiline
/// emphasis_.
/// be_sure_we_got_to_the_end_of_it
fn test_emphasis() {
}

/// This tests units. See also #835.
/// kiB MiB GiB TiB PiB EiB
/// kib Mib Gib Tib Pib Eib
/// kB MB GB TB PB EB
/// kb Mb Gb Tb Pb Eb
/// 32kiB 32MiB 32GiB 32TiB 32PiB 32EiB
/// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib
/// 32kB 32MB 32GB 32TB 32PB 32EB
/// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb
/// NaN
/// be_sure_we_got_to_the_end_of_it
fn test_units() {
}

/// This test has [a link_with_underscores][chunked-example] inside it. See #823.
/// See also [the issue tracker](https://github.com/Manishearth/rust-clippy/search?q=doc_markdown&type=Issues)
/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
/// It can also be [inline_link2].
///
/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
/// [inline_link]: https://foobar
/// [inline_link2]: https://foobar
/// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and
/// `multiline_ticks` functions.
///
/// expression of the type  `_ <bit_op> m <cmp_op> c` (where `<bit_op>`
/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` ,
/// be_sure_we_got_to_the_end_of_it
fn main() {
    foo_bar();
    multiline_codeblock();
    test_emphasis();
    test_units();
}

/// ## CamelCaseThing
/// Talks about `CamelCaseThing`. Titles should be ignored, see issue #897.
///
/// # CamelCaseThing
///
/// Not a title #897 CamelCaseThing
/// be_sure_we_got_to_the_end_of_it
fn issue897() {
}

/// I am confused by brackets? (`x_y`)
/// I am confused by brackets? (foo `x_y`)
/// I am confused by brackets? (`x_y` foo)
/// be_sure_we_got_to_the_end_of_it
fn issue900() {
}

/// Diesel queries also have a similar problem to [Iterator][iterator], where
/// /// More talking
/// returning them from a function requires exposing the implementation of that
/// function. The [`helper_types`][helper_types] module exists to help with this,
/// but you might want to hide the return type or have it conditionally change.
/// Boxing can achieve both.
///
/// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html
/// [helper_types]: ../helper_types/index.html
/// be_sure_we_got_to_the_end_of_it
fn issue883() {
}

/// `foo_bar
/// baz_quz`
/// [foo
/// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html)
fn multiline() {
}

/** E.g. serialization of an empty list: FooBar
```
That's in a code block: `PackedNode`
```

And BarQuz too.
be_sure_we_got_to_the_end_of_it
*/
fn issue1073() {
}

/** E.g. serialization of an empty list: FooBar
```
That's in a code block: PackedNode
```

And BarQuz too.
be_sure_we_got_to_the_end_of_it
*/
fn issue1073_alt() {
}

/// Test more than three quotes:
/// ````
/// DoNotWarn
/// ```
/// StillDont
/// ````
/// be_sure_we_got_to_the_end_of_it
fn four_quotes() {
}
<commit_msg>Add a new `doc_markdown` test from issue comments<commit_after>//! This file tests for the DOC_MARKDOWN lint

#![feature(plugin)]
#![plugin(clippy)]
#![allow(dead_code)]
#![warn(doc_markdown)]

/// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
/// Markdown is _weird_. I mean _really weird_.  This \_ is ok. So is `_`. But not Foo::some_fun
/// which should be reported only once despite being __doubly bad__.
/// Here be ::a::global:path.
/// That's not code ~NotInCodeBlock~.
/// be_sure_we_got_to_the_end_of_it
fn foo_bar() {
}

/// That one tests multiline ticks.
/// ```rust
/// foo_bar FOO_BAR
/// _foo bar_
/// ```
///
/// ~~~rust
/// foo_bar FOO_BAR
/// _foo bar_
/// ~~~
/// be_sure_we_got_to_the_end_of_it
fn multiline_codeblock() {
}

/// This _is a test for
/// multiline
/// emphasis_.
/// be_sure_we_got_to_the_end_of_it
fn test_emphasis() {
}

/// This tests units. See also #835.
/// kiB MiB GiB TiB PiB EiB
/// kib Mib Gib Tib Pib Eib
/// kB MB GB TB PB EB
/// kb Mb Gb Tb Pb Eb
/// 32kiB 32MiB 32GiB 32TiB 32PiB 32EiB
/// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib
/// 32kB 32MB 32GB 32TB 32PB 32EB
/// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb
/// NaN
/// be_sure_we_got_to_the_end_of_it
fn test_units() {
}

/// This test has [a link_with_underscores][chunked-example] inside it. See #823.
/// See also [the issue tracker](https://github.com/Manishearth/rust-clippy/search?q=doc_markdown&type=Issues)
/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
/// It can also be [inline_link2].
///
/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
/// [inline_link]: https://foobar
/// [inline_link2]: https://foobar
/// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and
/// `multiline_ticks` functions.
///
/// expression of the type  `_ <bit_op> m <cmp_op> c` (where `<bit_op>`
/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` ,
/// be_sure_we_got_to_the_end_of_it
fn main() {
    foo_bar();
    multiline_codeblock();
    test_emphasis();
    test_units();
}

/// ## CamelCaseThing
/// Talks about `CamelCaseThing`. Titles should be ignored, see issue #897.
///
/// # CamelCaseThing
///
/// Not a title #897 CamelCaseThing
/// be_sure_we_got_to_the_end_of_it
fn issue897() {
}

/// I am confused by brackets? (`x_y`)
/// I am confused by brackets? (foo `x_y`)
/// I am confused by brackets? (`x_y` foo)
/// be_sure_we_got_to_the_end_of_it
fn issue900() {
}

/// Diesel queries also have a similar problem to [Iterator][iterator], where
/// /// More talking
/// returning them from a function requires exposing the implementation of that
/// function. The [`helper_types`][helper_types] module exists to help with this,
/// but you might want to hide the return type or have it conditionally change.
/// Boxing can achieve both.
///
/// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html
/// [helper_types]: ../helper_types/index.html
/// be_sure_we_got_to_the_end_of_it
fn issue883() {
}

/// `foo_bar
/// baz_quz`
/// [foo
/// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html)
fn multiline() {
}

/** E.g. serialization of an empty list: FooBar
```
That's in a code block: `PackedNode`
```

And BarQuz too.
be_sure_we_got_to_the_end_of_it
*/
fn issue1073() {
}

/** E.g. serialization of an empty list: FooBar
```
That's in a code block: PackedNode
```

And BarQuz too.
be_sure_we_got_to_the_end_of_it
*/
fn issue1073_alt() {
}

/// Test more than three quotes:
/// ````
/// DoNotWarn
/// ```
/// StillDont
/// ````
/// be_sure_we_got_to_the_end_of_it
fn four_quotes() {
}

/// See [NIST SP 800-56A, revision 2].
///
/// [NIST SP 800-56A, revision 2]:
///     https://github.com/Manishearth/rust-clippy/issues/902#issuecomment-261919419
fn issue_902_comment() {}
<|endoftext|>