<commit_before>use std::path::PathBuf;

pub use self::imp::*;

#[cfg(target_family = "unix")]
mod imp {
    use std::io::Result;
    use std::path::PathBuf;
    use std::process::Command;

    pub struct Process {
        pid: i32,
    }

    impl Process {
        pub fn new(cmd: &str, updated_paths: Vec<PathBuf>) -> Result<Process> {
            use std::io;
            use std::os::unix::process::CommandExt;
            use nix::unistd::setpgid;

            let mut command = Command::new("sh");
            command.arg("-c").arg(cmd);

            if let Some(single_path) = super::get_single_updated_path(&updated_paths) {
                command.env("WATCHEXEC_UPDATED_PATH", single_path);
            }

            if let Some(common_path) = super::get_longest_common_path(&updated_paths) {
                command.env("WATCHEXEC_COMMON_PATH", common_path);
            }

            command.before_exec(|| setpgid(0, 0).map_err(io::Error::from))
                .spawn()
                .and_then(|p| Ok(Process { pid: p.id() as i32 }))
        }

        pub fn kill(&self) {
            use libc;

            extern "C" {
                fn killpg(pgrp: libc::pid_t, sig: libc::c_int) -> libc::c_int;
            }

            unsafe {
                killpg(self.pid, libc::SIGTERM);
            }
        }

        pub fn wait(&self) {
            use nix::sys::wait::waitpid;

            let _ = waitpid(-self.pid, None);
        }
    }
}

#[cfg(target_family = "windows")]
mod imp {
    use std::io;
    use std::io::Result;
    use std::mem;
    use std::path::PathBuf;
    use std::process::Command;
    use kernel32::*;
    use winapi::*;

    pub struct Process {
        job: HANDLE,
    }

    impl Process {
        pub fn new(cmd: &str, updated_paths: Vec<PathBuf>) -> Result<Process> {
            use std::os::windows::io::IntoRawHandle;

            fn last_err() -> io::Error {
                io::Error::last_os_error()
            }

            let job = unsafe { CreateJobObjectW(0 as *mut _, 0 as *const _) };
            if job.is_null() {
                panic!("failed to create job object: {}", last_err());
            }

            let mut info: JOBOBJECT_EXTENDED_LIMIT_INFORMATION = unsafe { mem::zeroed() };
            info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
            let r = unsafe {
                SetInformationJobObject(job,
                                        JobObjectExtendedLimitInformation,
                                        &mut info as *mut _ as LPVOID,
                                        mem::size_of_val(&info) as DWORD)
            };
            if r == 0 {
                panic!("failed to set job info: {}", last_err());
            }

            let mut command = Command::new("cmd.exe");
            command.arg("/C").arg(cmd);

            if let Some(single_path) = super::get_single_updated_path(&updated_paths) {
                command.env("WATCHEXEC_UPDATED_PATH", single_path);
            }

            if let Some(common_path) = super::get_longest_common_path(&updated_paths) {
                command.env("WATCHEXEC_COMMON_PATH", common_path);
            }

            command.spawn()
                .and_then(|p| {
                    let r = unsafe { AssignProcessToJobObject(job, p.into_raw_handle()) };
                    if r == 0 {
                        panic!("failed to add to job object: {}", last_err());
                    }

                    Ok(Process { job: job })
                })
        }

        pub fn kill(&self) {
            unsafe {
                let _ = TerminateJobObject(self.job, 1);
            }
        }

        pub fn wait(&self) {
            unsafe {
                let _ = WaitForSingleObject(self.job, INFINITE);
            }
        }
    }

    impl Drop for Process {
        fn drop(&mut self) {
            unsafe {
                let _ = CloseHandle(self.job);
            }
        }
    }

    unsafe impl Send for Process {}
    unsafe impl Sync for Process {}
}

fn get_single_updated_path(paths: &[PathBuf]) -> Option<&str> {
    paths.get(0).and_then(|p| p.to_str())
}

fn get_longest_common_path(paths: &[PathBuf]) -> Option<String> {
    match paths.len() {
        0 => return None,
        1 => return paths[0].to_str().map(|ref_val| ref_val.to_string()),
        _ => {}
    };

    let mut longest_path: Vec<_> = paths[0].components().collect();

    for path in &paths[1..] {
        let mut greatest_distance = 0;
        for component_pair in path.components().zip(longest_path.iter()) {
            if component_pair.0 != *component_pair.1 {
                break;
            }

            greatest_distance += 1;
        }

        if greatest_distance != longest_path.len() {
            longest_path.truncate(greatest_distance);
        }
    }

    let mut result = PathBuf::new();
    for component in longest_path {
        result.push(component.as_os_str());
    }

    result.to_str().map(|ref_val| ref_val.to_string())
}

#[cfg(test)]
#[cfg(target_family = "unix")]
mod tests {
    use std::path::{Path, PathBuf};
    use std::thread;
    use std::time::Duration;

    use mktemp::Temp;

    use super::imp::Process;
    use super::get_longest_common_path;

    fn file_contents(path: &Path) -> String {
        use std::fs::File;
        use std::io::Read;

        let mut f = File::open(path).unwrap();
        let mut s = String::new();
        f.read_to_string(&mut s).unwrap();

        s
    }

    #[test]
    fn test_start() {
        let process = Process::new("echo hi", vec![]);

        assert!(process.is_ok());
    }

    #[test]
    fn test_wait() {
        let file = Temp::new_file().unwrap();
        let path = file.to_path_buf();
        let mut process = Process::new(&format!("echo hi > {}", path.to_str().unwrap()), vec![])
            .unwrap();
        process.wait();

        assert!(file_contents(&path).starts_with("hi"));
    }

    #[test]
    fn test_kill() {
        let file = Temp::new_file().unwrap();
        let path = file.to_path_buf();

        let mut process = Process::new(&format!("sleep 20; echo hi > {}", path.to_str().unwrap()),
                                       vec![])
            .unwrap();
        thread::sleep(Duration::from_millis(250));
        process.kill();
        process.wait();

        assert!(file_contents(&path) == "");
    }

    #[test]
    fn longest_common_path_should_return_correct_value() {
        let single_path = vec![PathBuf::from("/tmp/random/")];
        let single_result = get_longest_common_path(&single_path).unwrap();
        assert_eq!(single_result, "/tmp/random/");

        let common_paths = vec![PathBuf::from("/tmp/logs/hi"),
                                PathBuf::from("/tmp/logs/bye"),
                                PathBuf::from("/tmp/logs/bye"),
                                PathBuf::from("/tmp/logs/fly")];

        let common_result = get_longest_common_path(&common_paths).unwrap();
        assert_eq!(common_result, "/tmp/logs");

        let diverging_paths = vec![PathBuf::from("/tmp/logs/hi"), PathBuf::from("/var/logs/hi")];

        let diverging_result = get_longest_common_path(&diverging_paths).unwrap();
        assert_eq!(diverging_result, "/");

        let uneven_paths = vec![PathBuf::from("/tmp/logs/hi"),
                                PathBuf::from("/tmp/logs/"),
                                PathBuf::from("/tmp/logs/bye")];

        let uneven_result = get_longest_common_path(&uneven_paths).unwrap();
        assert_eq!(uneven_result, "/tmp/logs");
    }
}
<commit_msg>Fix warnings in tests<commit_after>use std::path::PathBuf;

pub use self::imp::*;

#[cfg(target_family = "unix")]
mod imp {
    use std::io::Result;
    use std::path::PathBuf;
    use std::process::Command;

    pub struct Process {
        pid: i32,
    }

    impl Process {
        pub fn new(cmd: &str, updated_paths: Vec<PathBuf>) -> Result<Process> {
            use std::io;
            use std::os::unix::process::CommandExt;
            use nix::unistd::setpgid;

            let mut command = Command::new("sh");
            command.arg("-c").arg(cmd);

            if let Some(single_path) = super::get_single_updated_path(&updated_paths) {
                command.env("WATCHEXEC_UPDATED_PATH", single_path);
            }

            if let Some(common_path) = super::get_longest_common_path(&updated_paths) {
                command.env("WATCHEXEC_COMMON_PATH", common_path);
            }

            command.before_exec(|| setpgid(0, 0).map_err(io::Error::from))
                .spawn()
                .and_then(|p| Ok(Process { pid: p.id() as i32 }))
        }

        pub fn kill(&self) {
            use libc;

            extern "C" {
                fn killpg(pgrp: libc::pid_t, sig: libc::c_int) -> libc::c_int;
            }

            unsafe {
                killpg(self.pid, libc::SIGTERM);
            }
        }

        pub fn wait(&self) {
            use nix::sys::wait::waitpid;

            let _ = waitpid(-self.pid, None);
        }
    }
}

#[cfg(target_family = "windows")]
mod imp {
    use std::io;
    use std::io::Result;
    use std::mem;
    use std::path::PathBuf;
    use std::process::Command;
    use kernel32::*;
    use winapi::*;

    pub struct Process {
        job: HANDLE,
    }

    impl Process {
        pub fn new(cmd: &str, updated_paths: Vec<PathBuf>) -> Result<Process> {
            use std::os::windows::io::IntoRawHandle;

            fn last_err() -> io::Error {
                io::Error::last_os_error()
            }

            let job = unsafe { CreateJobObjectW(0 as *mut _, 0 as *const _) };
            if job.is_null() {
                panic!("failed to create job object: {}", last_err());
            }

            let mut info: JOBOBJECT_EXTENDED_LIMIT_INFORMATION = unsafe { mem::zeroed() };
            info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
            let r = unsafe {
                SetInformationJobObject(job,
                                        JobObjectExtendedLimitInformation,
                                        &mut info as *mut _ as LPVOID,
                                        mem::size_of_val(&info) as DWORD)
            };
            if r == 0 {
                panic!("failed to set job info: {}", last_err());
            }

            let mut command = Command::new("cmd.exe");
            command.arg("/C").arg(cmd);

            if let Some(single_path) = super::get_single_updated_path(&updated_paths) {
                command.env("WATCHEXEC_UPDATED_PATH", single_path);
            }

            if let Some(common_path) = super::get_longest_common_path(&updated_paths) {
                command.env("WATCHEXEC_COMMON_PATH", common_path);
            }

            command.spawn()
                .and_then(|p| {
                    let r = unsafe { AssignProcessToJobObject(job, p.into_raw_handle()) };
                    if r == 0 {
                        panic!("failed to add to job object: {}", last_err());
                    }

                    Ok(Process { job: job })
                })
        }

        pub fn kill(&self) {
            unsafe {
                let _ = TerminateJobObject(self.job, 1);
            }
        }

        pub fn wait(&self) {
            unsafe {
                let _ = WaitForSingleObject(self.job, INFINITE);
            }
        }
    }

