<commit_before>use std::{
    collections::{HashMap, HashSet},
    path::{Path, PathBuf},
};

use hir::Crate;
use log::trace;
use petgraph::graph::{EdgeIndex, NodeIndex};
use ra_ap_hir::{self as hir, ModuleSource};
use ra_ap_ide_db::RootDatabase;
use ra_ap_vfs::Vfs;

use crate::graph::{orphans::add_orphan_nodes_to, util, Edge, EdgeKind, Graph, Node};

#[derive(Clone, PartialEq, Debug)]
pub struct Options {
    pub focus_on: Option<String>,
    pub max_depth: Option<usize>,
    pub with_types: bool,
    pub with_orphans: bool,
    pub with_uses: bool,
    pub with_externs: bool,
}

#[derive(Debug)]
pub struct Builder<'a> {
    options: Options,
    db: &'a RootDatabase,
    vfs: &'a Vfs,
    krate: hir::Crate,
    graph: Graph,
    nodes: HashMap<String, NodeIndex>,
    edges: HashMap<(NodeIndex, EdgeKind, NodeIndex), EdgeIndex>,
}

impl<'a> Builder<'a> {
    pub fn new(options: Options, db: &'a RootDatabase, vfs: &'a Vfs, krate: hir::Crate) -> Self {
        let graph = Graph::default();
        let nodes = HashMap::default();
        let edges = HashMap::default();
        Self {
            options,
            db,
            vfs,
            krate,
            graph,
            nodes,
            edges,
        }
    }

    pub fn build(mut self, krate: Crate) -> anyhow::Result<Graph> {
        trace!("Scanning project ...");

        self.process_crate(krate)?;

        Ok(self.graph)
    }

    fn process_crate(&mut self, krate: Crate) -> anyhow::Result<()> {
        let root_module = krate.root_module(self.db);
        let root_module_def = hir::ModuleDef::Module(root_module);

        self.process_owned_module_def(None, root_module_def)?;

        Ok(())
    }

    fn process_owned_module_def(
        &mut self,
        owner: Option<(hir::Module, NodeIndex)>,
        owned_module_def: hir::ModuleDef,
    ) -> anyhow::Result<Option<NodeIndex>> {
        if !self.options.with_types {
            // Check if target is a type (i.e. not a module).
            let is_module = matches!(owned_module_def, hir::ModuleDef::Module(_));

            // If it is a type we bail out:
            if !is_module {
                return Ok(None);
            }
        }

        let (_owner_module, owner_idx) = match owner {
            Some((module, idx)) => (Some(module), Some(idx)),
            None => (None, None),
        };

        let owned_path = util::path(owned_module_def, self.db);

        // Check if we already processed the node:
        let owned_idx = match self.nodes.get(&owned_path) {
            Some(node_idx) => {
                // If we did indeed already process it, then retrieve its index:
                *node_idx
            }
            None => {
                // Otherwise add a node for owned:
                self.add_node(owned_module_def)
            }
        };

        if let Some(owner_idx) = owner_idx {
            self.add_edge(owner_idx, owned_idx, Edge::Owns);
        }

        if let hir::ModuleDef::Module(owned_module) = owned_module_def {
            trace!(
                "Scanning module {:?}",
                util::path(owned_module_def, self.db)
            );

            let mut local_definitions: HashSet<hir::ModuleDef> = HashSet::new();

            for module_sub_def in owned_module.declarations(self.db) {
                local_definitions.insert(module_sub_def);

                self.process_owned_module_def(Some((owned_module, owned_idx)), module_sub_def)?;
            }

            for (_name, scope_def) in owned_module.scope(self.db, None) {
                if let hir::ScopeDef::ModuleDef(scope_module_def) = scope_def {
                    // Skip local child declarations:
                    if local_definitions.contains(&scope_module_def) {
                        continue;
                    }

                    self.process_used_module_def((owned_module, owned_idx), scope_module_def)?;
                }
            }

            if self.options.with_orphans {
                add_orphan_nodes_to(&mut self.graph, owned_idx);
            }
        }

        Ok(Some(owned_idx))
    }

    fn process_used_module_def(
        &mut self,
        user: (hir::Module, NodeIndex),
        used_module_def: hir::ModuleDef,
    ) -> anyhow::Result<Option<NodeIndex>> {
        if !self.options.with_uses {
            return Ok(None);
        }

        let (_user_module, user_idx) = user;

        let mut resolved_module_def = Some(used_module_def);

        if !self.options.with_types {
            // Check if target is a type (i.e. not a module).
            let is_module = matches!(used_module_def, hir::ModuleDef::Module(_));

            // If it is a type we need to resolve to its parent module instead:
            if !is_module {
                let parent_module = used_module_def.module(self.db);
                resolved_module_def = parent_module.map(|m| hir::ModuleDef::Module(m));
            }
        }

        let module_def_krate = util::krate(used_module_def, self.db);

        // Check if target is from an extern crate.
        // If it is we need to resolve to its parent module instead:
        if module_def_krate != Some(self.krate) {
            resolved_module_def = if self.options.with_externs {
                module_def_krate.map(|krate| hir::ModuleDef::Module(krate.root_module(self.db)))
            } else {
                None
            };
        }

        // Depending on the options we might not want to add the target as is,
        // but resolve it to its module or crate, e.g., so we do that here:
        let resolved_module_def = match resolved_module_def {
            Some(resolved_module_def) => resolved_module_def,
            None => return Ok(None),
        };

        let used_path = util::path(resolved_module_def, self.db);

        // Check if we already processed the node:
        let used_idx = match self.nodes.get(&used_path) {
            Some(node_idx) => {
                // If we did indeed already process it, then retrieve its index:
                *node_idx
            }
            None => {
                // Otherwise add a node for target:
                self.add_node(resolved_module_def)
            }
        };

        self.add_edge(user_idx, used_idx, Edge::Uses);

        Ok(Some(used_idx))
    }

    fn add_node(&mut self, module_def: hir::ModuleDef) -> NodeIndex {
        let node_id = util::path(module_def, self.db);

        trace!("Adding module node: {:?}", node_id);

        // Check if we already added an equivalent node:
        match self.nodes.get(&node_id) {
            Some(node_idx) => {
                // If we did indeed already process it, then retrieve its index:
                *node_idx
            }
            None => {
                // Otherwise add a node:
                let node_idx = self.graph.add_node(self.node_weight(module_def));
                self.nodes.insert(node_id, node_idx);

                node_idx
            }
        }
    }

    fn add_edge(&mut self, source_idx: NodeIndex, target_idx: NodeIndex, edge: Edge) -> EdgeIndex {
        let edge_id = (source_idx, edge.kind(), target_idx);

        trace!(
            "Adding edge: {:?} --({:?})-> {:?}",
            edge_id.0,
            edge_id.1,
            edge_id.2
        );

        // Check if we already added an equivalent edge:
        match self.edges.get(&edge_id) {
            Some(edge_idx) => {
                // If we did indeed already process it, then retrieve its index:
                *edge_idx
            }
            None => {
                // Otherwise add an edge:
                let edge_idx = self.graph.add_edge(source_idx, target_idx, edge);
                self.edges.insert(edge_id, edge_idx);

                edge_idx
            }
        }
    }

    fn node_weight(&self, module_def: hir::ModuleDef) -> Node {
        let path = util::path(module_def, self.db);
        let file_path = {
            match module_def {
                hir::ModuleDef::Module(module) => Some(module),
                _ => None,
            }
            .and_then(|module| {
                self.module_file(module.definition_source(self.db))
                    .map(Into::into)
            })
        };

        let hir = Some(module_def);

        Node {
            path,
            file_path,
            hir,
        }
    }

    fn module_file(&self, module_source: hir::InFile<hir::ModuleSource>) -> Option<PathBuf> {
        let is_file_module: bool = match &module_source.value {
            ModuleSource::SourceFile(_) => true,
            ModuleSource::Module(_) => false,
        };

        if !is_file_module {
            return None;
        }

        let file_id = module_source.file_id.original_file(self.db);
        let vfs_path = self.vfs.file_path(file_id);
        let abs_path = vfs_path.as_path().expect("Could not convert to path");

        let path: &Path = &*abs_path;

        let file_extension = path.extension().and_then(|ext| ext.to_str());

        if file_extension != Some("rs") {
            return None;
        }

        Some(path.to_owned())
    }
}
<commit_msg>Simplified logic for adding nodes/edges in builder<commit_after>use std::{
    collections::{HashMap, HashSet},
    path::{Path, PathBuf},
};

use hir::Crate;
use log::trace;
use petgraph::graph::{EdgeIndex, NodeIndex};
use ra_ap_hir::{self as hir, ModuleSource};
use ra_ap_ide_db::RootDatabase;
use ra_ap_vfs::Vfs;

use crate::graph::{orphans::add_orphan_nodes_to, util, Edge, EdgeKind, Graph, Node};

#[derive(Clone, PartialEq, Debug)]
pub struct Options {
    pub focus_on: Option<String>,
    pub max_depth: Option<usize>,
    pub with_types: bool,
    pub with_orphans: bool,
    pub with_uses: bool,
    pub with_externs: bool,
}

#[derive(Debug)]
pub struct Builder<'a> {
    options: Options,
    db: &'a RootDatabase,
    vfs: &'a Vfs,
    krate: hir::Crate,
    graph: Graph,
    nodes: HashMap<String, NodeIndex>,
    edges: HashMap<(NodeIndex, EdgeKind, NodeIndex), EdgeIndex>,
}

impl<'a> Builder<'a> {
    pub fn new(options: Options, db: &'a RootDatabase, vfs: &'a Vfs, krate: hir::Crate) -> Self {
        let graph = Graph::default();
        let nodes = HashMap::default();
        let edges = HashMap::default();
        Self {
            options,
            db,
            vfs,
            krate,
            graph,
            nodes,
            edges,
        }
    }

    pub fn build(mut self, krate: Crate) -> anyhow::Result<Graph> {
        trace!("Scanning project ...");

        self.process_crate(krate)?;

        Ok(self.graph)
    }

    fn process_crate(&mut self, krate: Crate) -> anyhow::Result<()> {
        let root_module = krate.root_module(self.db);
        let root_module_def = hir::ModuleDef::Module(root_module);

        self.process_owned_module_def(None, root_module_def)?;

        Ok(())
    }

    fn process_owned_module_def(
        &mut self,
        owner: Option<(hir::Module, NodeIndex)>,
        owned_module_def: hir::ModuleDef,
    ) -> anyhow::Result<Option<NodeIndex>> {
        if !self.options.with_types {
            // Check if target is a type (i.e. not a module).
            let is_module = matches!(owned_module_def, hir::ModuleDef::Module(_));

            // If it is a type we bail out:
            if !is_module {
                return Ok(None);
            }
        }

        let (_owner_module, owner_idx) = match owner {
            Some((module, idx)) => (Some(module), Some(idx)),
            None => (None, None),
        };

        let owned_idx = self.add_node(owned_module_def);

        if let Some(owner_idx) = owner_idx {
            self.add_edge(owner_idx, owned_idx, Edge::Owns);
        }

        if let hir::ModuleDef::Module(owned_module) = owned_module_def {
            trace!(
                "Scanning module {:?}",
                util::path(owned_module_def, self.db)
            );

            let mut local_definitions: HashSet<hir::ModuleDef> = HashSet::new();

            for module_sub_def in owned_module.declarations(self.db) {
                local_definitions.insert(module_sub_def);

                self.process_owned_module_def(Some((owned_module, owned_idx)), module_sub_def)?;
            }

            for (_name, scope_def) in owned_module.scope(self.db, None) {
                if let hir::ScopeDef::ModuleDef(scope_module_def) = scope_def {
                    // Skip local child declarations:
                    if local_definitions.contains(&scope_module_def) {
                        continue;
                    }

                    self.process_used_module_def((owned_module, owned_idx), scope_module_def)?;
                }
            }

            if self.options.with_orphans {
                add_orphan_nodes_to(&mut self.graph, owned_idx);
            }
        }

        Ok(Some(owned_idx))
    }