    impl Drop for Process {
        fn drop(&mut self) {
            unsafe {
                let _ = CloseHandle(self.job);
            }
        }
    }

    unsafe impl Send for Process {}
    unsafe impl Sync for Process {}
}

fn get_single_updated_path(paths: &[PathBuf]) -> Option<&str> {
    paths.get(0).and_then(|p| p.to_str())
}

fn get_longest_common_path(paths: &[PathBuf]) -> Option<String> {
    match paths.len() {
        0 => return None,
        1 => return paths[0].to_str().map(|ref_val| ref_val.to_string()),
        _ => {}
    };

    let mut longest_path: Vec<_> = paths[0].components().collect();

    for path in &paths[1..] {
        let mut greatest_distance = 0;
        for component_pair in path.components().zip(longest_path.iter()) {
            if component_pair.0 != *component_pair.1 {
                break;
            }

            greatest_distance += 1;
        }

        if greatest_distance != longest_path.len() {
            longest_path.truncate(greatest_distance);
        }
    }

    let mut result = PathBuf::new();
    for component in longest_path {
        result.push(component.as_os_str());
    }

    result.to_str().map(|ref_val| ref_val.to_string())
}

#[cfg(test)]
#[cfg(target_family = "unix")]
mod tests {
    use std::path::{Path, PathBuf};
    use std::thread;
    use std::time::Duration;

    use mktemp::Temp;

    use super::imp::Process;
    use super::get_longest_common_path;

    fn file_contents(path: &Path) -> String {
        use std::fs::File;
        use std::io::Read;

        let mut f = File::open(path).unwrap();
        let mut s = String::new();
        f.read_to_string(&mut s).unwrap();

        s
    }

    #[test]
    fn test_start() {
        let process = Process::new("echo hi", vec![]);

        assert!(process.is_ok());
    }

    #[test]
    fn test_wait() {
        let file = Temp::new_file().unwrap();
        let path = file.to_path_buf();
        let process = Process::new(&format!("echo hi > {}", path.to_str().unwrap()), vec![])
            .unwrap();
        process.wait();

        assert!(file_contents(&path).starts_with("hi"));
    }

    #[test]
    fn test_kill() {
        let file = Temp::new_file().unwrap();
        let path = file.to_path_buf();

        let process = Process::new(&format!("sleep 20; echo hi > {}", path.to_str().unwrap()),
                                       vec![])
            .unwrap();
        thread::sleep(Duration::from_millis(250));
        process.kill();
        process.wait();

        assert!(file_contents(&path) == "");
    }

    #[test]
    fn longest_common_path_should_return_correct_value() {
        let single_path = vec![PathBuf::from("/tmp/random/")];
        let single_result = get_longest_common_path(&single_path).unwrap();
        assert_eq!(single_result, "/tmp/random/");

        let common_paths = vec![PathBuf::from("/tmp/logs/hi"),
                                PathBuf::from("/tmp/logs/bye"),
                                PathBuf::from("/tmp/logs/bye"),
                                PathBuf::from("/tmp/logs/fly")];

        let common_result = get_longest_common_path(&common_paths).unwrap();
        assert_eq!(common_result, "/tmp/logs");

        let diverging_paths = vec![PathBuf::from("/tmp/logs/hi"), PathBuf::from("/var/logs/hi")];

        let diverging_result = get_longest_common_path(&diverging_paths).unwrap();
        assert_eq!(diverging_result, "/");

        let uneven_paths = vec![PathBuf::from("/tmp/logs/hi"),
                                PathBuf::from("/tmp/logs/"),
                                PathBuf::from("/tmp/logs/bye")];

        let uneven_result = get_longest_common_path(&uneven_paths).unwrap();
        assert_eq!(uneven_result, "/tmp/logs");
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

use std::collections::HashMap;
use rustc_serialize::json;

/// This enum represents the various types of HTTP requests.
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
pub enum Method {
    Get,
    Put,
    Post,
    Delete,
    NoImpl,
}

/// A trait that allows for extracting variables from URIs.
pub trait FromUri {
    /// A function to parse a string into the correct type.
    fn from_uri(data: &str) -> Self;
}

impl FromUri for String {
    fn from_uri(data: &str) -> String {
        String::from(data)
    }
}

impl FromUri for i32 {
    fn from_uri(data: &str) -> i32 {
        match data.parse::<i32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched integer can't be parsed: {:?}", e),
        }
    }
}

impl FromUri for u32 {
    fn from_uri(data: &str) -> u32 {
        match data.parse::<u32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched integer can't be parsed: {:?}", e),
        }
    }
}

impl FromUri for f32 {
    fn from_uri(data: &str) -> f32 {
        match data.parse::<f32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched float can't be parsed: {:?}", e),
        }
    }
}

/// This struct represents a request from an HTTP client.
#[derive(Debug)]
pub struct Request {
    pub method:  Method,
    pub path:    String,
    pub payload: Vec<u8>,
    pub params:  HashMap<String, String>,
    headers:     HashMap<String, String>,
}

impl Request {
    /// Create a new, empty Request.
    pub fn new() -> Request {
        Request {
            method:  Method::NoImpl,
            path:    String::new(),
            headers: HashMap::new(),
            params:  HashMap::new(),
            payload: Vec::with_capacity(2048),
        }
    }

    /// Create a Request from an HTTP request string.
    pub fn from_str(rqstr: &str) -> Request {
        let mut req = Request::new();
        req.parse(rqstr);
        req
    }

    /// Get a variable from the URI.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the route "/hello/<str:name>"
    /// fn handler(req: &Request) -> Response {
    ///     let name: String = req.get("name");
    ///     utils::make_response(format!("<b>Hello, {}!</b>", name), "text/html", 200)
    /// }
    /// ```
    pub fn get<T: FromUri>(&self, name: &str) -> T {
        if !self.params.contains_key(name) {
            panic!("invalid route parameter {:?}", name);
        }

        FromUri::from_uri(&self.params[name])
    }

    /// Get a raw JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data = req.get_json();
    ///
    ///     match data {
    ///         Some(val) => utils::make_response(format!("We got: {}", val), "text/plain", 200),
    ///         None      => utils::make_response("We got nothing :(", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_json(&self) -> Option<json::Json> {
        match String::from_utf8(self.payload.clone()) {
            Err(_)      => None,
            Ok(payload) => {
                match json::Json::from_str(&payload) {
                    Ok(data)    => Some(data),
                    Err(_)      => None,
                }
            }
        }
    }

    fn parse(&mut self, rqstr: &str) {
        let mut buf: Vec<&str> = rqstr.splitn(2, "\r\n").collect();
        let ask: Vec<&str> = buf[0].splitn(3, ' ').collect();

        self.method = match ask[0] {
            "GET"           => Method::Get,
            "PUT" | "PATCH" => Method::Put,
            "POST"          => Method::Post,
            "DELETE"        => Method::Delete,
            _               => Method::NoImpl,
        };
        self.path = String::from(ask[1]);

        loop {
            buf = buf[1].splitn(2, "\r\n").collect();

            if buf[0] == "" {
                if buf.len() == 1 || buf[1] == "" {
                    // no payload
                    break;
                }

                self.payload.extend(buf[1].as_bytes());
                break;
            }

            let hdr: Vec<&str> = buf[0].splitn(2, ": ").collect();

            if hdr.len() == 2 {
                self.headers.insert(String::from(hdr[0]), String::from(hdr[1]));
            }
        }
    }
}

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

    #[test]
    fn test_fromuri_trait_i32() {
        let pos = String::from("1234");
        assert_eq!(1234, FromUri::from_uri(&pos));

        let neg = String::from("-4321");
        assert_eq!(-4321, FromUri::from_uri(&neg));
    }

    #[test]
    fn test_fromuri_trait_u32() {
        let orig = String::from("1234");
        assert_eq!(1234, FromUri::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_string() {
        let orig = String::from("foobar");
        assert_eq!("foobar", <String as FromUri>::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_float() {
        let pos = String::from("123.45");
        assert_eq!(123.45f32, FromUri::from_uri(&pos));

        let neg = String::from("-54.321");
        assert_eq!(-54.321f32, FromUri::from_uri(&neg));
    }

    #[test]
    fn test_get_fromuri_i32() {
        let mut req = Request::new();
        req.params.insert(String::from("test"), String::from("1234"));

        assert_eq!(1234, req.get("test"));
    }

    #[test]
    fn test_get_json() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"foo\": 123 }".as_bytes());

        let data = req.get_json().unwrap();

        assert_eq!(true, data.is_object());

        let obj = data.as_object().unwrap();
        let val = obj.get("foo").unwrap();

        assert_eq!(true, val.is_u64());
        assert_eq!(123u64, val.as_u64().unwrap());
    }
}
<commit_msg>add Request::get_json_obj() which will decode into a structure that's derived RustcDecodable<commit_after>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

use std::collections::HashMap;
use rustc_serialize::{json, Decodable};

/// This enum represents the various types of HTTP requests.
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
pub enum Method {
    Get,
    Put,
    Post,
    Delete,
    NoImpl,
}

/// A trait that allows for extracting variables from URIs.
pub trait FromUri {
    /// A function to parse a string into the correct type.
    fn from_uri(data: &str) -> Self;
}

impl FromUri for String {
    fn from_uri(data: &str) -> String {
        String::from(data)
    }
}

impl FromUri for i32 {
    fn from_uri(data: &str) -> i32 {
        match data.parse::<i32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched integer can't be parsed: {:?}", e),
        }
    }
}

impl FromUri for u32 {
    fn from_uri(data: &str) -> u32 {
        match data.parse::<u32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched integer can't be parsed: {:?}", e),
        }
    }
}

impl FromUri for f32 {
    fn from_uri(data: &str) -> f32 {
        match data.parse::<f32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched float can't be parsed: {:?}", e),
        }
    }
}

/// This struct represents a request from an HTTP client.
#[derive(Debug)]
pub struct Request {
    pub method:  Method,
    pub path:    String,
    pub payload: Vec<u8>,
    pub params:  HashMap<String, String>,
    headers:     HashMap<String, String>,
}

impl Request {
    /// Create a new, empty Request.
    pub fn new() -> Request {
        Request {
            method:  Method::NoImpl,
            path:    String::new(),
            headers: HashMap::new(),
            params:  HashMap::new(),
            payload: Vec::with_capacity(2048),
        }
    }

    /// Create a Request from an HTTP request string.
    pub fn from_str(rqstr: &str) -> Request {
        let mut req = Request::new();
        req.parse(rqstr);
        req
    }

    /// Get a variable from the URI.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the route "/hello/<str:name>"
    /// fn handler(req: &Request) -> Response {
    ///     let name: String = req.get("name");
    ///     utils::make_response(format!("<b>Hello, {}!</b>", name), "text/html", 200)
    /// }
    /// ```
    pub fn get<T: FromUri>(&self, name: &str) -> T {
        if !self.params.contains_key(name) {
            panic!("invalid route parameter {:?}", name);
        }

        FromUri::from_uri(&self.params[name])
    }

    /// Get a raw JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data = req.get_json();
    ///
    ///     match data {
    ///         Some(val) => utils::make_response(format!("We got: {}", val), "text/plain", 200),
    ///         None      => utils::make_response("We got nothing :(", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_json(&self) -> Option<json::Json> {
        match String::from_utf8(self.payload.clone()) {
            Err(_)      => None,
            Ok(payload) => {
                match json::Json::from_str(&payload) {
                    Ok(data)    => Some(data),
                    Err(_)      => None,
                }
            }
        }
    }

    /// Get a composed JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// use canteen::{Request, Response};
    ///
    /// #[derive(RustcDecodable)]
    /// struct Foo {
    ///     item: i32,
    /// }
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data: Foo = req.get_json_obj();
    ///     utils::make_response(format!("We got: {}!", data.item), "text/html", 200)
    /// }
    /// ```
    pub fn get_json_obj<T: Decodable>(&self) -> Result<T, json::DecoderError> {
        let data = String::from_utf8(self.payload.clone()).unwrap();
        json::decode(&data)
    }

    fn parse(&mut self, rqstr: &str) {
        let mut buf: Vec<&str> = rqstr.splitn(2, "\r\n").collect();
        let ask: Vec<&str> = buf[0].splitn(3, ' ').collect();

        self.method = match ask[0] {
            "GET"           => Method::Get,
            "PUT" | "PATCH" => Method::Put,
            "POST"          => Method::Post,
            "DELETE"        => Method::Delete,
            _               => Method::NoImpl,
        };
        self.path = String::from(ask[1]);

        loop {
            buf = buf[1].splitn(2, "\r\n").collect();

            if buf[0] == "" {
                if buf.len() == 1 || buf[1] == "" {
                    // no payload
                    break;
                }

                self.payload.extend(buf[1].as_bytes());
                break;
            }

            let hdr: Vec<&str> = buf[0].splitn(2, ": ").collect();

            if hdr.len() == 2 {
                self.headers.insert(String::from(hdr[0]), String::from(hdr[1]));
            }
        }
    }
}

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

    #[derive(RustcDecodable)]
    struct Foo {
        item: i32,
    }

    #[test]
    fn test_fromuri_trait_i32() {
        let pos = String::from("1234");
        assert_eq!(1234, FromUri::from_uri(&pos));

        let neg = String::from("-4321");
        assert_eq!(-4321, FromUri::from_uri(&neg));
    }

    #[test]
    fn test_fromuri_trait_u32() {
        let orig = String::from("1234");
        assert_eq!(1234, FromUri::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_string() {
        let orig = String::from("foobar");
        assert_eq!("foobar", <String as FromUri>::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_float() {
        let pos = String::from("123.45");
        assert_eq!(123.45f32, FromUri::from_uri(&pos));

        let neg = String::from("-54.321");
        assert_eq!(-54.321f32, FromUri::from_uri(&neg));
    }

    #[test]
    fn test_get_fromuri_i32() {
        let mut req = Request::new();
        req.params.insert(String::from("test"), String::from("1234"));

        assert_eq!(1234, req.get("test"));
    }

    #[test]
    fn test_get_json() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data = req.get_json().unwrap();

        assert_eq!(true, data.is_object());

        let obj = data.as_object().unwrap();
        let val = obj.get("item").unwrap();

        assert_eq!(true, val.is_u64());
        assert_eq!(123u64, val.as_u64().unwrap());
    }

    #[test]
    fn test_get_json_obj() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data: Foo = req.get_json_obj().unwrap();

        assert_eq!(123, data.item);
    }
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use syntax::ast::*;
use syntax::codemap::{Span, Spanned};
use syntax::visit::FnKind;

use utils::{span_lint, span_lint_and_then, snippet_opt, match_path_ast, in_external_macro};

/// **What it does:** This lint checks for return statements at the end of a block.
///
/// **Why is this bad?** Removing the `return` and semicolon will make the code more rusty.
///
/// **Known problems:** None
///
/// **Example:** `fn foo(x: usize) { return x; }`
declare_lint! {
    pub NEEDLESS_RETURN, Warn,
    "using a return statement like `return expr;` where an expression would suffice"
}

/// **What it does:** This lint checks for `let`-bindings, which are subsequently returned.
///
/// **Why is this bad?** It is just extraneous code. Remove it to make your code more rusty.
///
/// **Known problems:** None
///
/// **Example:** `{ let x = ..; x }`
declare_lint! {
    pub LET_AND_RETURN, Warn,
    "creating a let-binding and then immediately returning it like `let x = expr; x` at \
     the end of a block"
}

#[derive(Copy, Clone)]
pub struct ReturnPass;

impl ReturnPass {
    // Check the final stmt or expr in a block for unnecessary return.
    fn check_block_return(&mut self, cx: &EarlyContext, block: &Block) {
        if let Some(ref expr) = block.expr {
            self.check_final_expr(cx, expr);
        } else if let Some(stmt) = block.stmts.last() {
            if let StmtKind::Semi(ref expr, _) = stmt.node {
                if let ExprKind::Ret(Some(ref inner)) = expr.node {
                    self.emit_return_lint(cx, (stmt.span, inner.span));
                }
            }
        }
    }

    // Check a the final expression in a block if it's a return.
    fn check_final_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
        match expr.node {
            // simple return is always "bad"
            ExprKind::Ret(Some(ref inner)) => {
                self.emit_return_lint(cx, (expr.span, inner.span));
            }
            // a whole block? check it!
            ExprKind::Block(ref block) => {
                self.check_block_return(cx, block);
            }
            // an if/if let expr, check both exprs
            // note, if without else is going to be a type checking error anyways
            // (except for unit type functions) so we don't match it
            ExprKind::If(_, ref ifblock, Some(ref elsexpr)) => {
                self.check_block_return(cx, ifblock);
                self.check_final_expr(cx, elsexpr);
            }
            // a match expr, check all arms
            ExprKind::Match(_, ref arms) => {
                for arm in arms {
                    self.check_final_expr(cx, &arm.body);
                }
            }
            _ => {}
        }
    }

    fn emit_return_lint(&mut self, cx: &EarlyContext, spans: (Span, Span)) {
        if in_external_macro(cx, spans.1) {
            return;
        }
        span_lint_and_then(cx, NEEDLESS_RETURN, spans.0, "unneeded return statement", |db| {
            if let Some(snippet) = snippet_opt(cx, spans.1) {
                db.span_suggestion(spans.0, "remove `return` as shown:", snippet);
            }
        });
    }

    // Check for "let x = EXPR; x"
    fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) {
        // we need both a let-binding stmt and an expr
        if_let_chain! {
            [
                let Some(stmt) = block.stmts.last(),
                let Some(ref retexpr) = block.expr,
                let StmtKind::Decl(ref decl, _) = stmt.node,
                let DeclKind::Local(ref local) = decl.node,
                let Some(ref initexpr) = local.init,
                let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node,
                let ExprKind::Path(_, ref path) = retexpr.node,
                match_path_ast(path, &[&id.name.as_str()])
            ], {
                self.emit_let_lint(cx, retexpr.span, initexpr.span);
            }
        }
    }

    fn emit_let_lint(&mut self, cx: &EarlyContext, lint_span: Span, note_span: Span) {
        if in_external_macro(cx, note_span) {
            return;
        }
        let mut db = span_lint(cx,
                               LET_AND_RETURN,
                               lint_span,
                               "returning the result of a let binding from a block. Consider returning the \
                                expression directly.");
        if cx.current_level(LET_AND_RETURN) != Level::Allow {
            db.span_note(note_span, "this expression can be directly returned");
        }
    }
}

impl LintPass for ReturnPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(NEEDLESS_RETURN, LET_AND_RETURN)
    }
}

impl EarlyLintPass for ReturnPass {
    fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: NodeId) {
        self.check_block_return(cx, block);
    }

    fn check_block(&mut self, cx: &EarlyContext, block: &Block) {
        self.check_let_return(cx, block);
    }
}
<commit_msg>add a note of rust-lang/rust/#31439 to the wiki text<commit_after>use rustc::lint::*;
use syntax::ast::*;
use syntax::codemap::{Span, Spanned};
use syntax::visit::FnKind;

use utils::{span_lint, span_lint_and_then, snippet_opt, match_path_ast, in_external_macro};

/// **What it does:** This lint checks for return statements at the end of a block.
///
/// **Why is this bad?** Removing the `return` and semicolon will make the code more rusty.
///
/// **Known problems:** Following this lint's advice may currently run afoul of Rust issue [#31439](https://github.com/rust-lang/rust/issues/31439), so if you get lifetime errors, please roll back the change until that issue is fixed.
///
/// **Example:** `fn foo(x: usize) { return x; }`
declare_lint! {
    pub NEEDLESS_RETURN, Warn,
    "using a return statement like `return expr;` where an expression would suffice"
}

/// **What it does:** This lint checks for `let`-bindings, which are subsequently returned.
///
/// **Why is this bad?** It is just extraneous code. Remove it to make your code more rusty.
///
/// **Known problems:** Following this lint's advice may currently run afoul of Rust issue [#31439](https://github.com/rust-lang/rust/issues/31439), so if you get lifetime errors, please roll back the change until that issue is fixed.
///
/// **Example:** `{ let x = ..; x }`
declare_lint! {
    pub LET_AND_RETURN, Warn,
    "creating a let-binding and then immediately returning it like `let x = expr; x` at \
     the end of a block"
}

#[derive(Copy, Clone)]
pub struct ReturnPass;

impl ReturnPass {
    // Check the final stmt or expr in a block for unnecessary return.
    fn check_block_return(&mut self, cx: &EarlyContext, block: &Block) {
        if let Some(ref expr) = block.expr {
            self.check_final_expr(cx, expr);
        } else if let Some(stmt) = block.stmts.last() {
            if let StmtKind::Semi(ref expr, _) = stmt.node {
                if let ExprKind::Ret(Some(ref inner)) = expr.node {
                    self.emit_return_lint(cx, (stmt.span, inner.span));
                }
            }
        }
    }