    fn process_used_module_def(
        &mut self,
        user: (hir::Module, NodeIndex),
        used_module_def: hir::ModuleDef,
    ) -> anyhow::Result<Option<NodeIndex>> {
        if !self.options.with_uses {
            return Ok(None);
        }

        let (_user_module, user_idx) = user;

        let mut resolved_module_def = Some(used_module_def);

        if !self.options.with_types {
            // Check if target is a type (i.e. not a module).
            let is_module = matches!(used_module_def, hir::ModuleDef::Module(_));

            // If it is a type we need to resolve to its parent module instead:
            if !is_module {
                let parent_module = used_module_def.module(self.db);
                resolved_module_def = parent_module.map(|m| hir::ModuleDef::Module(m));
            }
        }

        let module_def_krate = util::krate(used_module_def, self.db);

        // Check if target is from an extern crate.
        // If it is we need to resolve to its parent module instead:
        if module_def_krate != Some(self.krate) {
            resolved_module_def = if self.options.with_externs {
                module_def_krate.map(|krate| hir::ModuleDef::Module(krate.root_module(self.db)))
            } else {
                None
            };
        }

        // Depending on the options we might not want to add the target as is,
        // but resolve it to its module or crate, e.g., so we do that here:
        let resolved_module_def = match resolved_module_def {
            Some(resolved_module_def) => resolved_module_def,
            None => return Ok(None),
        };

        let used_idx = self.add_node(resolved_module_def);

        self.add_edge(user_idx, used_idx, Edge::Uses);

        Ok(Some(used_idx))
    }

    fn add_node(&mut self, module_def: hir::ModuleDef) -> NodeIndex {
        let node_id = util::path(module_def, self.db);

        trace!("Adding module node: {:?}", node_id);

        // Check if we already added an equivalent node:
        match self.nodes.get(&node_id) {
            Some(node_idx) => {
                // If we did indeed already process it, then retrieve its index:
                *node_idx
            }
            None => {
                // Otherwise add a node:
                let node_idx = self.graph.add_node(self.node_weight(module_def));
                self.nodes.insert(node_id, node_idx);

                node_idx
            }
        }
    }

    fn add_edge(&mut self, source_idx: NodeIndex, target_idx: NodeIndex, edge: Edge) -> EdgeIndex {
        let edge_id = (source_idx, edge.kind(), target_idx);

        trace!(
            "Adding edge: {:?} --({:?})-> {:?}",
            edge_id.0,
            edge_id.1,
            edge_id.2
        );

        // Check if we already added an equivalent edge:
        match self.edges.get(&edge_id) {
            Some(edge_idx) => {
                // If we did indeed already process it, then retrieve its index:
                *edge_idx
            }
            None => {
                // Otherwise add an edge:
                let edge_idx = self.graph.add_edge(source_idx, target_idx, edge);
                self.edges.insert(edge_id, edge_idx);

                edge_idx
            }
        }
    }

    fn node_weight(&self, module_def: hir::ModuleDef) -> Node {
        let path = util::path(module_def, self.db);
        let file_path = {
            match module_def {
                hir::ModuleDef::Module(module) => Some(module),
                _ => None,
            }
            .and_then(|module| {
                self.module_file(module.definition_source(self.db))
                    .map(Into::into)
            })
        };

        let hir = Some(module_def);

        Node {
            path,
            file_path,
            hir,
        }
    }

    fn module_file(&self, module_source: hir::InFile<hir::ModuleSource>) -> Option<PathBuf> {
        let is_file_module: bool = match &module_source.value {
            ModuleSource::SourceFile(_) => true,
            ModuleSource::Module(_) => false,
        };

        if !is_file_module {
            return None;
        }

        let file_id = module_source.file_id.original_file(self.db);
        let vfs_path = self.vfs.file_path(file_id);
        let abs_path = vfs_path.as_path().expect("Could not convert to path");

        let path: &Path = &*abs_path;

        let file_extension = path.extension().and_then(|ext| ext.to_str());

        if file_extension != Some("rs") {
            return None;
        }

        Some(path.to_owned())
    }
}
<|endoftext|>


<commit_before>use std::sync::Mutex;
use message::{BackendServices, PackageId, Notification};
use handler::{Transfers, HandleMessageParams};

#[derive(RustcDecodable)]
pub struct AbortParams {
    pub package: PackageId,
}

impl HandleMessageParams for AbortParams {
    fn handle(&self,
              _: &Mutex<BackendServices>,
              transfers: &Mutex<Transfers>,
              _: &str, _: &str, _: &str) -> bool {
        let mut transfers = transfers.lock().unwrap();

        match transfers.remove(&self.package) {
            Some(..) => {
                info!("Transfer for package {} aborted", self.package);
                true
            },
            None => {
                error!("No transfer for package {}, ignoring abort",
                       self.package);
                false
            }
        }
    }

    fn get_message(&self) -> Option<Notification> { None }
}

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

    use std::sync::Mutex;
    use std::collections::HashMap;

    use handler::HandleMessageParams;
    use persistence::Transfer;

    #[test]
    fn it_removes_existing_transfers() {
        test_init!();

        let services = Mutex::new(get_empty_backend());

        let prefix = PathPrefix::new();
        let mut transfer = Transfer::new_test(&prefix);
        let package = transfer.randomize(10);

        let transfers = Mutex::new(HashMap::new());
        transfers.lock().unwrap().insert(package.clone(), transfer);

        let abort = AbortParams {
            package: package
        };

        assert!(abort.handle(&services, &transfers, "", "", ""));
        assert!(transfers.lock().unwrap().is_empty());
    }

    #[test]
    fn it_doesnt_do_anything_for_nonexistent_transfers() {
        let services = Mutex::new(get_empty_backend());

        let prefix = PathPrefix::new();
        let mut transfer = Transfer::new_test(&prefix);
        let package = transfer.randomize(10);

        let transfers = Mutex::new(HashMap::new());
        transfers.lock().unwrap().insert(package, transfer);

        let abort = AbortParams {
            package: generate_random_package(9)
        };

        assert!(! abort.handle(&services, &transfers, "", "", ""));
        assert!(! transfers.lock().unwrap().is_empty());
    }
}
<commit_msg>Abort stops all transfers<commit_after>use std::sync::Mutex;
use message::{BackendServices, Notification};
use handler::{Transfers, HandleMessageParams};

#[derive(RustcDecodable)]
pub struct AbortParams;

impl HandleMessageParams for AbortParams {
    fn handle(&self,
              _: &Mutex<BackendServices>,
              transfers: &Mutex<Transfers>,
              _: &str, _: &str, _: &str) -> bool {
        let mut transfers = transfers.lock().unwrap();
        transfers.clear();
        true
    }

    fn get_message(&self) -> Option<Notification> { None }
}

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

    use std::sync::Mutex;
    use std::collections::HashMap;

    use handler::HandleMessageParams;
    use persistence::Transfer;

    #[test]
    fn it_removes_a_single_transfer() {
        test_init!();

        let services = Mutex::new(get_empty_backend());

        let prefix = PathPrefix::new();
        let mut transfer = Transfer::new_test(&prefix);
        let package = transfer.randomize(10);

        let transfers = Mutex::new(HashMap::new());
        transfers.lock().unwrap().insert(package.clone(), transfer);

        let abort = AbortParams;
        assert!(abort.handle(&services, &transfers, "", "", ""));
        assert!(transfers.lock().unwrap().is_empty());
    }

    #[test]
    fn it_removes_all_transfers() {
        test_init!();
        let services = Mutex::new(get_empty_backend());
        let prefix = PathPrefix::new();

        let transfers = Mutex::new(HashMap::new());
        for i in 1..20 {
            let mut transfer = Transfer::new_test(&prefix);
            let package = transfer.randomize(i);
            transfers.lock().unwrap().insert(package, transfer);
        }

        let abort = AbortParams;
        assert!(abort.handle(&services, &transfers, "", "", ""));
        assert!(transfers.lock().unwrap().is_empty());
    }
}
<|endoftext|>


<commit_before>extern crate tempdir;

use nix::unistd::*;
use nix::unistd::ForkResult::*;
use nix::sys::wait::*;
use nix::sys::stat;
use std::iter;
use std::ffi::CString;
use std::io::{Write, Read};
use std::os::unix::prelude::*;
use std::env::current_dir;
use tempfile::tempfile;
use tempdir::TempDir;
use libc::off_t;