    // Check a the final expression in a block if it's a return.
    fn check_final_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
        match expr.node {
            // simple return is always "bad"
            ExprKind::Ret(Some(ref inner)) => {
                self.emit_return_lint(cx, (expr.span, inner.span));
            }
            // a whole block? check it!
            ExprKind::Block(ref block) => {
                self.check_block_return(cx, block);
            }
            // an if/if let expr, check both exprs
            // note, if without else is going to be a type checking error anyways
            // (except for unit type functions) so we don't match it
            ExprKind::If(_, ref ifblock, Some(ref elsexpr)) => {
                self.check_block_return(cx, ifblock);
                self.check_final_expr(cx, elsexpr);
            }
            // a match expr, check all arms
            ExprKind::Match(_, ref arms) => {
                for arm in arms {
                    self.check_final_expr(cx, &arm.body);
                }
            }
            _ => {}
        }
    }

    fn emit_return_lint(&mut self, cx: &EarlyContext, spans: (Span, Span)) {
        if in_external_macro(cx, spans.1) {
            return;
        }
        span_lint_and_then(cx, NEEDLESS_RETURN, spans.0, "unneeded return statement", |db| {
            if let Some(snippet) = snippet_opt(cx, spans.1) {
                db.span_suggestion(spans.0, "remove `return` as shown:", snippet);
            }
        });
    }

    // Check for "let x = EXPR; x"
    fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) {
        // we need both a let-binding stmt and an expr
        if_let_chain! {
            [
                let Some(stmt) = block.stmts.last(),
                let Some(ref retexpr) = block.expr,
                let StmtKind::Decl(ref decl, _) = stmt.node,
                let DeclKind::Local(ref local) = decl.node,
                let Some(ref initexpr) = local.init,
                let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node,
                let ExprKind::Path(_, ref path) = retexpr.node,
                match_path_ast(path, &[&id.name.as_str()])
            ], {
                self.emit_let_lint(cx, retexpr.span, initexpr.span);
            }
        }
    }

    fn emit_let_lint(&mut self, cx: &EarlyContext, lint_span: Span, note_span: Span) {
        if in_external_macro(cx, note_span) {
            return;
        }
        let mut db = span_lint(cx,
                               LET_AND_RETURN,
                               lint_span,
                               "returning the result of a let binding from a block. Consider returning the \
                                expression directly.");
        if cx.current_level(LET_AND_RETURN) != Level::Allow {
            db.span_note(note_span, "this expression can be directly returned");
        }
    }
}

impl LintPass for ReturnPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(NEEDLESS_RETURN, LET_AND_RETURN)
    }
}

impl EarlyLintPass for ReturnPass {
    fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: NodeId) {
        self.check_block_return(cx, block);
    }

    fn check_block(&mut self, cx: &EarlyContext, block: &Block) {
        self.check_let_return(cx, block);
    }
}
<|endoftext|>


<commit_before>use std::cell::Cell;
use std::cmp;

pub struct Scanner<'t> {
    source: &'t str,
    index: Cell<usize>,
    length: usize
}

impl<'t> Scanner<'t> {
    pub fn new<'a>(source: &'a str) -> Scanner<'a> {
        Scanner {
            source: source,
            index: Cell::new(0),
            length: source.len()
        }
    }

    pub fn position(&self) -> usize {
        cmp::min(self.index.get(), self.length)
    }

    pub fn is_eos(&self) -> bool {
        self.position() == self.length
    }

    pub fn skip(&self, n: usize) {
        let pos = cmp::min(self.position() + n, self.length);
        self.index.set(pos);
    }

    pub fn rest(&self) -> Option<&str> {
        if self.is_eos() { return None; }
        Some(self.raw())
    }

    pub fn get_char(&self) -> Option<&str> {
        if self.is_eos() { return None; }

        let rest = self.raw();
        let chr  = &rest[0..1];
        self.skip(chr.len());

        Some(chr)
    }

    pub fn scan(&self, pattern: &::regex::Regex) -> Option<&str> {
        self.skip_whitespace();
        let rest = self.raw();

        match pattern.captures(rest) {
            None => None,
            Some(captures) => { self.get_match(rest, &captures) }
        }
    }

    pub fn check(&self, pattern: &::regex::Regex) -> bool {
        self.skip_whitespace();
        let rest = self.raw();

        pattern.captures(rest).is_some()
    }

    fn skip_whitespace(&self) {
        self.skip(self.leading_chars(self.raw()));
    }

    fn get_match<'a>(&'a self, source: &'a str, captures: &::regex::Captures) -> Option<&str> {
        match captures.pos(0) {
            None => None,
            Some((_, count)) => {
                let matched   = &source[0..count];
                let remaining = &source[count..];

                self.skip(count + self.leading_chars(remaining));
                Some(matched)
            }
        }
    }

    fn leading_chars(&self, string: &str) -> usize {
        string.len() - string.trim_left_matches(char::is_whitespace).len()
    }

    fn raw(&self) -> &str {
        &self.source[self.position()..]
    }
}

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

    #[test]
    fn new_returns_a_new_scanner() {
        let scanner = Scanner::new("test string");
        assert_eq!("test string", scanner.rest().unwrap());
        assert_eq!(0, scanner.position());
    }

    #[test]
    fn rest_returns_all_characters_from_the_current_position() {
        let scanner = Scanner::new("test string");
        assert_eq!("test string", scanner.rest().unwrap());

        scanner.skip(5);
        assert_eq!("string", scanner.rest().unwrap());
    }

    #[test]
    fn is_eos_when_not_at_the_end_of_a_string() {
        let scanner = Scanner::new("test string");
        assert_eq!(false, scanner.is_eos());

        scanner.skip(4);
        assert_eq!(false, scanner.is_eos());
    }

    #[test]
    fn is_eos_is_true_when_at_the_end_of_a_string() {
        let scanner = Scanner::new("test");
        scanner.skip(4);

        assert_eq!(true, scanner.is_eos());
    }

    #[test]
    fn skip_moves_n_characters_ahead() {
        let scanner = Scanner::new("test");
        assert_eq!(0, scanner.position());

        scanner.skip(1);
        assert_eq!(1, scanner.position());

        scanner.skip(2);
        assert_eq!(3, scanner.position());
    }

    #[test]
    fn get_char_returns_the_current_character_and_pushes_the_index() {
        let scanner = Scanner::new("test");
        assert_eq!("t", scanner.get_char().unwrap());
        assert_eq!("e", scanner.get_char().unwrap());
        assert_eq!("s", scanner.get_char().unwrap());
        assert_eq!("t", scanner.get_char().unwrap());
    }

    #[test]
    fn get_char_when_eos_returns_none() {
        let scanner = Scanner::new("test");
        scanner.skip(4);

        assert_eq!(None, scanner.get_char());
    }

    #[test]
    fn scan_retrieves_tokens_from_the_current_position_until_the_end() {
        let pattern = ::regex::Regex::new(r"^\w+").unwrap();
        let scanner = Scanner::new("test string words");
        assert_eq!("test", scanner.scan(&pattern).unwrap());
        assert_eq!("string", scanner.scan(&pattern).unwrap());
        assert_eq!("words", scanner.scan(&pattern).unwrap());
        assert_eq!(None, scanner.scan(&pattern));
    }

    #[test]
    fn scan_returns_none_when_not_found() {
        let pattern = ::regex::Regex::new(r"^\d+").unwrap();
        let scanner = Scanner::new("test string");
        assert_eq!(None, scanner.scan(&pattern));
    }

    #[test]
    fn scan_returns_none_when_is_eos() {
        let pattern = ::regex::Regex::new(r"^\w+").unwrap();
        let scanner = Scanner::new("");
        assert_eq!(None, scanner.scan(&pattern));
    }

    #[test]
    fn scan_returns_none_when_only_whitespace_characters_remain() {
        let pattern = ::regex::Regex::new(r"^\w+").unwrap();
        let scanner = Scanner::new("  \t \r\n ");
        assert_eq!(None, scanner.scan(&pattern));
        assert!(scanner.is_eos())
    }
}
<commit_msg>tidying up scanner<commit_after>use std::cell::Cell;
use std::cmp;

use regex::{Captures,Regex};

pub struct Scanner<'t> {
    source: &'t str,
    index: Cell<usize>,
    length: usize
}

impl<'t> Scanner<'t> {
    pub fn new<'a>(source: &'a str) -> Scanner<'a> {
        Scanner {
            source: source,
            index: Cell::new(0),
            length: source.len()
        }
    }

    pub fn position(&self) -> usize {
        cmp::min(self.index.get(), self.length)
    }

    pub fn is_eos(&self) -> bool {
        self.position() == self.length
    }

    pub fn skip(&self, n: usize) {
        let pos = cmp::min(self.position() + n, self.length);
        self.index.set(pos);
    }

    pub fn rest(&self) -> Option<&str> {
        if self.is_eos() { return None; }
        Some(self.raw())
    }

    pub fn get_char(&self) -> Option<&str> {
        if self.is_eos() { return None; }

        let rest = self.raw();
        let chr  = &rest[0..1];
        self.skip(chr.len());

        Some(chr)
    }

    pub fn scan(&self, pattern: &Regex) -> Option<&str> {
        self.skip_whitespace();
        let rest = self.raw();

        pattern.captures(rest).and_then(|captures| self.get_match(rest, &captures))
    }

    pub fn check(&self, pattern: &Regex) -> bool {
        self.skip_whitespace();
        let rest = self.raw();

        pattern.captures(rest).is_some()
    }

    fn skip_whitespace(&self) {
        self.skip(self.leading_chars(self.raw()));
    }

    fn get_match<'a>(&'a self, source: &'a str, captures: &Captures) -> Option<&str> {
        captures
            .pos(0)
            .and_then(|(_, count)| {
                let matched   = &source[0..count];
                let remaining = &source[count..];

                self.skip(count + self.leading_chars(remaining));
                Some(matched)
            })
    }

    fn leading_chars(&self, string: &str) -> usize {
        string.len() - string.trim_left_matches(char::is_whitespace).len()
    }

    fn raw(&self) -> &str {
        &self.source[self.position()..]
    }
}

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

    #[test]
    fn new_returns_a_new_scanner() {
        let scanner = Scanner::new("test string");
        assert_eq!("test string", scanner.rest().unwrap());
        assert_eq!(0, scanner.position());
    }

    #[test]
    fn rest_returns_all_characters_from_the_current_position() {
        let scanner = Scanner::new("test string");
        assert_eq!("test string", scanner.rest().unwrap());

        scanner.skip(5);
        assert_eq!("string", scanner.rest().unwrap());
    }

    #[test]
    fn is_eos_when_not_at_the_end_of_a_string() {
        let scanner = Scanner::new("test string");
        assert_eq!(false, scanner.is_eos());

        scanner.skip(4);
        assert_eq!(false, scanner.is_eos());
    }

    #[test]
    fn is_eos_is_true_when_at_the_end_of_a_string() {
        let scanner = Scanner::new("test");
        scanner.skip(4);

        assert_eq!(true, scanner.is_eos());
    }

    #[test]
    fn skip_moves_n_characters_ahead() {
        let scanner = Scanner::new("test");
        assert_eq!(0, scanner.position());

        scanner.skip(1);
        assert_eq!(1, scanner.position());

        scanner.skip(2);
        assert_eq!(3, scanner.position());
    }

    #[test]
    fn get_char_returns_the_current_character_and_pushes_the_index() {
        let scanner = Scanner::new("test");
        assert_eq!("t", scanner.get_char().unwrap());
        assert_eq!("e", scanner.get_char().unwrap());
        assert_eq!("s", scanner.get_char().unwrap());
        assert_eq!("t", scanner.get_char().unwrap());
    }

    #[test]
    fn get_char_when_eos_returns_none() {
        let scanner = Scanner::new("test");
        scanner.skip(4);

        assert_eq!(None, scanner.get_char());
    }

    #[test]
    fn scan_retrieves_tokens_from_the_current_position_until_the_end() {
        let pattern = Regex::new(r"^\w+").unwrap();
        let scanner = Scanner::new("test string words");
        assert_eq!("test", scanner.scan(&pattern).unwrap());
        assert_eq!("string", scanner.scan(&pattern).unwrap());
        assert_eq!("words", scanner.scan(&pattern).unwrap());
        assert_eq!(None, scanner.scan(&pattern));
    }

    #[test]
    fn scan_returns_none_when_not_found() {
        let pattern = Regex::new(r"^\d+").unwrap();
        let scanner = Scanner::new("test string");
        assert_eq!(None, scanner.scan(&pattern));
    }

    #[test]
    fn scan_returns_none_when_is_eos() {
        let pattern = Regex::new(r"^\w+").unwrap();
        let scanner = Scanner::new("");
        assert_eq!(None, scanner.scan(&pattern));
    }

    #[test]
    fn scan_returns_none_when_only_whitespace_characters_remain() {
        let pattern = Regex::new(r"^\w+").unwrap();
        let scanner = Scanner::new("  \t \r\n ");
        assert_eq!(None, scanner.scan(&pattern));
        assert!(scanner.is_eos())
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::io;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering};

use futures::{future, Future, BoxFuture, Stream, Sink};
use futures::sync::mpsc::{channel, Sender};
use tokio_core::reactor::Remote;
use tokio_proto::streaming::{Message, Body};
use tokio_service::Service;

use bytes::{BufMut, Bytes, BytesMut};

use admin;
use codec::PacketHeader;
use job::Job;
use packet::PacketMagic;
use queues::{HandleJobStorage, JobQueuePriority, SharedJobStorage};
use worker::{SharedWorkers, Worker, Wake};
use constants::*;

pub type GearmanBody = Body<BytesMut, io::Error>;
pub type GearmanMessage = Message<PacketHeader, GearmanBody>;

const WAKE_BACKLOG_SIZE: usize = 8;

fn new_res(ptype: u32, data: BytesMut) -> GearmanMessage {
    Message::WithBody(PacketHeader {
                          magic: PacketMagic::RES,
                          ptype: ptype,
                          psize: data.len() as u32,
                      },
                      Body::from(data))
}

pub fn new_wake() -> GearmanMessage {
    new_res(NOOP, BytesMut::new())
}

pub struct GearmanService {
    pub conn_id: usize,
    pub queues: SharedJobStorage,
    pub workers: SharedWorkers,
    pub worker: Arc<Mutex<Worker>>,
    pub job_count: Arc<AtomicUsize>,
    pub connections: Arc<Mutex<HashMap<usize, Sender<()>>>>,
    remote: Remote,
}

fn next_field(buf: &mut BytesMut) -> Result<Bytes, io::Error> {
    match buf[..].iter().position(|b| *b == b'\0') {
        Some(null_pos) => {
            let value = buf.split_to(null_pos);
            buf.split_to(1);
            Ok(value.freeze())
        }
        None => Err(io::Error::new(io::ErrorKind::Other, "Can't find null")),
    }
}

impl GearmanService {
    /// Things that don't require a body should use this
    fn response_from_header(&self,
                            header: &PacketHeader)
                            -> Message<PacketHeader, Body<BytesMut, io::Error>> {
        match header.ptype {
            ADMIN_VERSION => {
                let resp_str = "OK some-rustygear-version\n";
                let mut resp_body = BytesMut::with_capacity(resp_str.len());
                resp_body.put(&resp_str[..]);
                let resp_body = Body::from(resp_body);
                Message::WithBody(PacketHeader {
                                      magic: PacketMagic::TEXT,
                                      ptype: header.ptype,
                                      psize: resp_str.len() as u32,
                                  },
                                  resp_body)
            }
            ADMIN_STATUS => admin::admin_command_status(self.queues.clone(), self.workers.clone()),
            _ => {
                panic!("response_from_header called with invalid ptype: {}",
                       header.ptype)
            }
        }
    }

    pub fn new(conn_id: usize,
               queues: SharedJobStorage,
               workers: SharedWorkers,
               job_count: Arc<AtomicUsize>,
               connections: Arc<Mutex<HashMap<usize, Sender<()>>>>,
               remote: Remote)
               -> GearmanService {
        GearmanService {
            conn_id: conn_id,
            queues: queues,
            worker: Arc::new(Mutex::new((Worker::new()))),
            workers: workers,
            job_count: job_count,
            connections: connections,
            remote: remote,
        }
    }

    fn no_response() -> GearmanMessage {
        Message::WithBody(PacketHeader {
                              magic: PacketMagic::TEXT,
                              ptype: ADMIN_RESPONSE,
                              psize: 0,
                          },
                          Body::from(BytesMut::new()))
    }

    fn handle_can_do(&self, body: GearmanBody) -> BoxFuture<GearmanMessage, io::Error> {
        let worker = self.worker.clone();
        let workers = self.workers.clone();
        let conn_id = self.conn_id;
        trace!("handle_can_do");
        body.concat2()
            .and_then(move |fname| {
                let fname = fname.freeze();
                debug!("CAN_DO fname = {:?}", fname);
                let mut worker = worker.lock().unwrap();
                worker.can_do(fname);
                workers.clone().wakeup(&mut worker, conn_id);
                future::finished(Self::no_response())
            })
            .boxed()
    }

    fn handle_cant_do(&self, body: GearmanBody) -> BoxFuture<GearmanMessage, io::Error> {
        let worker = self.worker.clone();
        body.concat2()
            .and_then(move |fname| {
                let fname = fname.freeze();
                debug!("CANT_DO fname = {:?}", fname);
                let mut worker = worker.lock().unwrap();
                worker.cant_do(&fname);
                future::finished(Self::no_response())
            })
            .boxed()
    }

    fn handle_grab_job_all(&self, body: GearmanBody) -> BoxFuture<GearmanMessage, io::Error> {
        let mut queues = self.queues.clone();
        let worker = self.worker.clone();
        trace!("handle_grab_job_all");
        body.concat2()
            .and_then(move |_| {
                let mut worker = worker.lock().unwrap();
                let ref mut worker = worker;
                if queues.get_job(worker) {
                    match worker.job() {
                        Some(ref j) => {
                            let mut data = BytesMut::with_capacity(4 + j.handle.len() +
                                                                   j.fname.len() +
                                                                   j.unique.len() +
                                                                   j.data.len());
                            data.extend(&j.handle);
                            data.put_u8(b'\0');
                            data.extend(&j.fname);
                            data.put_u8(b'\0');
                            data.extend(&j.unique);
                            data.put_u8(b'\0');
                            // reducer not implemented
                            data.put_u8(b'\0');
                            data.extend(&j.data);
                            return future::finished(new_res(JOB_ASSIGN_ALL, data)).boxed();
                        }
                        None => {}
                    }
                };
                future::finished(new_res(NO_JOB, BytesMut::new())).boxed()
            })
            .boxed()
    }

    fn handle_grab_job_uniq(&self, body: GearmanBody) -> BoxFuture<GearmanMessage, io::Error> {
        let mut queues = self.queues.clone();
        let worker = self.worker.clone();
        trace!("handle_grab_job_uniq");
        body.concat2()
            .and_then(move |_| {
                let mut worker = worker.lock().unwrap();
                let ref mut worker = worker;
                if queues.get_job(worker) {
                    match worker.job() {
                        Some(ref j) => {
                            let mut data = BytesMut::with_capacity(3 + j.handle.len() +
                                                                   j.fname.len() +
                                                                   j.unique.len() +
                                                                   j.data.len());
                            data.extend(&j.handle);
                            data.put_u8(b'\0');
                            data.extend(&j.fname);
                            data.put_u8(b'\0');
                            data.extend(&j.unique);
                            data.put_u8(b'\0');
                            data.extend(&j.data);
                            return future::finished(new_res(JOB_ASSIGN_UNIQ, data)).boxed();
                        }
                        None => {}
                    }
                };
                future::finished(new_res(NO_JOB, BytesMut::new())).boxed()
            })
            .boxed()
    }

    fn handle_grab_job(&self, body: GearmanBody) -> BoxFuture<GearmanMessage, io::Error> {
        let mut queues = self.queues.clone();
        let worker = self.worker.clone();
        trace!("handle_grab_job");
        body.concat2()
            .and_then(move |_| {
                let mut worker = worker.lock().unwrap();
                let ref mut worker = worker;
                if queues.get_job(worker) {
                    match worker.job() {
                        Some(ref j) => {
                            let mut data = BytesMut::with_capacity(2 + j.handle.len() +
                                                                   j.fname.len() +
                                                                   j.data.len());
                            data.extend(&j.handle);
                            data.put_u8(b'\0');
                            data.extend(&j.fname);
                            data.put_u8(b'\0');
                            data.extend(&j.data);
                            return future::finished(new_res(JOB_ASSIGN, data)).boxed();
                        }
                        None => {}
                    }
                };
                future::finished(new_res(NO_JOB, BytesMut::new())).boxed()
            })
            .boxed()
    }

    fn handle_pre_sleep(&self) -> BoxFuture<GearmanMessage, io::Error> {
        let worker = self.worker.clone();
        let ref mut w = worker.lock().unwrap();
        self.workers.clone().sleep(w, self.conn_id);
        // When we get woke, send a NOOP
        let (tx, rx) = channel(WAKE_BACKLOG_SIZE);
        {
            let mut connections = self.connections.lock().unwrap();
            connections.insert(self.conn_id, tx);
        }
        let resp = new_res(NOOP, BytesMut::new());
        // If there are more, they are pointless until the NOOP is queued, and once it is queued,
        // the connections hashmap will have dropped the sender, and this future resolving
        // should drop the receiver and all of its backed up items.
        let connections = self.connections.clone();
        let conn_id = self.conn_id;
        rx.take(1).for_each(move |_| {
            {
                let mut connections = connections.lock().unwrap();
                connections.remove(&conn_id);
            }
            Ok(())
        })
        .map_err(move |_| {
            io::Error::new(io::ErrorKind::Other, "receiver error")
        })
        .map(move |_| resp)
        .boxed()
    }