#[test]
fn test_fork_and_waitpid() {
    let pid = fork();
    match pid {
        Ok(Child) => {} // ignore child here
        Ok(Parent { child }) => {
            // assert that child was created and pid > 0
            assert!(child > 0);
            let wait_status = waitpid(child, None);
            match wait_status {
                // assert that waitpid returned correct status and the pid is the one of the child
                Ok(WaitStatus::Exited(pid_t, _)) =>  assert!(pid_t == child),

                // panic, must never happen
                Ok(_) => panic!("Child still alive, should never happen"),

                // panic, waitpid should never fail
                Err(_) => panic!("Error: waitpid Failed")
            }

        },
        // panic, fork should never fail unless there is a serious problem with the OS
        Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_wait() {
    let pid = fork();
    match pid {
        Ok(Child) => {} // ignore child here
        Ok(Parent { child }) => {
            let wait_status = wait();

            // just assert that (any) one child returns with WaitStatus::Exited
            assert_eq!(wait_status, Ok(WaitStatus::Exited(child, 0)));
        },
        // panic, fork should never fail unless there is a serious problem with the OS
        Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_mkstemp() {
    let result = mkstemp("/tmp/nix_tempfile.XXXXXXXX");
    match result {
        Ok((fd, path)) => {
            close(fd).unwrap();
            unlink(path.as_path()).unwrap();
        }
        Err(e) => panic!("mkstemp failed: {}", e)
    }
}

#[test]
fn test_getpid() {
    let pid = getpid();
    let ppid = getppid();
    assert!(pid > 0);
    assert!(ppid > 0);
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux_android {
    use nix::unistd::gettid;

    #[test]
    fn test_gettid() {
        let tid = gettid();
        assert!(tid > 0);
    }
}

macro_rules! execve_test_factory(
    ($test_name:ident, $syscall:ident, $unix_sh:expr, $android_sh:expr) => (
    #[test]
    fn $test_name() {
        // The `exec`d process will write to `writer`, and we'll read that
        // data from `reader`.
        let (reader, writer) = pipe().unwrap();

        match fork().unwrap() {
            Child => {
                #[cfg(not(target_os = "android"))]
                const SH_PATH: &'static [u8] = $unix_sh;

                #[cfg(target_os = "android")]
                const SH_PATH: &'static [u8] = $android_sh;

                // Close stdout.
                close(1).unwrap();
                // Make `writer` be the stdout of the new process.
                dup(writer).unwrap();
                // exec!
                $syscall(
                    &CString::new(SH_PATH).unwrap(),
                    &[CString::new(b"".as_ref()).unwrap(),
                      CString::new(b"-c".as_ref()).unwrap(),
                      CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
                                   .as_ref()).unwrap()],
                    &[CString::new(b"foo=bar".as_ref()).unwrap(),
                      CString::new(b"baz=quux".as_ref()).unwrap()]).unwrap();
            },
            Parent { child } => {
                // Wait for the child to exit.
                waitpid(child, None).unwrap();
                // Read 1024 bytes.
                let mut buf = [0u8; 1024];
                read(reader, &mut buf).unwrap();
                // It should contain the things we printed using `/bin/sh`.
                let string = String::from_utf8_lossy(&buf);
                assert!(string.contains("nix!!!"));
                assert!(string.contains("foo=bar"));
                assert!(string.contains("baz=quux"));
            }
        }
    }
    )
);

#[test]
fn test_getcwd() {
    let mut tmp_dir = TempDir::new("test_getcwd").unwrap().into_path();
    assert!(chdir(tmp_dir.as_path()).is_ok());
    assert_eq!(getcwd().unwrap(), current_dir().unwrap());

    // make path 500 chars longer so that buffer doubling in getcwd kicks in.
    // Note: One path cannot be longer than 255 bytes (NAME_MAX)
    // whole path cannot be longer than PATH_MAX (usually 4096 on linux, 1024 on macos)
    for _ in 0..5 {
        let newdir = iter::repeat("a").take(100).collect::<String>();
        tmp_dir.push(newdir);
        assert!(mkdir(tmp_dir.as_path(), stat::S_IRWXU).is_ok());
    }
    assert!(chdir(tmp_dir.as_path()).is_ok());
    assert_eq!(getcwd().unwrap(), current_dir().unwrap());
}

#[test]
fn test_lseek() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();

    let offset: off_t = 5;
    lseek(tmp.as_raw_fd(), offset, Whence::SeekSet).unwrap();

    let mut buf = String::new();
    tmp.read_to_string(&mut buf).unwrap();
    assert_eq!(b"f123456", buf.as_bytes());

    close(tmp.as_raw_fd()).unwrap();
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn test_lseek64() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();

    lseek64(tmp.as_raw_fd(), 5, Whence::SeekSet).unwrap();

    let mut buf = String::new();
    tmp.read_to_string(&mut buf).unwrap();
    assert_eq!(b"f123456", buf.as_bytes());

    close(tmp.as_raw_fd()).unwrap();
}

execve_test_factory!(test_execve, execve, b"/bin/sh", b"/system/bin/sh");

#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(feature = "execvpe")]
execve_test_factory!(test_execvpe, execvpe, b"sh", b"sh");
<commit_msg>test also that mkstemp fails when there's no X at the end<commit_after>extern crate tempdir;

use nix::unistd::*;
use nix::unistd::ForkResult::*;
use nix::sys::wait::*;
use nix::sys::stat;
use std::iter;
use std::ffi::CString;
use std::io::{Write, Read};
use std::os::unix::prelude::*;
use std::env::current_dir;
use tempfile::tempfile;
use tempdir::TempDir;
use libc::off_t;

#[test]
fn test_fork_and_waitpid() {
    let pid = fork();
    match pid {
        Ok(Child) => {} // ignore child here
        Ok(Parent { child }) => {
            // assert that child was created and pid > 0
            assert!(child > 0);
            let wait_status = waitpid(child, None);
            match wait_status {
                // assert that waitpid returned correct status and the pid is the one of the child
                Ok(WaitStatus::Exited(pid_t, _)) =>  assert!(pid_t == child),

                // panic, must never happen
                Ok(_) => panic!("Child still alive, should never happen"),

                // panic, waitpid should never fail
                Err(_) => panic!("Error: waitpid Failed")
            }

        },
        // panic, fork should never fail unless there is a serious problem with the OS
        Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_wait() {
    let pid = fork();
    match pid {
        Ok(Child) => {} // ignore child here
        Ok(Parent { child }) => {
            let wait_status = wait();

            // just assert that (any) one child returns with WaitStatus::Exited
            assert_eq!(wait_status, Ok(WaitStatus::Exited(child, 0)));
        },
        // panic, fork should never fail unless there is a serious problem with the OS
        Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_mkstemp() {
    let result = mkstemp("/tmp/nix_tempfile.XXXXXX");
    match result {
        Ok((fd, path)) => {
            close(fd).unwrap();
            unlink(path.as_path()).unwrap();
        },
        Err(e) => panic!("mkstemp failed: {}", e)
    }

    let result = mkstemp("/tmp/nix_tempfile");
    match result {
        Ok(_) => {
            panic!("mkstemp succeeded even though it should fail (no X at the end)");
        },
        Err(_) => {}
    }
}

#[test]
fn test_getpid() {
    let pid = getpid();
    let ppid = getppid();
    assert!(pid > 0);
    assert!(ppid > 0);
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux_android {
    use nix::unistd::gettid;

    #[test]
    fn test_gettid() {
        let tid = gettid();
        assert!(tid > 0);
    }
}

macro_rules! execve_test_factory(
    ($test_name:ident, $syscall:ident, $unix_sh:expr, $android_sh:expr) => (
    #[test]
    fn $test_name() {
        // The `exec`d process will write to `writer`, and we'll read that
        // data from `reader`.
        let (reader, writer) = pipe().unwrap();

        match fork().unwrap() {
            Child => {
                #[cfg(not(target_os = "android"))]
                const SH_PATH: &'static [u8] = $unix_sh;

                #[cfg(target_os = "android")]
                const SH_PATH: &'static [u8] = $android_sh;

                // Close stdout.
                close(1).unwrap();
                // Make `writer` be the stdout of the new process.
                dup(writer).unwrap();
                // exec!
                $syscall(
                    &CString::new(SH_PATH).unwrap(),
                    &[CString::new(b"".as_ref()).unwrap(),
                      CString::new(b"-c".as_ref()).unwrap(),
                      CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
                                   .as_ref()).unwrap()],
                    &[CString::new(b"foo=bar".as_ref()).unwrap(),
                      CString::new(b"baz=quux".as_ref()).unwrap()]).unwrap();
            },
            Parent { child } => {
                // Wait for the child to exit.
                waitpid(child, None).unwrap();
                // Read 1024 bytes.
                let mut buf = [0u8; 1024];
                read(reader, &mut buf).unwrap();
                // It should contain the things we printed using `/bin/sh`.
                let string = String::from_utf8_lossy(&buf);
                assert!(string.contains("nix!!!"));
                assert!(string.contains("foo=bar"));
                assert!(string.contains("baz=quux"));
            }
        }
    }
    )
);

#[test]
fn test_getcwd() {
    let mut tmp_dir = TempDir::new("test_getcwd").unwrap().into_path();
    assert!(chdir(tmp_dir.as_path()).is_ok());
    assert_eq!(getcwd().unwrap(), current_dir().unwrap());

    // make path 500 chars longer so that buffer doubling in getcwd kicks in.
    // Note: One path cannot be longer than 255 bytes (NAME_MAX)
    // whole path cannot be longer than PATH_MAX (usually 4096 on linux, 1024 on macos)
    for _ in 0..5 {
        let newdir = iter::repeat("a").take(100).collect::<String>();
        tmp_dir.push(newdir);
        assert!(mkdir(tmp_dir.as_path(), stat::S_IRWXU).is_ok());
    }
    assert!(chdir(tmp_dir.as_path()).is_ok());
    assert_eq!(getcwd().unwrap(), current_dir().unwrap());
}

#[test]
fn test_lseek() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();

    let offset: off_t = 5;
    lseek(tmp.as_raw_fd(), offset, Whence::SeekSet).unwrap();

    let mut buf = String::new();
    tmp.read_to_string(&mut buf).unwrap();
    assert_eq!(b"f123456", buf.as_bytes());

    close(tmp.as_raw_fd()).unwrap();
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn test_lseek64() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();

    lseek64(tmp.as_raw_fd(), 5, Whence::SeekSet).unwrap();

    let mut buf = String::new();
    tmp.read_to_string(&mut buf).unwrap();
    assert_eq!(b"f123456", buf.as_bytes());

    close(tmp.as_raw_fd()).unwrap();
}

execve_test_factory!(test_execve, execve, b"/bin/sh", b"/system/bin/sh");

#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(feature = "execvpe")]
execve_test_factory!(test_execvpe, execvpe, b"sh", b"sh");
<|endoftext|>


<commit_before>extern crate tempdir;

use nix::unistd::*;
use nix::unistd::ForkResult::*;
use nix::sys::wait::*;
use nix::sys::stat;
use std::iter;
use std::ffi::CString;
use std::io::{Write, Read};
use std::os::unix::prelude::*;
use std::env::current_dir;
use tempfile::tempfile;
use tempdir::TempDir;
use libc::off_t;

#[test]
fn test_fork_and_waitpid() {
    let pid = fork();
    match pid {
      Ok(Child) => {} // ignore child here
      Ok(Parent { child }) => {
          // assert that child was created and pid > 0
          assert!(child > 0);
          let wait_status = waitpid(child, None);
          match wait_status {
              // assert that waitpid returned correct status and the pid is the one of the child
              Ok(WaitStatus::Exited(pid_t, _)) =>  assert!(pid_t == child),

              // panic, must never happen
              Ok(_) => panic!("Child still alive, should never happen"),

              // panic, waitpid should never fail
              Err(_) => panic!("Error: waitpid Failed")
          }

      },
      // panic, fork should never fail unless there is a serious problem with the OS
      Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_wait() {
    let pid = fork();
    match pid {
      Ok(Child) => {} // ignore child here
      Ok(Parent { child }) => {
          let wait_status = wait();

          // just assert that (any) one child returns with WaitStatus::Exited
          assert_eq!(wait_status, Ok(WaitStatus::Exited(child, 0)));
      },
      // panic, fork should never fail unless there is a serious problem with the OS
      Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_getpid() {
    let pid = getpid();
    let ppid = getppid();
    assert!(pid > 0);
    assert!(ppid > 0);
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux_android {
    use nix::unistd::gettid;

    #[test]
    fn test_gettid() {
        let tid = gettid();
        assert!(tid > 0);
    }
}

macro_rules! execve_test_factory(
    ($test_name:ident, $syscall:ident, $unix_sh:expr, $android_sh:expr) => (
    #[test]
    fn $test_name() {
        // The `exec`d process will write to `writer`, and we'll read that
        // data from `reader`.
        let (reader, writer) = pipe().unwrap();

        match fork().unwrap() {
            Child => {
                #[cfg(not(target_os = "android"))]
                const SH_PATH: &'static [u8] = $unix_sh;

                #[cfg(target_os = "android")]
                const SH_PATH: &'static [u8] = $android_sh;

                // Close stdout.
                close(1).unwrap();
                // Make `writer` be the stdout of the new process.
                dup(writer).unwrap();
                // exec!
                $syscall(
                    &CString::new(SH_PATH).unwrap(),
                    &[CString::new(b"".as_ref()).unwrap(),
                      CString::new(b"-c".as_ref()).unwrap(),
                      CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
                                   .as_ref()).unwrap()],
                    &[CString::new(b"foo=bar".as_ref()).unwrap(),
                      CString::new(b"baz=quux".as_ref()).unwrap()]).unwrap();
            },
            Parent { child } => {
                // Wait for the child to exit.
                waitpid(child, None).unwrap();
                // Read 1024 bytes.
                let mut buf = [0u8; 1024];
                read(reader, &mut buf).unwrap();
                // It should contain the things we printed using `/bin/sh`.
                let string = String::from_utf8_lossy(&buf);
                assert!(string.contains("nix!!!"));
                assert!(string.contains("foo=bar"));
                assert!(string.contains("baz=quux"));
            }
        }
    }
    )
);

#[test]
fn test_getcwd() {
  let mut tmp_dir = TempDir::new("test_getcwd").unwrap().into_path();
  assert!(chdir(tmp_dir.as_path()).is_ok());
  assert_eq!(getcwd().unwrap(), current_dir().unwrap());

  // make path 500 chars longer so that buffer doubling in getcwd kicks in.
  // Note: One path cannot be longer than 255 bytes (NAME_MAX)
  // whole path cannot be longer than PATH_MAX (usually 4096 on linux, 1024 on macos)
  for _ in 0..5 {
    let newdir = iter::repeat("a").take(100).collect::<String>();
    tmp_dir.push(newdir);
    assert!(mkdir(tmp_dir.as_path(), stat::S_IRWXU).is_ok());
  }
  assert!(chdir(tmp_dir.as_path()).is_ok());
  assert_eq!(getcwd().unwrap(), current_dir().unwrap());
}

#[test]
fn test_lseek() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();

    let offset: off_t = 5;
    lseek(tmp.as_raw_fd(), offset, Whence::SeekSet).unwrap();

    let mut buf = String::new();
     tmp.read_to_string(&mut buf).unwrap();
     assert_eq!(b"f123456", buf.as_bytes());

     close(tmp.as_raw_fd()).unwrap();
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn test_lseek64() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();

    lseek64(tmp.as_raw_fd(), 5, Whence::SeekSet).unwrap();

    let mut buf = String::new();
    tmp.read_to_string(&mut buf).unwrap();
    assert_eq!(b"f123456", buf.as_bytes());

    close(tmp.as_raw_fd()).unwrap();
}

execve_test_factory!(test_execve, execve, b"/bin/sh", b"/system/bin/sh");

#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(feature = "execvpe")]
execve_test_factory!(test_execvpe, execvpe, b"sh", b"sh");
<commit_msg>fixed indentation<commit_after>extern crate tempdir;

use nix::unistd::*;
use nix::unistd::ForkResult::*;
use nix::sys::wait::*;
use nix::sys::stat;
use std::iter;
use std::ffi::CString;
use std::io::{Write, Read};
use std::os::unix::prelude::*;
use std::env::current_dir;
use tempfile::tempfile;
use tempdir::TempDir;
use libc::off_t;

#[test]
fn test_fork_and_waitpid() {
    let pid = fork();
    match pid {
        Ok(Child) => {} // ignore child here
        Ok(Parent { child }) => {
            // assert that child was created and pid > 0
            assert!(child > 0);
            let wait_status = waitpid(child, None);
            match wait_status {
                // assert that waitpid returned correct status and the pid is the one of the child
                Ok(WaitStatus::Exited(pid_t, _)) =>  assert!(pid_t == child),

                // panic, must never happen
                Ok(_) => panic!("Child still alive, should never happen"),

                // panic, waitpid should never fail
                Err(_) => panic!("Error: waitpid Failed")
            }

        },
        // panic, fork should never fail unless there is a serious problem with the OS
        Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_wait() {
    let pid = fork();
    match pid {
        Ok(Child) => {} // ignore child here
        Ok(Parent { child }) => {
            let wait_status = wait();

            // just assert that (any) one child returns with WaitStatus::Exited
            assert_eq!(wait_status, Ok(WaitStatus::Exited(child, 0)));
        },
        // panic, fork should never fail unless there is a serious problem with the OS
        Err(_) => panic!("Error: Fork Failed")
    }
}

#[test]
fn test_getpid() {
    let pid = getpid();
    let ppid = getppid();
    assert!(pid > 0);
    assert!(ppid > 0);
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux_android {
    use nix::unistd::gettid;

    #[test]
    fn test_gettid() {
        let tid = gettid();
        assert!(tid > 0);
    }
}

macro_rules! execve_test_factory(
    ($test_name:ident, $syscall:ident, $unix_sh:expr, $android_sh:expr) => (
    #[test]
    fn $test_name() {
        // The `exec`d process will write to `writer`, and we'll read that
        // data from `reader`.
        let (reader, writer) = pipe().unwrap();

        match fork().unwrap() {
            Child => {
                #[cfg(not(target_os = "android"))]
                const SH_PATH: &'static [u8] = $unix_sh;

                #[cfg(target_os = "android")]
                const SH_PATH: &'static [u8] = $android_sh;

                // Close stdout.
                close(1).unwrap();
                // Make `writer` be the stdout of the new process.
                dup(writer).unwrap();
                // exec!
                $syscall(
                    &CString::new(SH_PATH).unwrap(),
                    &[CString::new(b"".as_ref()).unwrap(),
                      CString::new(b"-c".as_ref()).unwrap(),
                      CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
                                   .as_ref()).unwrap()],
                    &[CString::new(b"foo=bar".as_ref()).unwrap(),
                      CString::new(b"baz=quux".as_ref()).unwrap()]).unwrap();
            },
            Parent { child } => {
                // Wait for the child to exit.
                waitpid(child, None).unwrap();
                // Read 1024 bytes.
                let mut buf = [0u8; 1024];
                read(reader, &mut buf).unwrap();
                // It should contain the things we printed using `/bin/sh`.
                let string = String::from_utf8_lossy(&buf);
                assert!(string.contains("nix!!!"));
                assert!(string.contains("foo=bar"));
                assert!(string.contains("baz=quux"));
            }
        }
    }
    )
);

#[test]
fn test_getcwd() {
    let mut tmp_dir = TempDir::new("test_getcwd").unwrap().into_path();
    assert!(chdir(tmp_dir.as_path()).is_ok());
    assert_eq!(getcwd().unwrap(), current_dir().unwrap());

    // make path 500 chars longer so that buffer doubling in getcwd kicks in.
    // Note: One path cannot be longer than 255 bytes (NAME_MAX)
    // whole path cannot be longer than PATH_MAX (usually 4096 on linux, 1024 on macos)
    for _ in 0..5 {
        let newdir = iter::repeat("a").take(100).collect::<String>();
        tmp_dir.push(newdir);
        assert!(mkdir(tmp_dir.as_path(), stat::S_IRWXU).is_ok());
    }
    assert!(chdir(tmp_dir.as_path()).is_ok());
    assert_eq!(getcwd().unwrap(), current_dir().unwrap());
}

#[test]
fn test_lseek() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();

    let offset: off_t = 5;
    lseek(tmp.as_raw_fd(), offset, Whence::SeekSet).unwrap();

    let mut buf = String::new();
    tmp.read_to_string(&mut buf).unwrap();
    assert_eq!(b"f123456", buf.as_bytes());

    close(tmp.as_raw_fd()).unwrap();
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn test_lseek64() {
    const CONTENTS: &'static [u8] = b"abcdef123456";
    let mut tmp = tempfile().unwrap();
    tmp.write(CONTENTS).unwrap();

    lseek64(tmp.as_raw_fd(), 5, Whence::SeekSet).unwrap();

    let mut buf = String::new();
    tmp.read_to_string(&mut buf).unwrap();
    assert_eq!(b"f123456", buf.as_bytes());

    close(tmp.as_raw_fd()).unwrap();
}

execve_test_factory!(test_execve, execve, b"/bin/sh", b"/system/bin/sh");

#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(feature = "execvpe")]
execve_test_factory!(test_execvpe, execvpe, b"sh", b"sh");
<|endoftext|>


<commit_before>//! This module focuses on handling errors generated when using Ardite in a
//! graceful manner.

use std::io::Error as IOError;
use std::error::Error as ErrorTrait;

#[cfg(test)]
use regex::Regex;
use serde_json::error::Error as JSONError;
use serde_yaml::error::Error as YAMLError;

/// The code of an error. Designed to easily map to [HTTP status codes][1].
///
/// [1]: http://www.restapitutorial.com/httpstatuscodes.html
#[derive(PartialEq, Clone, Debug)]
pub enum ErrorCode {
  /// A bad syntax was used. Maps to 400.
  BadRequest = 400,
  /// Permissions do not allow this to happen. Maps to 403.
  Forbidden = 403,
  /// Resource was not found. Maps to 404.
  NotFound = 404,
  /// The requested resource is not acceptable. Maps to 406.
  NotAcceptable = 406,
  /// Present data made the request fail. Maps to 409.
  Conflict = 409,
  /// There was an invalid range. Maps to 416.
  BadRange = 416,
  /// Something bad happened inside a driver. Maps to 500.
  Internal = 500,
  /// The feature has not been implemented. Maps to 501.
  NotImplemented = 501
}

/// Any error generated by Ardite or it‘s drivers should be output using this
/// type. This allows for a comprehensive display of the error when a service
/// reports it to the user.
///
/// Information included with the error includes an `ErrorCode` (which maps to
/// an HTTP status code), a message, and an optional hint telling the user how
/// to fix the error.
///
/// Typically hints should be included for what would be considered the `4xx`
/// (in HTTP language) class of error codes.
///
/// # Tips For Writing Good Hint Messages
/// - Write in the second person (“You should…”).
/// - Always recommend a solution (“You should try…”, not “You must do…”).
/// - Be as specific as possible, if you have line numbers give them. If you
///   have file paths provide them.
/// - If it is a common error which generally confuses developers, provide a
///   link to a page which better explains the error and specific steps to
///   fix it.
#[derive(PartialEq, Debug)]
pub struct Error {
  /// A specific error code which describes the error.
  code: ErrorCode,
  /// A message providing more detail beyond the error code.
  message: String,
  /// A hint to the user on what to do next to try and avoid the error
  /// happening again. This is optional.
  hint: Option<String>
}

impl Error {
  /// Easily create a new error.
  pub fn new<S>(code: ErrorCode, message: S, hint: Option<S>) -> Self where S: Into<String> {
    Error {
      code: code,
      message: message.into(),
      hint: hint.map(|string| string.into())
    }
  }

  /// Get the code for the error.
  pub fn code(&self) -> ErrorCode {
    self.code.to_owned()
  }

  /// Get the message for the error.
  pub fn message(&self) -> String {
    self.message.to_owned()
  }

  /// Get the hint—for the error (see what I did there?).
  pub fn hint(&self) -> Option<String> {
    self.hint.to_owned()
  }

  /// Convenience function for saying a thing failed validation using
  /// `ErrorCode::BadRequest`.
  ///
  /// # Example
  /// ```rust
  /// use ardite::error::{Error, ErrorCode};
  ///
  /// let error = Error::validation("Failed validation.", "Try fixing your syntax!");
  ///
  /// assert_eq!(error, Error::new(ErrorCode::BadRequest, "Failed validation.", Some("Try fixing your syntax!")));
  /// ```
  pub fn validation<S1, S2>(message: S1, hint: S2) -> Self where S1: Into<String>, S2: Into<String> {
    Error {
      code: ErrorCode::BadRequest,
      message: message.into(),
      hint: Some(hint.into())
    }
  }

  /// Convenience function for saying there was an internal error using
  /// `ErrorCode::Internal`.
  ///
  /// # Example
  /// ```rust
  /// use ardite::error::{Error, ErrorCode};
  ///
  /// let error = Error::internal("Something blew up.");
  ///
  /// assert_eq!(error, Error::new(ErrorCode::Internal, "Something blew up.", None));
  /// ```
  pub fn internal<S>(message: S) -> Self where S: Into<String> {
    Error {
      code: ErrorCode::Internal,
      message: message.into(),
      hint: None
    }
  }

  /// Convenience function for creating an unimplemented error with a plain
  /// message describing what is unimplemented using
  /// `ErrorCode::NotImplemented`.
  ///
  /// # Example
  /// ```rust
  /// use ardite::error::{Error, ErrorCode};
  ///
  /// let error = Error::unimplemented("Cache invalidation is hard.");
  ///
  /// assert_eq!(error, Error::new(ErrorCode::NotImplemented, "Cache invalidation is hard.", None));
  /// ```
  pub fn unimplemented<S>(message: S) -> Self where S: Into<String> {
    Error {
      code: ErrorCode::NotImplemented,
      message: message.into(),
      hint: None
    }
  }

  /// Special assertion for error messages. Takes a regular expression string
  /// argument which will automatically be constructed into a regualr
  /// expression. Only available in testing environments. Panics if the regular
  /// expression doesn’t match the error message string.
  #[cfg(test)]
  pub fn assert_message(&self, regex_str: &str) {
    if !Regex::new(regex_str).unwrap().is_match(&self.message) {
      panic!("Error message \"{}\" does not match regex /{}/", self.message, regex_str);
    }
  }
}

impl From<IOError> for Error {
  fn from(error: IOError) -> Self {
    Error {
      code: ErrorCode::Internal,
      message: error.description().to_owned(),
      hint: None
    }
  }
}

impl From<JSONError> for Error {
  fn from(error: JSONError) -> Self {
    match error {
      JSONError::Syntax(_, line, column) => {
        Error {
          code: ErrorCode::BadRequest,
          message: "Syntax error.".to_owned(),
          hint: Some(format!("Max sure your JSON syntax is correct around line {} column {}.", line, column))
        }
      },
      _ => {
        Error {
          code: ErrorCode::Internal,
          message: error.description().to_owned(),
          hint: None
        }
      }
    }
  }
}

impl From<YAMLError> for Error {
  fn from(error: YAMLError) -> Self {
    match error {
      YAMLError::Custom(ref message) => {
        Error {
          code: ErrorCode::BadRequest,
          message: message.to_owned(),
          hint: Some("Make sure your YAML syntax is correct.".to_owned())
        }
      },
      _ => {
        Error {
          code: ErrorCode::Internal,
          message: error.description().to_owned(),
          hint: None
        }
      }
    }
  }
}
<commit_msg>feat(error): error now impls display and error<commit_after>//! This module focuses on handling errors generated when using Ardite in a
//! graceful manner.

use std::io::Error as IOError;
use std::error::Error as ErrorTrait;
use std::fmt::{Display, Formatter, Result as FmtResult};

#[cfg(test)]
use regex::Regex;
use serde_json::error::Error as JSONError;
use serde_yaml::error::Error as YAMLError;

/// Any error generated by Ardite or it‘s drivers should be output using this
/// type. This allows for a comprehensive display of the error when a service
/// reports it to the user.
///
/// Information included with the error includes an `ErrorCode` (which maps to
/// an HTTP status code), a message, and an optional hint telling the user how
/// to fix the error.
///
/// Typically hints should be included for what would be considered the `4xx`
/// (in HTTP language) class of error codes.
///
/// # Tips For Writing Good Hint Messages
/// - Write in the second person (“You should…”).
/// - Always recommend a solution (“You should try…”, not “You must do…”).
/// - Be as specific as possible, if you have line numbers give them. If you
///   have file paths provide them.
/// - If it is a common error which generally confuses developers, provide a
///   link to a page which better explains the error and specific steps to
///   fix it.
#[derive(PartialEq, Debug)]
pub struct Error {
  /// A specific error code which describes the error.
  code: ErrorCode,
  /// A message providing more detail beyond the error code.
  message: String,
  /// A hint to the user on what to do next to try and avoid the error
  /// happening again. This is optional.
  hint: Option<String>
}

impl Error {
  /// Easily create a new error.
  pub fn new<S>(code: ErrorCode, message: S, hint: Option<S>) -> Self where S: Into<String> {
    Error {
      code: code,
      message: message.into(),
      hint: hint.map(|string| string.into())
    }
  }

  /// Get the code for the error.
  pub fn code(&self) -> ErrorCode {
    self.code.to_owned()
  }

  /// Get the message for the error.
  pub fn message(&self) -> String {
    self.message.to_owned()
  }

  /// Get the hint—for the error (see what I did there?).
  pub fn hint(&self) -> Option<String> {
    self.hint.to_owned()
  }

  /// Convenience function for saying a thing failed validation using
  /// `ErrorCode::BadRequest`.
  ///
  /// # Example
  /// ```rust
  /// use ardite::error::{Error, ErrorCode};
  ///
  /// let error = Error::validation("Failed validation.", "Try fixing your syntax!");
  ///
  /// assert_eq!(error, Error::new(ErrorCode::BadRequest, "Failed validation.", Some("Try fixing your syntax!")));
  /// ```
  pub fn validation<S1, S2>(message: S1, hint: S2) -> Self where S1: Into<String>, S2: Into<String> {
    Error {
      code: ErrorCode::BadRequest,
      message: message.into(),
      hint: Some(hint.into())
    }
  }

  /// Convenience function for saying there was an internal error using
  /// `ErrorCode::Internal`.
  ///
  /// # Example
  /// ```rust
  /// use ardite::error::{Error, ErrorCode};
  ///
  /// let error = Error::internal("Something blew up.");
  ///
  /// assert_eq!(error, Error::new(ErrorCode::Internal, "Something blew up.", None));
  /// ```
  pub fn internal<S>(message: S) -> Self where S: Into<String> {
    Error {
      code: ErrorCode::Internal,
      message: message.into(),
      hint: None
    }
  }

  /// Convenience function for creating an unimplemented error with a plain
  /// message describing what is unimplemented using
  /// `ErrorCode::NotImplemented`.
  ///
  /// # Example
  /// ```rust
  /// use ardite::error::{Error, ErrorCode};
  ///
  /// let error = Error::unimplemented("Cache invalidation is hard.");
  ///
  /// assert_eq!(error, Error::new(ErrorCode::NotImplemented, "Cache invalidation is hard.", None));
  /// ```
  pub fn unimplemented<S>(message: S) -> Self where S: Into<String> {
    Error {
      code: ErrorCode::NotImplemented,
      message: message.into(),
      hint: None
    }
  }

  /// Special assertion for error messages. Takes a regular expression string
  /// argument which will automatically be constructed into a regualr
  /// expression. Only available in testing environments. Panics if the regular
  /// expression doesn’t match the error message string.
  #[cfg(test)]
  pub fn assert_message(&self, regex_str: &str) {
    if !Regex::new(regex_str).unwrap().is_match(&self.message) {
      panic!("Error message \"{}\" does not match regex /{}/", self.message, regex_str);
    }
  }
}

impl Display for Error {
  fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
    try!(write!(fmt, "\ncode: {}", self.code));
    try!(write!(fmt, "\nmessage: {}", self.message));

    if let Some(ref hint) = self.hint {
      try!(write!(fmt, "\nhint: {}", hint));
    }

    Ok(())
  }
}

impl ErrorTrait for Error {
  fn description(&self) -> &str {
    self.message.as_str()
  }
}

impl From<IOError> for Error {
  fn from(error: IOError) -> Self {
    Error {
      code: ErrorCode::Internal,
      message: error.description().to_owned(),
      hint: None
    }
  }
}

impl From<JSONError> for Error {
  fn from(error: JSONError) -> Self {
    match error {
      JSONError::Syntax(_, line, column) => {
        Error {
          code: ErrorCode::BadRequest,
          message: "Syntax error.".to_owned(),
          hint: Some(format!("Max sure your JSON syntax is correct around line {} column {}.", line, column))
        }
      },
      _ => {
        Error {
          code: ErrorCode::Internal,
          message: error.description().to_owned(),
          hint: None
        }
      }
    }
  }
}

impl From<YAMLError> for Error {
  fn from(error: YAMLError) -> Self {
    match error {
      YAMLError::Custom(ref message) => {
        Error {
          code: ErrorCode::BadRequest,
          message: message.to_owned(),
          hint: Some("Make sure your YAML syntax is correct.".to_owned())
        }
      },
      _ => {
        Error {
          code: ErrorCode::Internal,
          message: error.description().to_owned(),
          hint: None
        }
      }
    }
  }
}

/// The code of an error. Designed to easily map to [HTTP status codes][1],
/// however only a subset of these codes are supported and some custom codes
/// were added.
///
/// [1]: http://www.restapitutorial.com/httpstatuscodes.html
#[derive(PartialEq, Debug)]
pub enum ErrorCode {
  /// A bad syntax was used.
  BadRequest,
  /// Permissions do not allow this to happen.
  Forbidden,
  /// Resource was not found.
  NotFound,
  /// The requested resource is not acceptable.
  NotAcceptable,
  /// Present data made the request fail.
  Conflict,
  /// There was an invalid range.
  BadRange,
  /// Something bad happened inside a driver.
  Internal,
  /// The feature has not been implemented.
  NotImplemented
}

// Dump all the error codes into the export space.
pub use ErrorCode::*;

impl ErrorCode {
  pub fn code(&self) -> u16 {
    match *self {
      BadRequest => 400,
      Forbidden => 403,
      NotFound => 404,
      NotAcceptable => 406,
      Conflict => 409,
      BadRange => 416,
      Internal => 500,
      NotImplemented => 501
    }
  }

  pub fn reason(&self) -> &str {
    match *self {
      BadRequest => "Bad Request",
      Forbidden => "Forbidden",
      NotFound => "Not Found",
      NotAcceptable => "Not Acceptable",
      Conflict => "Conflict",
      BadRange => "Range Not Satisfiable",
      Internal => "Internal Error",
      NotImplemented => "Not Implemented"
    }
  }
}

impl Display for ErrorCode {
  fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
    try!(write!(fmt, "{} {}", self.code(), self.reason()));
    Ok(())
  }
}
<|endoftext|>


<commit_before>//! Currently only contains types for keyboard keycodes and modifier keys.

pub use sdl2::keyboard::Keycode;
pub use sdl2::keyboard::Mod;
<commit_msg>Added mouse events<commit_after>//! Currently only contains types for keyboard keycodes and modifier keys.
//! As well as mouse states.

pub use sdl2::keyboard::Keycode;
pub use sdl2::keyboard::Mod;
pub use sdl2::mouse::Mouse;
pub use sdl2::mouse::MouseState;
<|endoftext|>


<commit_before>//! Functions for computing [integral images](https://en.wikipedia.org/wiki/Summed_area_table)
//! and running sums of rows and columns.

extern crate image;

use image::{
    Luma,
    GrayImage,
    GenericImage,
    ImageBuffer
};

use definitions::Image;

/// Computes the 2d running sum of a grayscale image.
///
/// An integral image I has width and height one greater than its source image F,
/// and is defined by I(x, y) = sum of F(x', y') for x' < x, y' < y, i.e. each pixel
/// in the integral image contains the sum of the pixel intensities of all input pixels
/// that are strictly above it and strictly to its left. In particular, the left column
/// and top row of an integral image are all 0, and the value of the bottom right pixel of
/// an integral image is equal to the sum of all pixels in the source image.
///
/// Integral images have the helpful property of allowing us to
/// compute the sum of pixel intensities in a rectangular region of an image
/// in constant time. Specifically, given a rectangle [l, r] * [t, b] in F,
/// the sum of the pixels in this rectangle is
/// I(r + 1, b + 1) - I(r + 1, t) - I(l, b + 1) + I(l, t).
///
/// # Examples
/// ```
/// # extern crate image;
/// # #[macro_use]
/// # extern crate imageproc;
/// # fn main() {
/// use imageproc::integralimage::{integral_image, sum_image_pixels};
///
/// let image = gray_image!(
///     1, 2, 3;
///     4, 5, 6);
///
/// let integral = gray_image_u32!(
///     0,  0,  0,  0;
///     0,  1,  3,  6;
///     0,  5, 12, 21);
///
/// assert_pixels_eq!(integral_image(&image), integral);
///
/// // Compute the sum of all pixels in the right two columns
/// assert_eq!(sum_image_pixels(&integral, 1, 0, 2, 1), 2 + 3 + 5 + 6);
///
/// // Compute the sum of all pixels in the top row
/// assert_eq!(sum_image_pixels(&integral, 0, 0, 2, 0), 1 + 2 + 3);
/// # }
/// ```
pub fn integral_image(image: &GrayImage) -> Image<Luma<u32>> {
    integral_image_impl(image, false)
}

/// Computes the 2d running sum of the squares of the intensities in a grayscale image.
///
/// See the [`integral_image`](fn.integral_image.html) documentation for more informaton on integral images.
///
/// # Examples
/// ```
/// # extern crate image;
/// # #[macro_use]
/// # extern crate imageproc;
/// # fn main() {
/// use imageproc::integralimage::{integral_squared_image, sum_image_pixels};
///
/// let image = gray_image!(
///     1, 2, 3;
///     4, 5, 6);
///
/// let integral = gray_image_u32!(
///     0,  0,  0,  0;
///     0,  1,  5, 14;
///     0, 17, 46, 91);
///
/// assert_pixels_eq!(integral_squared_image(&image), integral);
///
/// // Compute the sum of the squares of all pixels in the right two columns
/// assert_eq!(sum_image_pixels(&integral, 1, 0, 2, 1), 4 + 9 + 25 + 36);
///
/// // Compute the sum of the squares of all pixels in the top row
/// assert_eq!(sum_image_pixels(&integral, 0, 0, 2, 0), 1 + 4 + 9);
/// # }
/// ```
pub fn integral_squared_image(image: &GrayImage) -> Image<Luma<u32>> {
    integral_image_impl(image, true)
}

/// Implementation of `integral_image` and `integral_squared_image`.
fn integral_image_impl(image: &GrayImage, square: bool) -> Image<Luma<u32>> {
    // TODO: Support more formats, make faster, add a new IntegralImage type
    // TODO: to make it harder to make off-by-one errors when computing sums of regions.
    let (in_width, in_height) = image.dimensions();
    let out_width = in_width + 1;
    let out_height = in_height + 1;

    let mut out = ImageBuffer::from_pixel(out_width, out_height, Luma([0u32]));

    if in_width == 0 || in_height == 0 {
        return out;
    }

    for y in 1..out_height {
        let mut sum = 0;
        for x in 1..out_width {
            unsafe {
                let pix = image.unsafe_get_pixel(x - 1, y - 1)[0] as u32;
                if square {
                    sum += pix * pix;
                } else {
                    sum += pix;
                }
                let above = out.unsafe_get_pixel(x, y - 1)[0];
                out.unsafe_put_pixel(x, y, Luma([above + sum]))
            }
        }
    }

    out
}

/// Sums the pixels in positions [left, right] * [top, bottom] in F, where `integral_image` is the
/// integral image of F.
///
/// See the [`integral_image`](fn.integral_image.html) documentation for examples.
pub fn sum_image_pixels(integral_image: &Image<Luma<u32>>, left: u32, top: u32, right: u32, bottom: u32) -> u32 {
    // TODO: better type-safety. It's too easy to pass the original image in here by mistake.
    let sum = integral_image.get_pixel(right + 1, bottom + 1)[0] as i32
            - integral_image.get_pixel(right + 1, top)[0] as i32
            - integral_image.get_pixel(left, bottom + 1)[0] as i32
            + integral_image.get_pixel(left, top)[0] as i32;
    sum as u32
}

/// Computes the running sum of one row of image, padded
/// at the beginning and end. The padding is by continuity.
/// Takes a reference to buffer so that this can be reused
/// for all rows in an image.
pub fn row_running_sum(image: &GrayImage, row: u32, buffer: &mut [u32], padding: u32) {
    // TODO: faster, more formats
    let (width, height) = image.dimensions();
    assert!(buffer.len() >= (width + 2 * padding) as usize,
        format!("Buffer length {} is less than {} + 2 * {}", buffer.len(), width, padding));
    assert!(row < height, format!("row out of bounds: {} >= {}", row, height));

    unsafe {
        let mut sum = 0;
        for x in 0..padding {
            sum += image.unsafe_get_pixel(0, row)[0] as u32;
            *buffer.get_unchecked_mut(x as usize) = sum;
        }

        for x in 0..width {
            sum += image.unsafe_get_pixel(x, row)[0] as u32;
            *buffer.get_unchecked_mut((x + padding) as usize) = sum;
        }

        for x in 0..padding {
            sum += image.unsafe_get_pixel(width - 1, row)[0] as u32;
            *buffer.get_unchecked_mut((x + width + padding) as usize) = sum;
        }
    }
}

/// Computes the running sum of one column of image, padded
/// at the top and bottom. The padding is by continuity.
/// Takes a reference to buffer so that this can be reused
/// for all columns in an image.
// TODO: faster, more formats
pub fn column_running_sum(image: &GrayImage, column: u32, buffer: &mut [u32], padding: u32) {

    let (width, height) = image.dimensions();
    assert!(buffer.len() >= (height + 2 * padding) as usize,
        format!("Buffer length {} is less than {} + 2 * {}", buffer.len(), height, padding));
    assert!(column < width, format!("column out of bounds: {} >= {}", column, width));

    unsafe {
        let mut sum = 0;
        for y in 0..padding {
            sum += image.unsafe_get_pixel(column, 0)[0] as u32;
            *buffer.get_unchecked_mut(y as usize) = sum;
        }

        for y in 0..height {
            sum += image.unsafe_get_pixel(column, y)[0] as u32;
            *buffer.get_unchecked_mut((y + padding) as usize) = sum;
        }

        for y in 0..padding {
            sum += image.unsafe_get_pixel(column, height - 1)[0] as u32;
            *buffer.get_unchecked_mut((y + height + padding) as usize) = sum;
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use utils::{
        gray_bench_image,
        GrayTestImage,
        pixel_diff_summary
    };
    use image::{
        GenericImage,
        ImageBuffer,
        Luma
    };
    use quickcheck::{
        quickcheck,
        TestResult
    };
    use definitions::{
        Image
    };
    use test;

    #[test]
    fn test_sum_image_pixels() {
        let image = gray_image!(
            1, 2;
            3, 4);

        let integral = ::integralimage::integral_image(&image);

        assert_eq!(sum_image_pixels(&integral, 0, 0, 0, 0), 1);
        assert_eq!(sum_image_pixels(&integral, 0, 0, 1, 0), 3);
        assert_eq!(sum_image_pixels(&integral, 0, 0, 0, 1), 4);
        assert_eq!(sum_image_pixels(&integral, 0, 0, 1, 1), 10);
        assert_eq!(sum_image_pixels(&integral, 1, 0, 1, 0), 2);
        assert_eq!(sum_image_pixels(&integral, 1, 0, 1, 1), 6);
        assert_eq!(sum_image_pixels(&integral, 0, 1, 0, 1), 3);
        assert_eq!(sum_image_pixels(&integral, 0, 1, 1, 1), 7);
        assert_eq!(sum_image_pixels(&integral, 1, 1, 1, 1), 4);
    }

    #[test]
    fn test_integral_image() {
        let image = gray_image!(
            1, 2, 3;
            4, 5, 6);

        let expected = gray_image_u32!(
            0,  0,  0,  0;
            0,  1,  3,  6;
            0,  5, 12, 21);

        assert_pixels_eq!(integral_image(&image), expected);
    }

    #[bench]
    fn bench_integral_image(b: &mut test::Bencher) {
        let image = gray_bench_image(500, 500);
        b.iter(|| {
            let integral = integral_image(&image);
            test::black_box(integral);
            });
    }

    /// Simple implementation of integral_image to validate faster versions against.
    fn integral_image_ref<I>(image: &I) -> Image<Luma<u32>>
        where I: GenericImage<Pixel=Luma<u8>>
    {
        let (in_width, in_height) = image.dimensions();
        let (out_width, out_height) = (in_width + 1, in_height + 1);
        let mut out = ImageBuffer::from_pixel(out_width, out_height, Luma([0u32]));

        for y in 1..out_height {
            for x in 0..out_width {
                let mut sum = 0u32;

                for iy in 0..y {
                    for ix in 0..x {
                        sum += image.get_pixel(ix, iy)[0] as u32;
                    }
                }

                out.put_pixel(x, y, Luma([sum]));
            }
        }

        out
    }

    #[test]
    fn test_integral_image_matches_reference_implementation() {
        fn prop(image: GrayTestImage) -> TestResult {
            let expected = integral_image_ref(&image.0);
            let actual = integral_image(&image.0);
            match pixel_diff_summary(&actual, &expected) {
                None => TestResult::passed(),
                Some(err) => TestResult::error(err)
            }
        }
        quickcheck(prop as fn(GrayTestImage) -> TestResult);
    }

    #[test]
    fn test_row_running_sum() {
        let image = gray_image!(
            1, 2, 3;
            4, 5, 6);

        let expected = [1, 2, 4, 7, 10];

        let mut buffer = [0; 5];
        row_running_sum(&image, 0, &mut buffer, 1);

        assert_eq!(buffer, expected);
    }

    #[bench]
    fn bench_row_running_sum(b: &mut test::Bencher) {
        let image = gray_bench_image(1000, 1);
        let mut buffer = [0; 1010];
        b.iter(|| {
            row_running_sum(&image, 0, &mut buffer, 5);
            });
    }

    #[test]
    fn test_column_running_sum() {
        let image = gray_image!(
            1, 4;
            2, 5;
            3, 6);

        let expected = [1, 2, 4, 7, 10];

        let mut buffer = [0; 5];
        column_running_sum(&image, 0, &mut buffer, 1);

        assert_eq!(buffer, expected);
    }

    #[bench]
    fn bench_column_running_sum(b: &mut test::Bencher) {
        let image = gray_bench_image(100, 1000);
        let mut buffer = [0; 1010];
        b.iter(|| {
            column_running_sum(&image, 0, &mut buffer, 5);
            });
    }
}
<commit_msg>Add function for constant-time variance calculation using integral images<commit_after>//! Functions for computing [integral images](https://en.wikipedia.org/wiki/Summed_area_table)
//! and running sums of rows and columns.

extern crate image;

use image::{
    Luma,
    GrayImage,
    GenericImage,
    ImageBuffer
};

use definitions::Image;

/// Computes the 2d running sum of a grayscale image.
///
/// An integral image I has width and height one greater than its source image F,
/// and is defined by I(x, y) = sum of F(x', y') for x' < x, y' < y, i.e. each pixel
/// in the integral image contains the sum of the pixel intensities of all input pixels
/// that are strictly above it and strictly to its left. In particular, the left column
/// and top row of an integral image are all 0, and the value of the bottom right pixel of
/// an integral image is equal to the sum of all pixels in the source image.
///
/// Integral images have the helpful property of allowing us to
/// compute the sum of pixel intensities in a rectangular region of an image
/// in constant time. Specifically, given a rectangle [l, r] * [t, b] in F,
/// the sum of the pixels in this rectangle is
/// I(r + 1, b + 1) - I(r + 1, t) - I(l, b + 1) + I(l, t).
///
/// # Examples
/// ```
/// # extern crate image;
/// # #[macro_use]
/// # extern crate imageproc;
/// # fn main() {
/// use imageproc::integralimage::{integral_image, sum_image_pixels};
///
/// let image = gray_image!(
///     1, 2, 3;
///     4, 5, 6);
///
/// let integral = gray_image_u32!(
///     0,  0,  0,  0;
///     0,  1,  3,  6;
///     0,  5, 12, 21);
///
/// assert_pixels_eq!(integral_image(&image), integral);
///
/// // Compute the sum of all pixels in the right two columns
/// assert_eq!(sum_image_pixels(&integral, 1, 0, 2, 1), 2 + 3 + 5 + 6);
///
/// // Compute the sum of all pixels in the top row
/// assert_eq!(sum_image_pixels(&integral, 0, 0, 2, 0), 1 + 2 + 3);
/// # }
/// ```
pub fn integral_image(image: &GrayImage) -> Image<Luma<u32>> {
    integral_image_impl(image, false)
}

/// Computes the 2d running sum of the squares of the intensities in a grayscale image.
///
/// See the [`integral_image`](fn.integral_image.html) documentation for more information on integral images.
///
/// # Examples
/// ```
/// # extern crate image;
/// # #[macro_use]
/// # extern crate imageproc;
/// # fn main() {
/// use imageproc::integralimage::{integral_squared_image, sum_image_pixels};
///
/// let image = gray_image!(
///     1, 2, 3;
///     4, 5, 6);
///
/// let integral = gray_image_u32!(
///     0,  0,  0,  0;
///     0,  1,  5, 14;
///     0, 17, 46, 91);
///
/// assert_pixels_eq!(integral_squared_image(&image), integral);
///
/// // Compute the sum of the squares of all pixels in the right two columns
/// assert_eq!(sum_image_pixels(&integral, 1, 0, 2, 1), 4 + 9 + 25 + 36);
///
/// // Compute the sum of the squares of all pixels in the top row
/// assert_eq!(sum_image_pixels(&integral, 0, 0, 2, 0), 1 + 4 + 9);
/// # }
/// ```
pub fn integral_squared_image(image: &GrayImage) -> Image<Luma<u32>> {
    integral_image_impl(image, true)
}

/// Implementation of `integral_image` and `integral_squared_image`.
fn integral_image_impl(image: &GrayImage, square: bool) -> Image<Luma<u32>> {
    // TODO: Support more formats, make faster, add a new IntegralImage type
    // TODO: to make it harder to make off-by-one errors when computing sums of regions.
    let (in_width, in_height) = image.dimensions();
    let out_width = in_width + 1;
    let out_height = in_height + 1;

    let mut out = ImageBuffer::from_pixel(out_width, out_height, Luma([0u32]));

    if in_width == 0 || in_height == 0 {
        return out;
    }

    for y in 1..out_height {
        let mut sum = 0;
        for x in 1..out_width {
            unsafe {
                let pix = image.unsafe_get_pixel(x - 1, y - 1)[0] as u32;
                if square {
                    sum += pix * pix;
                } else {
                    sum += pix;
                }
                let above = out.unsafe_get_pixel(x, y - 1)[0];
                out.unsafe_put_pixel(x, y, Luma([above + sum]))
            }
        }
    }

    out
}

/// Sums the pixels in positions [left, right] * [top, bottom] in F, where `integral_image` is the
/// integral image of F.
///
/// See the [`integral_image`](fn.integral_image.html) documentation for examples.
pub fn sum_image_pixels(integral_image: &Image<Luma<u32>>, left: u32, top: u32, right: u32, bottom: u32) -> u32 {
    // TODO: better type-safety. It's too easy to pass the original image in here by mistake.
    // TODO: it's also hard to see what the four u32s mean at the call site - use a Rect instead.
    let sum = integral_image.get_pixel(right + 1, bottom + 1)[0] as i32
            - integral_image.get_pixel(right + 1, top)[0] as i32
            - integral_image.get_pixel(left, bottom + 1)[0] as i32
            + integral_image.get_pixel(left, top)[0] as i32;
    sum as u32
}

/// Computes the variance of [left, right] * [top, bottom] in F, where `integral_image` is the
/// integral image of F and `integral_squared_image` is the integral image of the squares of the
/// pixels in F.
///
/// See the [`integral_image`](fn.integral_image.html) documentation for more information on integral images.
///
///# Examples
/// ```
/// # extern crate image;
/// # #[macro_use]
/// # extern crate imageproc;
/// # fn main() {
/// use std::f64;
/// use imageproc::integralimage::{integral_image, integral_squared_image, variance};
///
/// let image = gray_image!(
///     1, 2, 3;
///     4, 5, 6);
///
/// let integral = integral_image(&image);
/// let integral_squared = integral_squared_image(&image);
///
/// // Compute the variance of the pixels in the right two columns
/// let mean: f64 = (2.0 + 3.0 + 5.0 + 6.0) / 4.0;
/// let var = ((2.0 - mean).powi(2)
///     + (3.0 - mean).powi(2)
///     + (5.0 - mean).powi(2)
///     + (6.0 - mean).powi(2)) / 4.0;
///
/// assert_eq!(variance(&integral, &integral_squared, 1, 0, 2, 1), var);
/// # }
/// ```
pub fn variance(
    integral_image: &Image<Luma<u32>>,
    integral_squared_image: &Image<Luma<u32>>,
    left: u32,
    top: u32,
    right: u32,
    bottom: u32) -> f64 {
    // TODO: same improvements as for sum_image_pixels, plus check that the given rect is valid.
    let n = (right - left + 1) as f64 * (bottom - top + 1) as f64;
    let sum_sq = sum_image_pixels(integral_squared_image, left, top, right, bottom);
    let sum = sum_image_pixels(integral_image, left, top, right, bottom);
    (sum_sq as f64 - (sum as f64).powi(2) / n) / n
}

/// Computes the running sum of one row of image, padded
/// at the beginning and end. The padding is by continuity.
/// Takes a reference to buffer so that this can be reused
/// for all rows in an image.
pub fn row_running_sum(image: &GrayImage, row: u32, buffer: &mut [u32], padding: u32) {
    // TODO: faster, more formats
    let (width, height) = image.dimensions();
    assert!(buffer.len() >= (width + 2 * padding) as usize,
        format!("Buffer length {} is less than {} + 2 * {}", buffer.len(), width, padding));
    assert!(row < height, format!("row out of bounds: {} >= {}", row, height));

    unsafe {
        let mut sum = 0;
        for x in 0..padding {
            sum += image.unsafe_get_pixel(0, row)[0] as u32;
            *buffer.get_unchecked_mut(x as usize) = sum;
        }

        for x in 0..width {
            sum += image.unsafe_get_pixel(x, row)[0] as u32;
            *buffer.get_unchecked_mut((x + padding) as usize) = sum;
        }

        for x in 0..padding {
            sum += image.unsafe_get_pixel(width - 1, row)[0] as u32;
            *buffer.get_unchecked_mut((x + width + padding) as usize) = sum;
        }
    }
}

/// Computes the running sum of one column of image, padded
/// at the top and bottom. The padding is by continuity.
/// Takes a reference to buffer so that this can be reused
/// for all columns in an image.
// TODO: faster, more formats
pub fn column_running_sum(image: &GrayImage, column: u32, buffer: &mut [u32], padding: u32) {

    let (width, height) = image.dimensions();
    assert!(buffer.len() >= (height + 2 * padding) as usize,
        format!("Buffer length {} is less than {} + 2 * {}", buffer.len(), height, padding));
    assert!(column < width, format!("column out of bounds: {} >= {}", column, width));

    unsafe {
        let mut sum = 0;
        for y in 0..padding {
            sum += image.unsafe_get_pixel(column, 0)[0] as u32;
            *buffer.get_unchecked_mut(y as usize) = sum;
        }

        for y in 0..height {
            sum += image.unsafe_get_pixel(column, y)[0] as u32;
            *buffer.get_unchecked_mut((y + padding) as usize) = sum;
        }

        for y in 0..padding {
            sum += image.unsafe_get_pixel(column, height - 1)[0] as u32;
            *buffer.get_unchecked_mut((y + height + padding) as usize) = sum;
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use utils::{
        gray_bench_image,
        GrayTestImage,
        pixel_diff_summary
    };
    use image::{
        GenericImage,
        ImageBuffer,
        Luma
    };
    use quickcheck::{
        quickcheck,
        TestResult
    };
    use definitions::{
        Image
    };
    use test;

    #[test]
    fn test_sum_image_pixels() {
        let image = gray_image!(
            1, 2;
            3, 4);

        let integral = ::integralimage::integral_image(&image);

        assert_eq!(sum_image_pixels(&integral, 0, 0, 0, 0), 1);
        assert_eq!(sum_image_pixels(&integral, 0, 0, 1, 0), 3);
        assert_eq!(sum_image_pixels(&integral, 0, 0, 0, 1), 4);
        assert_eq!(sum_image_pixels(&integral, 0, 0, 1, 1), 10);
        assert_eq!(sum_image_pixels(&integral, 1, 0, 1, 0), 2);
        assert_eq!(sum_image_pixels(&integral, 1, 0, 1, 1), 6);
        assert_eq!(sum_image_pixels(&integral, 0, 1, 0, 1), 3);
        assert_eq!(sum_image_pixels(&integral, 0, 1, 1, 1), 7);
        assert_eq!(sum_image_pixels(&integral, 1, 1, 1, 1), 4);
    }

    #[test]
    fn test_integral_image() {
        let image = gray_image!(
            1, 2, 3;
            4, 5, 6);

        let expected = gray_image_u32!(
            0,  0,  0,  0;
            0,  1,  3,  6;
            0,  5, 12, 21);

        assert_pixels_eq!(integral_image(&image), expected);
    }

    #[bench]
    fn bench_integral_image(b: &mut test::Bencher) {
        let image = gray_bench_image(500, 500);
        b.iter(|| {
            let integral = integral_image(&image);
            test::black_box(integral);
            });
    }

    /// Simple implementation of integral_image to validate faster versions against.
    fn integral_image_ref<I>(image: &I) -> Image<Luma<u32>>
        where I: GenericImage<Pixel=Luma<u8>>
    {
        let (in_width, in_height) = image.dimensions();
        let (out_width, out_height) = (in_width + 1, in_height + 1);
        let mut out = ImageBuffer::from_pixel(out_width, out_height, Luma([0u32]));

        for y in 1..out_height {
            for x in 0..out_width {
                let mut sum = 0u32;

                for iy in 0..y {
                    for ix in 0..x {
                        sum += image.get_pixel(ix, iy)[0] as u32;
                    }
                }

                out.put_pixel(x, y, Luma([sum]));
            }
        }

        out
    }

    #[test]
    fn test_integral_image_matches_reference_implementation() {
        fn prop(image: GrayTestImage) -> TestResult {
            let expected = integral_image_ref(&image.0);
            let actual = integral_image(&image.0);
            match pixel_diff_summary(&actual, &expected) {
                None => TestResult::passed(),
                Some(err) => TestResult::error(err)
            }
        }
        quickcheck(prop as fn(GrayTestImage) -> TestResult);
    }

    #[test]
    fn test_row_running_sum() {
        let image = gray_image!(
            1, 2, 3;
            4, 5, 6);

        let expected = [1, 2, 4, 7, 10];

        let mut buffer = [0; 5];
        row_running_sum(&image, 0, &mut buffer, 1);

        assert_eq!(buffer, expected);
    }

    #[bench]
    fn bench_row_running_sum(b: &mut test::Bencher) {
        let image = gray_bench_image(1000, 1);
        let mut buffer = [0; 1010];
        b.iter(|| {
            row_running_sum(&image, 0, &mut buffer, 5);
            });
    }

    #[test]
    fn test_column_running_sum() {
        let image = gray_image!(
            1, 4;
            2, 5;
            3, 6);

        let expected = [1, 2, 4, 7, 10];

        let mut buffer = [0; 5];
        column_running_sum(&image, 0, &mut buffer, 1);

        assert_eq!(buffer, expected);
    }

    #[bench]
    fn bench_column_running_sum(b: &mut test::Bencher) {
        let image = gray_bench_image(100, 1000);
        let mut buffer = [0; 1010];
        b.iter(|| {
            column_running_sum(&image, 0, &mut buffer, 5);
            });
    }
}
<|endoftext|>


<commit_before>// these are all unstable...
#![feature(io)]
#![feature(fs)]
#![feature(old_path)]
#![feature(core)]

extern crate "basic-hll" as hll;

#[cfg(test)]
mod tests {

    use std::num::{ Int, Float };
    use std::io::{ BufReader, BufReadExt };
    use std::fs::File;

    use hll::*;

    #[test]
    fn can_estimate_a_small_range_subset_of_the_system_dictionary () {
        let path = Path::new("/usr/share/dict/words");
        let file = BufReader::new(File::open(&path).unwrap());
        let mut store = HLL::new(0.0040625);
        let mut count = 0f64;
        let actual = 60000.0f64;

        for line in file.lines() {
            count += 1.0;
            if count > actual {
                break;
            }
            store.insert(&line.unwrap());
        }

        let count = store.count();
        let error = 1.04 / 65536.0f64.sqrt();

        if  (1.0 - (count / actual)) > error {
            panic!("expected {} to be within {} of {} (but was {})", count, error, actual, 1.0 - (count / actual));
        }
    }

    #[test]
    fn can_estimate_a_large_sequence_of_floating_points () {
        let limit = 2i64.pow(20);
        let mut store = HLL::new(0.0040625);
        let mut counter = 0i64;

        loop {
            store.insert(&counter);
            counter += 1;
            if counter > limit {
                break;
            }
        }

        let count = store.count();
        let error = 1.04 / 65536.0f64.sqrt();

        if (1.0 - (count / limit as f64)).abs() > error {
            panic!("expected {} to be within {} of {} (but was {})"
                   , count, error, limit, 1.0 - (count / limit as f64).abs());
        }
    }

}
<commit_msg>Use std::path::Path rather than old_path<commit_after>// these are all unstable...
#![feature(io)]
#![feature(fs)]
#![feature(path)]
#![feature(core)]

extern crate "basic-hll" as hll;

#[cfg(test)]
mod tests {

    use std::num::{ Int, Float };
    use std::io::{ BufReader, BufReadExt };
    use std::fs::File;
    use std::path::Path;

    use hll::*;

    #[test]
    fn can_estimate_a_small_range_subset_of_the_system_dictionary () {
        let path = Path::new("/usr/share/dict/words");
        let file = BufReader::new(File::open(&path).unwrap());
        let mut store = HLL::new(0.0040625);
        let mut count = 0f64;
        let actual = 60000.0f64;

        for line in file.lines() {
            count += 1.0;
            if count > actual {
                break;
            }
            store.insert(&line.unwrap());
        }

        let count = store.count();
        let error = 1.04 / 65536.0f64.sqrt();

        if  (1.0 - (count / actual)) > error {
            panic!("expected {} to be within {} of {} (but was {})", count, error, actual, 1.0 - (count / actual));
        }
    }

    #[test]
    fn can_estimate_a_large_sequence_of_floating_points () {
        let limit = 2i64.pow(20);
        let mut store = HLL::new(0.0040625);
        let mut counter = 0i64;

        loop {
            store.insert(&counter);
            counter += 1;
            if counter > limit {
                break;
            }
        }

        let count = store.count();
        let error = 1.04 / 65536.0f64.sqrt();

        if (1.0 - (count / limit as f64)).abs() > error {
            panic!("expected {} to be within {} of {} (but was {})"
                   , count, error, limit, 1.0 - (count / limit as f64).abs());
        }
    }

}
<|endoftext|>


<commit_before>#[macro_use]
extern crate lazy_static;
extern crate regex;

use std::collections::{HashMap, HashSet};
use std::io::Read;
use std::fs::File;

use regex::Regex;

lazy_static! {
    static ref WORDS: HashMap<String, usize> = {
        let mut f = File::open("data/big.txt").unwrap();
        let mut s = String::new();
        f.read_to_string(&mut s).unwrap();

        // Count occurrences of words found in `big.txt`
        let mut words = HashMap::new();

        for word in Regex::new(r"\W+").unwrap().split(&s) {
            let count = words.entry(word.to_lowercase()).or_insert(0);
            *count += 1;
        }

        return words;
    };
}

/// Most probable spelling correction for `word`.
pub fn correction(word: &str) -> String {
    if word == "" {
        return String::from("");
    }

    let mut best_match = word.to_string();
    let mut best_score = 0;

    for candidate in candidates(word) {
        if let Some(score) = WORDS.get(&candidate) {
            if *score > best_score {
                best_score = *score;
                best_match = candidate;
            }
        }
    }

    return best_match.to_string();
}

/// Generate possible spelling corrections for `word`.
fn candidates(word: &str) -> HashSet<String> {
    let mut word_set = HashSet::new();
    word_set.insert(word.to_string());

    if let Some(set) = known(word_set) {
        return set;
    } else if let Some(set) = known(edits(word)) {
        return set;
    } else if let Some(set) = known(edits2(word)) {
        return set;
    } else {
        let mut word_set = HashSet::new();
        word_set.insert(word.to_string());
        return word_set;
    }
}

/// The subset of `words` that appear in the dictionary of WORDS
fn known(words: HashSet<String>) -> Option<HashSet<String>> {
    let mut known_words = HashSet::new();

    for word in words {
        if WORDS.contains_key(&word) {
            known_words.insert(word);
        }
    }

    match known_words.len() {
        0 => None,
        _ => Some(known_words),
    }
}

/// All edits that are one edit away from `word`.
fn edits(word: &str) -> HashSet<String> {
    let letters = "abcdefghijklmnopqrstuvwxyz";

    // Construct vector of split variants of `word`
    // ghoti -> [("", "ghoti"), ("g", "hoti"), ... ("ghot", "i")]
    let mut splits: Vec<(&str, &str)> = Vec::new();
    for i in 0..word.len() {
        splits.push((&word[..i], &word[i..]));
    }

    let mut all_edits: HashSet<String> = HashSet::new();

    // Iterate through different edit permutations
    for (i, &(left, right)) in splits.iter().enumerate() {
        // Deletions
        let mut deletion = left.to_string();
        deletion += &right[1..];
        all_edits.insert(deletion);

        // Transpositions
        // Skip the final split to ensure `right` contains > 1 character
        if i < splits.len() - 1 {
            let mut transposition = left.to_string();
            transposition.push(right.chars().nth(1).unwrap());
            transposition.push(right.chars().nth(0).unwrap());
            transposition += &right[2..];
            all_edits.insert(transposition);
        }

        for letter in letters.chars() {
            // Replacements
            let mut replacement = left.to_string();
            replacement.push(letter);
            replacement += &right[1..];
            all_edits.insert(replacement);

            // Insertions
            let mut insertion = left.to_string();
            insertion.push(letter);
            insertion += right;
            all_edits.insert(insertion);
        }
    }

    // Insertions at end of word (appends?)
    for letter in letters.chars() {
        let mut insertion = word.to_string();
        insertion.push(letter);
        all_edits.insert(insertion);
    }

    return all_edits;
}

/// All edits that are two edits away from `word`
fn edits2(word: &str) -> HashSet<String> {
    let mut all_edits = HashSet::new();

    for single_edits in edits(word) {
        for edit in edits(&single_edits) {
            all_edits.insert(edit);
        }
    }

    return all_edits;
}

#[test]
fn edit_count() {
    // Words of length n > 1 will have:
    // - n deletions
    // - n-1 transpositions
    // - 26n replacements
    // - 26(n+1) insertions
    // = 54n + 25 total edits

    let test_word = "!@#$%^&*()";

    for i in 1..(test_word.len() + 1) {
        assert_eq!(edits(&test_word[..i]).len(), 54*i + 25);
    }
}

#[test]
fn possible_candidates() {
    let candidates = candidates("ct");
    assert!(candidates.contains("cat"));
    assert!(candidates.contains("cot"));
    assert!(candidates.contains("cut"));
    assert!(!candidates.contains("czt"));
}
<commit_msg>Expand binary assignment operations for strings<commit_after>#[macro_use]
extern crate lazy_static;
extern crate regex;

use std::collections::{HashMap, HashSet};
use std::io::Read;
use std::fs::File;

use regex::Regex;

lazy_static! {
    static ref WORDS: HashMap<String, usize> = {
        let mut f = File::open("data/big.txt").unwrap();
        let mut s = String::new();
        f.read_to_string(&mut s).unwrap();

        // Count occurrences of words found in `big.txt`
        let mut words = HashMap::new();

        for word in Regex::new(r"\W+").unwrap().split(&s) {
            let count = words.entry(word.to_lowercase()).or_insert(0);
            *count += 1;
        }

        return words;
    };
}

/// Most probable spelling correction for `word`.
pub fn correction(word: &str) -> String {
    if word == "" {
        return String::from("");
    }

    let mut best_match = word.to_string();
    let mut best_score = 0;

    for candidate in candidates(word) {
        if let Some(score) = WORDS.get(&candidate) {
            if *score > best_score {
                best_score = *score;
                best_match = candidate;
            }
        }
    }

    return best_match.to_string();
}

/// Generate possible spelling corrections for `word`.
fn candidates(word: &str) -> HashSet<String> {
    let mut word_set = HashSet::new();
    word_set.insert(word.to_string());

    if let Some(set) = known(word_set) {
        return set;
    } else if let Some(set) = known(edits(word)) {
        return set;
    } else if let Some(set) = known(edits2(word)) {
        return set;
    } else {
        let mut word_set = HashSet::new();
        word_set.insert(word.to_string());
        return word_set;
    }
}

/// The subset of `words` that appear in the dictionary of WORDS
fn known(words: HashSet<String>) -> Option<HashSet<String>> {
    let mut known_words = HashSet::new();

    for word in words {
        if WORDS.contains_key(&word) {
            known_words.insert(word);
        }
    }

    match known_words.len() {
        0 => None,
        _ => Some(known_words),
    }
}

/// All edits that are one edit away from `word`.
fn edits(word: &str) -> HashSet<String> {
    let letters = "abcdefghijklmnopqrstuvwxyz";

    // Construct vector of split variants of `word`
    // ghoti -> [("", "ghoti"), ("g", "hoti"), ... ("ghot", "i")]
    let mut splits: Vec<(&str, &str)> = Vec::new();
    for i in 0..word.len() {
        splits.push((&word[..i], &word[i..]));
    }

    let mut all_edits: HashSet<String> = HashSet::new();

    // Iterate through different edit permutations
    for (i, &(left, right)) in splits.iter().enumerate() {
        // Deletions
        let mut deletion = left.to_string();
        deletion = deletion + &right[1..];
        all_edits.insert(deletion);

        // Transpositions
        // Skip the final split to ensure `right` contains > 1 character
        if i < splits.len() - 1 {
            let mut transposition = left.to_string();
            transposition.push(right.chars().nth(1).unwrap());
            transposition.push(right.chars().nth(0).unwrap());
            transposition = transposition + &right[2..];
            all_edits.insert(transposition);
        }

        for letter in letters.chars() {
            // Replacements
            let mut replacement = left.to_string();
            replacement.push(letter);
            replacement = replacement + &right[1..];
            all_edits.insert(replacement);

            // Insertions
            let mut insertion = left.to_string();
            insertion.push(letter);
            insertion = insertion + right;
            all_edits.insert(insertion);
        }
    }

    // Insertions at end of word (appends?)
    for letter in letters.chars() {
        let mut insertion = word.to_string();
        insertion.push(letter);
        all_edits.insert(insertion);
    }

    return all_edits;
}

/// All edits that are two edits away from `word`
fn edits2(word: &str) -> HashSet<String> {
    let mut all_edits = HashSet::new();

    for single_edits in edits(word) {
        for edit in edits(&single_edits) {
            all_edits.insert(edit);
        }
    }

    return all_edits;
}

#[test]
fn edit_count() {
    // Words of length n > 1 will have:
    // - n deletions
    // - n-1 transpositions
    // - 26n replacements
    // - 26(n+1) insertions
    // = 54n + 25 total edits

    let test_word = "!@#$%^&*()";

    for i in 1..(test_word.len() + 1) {
        assert_eq!(edits(&test_word[..i]).len(), 54*i + 25);
    }
}

#[test]
fn possible_candidates() {
    let candidates = candidates("ct");
    assert!(candidates.contains("cat"));
    assert!(candidates.contains("cot"));
    assert!(candidates.contains("cut"));
    assert!(!candidates.contains("czt"));
}
<|endoftext|>