    fn handle_submit_job(&self,
                         priority: JobQueuePriority,
                         wait: bool,
                         body: GearmanBody)
                         -> BoxFuture<GearmanMessage, io::Error> {
        let mut queues = self.queues.clone();
        let conn_id = match wait {
            true => Some(self.conn_id),
            false => None,
        };
        let mut workers = self.workers.clone();
        let job_count = self.job_count.clone();
        let connections = self.connections.clone();
        //let wakes: Vec<sink::Send<BackchannelSender>> = Vec::new();
        let remote = self.remote.clone();

        let ret = body.concat2()
            .and_then(move |mut fields| {
                let fname = next_field(&mut fields).unwrap();
                let unique = next_field(&mut fields).unwrap();
                let data = fields.freeze();
                let mut add = false;
                let handle = match queues.coalesce_unique(&unique, conn_id) {
                    Some(handle) => handle,
                    None => {
                        {
                            let mut connections = connections.lock().unwrap();
                            for wake in workers.queue_wake(&fname) {
                                match connections.get_mut(&wake) {
                                    None => {
                                        debug!("No connection found to wake up for conn_id = {}",
                                               wake);
                                    }
                                    Some(tx) => {
                                        let tx = tx.clone();
                                        //let fut = tx.send(new_wake());
                                        //wakes.push(move |_| {fut});
                                        remote.spawn(move |handle| {
                                            handle.spawn(tx.send(()).then(|res|{
                                                match res {
                                                    Ok(_) => {},
                                                    Err(e) => error!("Send Error! {:?}", e),
                                                }
                                                Ok(())
                                            }));
                                            Ok(())
                                        });
                                    }
                                }
                            }
                        }
                        // H:091234567890
                        let mut handle = BytesMut::with_capacity(12);
                        let job_num = job_count.fetch_add(1, Ordering::Relaxed);
                        debug!("job_num = {}", job_num);
                        handle.extend(format!("H:{:010}", job_num).as_bytes());
                        add = true;
                        handle.freeze()
                    }
                };
                if add {
                    let job = Arc::new(Job::new(fname, unique, data, handle.clone()));
                    info!("Created job {:?}", job);
                    queues.add_job(job.clone(), priority, conn_id);
                }
                future::finished(new_res(JOB_CREATED, BytesMut::from(handle)))
            })
            .boxed();
        ret
    }
}

impl Service for GearmanService {
    type Request = GearmanMessage;
    type Response = GearmanMessage;
    type Error = io::Error;
    type Future = BoxFuture<Self::Response, Self::Error>;

    fn call(&self, req: Self::Request) -> Self::Future {
        debug!("Got a req {:?}", req);
        match req {
            Message::WithoutBody(header) => {
                match header.ptype {
                    ADMIN_VERSION | ADMIN_STATUS => {
                        future::ok(self.response_from_header(&header)).boxed()
                    }

                    _ => {
                        future::err(io::Error::new(io::ErrorKind::Other,
                                                   format!("Bodyless packet type = {}",
                                                           header.ptype)))
                            .boxed()
                    }
                }
            }
            Message::WithBody(header, body) => {
                match header.ptype {
                    SUBMIT_JOB => self.handle_submit_job(PRIORITY_NORMAL, false, body),
                    SUBMIT_JOB_HIGH => self.handle_submit_job(PRIORITY_HIGH, false, body),
                    SUBMIT_JOB_LOW => self.handle_submit_job(PRIORITY_LOW, false, body),
                    SUBMIT_JOB_BG => self.handle_submit_job(PRIORITY_NORMAL, true, body),
                    SUBMIT_JOB_HIGH_BG => self.handle_submit_job(PRIORITY_HIGH, true, body),
                    SUBMIT_JOB_LOW_BG => self.handle_submit_job(PRIORITY_LOW, true, body),
                    PRE_SLEEP => self.handle_pre_sleep(),
                    CAN_DO => self.handle_can_do(body),
                    CANT_DO => self.handle_cant_do(body),
                    GRAB_JOB => self.handle_grab_job(body),
                    GRAB_JOB_UNIQ => self.handle_grab_job_uniq(body),
                    GRAB_JOB_ALL => self.handle_grab_job_all(body),/*
                    WORK_COMPLETE => self.handle_work_complete(),
                    WORK_STATUS | WORK_DATA | WORK_WARNING => self.handle_work_update(),
                    ECHO_REQ => self.handle_echo_req(&req),*/
                    _ => {
                        error!("Unimplemented: {:?} processing packet", header);
                        future::err(io::Error::new(io::ErrorKind::Other,
                                                   format!("Invalid packet type {}", header.ptype)))
                            .boxed()
                    }
                }
            }
        }
    }
}
<commit_msg>remove cruft<commit_after>use std::collections::HashMap;
use std::io;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering};

use futures::{future, Future, BoxFuture, Stream, Sink};
use futures::sync::mpsc::{channel, Sender};
use tokio_core::reactor::Remote;
use tokio_proto::streaming::{Message, Body};
use tokio_service::Service;

use bytes::{BufMut, Bytes, BytesMut};

use admin;
use codec::PacketHeader;
use job::Job;
use packet::PacketMagic;
use queues::{HandleJobStorage, JobQueuePriority, SharedJobStorage};
use worker::{SharedWorkers, Worker, Wake};
use constants::*;

pub type GearmanBody = Body<BytesMut, io::Error>;
pub type GearmanMessage = Message<PacketHeader, GearmanBody>;

const WAKE_BACKLOG_SIZE: usize = 8;

fn new_res(ptype: u32, data: BytesMut) -> GearmanMessage {
    Message::WithBody(PacketHeader {
                          magic: PacketMagic::RES,
                          ptype: ptype,
                          psize: data.len() as u32,
                      },
                      Body::from(data))
}

pub fn new_wake() -> GearmanMessage {
    new_res(NOOP, BytesMut::new())
}

pub struct GearmanService {
    pub conn_id: usize,
    pub queues: SharedJobStorage,
    pub workers: SharedWorkers,
    pub worker: Arc<Mutex<Worker>>,
    pub job_count: Arc<AtomicUsize>,
    pub connections: Arc<Mutex<HashMap<usize, Sender<()>>>>,
    remote: Remote,
}

fn next_field(buf: &mut BytesMut) -> Result<Bytes, io::Error> {
    match buf[..].iter().position(|b| *b == b'\0') {
        Some(null_pos) => {
            let value = buf.split_to(null_pos);
            buf.split_to(1);
            Ok(value.freeze())
        }
        None => Err(io::Error::new(io::ErrorKind::Other, "Can't find null")),
    }
}

impl GearmanService {
    /// Things that don't require a body should use this
    fn response_from_header(&self,
                            header: &PacketHeader)
                            -> Message<PacketHeader, Body<BytesMut, io::Error>> {
        match header.ptype {
            ADMIN_VERSION => {
                let resp_str = "OK some-rustygear-version\n";
                let mut resp_body = BytesMut::with_capacity(resp_str.len());
                resp_body.put(&resp_str[..]);
                let resp_body = Body::from(resp_body);
                Message::WithBody(PacketHeader {
                                      magic: PacketMagic::TEXT,
                                      ptype: header.ptype,
                                      psize: resp_str.len() as u32,
                                  },
                                  resp_body)
            }
            ADMIN_STATUS => admin::admin_command_status(self.queues.clone(), self.workers.clone()),
            _ => {
                panic!("response_from_header called with invalid ptype: {}",
                       header.ptype)
            }
        }
    }

    pub fn new(conn_id: usize,
               queues: SharedJobStorage,
               workers: SharedWorkers,
               job_count: Arc<AtomicUsize>,
               connections: Arc<Mutex<HashMap<usize, Sender<()>>>>,
               remote: Remote)
               -> GearmanService {
        GearmanService {
            conn_id: conn_id,
            queues: queues,
            worker: Arc::new(Mutex::new((Worker::new()))),
            workers: workers,
            job_count: job_count,
            connections: connections,
            remote: remote,
        }
    }

    fn no_response() -> GearmanMessage {
        Message::WithBody(PacketHeader {
                              magic: PacketMagic::TEXT,
                              ptype: ADMIN_RESPONSE,
                              psize: 0,
                          },
                          Body::from(BytesMut::new()))
    }

    fn handle_can_do(&self, body: GearmanBody) -> BoxFuture<GearmanMessage, io::Error> {
        let worker = self.worker.clone();
        let workers = self.workers.clone();
        let conn_id = self.conn_id;
        trace!("handle_can_do");
        body.concat2()
            .and_then(move |fname| {
                let fname = fname.freeze();
                debug!("CAN_DO fname = {:?}", fname);
                let mut worker = worker.lock().unwrap();
                worker.can_do(fname);
                workers.clone().wakeup(&mut worker, conn_id);
                future::finished(Self::no_response())
            })
            .boxed()
    }

    fn handle_cant_do(&self, body: GearmanBody) -> BoxFuture<GearmanMessage, io::Error> {
        let worker = self.worker.clone();
        body.concat2()
            .and_then(move |fname| {
                let fname = fname.freeze();
                debug!("CANT_DO fname = {:?}", fname);
                let mut worker = worker.lock().unwrap();
                worker.cant_do(&fname);
                future::finished(Self::no_response())
            })
            .boxed()
    }

    fn handle_grab_job_all(&self, body: GearmanBody) -> BoxFuture<GearmanMessage, io::Error> {
        let mut queues = self.queues.clone();
        let worker = self.worker.clone();
        trace!("handle_grab_job_all");
        body.concat2()
            .and_then(move |_| {
                let mut worker = worker.lock().unwrap();
                let ref mut worker = worker;
                if queues.get_job(worker) {
                    match worker.job() {
                        Some(ref j) => {
                            let mut data = BytesMut::with_capacity(4 + j.handle.len() +
                                                                   j.fname.len() +
                                                                   j.unique.len() +
                                                                   j.data.len());
                            data.extend(&j.handle);
                            data.put_u8(b'\0');
                            data.extend(&j.fname);
                            data.put_u8(b'\0');
                            data.extend(&j.unique);
                            data.put_u8(b'\0');
                            // reducer not implemented
                            data.put_u8(b'\0');
                            data.extend(&j.data);
                            return future::finished(new_res(JOB_ASSIGN_ALL, data)).boxed();
                        }
                        None => {}
                    }
                };
                future::finished(new_res(NO_JOB, BytesMut::new())).boxed()
            })
            .boxed()
    }

    fn handle_grab_job_uniq(&self, body: GearmanBody) -> BoxFuture<GearmanMessage, io::Error> {
        let mut queues = self.queues.clone();
        let worker = self.worker.clone();
        trace!("handle_grab_job_uniq");
        body.concat2()
            .and_then(move |_| {
                let mut worker = worker.lock().unwrap();
                let ref mut worker = worker;
                if queues.get_job(worker) {
                    match worker.job() {
                        Some(ref j) => {
                            let mut data = BytesMut::with_capacity(3 + j.handle.len() +
                                                                   j.fname.len() +
                                                                   j.unique.len() +
                                                                   j.data.len());
                            data.extend(&j.handle);
                            data.put_u8(b'\0');
                            data.extend(&j.fname);
                            data.put_u8(b'\0');
                            data.extend(&j.unique);
                            data.put_u8(b'\0');
                            data.extend(&j.data);
                            return future::finished(new_res(JOB_ASSIGN_UNIQ, data)).boxed();
                        }
                        None => {}
                    }
                };
                future::finished(new_res(NO_JOB, BytesMut::new())).boxed()
            })
            .boxed()
    }

    fn handle_grab_job(&self, body: GearmanBody) -> BoxFuture<GearmanMessage, io::Error> {
        let mut queues = self.queues.clone();
        let worker = self.worker.clone();
        trace!("handle_grab_job");
        body.concat2()
            .and_then(move |_| {
                let mut worker = worker.lock().unwrap();
                let ref mut worker = worker;
                if queues.get_job(worker) {
                    match worker.job() {
                        Some(ref j) => {
                            let mut data = BytesMut::with_capacity(2 + j.handle.len() +
                                                                   j.fname.len() +
                                                                   j.data.len());
                            data.extend(&j.handle);
                            data.put_u8(b'\0');
                            data.extend(&j.fname);
                            data.put_u8(b'\0');
                            data.extend(&j.data);
                            return future::finished(new_res(JOB_ASSIGN, data)).boxed();
                        }
                        None => {}
                    }
                };
                future::finished(new_res(NO_JOB, BytesMut::new())).boxed()
            })
            .boxed()
    }

    fn handle_pre_sleep(&self) -> BoxFuture<GearmanMessage, io::Error> {
        let worker = self.worker.clone();
        let ref mut w = worker.lock().unwrap();
        self.workers.clone().sleep(w, self.conn_id);
        // When we get woke, send a NOOP
        let (tx, rx) = channel(WAKE_BACKLOG_SIZE);
        {
            let mut connections = self.connections.lock().unwrap();
            connections.insert(self.conn_id, tx);
        }
        let resp = new_res(NOOP, BytesMut::new());
        // If there are more, they are pointless until the NOOP is queued, and once it is queued,
        // the connections hashmap will have dropped the sender, and this future resolving
        // should drop the receiver and all of its backed up items.
        let connections = self.connections.clone();
        let conn_id = self.conn_id;
        rx.take(1).for_each(move |_| {
            {
                let mut connections = connections.lock().unwrap();
                connections.remove(&conn_id);
            }
            Ok(())
        })
        .map_err(move |_| {
            io::Error::new(io::ErrorKind::Other, "receiver error")
        })
        .map(move |_| resp)
        .boxed()
    }

    fn handle_submit_job(&self,
                         priority: JobQueuePriority,
                         wait: bool,
                         body: GearmanBody)
                         -> BoxFuture<GearmanMessage, io::Error> {
        let mut queues = self.queues.clone();
        let conn_id = match wait {
            true => Some(self.conn_id),
            false => None,
        };
        let mut workers = self.workers.clone();
        let job_count = self.job_count.clone();
        let connections = self.connections.clone();
        let remote = self.remote.clone();

        let ret = body.concat2()
            .and_then(move |mut fields| {
                let fname = next_field(&mut fields).unwrap();
                let unique = next_field(&mut fields).unwrap();
                let data = fields.freeze();
                let mut add = false;
                let handle = match queues.coalesce_unique(&unique, conn_id) {
                    Some(handle) => handle,
                    None => {
                        {
                            let mut connections = connections.lock().unwrap();
                            for wake in workers.queue_wake(&fname) {
                                match connections.get_mut(&wake) {
                                    None => {
                                        debug!("No connection found to wake up for conn_id = {}",
                                               wake);
                                    }
                                    Some(tx) => {
                                        let tx = tx.clone();
                                        //let fut = tx.send(new_wake());
                                        //wakes.push(move |_| {fut});
                                        remote.spawn(move |handle| {
                                            handle.spawn(tx.send(()).then(|res|{
                                                match res {
                                                    Ok(_) => {},
                                                    Err(e) => error!("Send Error! {:?}", e),
                                                }
                                                Ok(())
                                            }));
                                            Ok(())
                                        });
                                    }
                                }
                            }
                        }
                        // H:091234567890
                        let mut handle = BytesMut::with_capacity(12);
                        let job_num = job_count.fetch_add(1, Ordering::Relaxed);
                        debug!("job_num = {}", job_num);
                        handle.extend(format!("H:{:010}", job_num).as_bytes());
                        add = true;
                        handle.freeze()
                    }
                };
                if add {
                    let job = Arc::new(Job::new(fname, unique, data, handle.clone()));
                    info!("Created job {:?}", job);
                    queues.add_job(job.clone(), priority, conn_id);
                }
                future::finished(new_res(JOB_CREATED, BytesMut::from(handle)))
            })
            .boxed();
        ret
    }
}

impl Service for GearmanService {
    type Request = GearmanMessage;
    type Response = GearmanMessage;
    type Error = io::Error;
    type Future = BoxFuture<Self::Response, Self::Error>;

    fn call(&self, req: Self::Request) -> Self::Future {
        debug!("Got a req {:?}", req);
        match req {
            Message::WithoutBody(header) => {
                match header.ptype {
                    ADMIN_VERSION | ADMIN_STATUS => {
                        future::ok(self.response_from_header(&header)).boxed()
                    }

                    _ => {
                        future::err(io::Error::new(io::ErrorKind::Other,
                                                   format!("Bodyless packet type = {}",
                                                           header.ptype)))
                            .boxed()
                    }
                }
            }
            Message::WithBody(header, body) => {
                match header.ptype {
                    SUBMIT_JOB => self.handle_submit_job(PRIORITY_NORMAL, false, body),
                    SUBMIT_JOB_HIGH => self.handle_submit_job(PRIORITY_HIGH, false, body),
                    SUBMIT_JOB_LOW => self.handle_submit_job(PRIORITY_LOW, false, body),
                    SUBMIT_JOB_BG => self.handle_submit_job(PRIORITY_NORMAL, true, body),
                    SUBMIT_JOB_HIGH_BG => self.handle_submit_job(PRIORITY_HIGH, true, body),
                    SUBMIT_JOB_LOW_BG => self.handle_submit_job(PRIORITY_LOW, true, body),
                    PRE_SLEEP => self.handle_pre_sleep(),
                    CAN_DO => self.handle_can_do(body),
                    CANT_DO => self.handle_cant_do(body),
                    GRAB_JOB => self.handle_grab_job(body),
                    GRAB_JOB_UNIQ => self.handle_grab_job_uniq(body),
                    GRAB_JOB_ALL => self.handle_grab_job_all(body),/*
                    WORK_COMPLETE => self.handle_work_complete(),
                    WORK_STATUS | WORK_DATA | WORK_WARNING => self.handle_work_update(),
                    ECHO_REQ => self.handle_echo_req(&req),*/
                    _ => {
                        error!("Unimplemented: {:?} processing packet", header);
                        future::err(io::Error::new(io::ErrorKind::Other,
                                                   format!("Invalid packet type {}", header.ptype)))
                            .boxed()
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! A trait to allow interpolation over spatial structures.

use std::num::Float;

/// Used for interpolation over spatial structures.
pub trait Spatial {
    /// The scalar type.
    type Scalar;

    /// Add
    fn add(&self, other: &Self) -> Self;
    /// Subtract
    fn sub(&self, other: &Self) -> Self;
    /// Scales with a scalar.
    fn scale(&self, scalar: &<Self as Spatial>::Scalar) -> Self;
}

impl<T> Spatial for T
    where
        T: Float
{
    type Scalar = T;

    #[inline(always)]
    fn add(&self, other: &Self) -> Self {
        *self + *other
    }

    #[inline(always)]
    fn sub(&self, other: &Self) -> Self {
        *self - *other
    }

    #[inline(always)]
    fn scale(&self, other: &<Self as Spatial>::Scalar) -> Self {
        *self * *other
    }
}

/// Implementation of spatial for signed integers.
/// `scale` will cast the uint to the Scalar before multiplying and rounding to the nearest value.
macro_rules! impl_spatial_for_int {
    ($int: ident, $scalar: ident) => (
        impl Spatial for $int {
            type Scalar = $scalar;

            #[inline(always)]
            fn add(&self, other: &$int) -> $int {
                *self + *other
            }

            #[inline(always)]
            fn sub(&self, other: &$int) -> $int {
                *self - *other
            }

            #[inline(always)]
            fn scale(&self, other: &$scalar) -> $int {
                use std::num::Float;
                ((*self as $scalar) * *other).round() as $int
            }
        }
    )
}

impl_spatial_for_int!(i8,  f32);
impl_spatial_for_int!(i16, f32);
impl_spatial_for_int!(i32, f32);
impl_spatial_for_int!(i64, f64);

/// Implementation of spatial for unsigned integers.
/// `scale` will cast the uint to the Scalar before multiplying and rounding to the nearest value.
macro_rules! impl_spatial_for_uint {
    ($uint: ident, $scalar: ident) => (
        impl Spatial for $uint {
            type Scalar = $scalar;

            #[inline(always)]
            fn add(&self, other: &$uint) -> $uint {
                *self + *other
            }

            #[inline(always)]
            fn sub(&self, other: &$uint) -> $uint {
                // Find the absolute difference to avoid underflow.
                if *self >= *other {
                    *self - *other
                } else {
                    *other - *self
                }
            }

            #[inline(always)]
            fn scale(&self, other: &$scalar) -> $uint {
                use std::num::Float;
                ((*self as $scalar) * *other).round() as $uint
            }
        }
    )
}

impl_spatial_for_uint!(u8,  f32);
impl_spatial_for_uint!(u16, f32);
impl_spatial_for_uint!(u32, f32);
impl_spatial_for_uint!(u64, f64);

impl<T> Spatial for [T; 2]
    where
        T: Spatial
{
    type Scalar = <T as Spatial>::Scalar;

    #[inline(always)]
    fn add(&self, other: &Self) -> Self {
        [
            self[0].add(&other[0]),
            self[1].add(&other[1])
        ]
    }

    #[inline(always)]
    fn sub(&self, other: &Self) -> Self {
        [
            self[0].sub(&other[0]),
            self[1].sub(&other[1])
        ]
    }

    #[inline(always)]
    fn scale(&self, scalar: &<Self as Spatial>::Scalar) -> Self {
        [
            self[0].scale(scalar),
            self[1].scale(scalar),
        ]
    }
}

impl<T> Spatial for [T; 3]
    where
        T: Spatial
{
    type Scalar = <T as Spatial>::Scalar;

    #[inline(always)]
    fn add(&self, other: &Self) -> Self {
        [
            self[0].add(&other[0]),
            self[1].add(&other[1]),
            self[2].add(&other[2])
        ]
    }

    #[inline(always)]
    fn sub(&self, other: &Self) -> Self {
        [
            self[0].sub(&other[0]),
            self[1].sub(&other[1]),
            self[2].sub(&other[2])
        ]
    }

    #[inline(always)]
    fn scale(&self, scalar: &<Self as Spatial>::Scalar) -> Self {
        [
            self[0].scale(scalar),
            self[1].scale(scalar),
            self[2].scale(scalar)
        ]
    }
}

impl<T> Spatial for [T; 4]
    where
        T: Spatial
{
    type Scalar = <T as Spatial>::Scalar;

    #[inline(always)]
    fn add(&self, other: &Self) -> Self {
        [
            self[0].add(&other[0]),
            self[1].add(&other[1]),
            self[2].add(&other[2]),
            self[3].add(&other[3])
        ]
    }

    #[inline(always)]
    fn sub(&self, other: &Self) -> Self {
        [
            self[0].sub(&other[0]),
            self[1].sub(&other[1]),
            self[2].sub(&other[2]),
            self[3].sub(&other[3])
        ]
    }

    #[inline(always)]
    fn scale(&self, scalar: &<Self as Spatial>::Scalar) -> Self {
        [
            self[0].scale(scalar),
            self[1].scale(scalar),
            self[2].scale(scalar),
            self[3].scale(scalar)
        ]
    }
}
<commit_msg>Remove blanket impl due to new coherence rules<commit_after>//! A trait to allow interpolation over spatial structures.

/// Used for interpolation over spatial structures.
pub trait Spatial {
    /// The scalar type.
    type Scalar;

    /// Add
    fn add(&self, other: &Self) -> Self;
    /// Subtract
    fn sub(&self, other: &Self) -> Self;
    /// Scales with a scalar.
    fn scale(&self, scalar: &<Self as Spatial>::Scalar) -> Self;
}

/// Implementation of spatial for floats.
macro_rules! impl_spatial_for_float {
    ($float: ident) => (
        impl Spatial for $float {
            type Scalar = $float;

            #[inline(always)]
            fn add(&self, other: &$float) -> $float {
                *self + *other
            }

            #[inline(always)]
            fn sub(&self, other: &$float) -> $float {
                *self - *other
            }

            #[inline(always)]
            fn scale(&self, other: &$float) -> $float {
                *self * *other
            }
        }
    )
}

impl_spatial_for_float!(f32);
impl_spatial_for_float!(f64);

/// Implementation of spatial for signed integers.
/// `scale` will cast the int to the Scalar before multiplying and rounding to the nearest value.
macro_rules! impl_spatial_for_int {
    ($int: ident, $scalar: ident) => (
        impl Spatial for $int {
            type Scalar = $scalar;

            #[inline(always)]
            fn add(&self, other: &$int) -> $int {
                *self + *other
            }

            #[inline(always)]
            fn sub(&self, other: &$int) -> $int {
                *self - *other
            }

            #[inline(always)]
            fn scale(&self, other: &$scalar) -> $int {
                ((*self as $scalar) * *other).round() as $int
            }
        }
    )
}

impl_spatial_for_int!(i8,  f32);
impl_spatial_for_int!(i16, f32);
impl_spatial_for_int!(i32, f32);
impl_spatial_for_int!(i64, f64);

/// Implementation of spatial for unsigned integers.
/// `scale` will cast the uint to the Scalar before multiplying and rounding to the nearest value.
macro_rules! impl_spatial_for_uint {
    ($uint: ident, $scalar: ident) => (
        impl Spatial for $uint {
            type Scalar = $scalar;

            #[inline(always)]
            fn add(&self, other: &$uint) -> $uint {
                *self + *other
            }

            #[inline(always)]
            fn sub(&self, other: &$uint) -> $uint {
                // Find the absolute difference to avoid underflow.
                if *self >= *other {
                    *self - *other
                } else {
                    *other - *self
                }
            }

            #[inline(always)]
            fn scale(&self, other: &$scalar) -> $uint {
                ((*self as $scalar) * *other).round() as $uint
            }
        }
    )
}

impl_spatial_for_uint!(u8,  f32);
impl_spatial_for_uint!(u16, f32);
impl_spatial_for_uint!(u32, f32);
impl_spatial_for_uint!(u64, f64);

impl<T> Spatial for [T; 2]
    where
        T: Spatial
{
    type Scalar = <T as Spatial>::Scalar;

    #[inline(always)]
    fn add(&self, other: &Self) -> Self {
        [
            self[0].add(&other[0]),
            self[1].add(&other[1])
        ]
    }

    #[inline(always)]
    fn sub(&self, other: &Self) -> Self {
        [
            self[0].sub(&other[0]),
            self[1].sub(&other[1])
        ]
    }

    #[inline(always)]
    fn scale(&self, scalar: &<Self as Spatial>::Scalar) -> Self {
        [
            self[0].scale(scalar),
            self[1].scale(scalar),
        ]
    }
}

impl<T> Spatial for [T; 3]
    where
        T: Spatial
{
    type Scalar = <T as Spatial>::Scalar;

    #[inline(always)]
    fn add(&self, other: &Self) -> Self {
        [
            self[0].add(&other[0]),
            self[1].add(&other[1]),
            self[2].add(&other[2])
        ]
    }

    #[inline(always)]
    fn sub(&self, other: &Self) -> Self {
        [
            self[0].sub(&other[0]),
            self[1].sub(&other[1]),
            self[2].sub(&other[2])
        ]
    }

    #[inline(always)]
    fn scale(&self, scalar: &<Self as Spatial>::Scalar) -> Self {
        [
            self[0].scale(scalar),
            self[1].scale(scalar),
            self[2].scale(scalar)
        ]
    }
}

impl<T> Spatial for [T; 4]
    where
        T: Spatial
{
    type Scalar = <T as Spatial>::Scalar;

    #[inline(always)]
    fn add(&self, other: &Self) -> Self {
        [
            self[0].add(&other[0]),
            self[1].add(&other[1]),
            self[2].add(&other[2]),
            self[3].add(&other[3])
        ]
    }

    #[inline(always)]
    fn sub(&self, other: &Self) -> Self {
        [
            self[0].sub(&other[0]),
            self[1].sub(&other[1]),
            self[2].sub(&other[2]),
            self[3].sub(&other[3])
        ]
    }

    #[inline(always)]
    fn scale(&self, scalar: &<Self as Spatial>::Scalar) -> Self {
        [
            self[0].scale(scalar),
            self[1].scale(scalar),
            self[2].scale(scalar),
            self[3].scale(scalar)
        ]
    }
}
<|endoftext|>


<commit_before>#[cfg(any(target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "ios",
          target_os = "linux",
          target_os = "macos",
          target_os = "netbsd"))]
pub mod aio;

#[cfg(any(target_os = "android", target_os = "linux"))]
pub mod epoll;

#[cfg(any(target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "ios",
          target_os = "macos",
          target_os = "netbsd",
          target_os = "openbsd"))]
pub mod event;

#[cfg(target_os = "linux")]
pub mod eventfd;

#[cfg(target_os = "linux")]
pub mod memfd;

#[macro_use]
pub mod ioctl;

// TODO: Add support for dragonfly, freebsd, and ios/macos.
#[cfg(any(target_os = "android", target_os = "linux"))]
pub mod sendfile;

pub mod signal;

#[cfg(any(target_os = "android", target_os = "linux"))]
pub mod signalfd;

pub mod socket;

pub mod stat;

#[cfg(any(target_os = "linux"))]
pub mod reboot;

pub mod termios;

pub mod utsname;

pub mod wait;

pub mod mman;

pub mod uio;

pub mod time;

#[cfg(any(target_os = "android", target_os = "linux"))]
pub mod ptrace;

pub mod select;

#[cfg(target_os = "linux")]
pub mod quota;

#[cfg(all(target_os = "linux",
          any(target_arch = "x86",
              target_arch = "x86_64",
              target_arch = "arm")),
          )]
pub mod statfs;

#[cfg(all(any(target_os = "linux",
              target_os = "macos"),
          any(target_arch = "x86",
              target_arch = "x86_64",
              target_arch = "arm")),
          )]
pub mod statvfs;
pub mod pthread;
<commit_msg>Alphabetize modules under /sys<commit_after>#[cfg(any(target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "ios",
          target_os = "linux",
          target_os = "macos",
          target_os = "netbsd"))]
pub mod aio;

#[cfg(any(target_os = "android", target_os = "linux"))]
pub mod epoll;

#[cfg(any(target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "ios",
          target_os = "macos",
          target_os = "netbsd",
          target_os = "openbsd"))]
pub mod event;

#[cfg(target_os = "linux")]
pub mod eventfd;

#[macro_use]
pub mod ioctl;

#[cfg(target_os = "linux")]
pub mod memfd;

pub mod mman;

pub mod pthread;

#[cfg(any(target_os = "android", target_os = "linux"))]
pub mod ptrace;

#[cfg(target_os = "linux")]
pub mod quota;

#[cfg(any(target_os = "linux"))]
pub mod reboot;

pub mod select;

// TODO: Add support for dragonfly, freebsd, and ios/macos.
#[cfg(any(target_os = "android", target_os = "linux"))]
pub mod sendfile;

pub mod signal;

#[cfg(any(target_os = "android", target_os = "linux"))]
pub mod signalfd;

pub mod socket;

pub mod stat;

#[cfg(all(target_os = "linux",
          any(target_arch = "x86",
              target_arch = "x86_64",
              target_arch = "arm")),
          )]
pub mod statfs;

#[cfg(all(any(target_os = "linux",
              target_os = "macos"),
          any(target_arch = "x86",
              target_arch = "x86_64",
              target_arch = "arm")),
          )]
pub mod statvfs;

pub mod termios;

pub mod time;

pub mod uio;

pub mod utsname;

pub mod wait;
<|endoftext|>