<commit_before>//! # Type safety for the weary netlink user
//!
//! ## Rationale
//!
//! This crate aims to be a pure Rust implementation that defines
//! the necessary constants and wraps them in enums to distinguish between various categories of
//! constants in the context of netlink.

#![deny(missing_docs)]

extern crate buffering;
extern crate byteorder;
extern crate libc;
extern crate mio;
#[cfg(feature = "stream")]
extern crate tokio;

/// C constants defined as types
pub mod consts;
/// Wrapper for `libc` sockets
pub mod socket;
/// Netlink attribute handler
pub mod nlattr;
/// Top-level netlink header
pub mod nl;
/// Genetlink (generic netlink) header and attribute helpers
pub mod genl;
/// Route netlink bindings
pub mod rtnl;
/// Error module
pub mod err;

use std::ffi::CString;
use std::io::{Read,Write};
use std::mem;
use std::str;

pub use buffering::copy::{StreamReadBuffer,StreamWriteBuffer};
use byteorder::{NativeEndian,ReadBytesExt,WriteBytesExt};

use consts::alignto;
use err::{SerError,DeError};

/// Max supported message length for netlink messages supported by the kernel
pub const MAX_NL_LENGTH: usize = 32768;

/// Trait defining basic actions required for netlink communication
pub trait Nl: Sized {
    /// Serialization input type for stateful serialization - set to `()` for stateless
    /// serialization
    type SerIn;
    /// Deserialization input type for stateful deserialization - set to `()` for stateless
    /// deserialization
    type DeIn;

    /// Serialization method
    fn serialize(&self, _m: &mut StreamWriteBuffer) -> Result<(), SerError> {
        unimplemented!()
    }
    /// Serialization method
    fn serialize_with(&self, _m: &mut StreamWriteBuffer, _in: Self::SerIn) -> Result<(), SerError> {
        unimplemented!()
    }
    /// Stateless deserialization method
    fn deserialize<T>(_m: &mut StreamReadBuffer<T>) -> Result<Self, DeError> where T: AsRef<[u8]> {
        unimplemented!()
    }
    /// Stateful deserialization method
    fn deserialize_with<T>(_m: &mut StreamReadBuffer<T>, _in: Self::DeIn) -> Result<Self, DeError>
            where T: AsRef<[u8]> {
        unimplemented!()
    }
    /// The size of the binary representation of a struct - not aligned to word size
    fn size(&self) -> usize;
    /// The size of the binary representation of a struct - aligned to word size
    fn asize(&self) -> usize {
        alignto(self.size())
    }
}

impl Nl for u8 {
    type SerIn = ();
    type DeIn = ();

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        mem.write_u8(*self)?;
        Ok(())
    }

    fn deserialize<T>(mem: &mut StreamReadBuffer<T>) -> Result<Self, DeError> where T: AsRef<[u8]> {
        Ok(mem.read_u8()?)
    }

    fn size(&self) -> usize {
        mem::size_of::<u8>()
    }
}

impl Nl for u16 {
    type SerIn = ();
    type DeIn = ();

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        mem.write_u16::<NativeEndian>(*self)?;
        Ok(())
    }

    fn deserialize<T>(mem: &mut StreamReadBuffer<T>) -> Result<Self, DeError> where T: AsRef<[u8]> {
        Ok(mem.read_u16::<NativeEndian>()?)
    }

    fn size(&self) -> usize {
        mem::size_of::<u16>()
    }
}

impl Nl for u32 {
    type SerIn = ();
    type DeIn = ();

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        mem.write_u32::<NativeEndian>(*self)?;
        Ok(())
    }

    fn deserialize<T>(mem: &mut StreamReadBuffer<T>) -> Result<Self, DeError> where T: AsRef<[u8]> {
        Ok(mem.read_u32::<NativeEndian>()?)
    }

    fn size(&self) -> usize {
        mem::size_of::<u32>()
    }
}

impl Nl for i32 {
    type SerIn = ();
    type DeIn = ();

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        mem.write_i32::<NativeEndian>(*self)?;
        Ok(())
    }

    fn deserialize<T>(mem: &mut StreamReadBuffer<T>) -> Result<Self, DeError> where T: AsRef<[u8]> {
        Ok(mem.read_i32::<NativeEndian>()?)
    }

    fn size(&self) -> usize {
        mem::size_of::<i32>()
    }
}

impl<'a> Nl for &'a [u8] {
    type SerIn = ();
    type DeIn = &'a mut [u8];

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        let num_bytes = mem.write(self)?;
        if alignto(self.len()) - num_bytes > 0 {
            let padding = vec![0; self.len() - num_bytes];
            mem.write(&padding)?;
        }
        Ok(())
    }

    fn deserialize_with<T>(mem: &mut StreamReadBuffer<T>, input: &'a mut [u8]) -> Result<Self, DeError>
            where T: AsRef<[u8]> {
        mem.read_exact(input)?;
        Ok(input)
    }

    fn size(&self) -> usize {
        self.len()
    }
}

impl Nl for Vec<u8> {
    type SerIn = usize;
    type DeIn = usize;

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        let _ = mem.write(&self)?;
        Ok(())
    }

    fn serialize_with(&self, mem: &mut StreamWriteBuffer, input: usize) -> Result<(), SerError> {
        let bytes: Vec<u8> = self.iter().take(input).map(|u| *u).collect();
        let _ = mem.write(&bytes)?;
        Ok(())
    }

    fn deserialize<T>(mem: &mut StreamReadBuffer<T>) -> Result<Self, DeError> where T: AsRef<[u8]> {
        let mut v = Vec::new();
        let _ = mem.read_to_end(&mut v)?;
        Ok(v)
    }

    fn deserialize_with<T>(mem: &mut StreamReadBuffer<T>, input: usize) -> Result<Self, DeError>
            where T: AsRef<[u8]> {
        let mut v = vec![0; input];
        let _ = mem.read(v.as_mut_slice())?;
        Ok(v)
    }

    fn size(&self) -> usize {
        self.len()
    }
}

impl<'a> Nl for &'a str {
    type SerIn = usize;
    type DeIn = &'a mut [u8];

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        let c_str = try!(CString::new(self.as_bytes()).map_err(|_| {
            SerError::new("Unable to serialize string containing null byte")
        }));
        let bytes = c_str.as_bytes_with_nul();
        let _ = mem.write(bytes)?;
        Ok(())
    }

    fn serialize_with(&self, mem: &mut StreamWriteBuffer, input: usize) -> Result<(), SerError> {
        let c_str = try!(CString::new(self.as_bytes()).map_err(|_| {
            SerError::new("Unable to serialize string containing null byte")
        }));
        let bytes = c_str.as_bytes_with_nul();
        let num_bytes = mem.write(bytes)?;
        if input - num_bytes > 0 {
            mem.write(&vec![0; input - num_bytes])?;
        }
        Ok(())
    }

    fn deserialize_with<T>(mem: &mut StreamReadBuffer<T>, input: &'a mut [u8]) -> Result<Self, DeError>
            where T: AsRef<[u8]> {
        mem.read_exact(input)?;
        let idx = input.iter().position(|elem| *elem == 0);
        let mut new_input: (&[u8], &[u8]) = (&[], &[]);
        if let Some(i) = idx {
            new_input = input.split_at(i);
        }
        let (beginning, _) = new_input;
        Ok(str::from_utf8(beginning)?)
    }

    fn size(&self) -> usize {
        self.len()
    }
}

impl Nl for String {
    type SerIn = usize;
    type DeIn = usize;

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        let c_str = try!(CString::new(self.as_bytes()).map_err(|_| {
            SerError::new("Unable to serialize string containing null byte")
        }));
        let bytes = c_str.as_bytes_with_nul();
        let _ = mem.write(bytes)?;
        Ok(())
    }

    fn serialize_with(&self, mem: &mut StreamWriteBuffer, input: usize) -> Result<(), SerError> {
        let c_str = try!(CString::new(self.as_bytes()).map_err(|_| {
            SerError::new("Unable to serialize string containing null byte")
        }));
        let bytes = c_str.as_bytes_with_nul();
        let num_bytes = mem.write(bytes)?;
        if input - num_bytes > 0 {
            mem.write(&vec![0; input - num_bytes])?;
        }
        Ok(())
    }

    fn deserialize_with<T>(mem: &mut StreamReadBuffer<T>, input: usize) -> Result<Self, DeError>
            where T: AsRef<[u8]> {
        let mut v = vec![0; input];
        let _ = mem.read(v.as_mut_slice())?;
        let idx = v.iter().position(|elem| *elem == 0);
        if let Some(i) = idx {
            v.truncate(i);
        }
        Ok(String::from_utf8(v)?)
    }

    fn size(&self) -> usize {
        self.len() + 1
    }
}

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

    use std::io::Cursor;

    #[test]
    fn test_nl_u8() {
        let v: u8 = 5;
        let s: &mut [u8; 1] = &mut [0];
        {
            let mut mem = StreamWriteBuffer::new_sized(s);
            v.serialize(&mut mem).unwrap();
        }
        assert_eq!(s[0], v);

        let mut mem = StreamReadBuffer::new(&[5]);
        let v = u8::deserialize(&mut mem).unwrap();
        assert_eq!(v, 5)
    }

    #[test]
    fn test_nl_u16() {
        let v: u16 = 6000;
        let s: &mut [u8] = &mut [0; 2];
        {
            let mut mem = StreamWriteBuffer::new_sized(s);
            mem.write_u16::<NativeEndian>(6000).unwrap();
        }
        let s_test = &mut [0; 2];
        {
            let mut mem = StreamWriteBuffer::new_sized(s_test);
            v.serialize(&mut mem).unwrap();
        }
        assert_eq!(s, s_test);

        let s: &mut [u8] = &mut [0; 2];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u16::<NativeEndian>(6000).unwrap();
        }
        let v = {
            let mut mem = StreamReadBuffer::new(s);
            u16::deserialize(&mut mem).unwrap()
        };
        assert_eq!(v, 6000)
    }

    #[test]
    fn test_nl_u32() {
        let v: u32 = 600000;
        let s: &mut [u8] = &mut [0; 4];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u32::<NativeEndian>(600000).unwrap();
        }
        let s_test = &mut [0; 4];
        {
            let mut mem = StreamWriteBuffer::new_sized(s_test);
            v.serialize(&mut mem).unwrap();
        }
        assert_eq!(s, s_test);

        let s: &mut [u8] = &mut [0; 4];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u32::<NativeEndian>(600000).unwrap();
        }
        let v = {
            let mut mem = StreamReadBuffer::new(&*s);
            u32::deserialize(&mut mem).unwrap()
        };
        assert_eq!(v, 600000)
    }

    #[test]
    fn test_nl_vec() {
        let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        let s = &mut [0; 9];
        {
            let mut mem = StreamWriteBuffer::new_sized(s);
            v.serialize(&mut mem).unwrap();
        }
        assert_eq!(v, s.to_vec());

        let s = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0];
        let v = {
            let mut mem = StreamReadBuffer::new(s);
            Vec::<u8>::deserialize_with(&mut mem, 9).unwrap()
        };
        assert_eq!(v.as_slice(), &[1, 2, 3, 4, 5, 6, 7, 8, 9])
    }

    #[test]
    fn test_nl_string() {
        let s = "AAAAA".to_string();
        let sl = &mut [0; 6];
        {
            let mut mem = StreamWriteBuffer::new_sized(sl);
            s.serialize(&mut mem).unwrap();
        }
        assert_eq!(&[65, 65, 65, 65, 65, 0], sl);

        let s = &[65, 65, 65, 65, 65, 65, 65, 0];
        let mut mem = StreamReadBuffer::new(s);
        let string = String::deserialize_with(&mut mem, 8).unwrap();
        assert_eq!(string, "AAAAAAA".to_string());

        let s = &[65, 65, 65, 65, 65, 65, 0, 0];
        let mut mem = StreamReadBuffer::new(s);
        let string = String::deserialize_with(&mut mem, 7).unwrap();
        assert_eq!(string, "AAAAAA".to_string())
    }
}
<commit_msg>added impl Nl for u64 and test<commit_after>//! # Type safety for the weary netlink user
//!
//! ## Rationale
//!
//! This crate aims to be a pure Rust implementation that defines
//! the necessary constants and wraps them in enums to distinguish between various categories of
//! constants in the context of netlink.

#![deny(missing_docs)]

extern crate buffering;
extern crate byteorder;
extern crate libc;
extern crate mio;
#[cfg(feature = "stream")]
extern crate tokio;

/// C constants defined as types
pub mod consts;
/// Wrapper for `libc` sockets
pub mod socket;
/// Netlink attribute handler
pub mod nlattr;
/// Top-level netlink header
pub mod nl;
/// Genetlink (generic netlink) header and attribute helpers
pub mod genl;
/// Route netlink bindings
pub mod rtnl;
/// Error module
pub mod err;

use std::ffi::CString;
use std::io::{Read,Write};
use std::mem;
use std::str;

pub use buffering::copy::{StreamReadBuffer,StreamWriteBuffer};
use byteorder::{NativeEndian,ReadBytesExt,WriteBytesExt};

use consts::alignto;
use err::{SerError,DeError};

/// Max supported message length for netlink messages supported by the kernel
pub const MAX_NL_LENGTH: usize = 32768;

/// Trait defining basic actions required for netlink communication
pub trait Nl: Sized {
    /// Serialization input type for stateful serialization - set to `()` for stateless
    /// serialization
    type SerIn;
    /// Deserialization input type for stateful deserialization - set to `()` for stateless
    /// deserialization
    type DeIn;

    /// Serialization method
    fn serialize(&self, _m: &mut StreamWriteBuffer) -> Result<(), SerError> {
        unimplemented!()
    }
    /// Serialization method
    fn serialize_with(&self, _m: &mut StreamWriteBuffer, _in: Self::SerIn) -> Result<(), SerError> {
        unimplemented!()
    }
    /// Stateless deserialization method
    fn deserialize<T>(_m: &mut StreamReadBuffer<T>) -> Result<Self, DeError> where T: AsRef<[u8]> {
        unimplemented!()
    }
    /// Stateful deserialization method
    fn deserialize_with<T>(_m: &mut StreamReadBuffer<T>, _in: Self::DeIn) -> Result<Self, DeError>
            where T: AsRef<[u8]> {
        unimplemented!()
    }
    /// The size of the binary representation of a struct - not aligned to word size
    fn size(&self) -> usize;
    /// The size of the binary representation of a struct - aligned to word size
    fn asize(&self) -> usize {
        alignto(self.size())
    }
}

impl Nl for u8 {
    type SerIn = ();
    type DeIn = ();

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        mem.write_u8(*self)?;
        Ok(())
    }

    fn deserialize<T>(mem: &mut StreamReadBuffer<T>) -> Result<Self, DeError> where T: AsRef<[u8]> {
        Ok(mem.read_u8()?)
    }

    fn size(&self) -> usize {
        mem::size_of::<u8>()
    }
}

impl Nl for u16 {
    type SerIn = ();
    type DeIn = ();

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        mem.write_u16::<NativeEndian>(*self)?;
        Ok(())
    }

    fn deserialize<T>(mem: &mut StreamReadBuffer<T>) -> Result<Self, DeError> where T: AsRef<[u8]> {
        Ok(mem.read_u16::<NativeEndian>()?)
    }

    fn size(&self) -> usize {
        mem::size_of::<u16>()
    }
}

impl Nl for u32 {
    type SerIn = ();
    type DeIn = ();

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        mem.write_u32::<NativeEndian>(*self)?;
        Ok(())
    }

    fn deserialize<T>(mem: &mut StreamReadBuffer<T>) -> Result<Self, DeError> where T: AsRef<[u8]> {
        Ok(mem.read_u32::<NativeEndian>()?)
    }

    fn size(&self) -> usize {
        mem::size_of::<u32>()
    }
}

impl Nl for i32 {
    type SerIn = ();
    type DeIn = ();

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        mem.write_i32::<NativeEndian>(*self)?;
        Ok(())
    }

    fn deserialize<T>(mem: &mut StreamReadBuffer<T>) -> Result<Self, DeError> where T: AsRef<[u8]> {
        Ok(mem.read_i32::<NativeEndian>()?)
    }

    fn size(&self) -> usize {
        mem::size_of::<i32>()
    }
}

impl Nl for u64 {
    type SerIn = ();
    type DeIn = ();

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        mem.write_u64::<NativeEndian>(*self)?;
        Ok(())
    }

    fn deserialize<T>(mem: &mut StreamReadBuffer<T>) -> Result<Self, DeError> where T: AsRef<[u8]> {
        Ok(mem.read_u64::<NativeEndian>()?)
    }

    fn size(&self) -> usize {
        mem::size_of::<u64>()
    }
}

impl<'a> Nl for &'a [u8] {
    type SerIn = ();
    type DeIn = &'a mut [u8];

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        let num_bytes = mem.write(self)?;
        if alignto(self.len()) - num_bytes > 0 {
            let padding = vec![0; self.len() - num_bytes];
            mem.write(&padding)?;
        }
        Ok(())
    }

    fn deserialize_with<T>(mem: &mut StreamReadBuffer<T>, input: &'a mut [u8]) -> Result<Self, DeError>
            where T: AsRef<[u8]> {
        mem.read_exact(input)?;
        Ok(input)
    }

    fn size(&self) -> usize {
        self.len()
    }
}

impl Nl for Vec<u8> {
    type SerIn = usize;
    type DeIn = usize;

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        let _ = mem.write(&self)?;
        Ok(())
    }

    fn serialize_with(&self, mem: &mut StreamWriteBuffer, input: usize) -> Result<(), SerError> {
        let bytes: Vec<u8> = self.iter().take(input).map(|u| *u).collect();
        let _ = mem.write(&bytes)?;
        Ok(())
    }

    fn deserialize<T>(mem: &mut StreamReadBuffer<T>) -> Result<Self, DeError> where T: AsRef<[u8]> {
        let mut v = Vec::new();
        let _ = mem.read_to_end(&mut v)?;
        Ok(v)
    }

    fn deserialize_with<T>(mem: &mut StreamReadBuffer<T>, input: usize) -> Result<Self, DeError>
            where T: AsRef<[u8]> {
        let mut v = vec![0; input];
        let _ = mem.read(v.as_mut_slice())?;
        Ok(v)
    }

    fn size(&self) -> usize {
        self.len()
    }
}

impl<'a> Nl for &'a str {
    type SerIn = usize;
    type DeIn = &'a mut [u8];

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        let c_str = try!(CString::new(self.as_bytes()).map_err(|_| {
            SerError::new("Unable to serialize string containing null byte")
        }));
        let bytes = c_str.as_bytes_with_nul();
        let _ = mem.write(bytes)?;
        Ok(())
    }

    fn serialize_with(&self, mem: &mut StreamWriteBuffer, input: usize) -> Result<(), SerError> {
        let c_str = try!(CString::new(self.as_bytes()).map_err(|_| {
            SerError::new("Unable to serialize string containing null byte")
        }));
        let bytes = c_str.as_bytes_with_nul();
        let num_bytes = mem.write(bytes)?;
        if input - num_bytes > 0 {
            mem.write(&vec![0; input - num_bytes])?;
        }
        Ok(())
    }

    fn deserialize_with<T>(mem: &mut StreamReadBuffer<T>, input: &'a mut [u8]) -> Result<Self, DeError>
            where T: AsRef<[u8]> {
        mem.read_exact(input)?;
        let idx = input.iter().position(|elem| *elem == 0);
        let mut new_input: (&[u8], &[u8]) = (&[], &[]);
        if let Some(i) = idx {
            new_input = input.split_at(i);
        }
        let (beginning, _) = new_input;
        Ok(str::from_utf8(beginning)?)
    }

    fn size(&self) -> usize {
        self.len()
    }
}

impl Nl for String {
    type SerIn = usize;
    type DeIn = usize;

    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        let c_str = try!(CString::new(self.as_bytes()).map_err(|_| {
            SerError::new("Unable to serialize string containing null byte")
        }));
        let bytes = c_str.as_bytes_with_nul();
        let _ = mem.write(bytes)?;
        Ok(())
    }

    fn serialize_with(&self, mem: &mut StreamWriteBuffer, input: usize) -> Result<(), SerError> {
        let c_str = try!(CString::new(self.as_bytes()).map_err(|_| {
            SerError::new("Unable to serialize string containing null byte")
        }));
        let bytes = c_str.as_bytes_with_nul();
        let num_bytes = mem.write(bytes)?;
        if input - num_bytes > 0 {
            mem.write(&vec![0; input - num_bytes])?;
        }
        Ok(())
    }

    fn deserialize_with<T>(mem: &mut StreamReadBuffer<T>, input: usize) -> Result<Self, DeError>
            where T: AsRef<[u8]> {
        let mut v = vec![0; input];
        let _ = mem.read(v.as_mut_slice())?;
        let idx = v.iter().position(|elem| *elem == 0);
        if let Some(i) = idx {
            v.truncate(i);
        }
        Ok(String::from_utf8(v)?)
    }

    fn size(&self) -> usize {
        self.len() + 1
    }
}

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

    use std::io::Cursor;

    #[test]
    fn test_nl_u8() {
        let v: u8 = 5;
        let s: &mut [u8; 1] = &mut [0];
        {
            let mut mem = StreamWriteBuffer::new_sized(s);
            v.serialize(&mut mem).unwrap();
        }
        assert_eq!(s[0], v);

        let mut mem = StreamReadBuffer::new(&[5]);
        let v = u8::deserialize(&mut mem).unwrap();
        assert_eq!(v, 5)
    }

    #[test]
    fn test_nl_u16() {
        let v: u16 = 6000;
        let s: &mut [u8] = &mut [0; 2];
        {
            let mut mem = StreamWriteBuffer::new_sized(s);
            mem.write_u16::<NativeEndian>(6000).unwrap();
        }
        let s_test = &mut [0; 2];
        {
            let mut mem = StreamWriteBuffer::new_sized(s_test);
            v.serialize(&mut mem).unwrap();
        }
        assert_eq!(s, s_test);

        let s: &mut [u8] = &mut [0; 2];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u16::<NativeEndian>(6000).unwrap();
        }
        let v = {
            let mut mem = StreamReadBuffer::new(s);
            u16::deserialize(&mut mem).unwrap()
        };
        assert_eq!(v, 6000)
    }

    #[test]
    fn test_nl_u32() {
        let v: u32 = 600000;
        let s: &mut [u8] = &mut [0; 4];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u32::<NativeEndian>(600000).unwrap();
        }
        let s_test = &mut [0; 4];
        {
            let mut mem = StreamWriteBuffer::new_sized(s_test);
            v.serialize(&mut mem).unwrap();
        }
        assert_eq!(s, s_test);

        let s: &mut [u8] = &mut [0; 4];
        {
            let mut c = Cursor::new(&mut *s);
            c.write_u32::<NativeEndian>(600000).unwrap();
        }
        let v = {
            let mut mem = StreamReadBuffer::new(&*s);
            u32::deserialize(&mut mem).unwrap()
        };
        assert_eq!(v, 600000)
    }

    #[test]
    fn test_nl_u64() {
        let test_int: u64 = 12345678901234;
        let expected_serial: &mut [u8] = &mut [0; 8];
        {
            let mut c = Cursor::new(&mut *expected_serial);
            c.write_u64::<NativeEndian>(test_int).unwrap();
        }
        let test_serial = &mut [0; 8];
        {
            let mut mem = StreamWriteBuffer::new_sized(test_serial);
            test_int.serialize(&mut mem).unwrap();
        }
        assert_eq!(expected_serial, test_serial);

        let buffer: &mut [u8] = &mut [0; 8];
        {
            let mut c = Cursor::new(&mut *buffer);
            c.write_u64::<NativeEndian>(test_int).unwrap();
        }
        let deserialed_int = {
            let mut mem = StreamReadBuffer::new(&*buffer);
            u64::deserialize(&mut mem).unwrap()
        };
        assert_eq!(test_int, deserialed_int);
    }

    #[test]
    fn test_nl_vec() {
        let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        let s = &mut [0; 9];
        {
            let mut mem = StreamWriteBuffer::new_sized(s);
            v.serialize(&mut mem).unwrap();
        }
        assert_eq!(v, s.to_vec());

        let s = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0];
        let v = {
            let mut mem = StreamReadBuffer::new(s);
            Vec::<u8>::deserialize_with(&mut mem, 9).unwrap()
        };
        assert_eq!(v.as_slice(), &[1, 2, 3, 4, 5, 6, 7, 8, 9])
    }

    #[test]
    fn test_nl_string() {
        let s = "AAAAA".to_string();
        let sl = &mut [0; 6];
        {
            let mut mem = StreamWriteBuffer::new_sized(sl);
            s.serialize(&mut mem).unwrap();
        }
        assert_eq!(&[65, 65, 65, 65, 65, 0], sl);

        let s = &[65, 65, 65, 65, 65, 65, 65, 0];
        let mut mem = StreamReadBuffer::new(s);
        let string = String::deserialize_with(&mut mem, 8).unwrap();
        assert_eq!(string, "AAAAAAA".to_string());

        let s = &[65, 65, 65, 65, 65, 65, 0, 0];
        let mut mem = StreamReadBuffer::new(s);
        let string = String::deserialize_with(&mut mem, 7).unwrap();
        assert_eq!(string, "AAAAAA".to_string())
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate image;
extern crate gif;
extern crate gif_dispose;

use std::path::Path;
use std::fs::File;
use std::error::Error;

use image::{ImageRgba8, ImageFormat, ImageBuffer};
use gif::{Decoder, SetParameter, ColorOutput};
use gif_dispose::Screen;

mod utils;

use utils::{info, paginate, scan};

pub fn enimda(path: &Path,
              fppt: f32,
              flim: u32,
              size: u32,
              depth: f32,
              thres: f32,
              sppt: f32,
              slim: u32,
              deep: bool)
              -> Result<Vec<u32>, Box<Error>> {

    let (format, width, height, frames) = info(path)?;
    Ok(match format {
        ImageFormat::GIF => {
            if fppt < 0.0 || fppt > 1.0 {
                panic!("0.0 <= ppt <= 1.0 expected");
            }

            let mut decoder = Decoder::new(File::open(path)?);
            decoder.set(ColorOutput::Indexed);
            let mut reader = decoder.read_info().unwrap();
            let mut screen = Screen::new(&reader);

            let iframes = paginate(frames, fppt, flim)?;
            let mut variants = Vec::new();
            let mut iframe = 0;
            while let Some(frame) = reader.read_next_frame().unwrap() {
                if iframes.iter().any(|&x| x == iframe) {
                    screen.blit(&frame)?;
                    let mut buf: Vec<u8> = Vec::new();
                    for pixel in screen.pixels.iter() {
                        buf.push(pixel.r);
                        buf.push(pixel.g);
                        buf.push(pixel.b);
                        buf.push(pixel.a);
                    }
                    let im = ImageRgba8(ImageBuffer::from_raw(width, height, buf).unwrap());
                    variants.push(scan(&im, size, depth, thres, sppt, slim, deep)?);
                }

                iframe += 1;
            }

            let mut borders = vec![0, 0, 0, 0];
            for variant in variants.iter() {
                for i in 0..variant.len() {
                    if variant[i] == 0 || borders[i] < variant[i] {
                        borders[i] = variant[i];
                    }
                }
            }

            borders
        }
        _ => {
            let im = image::open(path)?;
            scan(&im, size, depth, thres, sppt, slim, deep)?
        }
    })
}
<commit_msg>gif checks, iter<commit_after>extern crate rand;
extern crate image;
extern crate gif;
extern crate gif_dispose;

use std::path::Path;
use std::fs::File;
use std::error::Error;

use image::{ImageRgba8, ImageFormat, ImageBuffer};
use gif::{Decoder, SetParameter, ColorOutput};
use gif_dispose::Screen;

mod utils;

use utils::{info, paginate, scan};

pub fn enimda(path: &Path,
              fppt: f32,
              flim: u32,
              size: u32,
              depth: f32,
              thres: f32,
              sppt: f32,
              slim: u32,
              deep: bool)
              -> Result<Vec<u32>, Box<Error>> {

    let (format, width, height, frames) = info(path)?;
    Ok(match format {
        ImageFormat::GIF => {
            if fppt < 0.0 || fppt > 1.0 {
                panic!("0.0 <= ppt <= 1.0 expected");
            }
            let frames = paginate(frames, fppt, flim)?;

            let mut decoder = Decoder::new(File::open(path)?);
            decoder.set(ColorOutput::Indexed);
            let mut reader = decoder.read_info().unwrap();
            let mut screen = Screen::new(&reader);

            let mut borders = vec![0, 0, 0, 0];
            let mut i = 0;
            while let Some(frame) = reader.read_next_frame().unwrap() {
                if fppt == 1.0 || flim == 0 || frames.iter().any(|&x| x == i) {
                    screen.blit(&frame)?;
                    let mut buf: Vec<u8> = Vec::new();
                    for pixel in screen.pixels.iter() {
                        buf.push(pixel.r);
                        buf.push(pixel.g);
                        buf.push(pixel.b);
                        buf.push(pixel.a);
                    }
                    let im = ImageRgba8(ImageBuffer::from_raw(width, height, buf).unwrap());
                    let variant = scan(&im, size, depth, thres, sppt, slim, deep)?;
                    for j in 0..borders.len() {
                        if variant[j] == 0 || borders[j] < variant[j] {
                            borders[j] = variant[j];
                        }
                    }
                }

                i += 1;
            }

            borders
        }
        _ => {
            let im = image::open(path)?;
            scan(&im, size, depth, thres, sppt, slim, deep)?
        }
    })
}
<|endoftext|>


<commit_before>//! Bindings for serial port I/O and futures
//!
//! This crate provides bindings between `mio_serial`, a mio crate for
//! serial port I/O, and `futures`.  The API is very similar to the
//! bindings in `mio_serial`
//!
#![deny(missing_docs)]

extern crate futures;
extern crate tokio_core;
extern crate tokio_io;
extern crate bytes;

extern crate mio_serial;

// Re-export serialport types and traits from mio_serial
pub use mio_serial::{BaudRate, DataBits, StopBits, FlowControl, Parity, SerialPort,
                     SerialPortSettings, Error, ErrorKind};

/// A type for results generated by interacting with serial ports.
pub type Result<T> = mio_serial::Result<T>;

use futures::{Async, Poll};
use tokio_core::reactor::{PollEvented, Handle};
use tokio_io::{AsyncRead, AsyncWrite};

use std::io::{self, Read, Write};
use std::path::Path;
use std::time::Duration;

/// Serial port I/O struct.
pub struct Serial {
    io: PollEvented<mio_serial::Serial>,
}

impl Serial {
    /// Open serial port from a provided path.
    pub fn from_path<P>(path: P,
                        settings: &mio_serial::SerialPortSettings,
                        handle: &Handle)
                        -> io::Result<Serial>
        where P: AsRef<Path>
    {

        let port = mio_serial::Serial::from_path(path.as_ref(), settings)?;
        let io = PollEvented::new(port, handle)?;

        Ok(Serial { io: io })
    }

    /// Test whether this serial port is ready to be read or not.
    ///
    /// If the serial port is *not* readable then the current task is scheduled to
    /// get a notification when the socket does become readable. That is, this
    /// is only suitable for calling in a `Future::poll` method and will
    /// automatically handle ensuring a retry once the socket is readable again.
    pub fn poll_read(&self) -> Async<()> {
        self.io.poll_read()
    }

    /// Test whether this socket is ready to be written to or not.
    ///
    /// If the socket is *not* writable then the current task is scheduled to
    /// get a notification when the socket does become writable. That is, this
    /// is only suitable for calling in a `Future::poll` method and will
    /// automatically handle ensuring a retry once the socket is writable again.
    pub fn poll_write(&self) -> Async<()> {
        self.io.poll_write()
    }

    /// Create a pair of pseudo serial terminals
    ///
    /// ## Returns
    /// Two connected, unnamed `Serial` objects.
    ///
    /// ## Errors
    /// Attempting any IO or parameter settings on the slave tty after the master
    /// tty is closed will return errors.
    ///
    #[cfg(unix)]
    pub fn pair(handle: &Handle) -> ::Result<(Self, Self)> {
        let (master, slave) = mio_serial::Serial::pair()?;

        let master = Serial { io: PollEvented::new(master, handle)? };
        let slave = Serial { io: PollEvented::new(slave, handle)? };
        Ok((master, slave))
    }

    /// Sets the exclusivity of the port
    ///
    /// If a port is exclusive, then trying to open the same device path again
    /// will fail.
    ///
    /// See the man pages for the tiocexcl and tiocnxcl ioctl's for more details.
    ///
    /// ## Errors
    ///
    /// * `Io` for any error while setting exclusivity for the port.
    #[cfg(unix)]
    pub fn set_exclusive(&mut self, exclusive: bool) -> ::Result<()> {
        self.io.get_mut().set_exclusive(exclusive)
    }

    /// Returns the exclusivity of the port
    ///
    /// If a port is exclusive, then trying to open the same device path again
    /// will fail.
    #[cfg(unix)]
    pub fn exclusive(&self) -> bool {
        self.io.get_ref().exclusive()
    }
}

impl ::SerialPort for Serial {
    /// Returns a struct with the current port settings
    fn settings(&self) -> ::SerialPortSettings {
        self.io.get_ref().settings()
    }

    /// Return the name associated with the serial port, if known.
    fn port_name(&self) -> Option<String> {
        self.io.get_ref().port_name()
    }

    /// Returns the current baud rate.
    ///
    /// This function returns `None` if the baud rate could not be determined. This may occur if
    /// the hardware is in an uninitialized state. Setting a baud rate with `set_baud_rate()`
    /// should initialize the baud rate to a supported value.
    fn baud_rate(&self) -> Option<::BaudRate> {
        self.io.get_ref().baud_rate()
    }

    /// Returns the character size.
    ///
    /// This function returns `None` if the character size could not be determined. This may occur
    /// if the hardware is in an uninitialized state or is using a non-standard character size.
    /// Setting a baud rate with `set_char_size()` should initialize the character size to a
    /// supported value.
    fn data_bits(&self) -> Option<::DataBits> {
        self.io.get_ref().data_bits()
    }

    /// Returns the flow control mode.
    ///
    /// This function returns `None` if the flow control mode could not be determined. This may
    /// occur if the hardware is in an uninitialized state or is using an unsupported flow control
    /// mode. Setting a flow control mode with `set_flow_control()` should initialize the flow
    /// control mode to a supported value.
    fn flow_control(&self) -> Option<::FlowControl> {
        self.io.get_ref().flow_control()
    }

    /// Returns the parity-checking mode.
    ///
    /// This function returns `None` if the parity mode could not be determined. This may occur if
    /// the hardware is in an uninitialized state or is using a non-standard parity mode. Setting
    /// a parity mode with `set_parity()` should initialize the parity mode to a supported value.
    fn parity(&self) -> Option<::Parity> {
        self.io.get_ref().parity()
    }

    /// Returns the number of stop bits.
    ///
    /// This function returns `None` if the number of stop bits could not be determined. This may
    /// occur if the hardware is in an uninitialized state or is using an unsupported stop bit
    /// configuration. Setting the number of stop bits with `set_stop-bits()` should initialize the
    /// stop bits to a supported value.
    fn stop_bits(&self) -> Option<::StopBits> {
        self.io.get_ref().stop_bits()
    }

    /// Returns the current timeout.
    fn timeout(&self) -> Duration {
        Duration::from_secs(0)
    }

    // Port settings setters

    /// Applies all settings for a struct. This isn't guaranteed to involve only
    /// a single call into the driver, though that may be done on some
    /// platforms.
    fn set_all(&mut self, settings: &::SerialPortSettings) -> ::Result<()> {
        self.io.get_mut().set_all(settings)
    }

    /// Sets the baud rate.
    ///
    /// ## Errors
    ///
    /// If the implementation does not support the requested baud rate, this function may return an
    /// `InvalidInput` error. Even if the baud rate is accepted by `set_baud_rate()`, it may not be
    /// supported by the underlying hardware.
    fn set_baud_rate(&mut self, baud_rate: ::BaudRate) -> ::Result<()> {
        self.io.get_mut().set_baud_rate(baud_rate)
    }

    /// Sets the character size.
    fn set_data_bits(&mut self, data_bits: ::DataBits) -> ::Result<()> {
        self.io.get_mut().set_data_bits(data_bits)
    }

    /// Sets the flow control mode.
    fn set_flow_control(&mut self, flow_control: ::FlowControl) -> ::Result<()> {
        self.io.get_mut().set_flow_control(flow_control)
    }

    /// Sets the parity-checking mode.
    fn set_parity(&mut self, parity: ::Parity) -> ::Result<()> {
        self.io.get_mut().set_parity(parity)
    }

    /// Sets the number of stop bits.
    fn set_stop_bits(&mut self, stop_bits: ::StopBits) -> ::Result<()> {
        self.io.get_mut().set_stop_bits(stop_bits)
    }

    /// Sets the timeout for future I/O operations.  This parameter is ignored but
    /// required for trait completeness.
    fn set_timeout(&mut self, _: Duration) -> ::Result<()> {
        Ok(())
    }

    // Functions for setting non-data control signal pins

    /// Sets the state of the RTS (Request To Send) control signal.
    ///
    /// Setting a value of `true` asserts the RTS control signal. `false` clears the signal.
    ///
    /// ## Errors
    ///
    /// This function returns an error if the RTS control signal could not be set to the desired
    /// state on the underlying hardware:
    ///
    /// * `NoDevice` if the device was disconnected.
    /// * `Io` for any other type of I/O error.
    fn write_request_to_send(&mut self, level: bool) -> ::Result<()> {
        self.io.get_mut().write_request_to_send(level)
    }

    /// Writes to the Data Terminal Ready pin
    ///
    /// Setting a value of `true` asserts the DTR control signal. `false` clears the signal.
    ///
    /// ## Errors
    ///
    /// This function returns an error if the DTR control signal could not be set to the desired
    /// state on the underlying hardware:
    ///
    /// * `NoDevice` if the device was disconnected.
    /// * `Io` for any other type of I/O error.
    fn write_data_terminal_ready(&mut self, level: bool) -> ::Result<()> {
        self.io.get_mut().write_data_terminal_ready(level)
    }

    // Functions for reading additional pins

    /// Reads the state of the CTS (Clear To Send) control signal.
    ///
    /// This function returns a boolean that indicates whether the CTS control signal is asserted.
    ///
    /// ## Errors
    ///
    /// This function returns an error if the state of the CTS control signal could not be read
    /// from the underlying hardware:
    ///
    /// * `NoDevice` if the device was disconnected.
    /// * `Io` for any other type of I/O error.
    fn read_clear_to_send(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_clear_to_send()
    }

    /// Reads the state of the Data Set Ready control signal.
    ///
    /// This function returns a boolean that indicates whether the DSR control signal is asserted.
    ///
    /// ## Errors
    ///
    /// This function returns an error if the state of the DSR control signal could not be read
    /// from the underlying hardware:
    ///
    /// * `NoDevice` if the device was disconnected.
    /// * `Io` for any other type of I/O error.
    fn read_data_set_ready(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_data_set_ready()
    }

    /// Reads the state of the Ring Indicator control signal.
    ///
    /// This function returns a boolean that indicates whether the RI control signal is asserted.
    ///
    /// ## Errors
    ///
    /// This function returns an error if the state of the RI control signal could not be read from
    /// the underlying hardware:
    ///
    /// * `NoDevice` if the device was disconnected.
    /// * `Io` for any other type of I/O error.
    fn read_ring_indicator(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_ring_indicator()
    }

    /// Reads the state of the Carrier Detect control signal.
    ///
    /// This function returns a boolean that indicates whether the CD control signal is asserted.
    ///
    /// ## Errors
    ///
    /// This function returns an error if the state of the CD control signal could not be read from
    /// the underlying hardware:
    ///
    /// * `NoDevice` if the device was disconnected.
    /// * `Io` for any other type of I/O error.
    fn read_carrier_detect(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_carrier_detect()
    }
}

impl Read for Serial {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.io.read(buf)
    }
}

impl Write for Serial {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.io.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.io.flush()
    }
}

impl<'a> Read for &'a Serial {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (&self.io).read(buf)
    }
}

impl<'a> Write for &'a Serial {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        (&self.io).write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        (&self.io).flush()
    }
}

#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd};
#[cfg(unix)]
impl AsRawFd for Serial {
    fn as_raw_fd(&self) -> RawFd {
        self.io.get_ref().as_raw_fd()
    }
}

impl AsyncRead for Serial {}

impl AsyncWrite for Serial {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        Ok(Async::Ready(()))
    }
}

// #[cfg(unix)]
// pub use unix::Serial;

// #[cfg(unix)]
// mod unix;

<commit_msg>Using accessors on PollEvented<mio_serial::Serial><commit_after>//! Bindings for serial port I/O and futures
//!
//! This crate provides bindings between `mio_serial`, a mio crate for
//! serial port I/O, and `futures`.  The API is very similar to the
//! bindings in `mio_serial`
//!
#![deny(missing_docs)]

extern crate futures;
extern crate tokio_core;
extern crate tokio_io;
extern crate bytes;

extern crate mio_serial;

// Re-export serialport types and traits from mio_serial
pub use mio_serial::{BaudRate, DataBits, StopBits, FlowControl, Parity, SerialPort,
                     SerialPortSettings, Error, ErrorKind};

/// A type for results generated by interacting with serial ports.
pub type Result<T> = mio_serial::Result<T>;

use futures::{Async, Poll};
use tokio_core::reactor::{PollEvented, Handle};
use tokio_io::{AsyncRead, AsyncWrite};

use std::io::{self, Read, Write};
use std::path::Path;
use std::time::Duration;

/// Serial port I/O struct.
pub struct Serial {
    io: PollEvented<mio_serial::Serial>,
}

impl Serial {
    /// Open serial port from a provided path.
    pub fn from_path<P>(path: P,
                        settings: &mio_serial::SerialPortSettings,
                        handle: &Handle)
                        -> io::Result<Serial>
        where P: AsRef<Path>
    {

        let port = mio_serial::Serial::from_path(path.as_ref(), settings)?;
        let io = PollEvented::new(port, handle)?;

        Ok(Serial { io: io })
    }

    /// Test whether this serial port is ready to be read or not.
    ///
    /// If the serial port is *not* readable then the current task is scheduled to
    /// get a notification when the socket does become readable. That is, this
    /// is only suitable for calling in a `Future::poll` method and will
    /// automatically handle ensuring a retry once the socket is readable again.
    pub fn poll_read(&self) -> Async<()> {
        self.io.poll_read()
    }

    /// Test whether this socket is ready to be written to or not.
    ///
    /// If the socket is *not* writable then the current task is scheduled to
    /// get a notification when the socket does become writable. That is, this
    /// is only suitable for calling in a `Future::poll` method and will
    /// automatically handle ensuring a retry once the socket is writable again.
    pub fn poll_write(&self) -> Async<()> {
        self.io.poll_write()
    }

    /// Create a pair of pseudo serial terminals
    ///
    /// ## Returns
    /// Two connected, unnamed `Serial` objects.
    ///
    /// ## Errors
    /// Attempting any IO or parameter settings on the slave tty after the master
    /// tty is closed will return errors.
    ///
    #[cfg(unix)]
    pub fn pair(handle: &Handle) -> ::Result<(Self, Self)> {
        let (master, slave) = mio_serial::Serial::pair()?;

        let master = Serial { io: PollEvented::new(master, handle)? };
        let slave = Serial { io: PollEvented::new(slave, handle)? };
        Ok((master, slave))
    }

    /// Sets the exclusivity of the port
    ///
    /// If a port is exclusive, then trying to open the same device path again
    /// will fail.
    ///
    /// See the man pages for the tiocexcl and tiocnxcl ioctl's for more details.
    ///
    /// ## Errors
    ///
    /// * `Io` for any error while setting exclusivity for the port.
    #[cfg(unix)]
    pub fn set_exclusive(&mut self, exclusive: bool) -> ::Result<()> {
        self.io.get_mut().set_exclusive(exclusive)
    }

    /// Returns the exclusivity of the port
    ///
    /// If a port is exclusive, then trying to open the same device path again
    /// will fail.
    #[cfg(unix)]
    pub fn exclusive(&self) -> bool {
        self.io.get_ref().exclusive()
    }
}

impl ::SerialPort for Serial {
    /// Returns a struct with the current port settings
    fn settings(&self) -> ::SerialPortSettings {
        self.io.get_ref().settings()
    }

    /// Return the name associated with the serial port, if known.
    fn port_name(&self) -> Option<String> {
        self.io.get_ref().port_name()
    }

    /// Returns the current baud rate.
    ///
    /// This function returns `None` if the baud rate could not be determined. This may occur if
    /// the hardware is in an uninitialized state. Setting a baud rate with `set_baud_rate()`
    /// should initialize the baud rate to a supported value.
    fn baud_rate(&self) -> Option<::BaudRate> {
        self.io.get_ref().baud_rate()
    }

    /// Returns the character size.
    ///
    /// This function returns `None` if the character size could not be determined. This may occur
    /// if the hardware is in an uninitialized state or is using a non-standard character size.
    /// Setting a baud rate with `set_char_size()` should initialize the character size to a
    /// supported value.
    fn data_bits(&self) -> Option<::DataBits> {
        self.io.get_ref().data_bits()
    }

    /// Returns the flow control mode.
    ///
    /// This function returns `None` if the flow control mode could not be determined. This may
    /// occur if the hardware is in an uninitialized state or is using an unsupported flow control
    /// mode. Setting a flow control mode with `set_flow_control()` should initialize the flow
    /// control mode to a supported value.
    fn flow_control(&self) -> Option<::FlowControl> {
        self.io.get_ref().flow_control()
    }

    /// Returns the parity-checking mode.
    ///
    /// This function returns `None` if the parity mode could not be determined. This may occur if
    /// the hardware is in an uninitialized state or is using a non-standard parity mode. Setting
    /// a parity mode with `set_parity()` should initialize the parity mode to a supported value.
    fn parity(&self) -> Option<::Parity> {
        self.io.get_ref().parity()
    }

    /// Returns the number of stop bits.
    ///
    /// This function returns `None` if the number of stop bits could not be determined. This may
    /// occur if the hardware is in an uninitialized state or is using an unsupported stop bit
    /// configuration. Setting the number of stop bits with `set_stop-bits()` should initialize the
    /// stop bits to a supported value.
    fn stop_bits(&self) -> Option<::StopBits> {
        self.io.get_ref().stop_bits()
    }

    /// Returns the current timeout.
    fn timeout(&self) -> Duration {
        Duration::from_secs(0)
    }

    // Port settings setters

    /// Applies all settings for a struct. This isn't guaranteed to involve only
    /// a single call into the driver, though that may be done on some
    /// platforms.
    fn set_all(&mut self, settings: &::SerialPortSettings) -> ::Result<()> {
        self.io.get_mut().set_all(settings)
    }

    /// Sets the baud rate.
    ///
    /// ## Errors
    ///
    /// If the implementation does not support the requested baud rate, this function may return an
    /// `InvalidInput` error. Even if the baud rate is accepted by `set_baud_rate()`, it may not be
    /// supported by the underlying hardware.
    fn set_baud_rate(&mut self, baud_rate: ::BaudRate) -> ::Result<()> {
        self.io.get_mut().set_baud_rate(baud_rate)
    }

    /// Sets the character size.
    fn set_data_bits(&mut self, data_bits: ::DataBits) -> ::Result<()> {
        self.io.get_mut().set_data_bits(data_bits)
    }

    /// Sets the flow control mode.
    fn set_flow_control(&mut self, flow_control: ::FlowControl) -> ::Result<()> {
        self.io.get_mut().set_flow_control(flow_control)
    }

    /// Sets the parity-checking mode.
    fn set_parity(&mut self, parity: ::Parity) -> ::Result<()> {
        self.io.get_mut().set_parity(parity)
    }

    /// Sets the number of stop bits.
    fn set_stop_bits(&mut self, stop_bits: ::StopBits) -> ::Result<()> {
        self.io.get_mut().set_stop_bits(stop_bits)
    }

    /// Sets the timeout for future I/O operations.  This parameter is ignored but
    /// required for trait completeness.
    fn set_timeout(&mut self, _: Duration) -> ::Result<()> {
        Ok(())
    }

    // Functions for setting non-data control signal pins

    /// Sets the state of the RTS (Request To Send) control signal.
    ///
    /// Setting a value of `true` asserts the RTS control signal. `false` clears the signal.
    ///
    /// ## Errors
    ///
    /// This function returns an error if the RTS control signal could not be set to the desired
    /// state on the underlying hardware:
    ///
    /// * `NoDevice` if the device was disconnected.
    /// * `Io` for any other type of I/O error.
    fn write_request_to_send(&mut self, level: bool) -> ::Result<()> {
        self.io.get_mut().write_request_to_send(level)
    }

    /// Writes to the Data Terminal Ready pin
    ///
    /// Setting a value of `true` asserts the DTR control signal. `false` clears the signal.
    ///
    /// ## Errors
    ///
    /// This function returns an error if the DTR control signal could not be set to the desired
    /// state on the underlying hardware:
    ///
    /// * `NoDevice` if the device was disconnected.
    /// * `Io` for any other type of I/O error.
    fn write_data_terminal_ready(&mut self, level: bool) -> ::Result<()> {
        self.io.get_mut().write_data_terminal_ready(level)
    }

    // Functions for reading additional pins

    /// Reads the state of the CTS (Clear To Send) control signal.
    ///
    /// This function returns a boolean that indicates whether the CTS control signal is asserted.
    ///
    /// ## Errors
    ///
    /// This function returns an error if the state of the CTS control signal could not be read
    /// from the underlying hardware:
    ///
    /// * `NoDevice` if the device was disconnected.
    /// * `Io` for any other type of I/O error.
    fn read_clear_to_send(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_clear_to_send()
    }

    /// Reads the state of the Data Set Ready control signal.
    ///
    /// This function returns a boolean that indicates whether the DSR control signal is asserted.
    ///
    /// ## Errors
    ///
    /// This function returns an error if the state of the DSR control signal could not be read
    /// from the underlying hardware:
    ///
    /// * `NoDevice` if the device was disconnected.
    /// * `Io` for any other type of I/O error.
    fn read_data_set_ready(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_data_set_ready()
    }

    /// Reads the state of the Ring Indicator control signal.
    ///
    /// This function returns a boolean that indicates whether the RI control signal is asserted.
    ///
    /// ## Errors
    ///
    /// This function returns an error if the state of the RI control signal could not be read from
    /// the underlying hardware:
    ///
    /// * `NoDevice` if the device was disconnected.
    /// * `Io` for any other type of I/O error.
    fn read_ring_indicator(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_ring_indicator()
    }

    /// Reads the state of the Carrier Detect control signal.
    ///
    /// This function returns a boolean that indicates whether the CD control signal is asserted.
    ///
    /// ## Errors
    ///
    /// This function returns an error if the state of the CD control signal could not be read from
    /// the underlying hardware:
    ///
    /// * `NoDevice` if the device was disconnected.
    /// * `Io` for any other type of I/O error.
    fn read_carrier_detect(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_carrier_detect()
    }
}

impl Read for Serial {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        //self.io.read(buf)
        self.io.get_mut().read(buf)
    }
}

impl Write for Serial {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        // self.io.write(buf)
        self.io.get_mut().write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        // self.io.flush()
        self.io.get_mut().flush()
    }
}

// impl<'a> Read for &'a Serial {
//     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
//         // (&self.io).read(buf)
//         self.io.get_mut().read(buf)
//     }
// }
//
// impl<'a> Write for &'a Serial {
//     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
//         // (&self.io).write(buf)
//         self.io.get_mut().write(buf)
//     }
//
//     fn flush(&mut self) -> io::Result<()> {
//         // (&self.io).flush()
//         self.io.get_mut().flush()
//     }
// }

#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd};
#[cfg(unix)]
impl AsRawFd for Serial {
    fn as_raw_fd(&self) -> RawFd {
        self.io.get_ref().as_raw_fd()
    }
}

impl AsyncRead for Serial {}

impl AsyncWrite for Serial {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        Ok(Async::Ready(()))
    }
}

// #[cfg(unix)]
// pub use unix::Serial;

// #[cfg(unix)]
// mod unix;

<|endoftext|>


<commit_before>use std::os::raw::c_void;

type Function = fn(data: *const c_void, n: i64, x: *const f64) -> f64;

#[repr(C)]
struct Closure {
    data: *const c_void,
    function: Function,
}

impl Closure {
    pub fn new<F>(function: &F) -> Closure where F: Fn(&[f64]) -> f64 {
        fn wrap<F>(closure: *const c_void, n: i64, x: *const f64) -> f64
                where F: Fn(&[f64]) -> f64 {
            use std::slice::from_raw_parts;
            let closure = closure as *const F;
            unsafe { (*closure)(from_raw_parts(x, n as usize)) }
        }
        Closure {data: &*function as *const _ as *const c_void, function: wrap::<F>}
    }
}

type FunctionMut = fn(data: *mut c_void, n: i64, x: *const f64) -> f64;

#[repr(C)]
struct ClosureMut {
    data: *mut c_void,
    function: FunctionMut,
}

impl ClosureMut {
    pub fn new<F>(function: &mut F) -> ClosureMut where F: FnMut(&[f64]) -> f64 {
        fn wrap<F>(closure: *mut c_void, n: i64, x: *const f64) -> f64
                where F: FnMut(&[f64]) -> f64 {
            use std::slice::from_raw_parts;
            let closure = closure as *mut F;
            unsafe { (*closure)(from_raw_parts(x, n as usize)) }
        }
        ClosureMut {data: &mut *function as *mut _ as *mut c_void, function: wrap::<F>}
    }
}

extern "C" {
    fn bobyqa_closure(function: *mut ClosureMut, n: i64, npt: i64, x: *mut f64,
        xl: *const f64, xu: *const f64, rhobeg: f64, rhoend: f64, maxfun: i64, w: *mut f64) -> f64;

    fn bobyqa_closure_const(function: *const Closure, n: i64, npt: i64, x: *mut f64,
        xl: *const f64, xu: *const f64, rhobeg: f64, rhoend: f64, maxfun: i64, w: *mut f64) -> f64;
}

#[derive(Clone)]
pub struct Bobyqa <'a> {
    variables_count: usize,
    number_of_interpolation_conditions: usize,
    initial_trust_region_radius: f64,
    final_trust_region_radius: f64,
    lower_bound: Option<&'a [f64]>,
    upper_bound: Option<&'a [f64]>,
    max_function_calls_count: usize,
}

impl <'a> Bobyqa <'a> {
    pub fn new() -> Bobyqa <'a> {
        const VARIABLES_COUNT: usize = 2;
        const NUMBER_OF_INTERPOLATION_CONDITIONS: usize = VARIABLES_COUNT + 2;
        static LOWER_BOUND: [f64; VARIABLES_COUNT] = [0.0, 0.0];
        static UPPER_BOUND: [f64; VARIABLES_COUNT] = [1.0, 1.0];
        Bobyqa {
            variables_count: VARIABLES_COUNT,
            number_of_interpolation_conditions: NUMBER_OF_INTERPOLATION_CONDITIONS,
            lower_bound: Some(&LOWER_BOUND),
            upper_bound: Some(&UPPER_BOUND),
            initial_trust_region_radius: 1e-6,
            final_trust_region_radius: 1e6,
            max_function_calls_count: 1000,
        }
    }

    pub fn variables_count(&mut self, value: usize) -> &mut Self {
        assert!(value >= 2);
        self.variables_count = value;
        if self.lower_bound.is_some() && self.lower_bound.unwrap().len() < self.variables_count {
            self.lower_bound = None;
        }
        if self.upper_bound.is_some() && self.upper_bound.unwrap().len() < self.variables_count {
            self.upper_bound = None;
        }
        self
    }

    pub fn number_of_interpolation_conditions(&mut self, value: usize) -> &mut Self {
        assert!(value >= 4);
        self.number_of_interpolation_conditions = value;
        self
    }

    pub fn lower_bound(&mut self, value: &'a [f64]) -> &mut Self {
        assert!(value.len() >= self.variables_count);
        self.lower_bound = Some(value);
        self
    }

    pub fn upper_bound(&mut self, value: &'a [f64]) -> &mut Self {
        assert!(value.len() >= self.variables_count);
        self.upper_bound = Some(value);
        self
    }

    pub fn initial_trust_region_radius(&mut self, value: f64) -> &mut Self {
        assert!(value <= self.final_trust_region_radius);
        self.initial_trust_region_radius = value;
        self
    }

    pub fn final_trust_region_radius(&mut self, value: f64) -> &mut Self {
        assert!(value >= self.initial_trust_region_radius);
        self.final_trust_region_radius = value;
        self
    }

    pub fn max_function_calls_count(&mut self, value: usize) -> &mut Self {
        self.max_function_calls_count = value;
        self
    }

    /// ```
    /// use bobyqa::Bobyqa;
    /// let mut x = [0.5, 0.5];
    /// let f = |x: &[f64]| -> f64 { x[0] + x[1] };
    /// assert_eq!(Bobyqa::new().perform(&mut x, &f), 0.0);
    /// assert_eq!(x, [0.0, 0.0]);
    /// ```
    pub fn perform<F>(&self, values: &mut [f64], function: &F) -> f64
            where F: Fn(&[f64]) -> f64 {
        self.check(values);
        let closure = Closure::new(function);
        let mut working_space = self.working_space();
        unsafe {
            bobyqa_closure_const(
                &closure as *const _,
                self.variables_count as i64,
                self.number_of_interpolation_conditions as i64,
                values.as_mut_ptr(),
                self.lower_bound.unwrap().as_ptr(),
                self.upper_bound.unwrap().as_ptr(),
                self.initial_trust_region_radius,
                self.final_trust_region_radius,
                self.max_function_calls_count as i64,
                working_space.as_mut_ptr(),
            )
        }
    }

    /// ```
    /// use bobyqa::Bobyqa;
    /// let mut c = Box::new(0_u64);
    /// let mut x = [0.5, 0.5];
    /// {
    ///     let mut f = |x: &[f64]| -> f64 { *c += 1; x[0] + x[1] };
    ///     assert_eq!(Bobyqa::new().perform_mut(&mut x, &mut f), 0.0);
    /// }
    /// assert_eq!(x, [0.0, 0.0]);
    /// assert_eq!(*c, 28);
    /// ```
    pub fn perform_mut<F>(&self, values: &mut [f64], function: &mut F) -> f64
            where F: FnMut(&[f64]) -> f64 {
        self.check(values);
        let mut closure = ClosureMut::new(function);
        let mut working_space = self.working_space();
        unsafe {
            bobyqa_closure(
                &mut closure as *mut _,
                self.variables_count as i64,
                self.number_of_interpolation_conditions as i64,
                values.as_mut_ptr(),
                self.lower_bound.unwrap().as_ptr(),
                self.upper_bound.unwrap().as_ptr(),
                self.initial_trust_region_radius,
                self.final_trust_region_radius,
                self.max_function_calls_count as i64,
                working_space.as_mut_ptr(),
            )
        }
    }

    fn check(&self, values: &[f64]) {
        assert!(values.len() >= self.variables_count);
        assert!(self.number_of_interpolation_conditions >= self.variables_count + 2);
        assert!(self.number_of_interpolation_conditions <=
            (self.variables_count + 1)*(self.variables_count + 2)/2);
        assert!(self.lower_bound.is_some());
        assert!(self.upper_bound.is_some());
        assert!(self.lower_bound.unwrap().len() >= self.variables_count);
        assert!(self.upper_bound.unwrap().len() >= self.variables_count);
    }

    fn working_space(&self) -> Vec<f64> {
        use std::iter::repeat;
        let working_space_size = Bobyqa::working_space_size(
            self.number_of_interpolation_conditions,
            self.variables_count);
        repeat(0.0).take(working_space_size).collect::<Vec<f64>>()
    }

    fn working_space_size(number_of_interpolation_conditions: usize, variables_count: usize) -> usize {
        3*variables_count*(variables_count + 3)/2
        + (number_of_interpolation_conditions + 13)
            *(number_of_interpolation_conditions + variables_count)
    }
}

#[test]
fn test_pefrorm_mut_with_all_settings_should_succeed() {
    let mut calls_count = Box::new(0);
    let mut values = [1.0, -1.0, 0.0];
    let lower_bound = [-3.0, -2.0, -1.0];
    let upper_bound = [1.0, 2.0, 3.0];
    let result = {
        let mut function = |x: &[f64]| -> f64 {
            assert_eq!(x.len(), 3);
            *calls_count += 1;
            x[0] + x[1] + x[2]
        };
        Bobyqa::new()
            .variables_count(values.len())
            .number_of_interpolation_conditions((values.len() + 1)*(values.len() + 2)/2)
            .initial_trust_region_radius(1e-3)
            .final_trust_region_radius(1e3)
            .lower_bound(&lower_bound)
            .upper_bound(&upper_bound)
            .max_function_calls_count(25)
            .perform_mut(&mut values, &mut function)
    };
    assert_eq!(values, lower_bound);
    assert_eq!(result, -6.0);
    assert_eq!(*calls_count, 25);
}
<commit_msg>Fix warnings<commit_after>use std::os::raw::c_void;

type Function = extern fn(data: *const c_void, n: i64, x: *const f64) -> f64;

#[repr(C)]
struct Closure {
    data: *const c_void,
    function: Function,
}

impl Closure {
    pub fn new<F>(function: &F) -> Closure where F: Fn(&[f64]) -> f64 {
        extern fn wrap<F>(closure: *const c_void, n: i64, x: *const f64) -> f64
                where F: Fn(&[f64]) -> f64 {
            use std::slice::from_raw_parts;
            let closure = closure as *const F;
            unsafe { (*closure)(from_raw_parts(x, n as usize)) }
        }
        Closure {data: &*function as *const _ as *const c_void, function: wrap::<F>}
    }
}

type FunctionMut = extern fn(data: *mut c_void, n: i64, x: *const f64) -> f64;

#[repr(C)]
struct ClosureMut {
    data: *mut c_void,
    function: FunctionMut,
}

impl ClosureMut {
    pub fn new<F>(function: &mut F) -> ClosureMut where F: FnMut(&[f64]) -> f64 {
        extern fn wrap<F>(closure: *mut c_void, n: i64, x: *const f64) -> f64
                where F: FnMut(&[f64]) -> f64 {
            use std::slice::from_raw_parts;
            let closure = closure as *mut F;
            unsafe { (*closure)(from_raw_parts(x, n as usize)) }
        }
        ClosureMut {data: &mut *function as *mut _ as *mut c_void, function: wrap::<F>}
    }
}

extern "C" {
    fn bobyqa_closure(function: *mut ClosureMut, n: i64, npt: i64, x: *mut f64,
        xl: *const f64, xu: *const f64, rhobeg: f64, rhoend: f64, maxfun: i64, w: *mut f64) -> f64;

    fn bobyqa_closure_const(function: *const Closure, n: i64, npt: i64, x: *mut f64,
        xl: *const f64, xu: *const f64, rhobeg: f64, rhoend: f64, maxfun: i64, w: *mut f64) -> f64;
}

#[derive(Clone)]
pub struct Bobyqa <'a> {
    variables_count: usize,
    number_of_interpolation_conditions: usize,
    initial_trust_region_radius: f64,
    final_trust_region_radius: f64,
    lower_bound: Option<&'a [f64]>,
    upper_bound: Option<&'a [f64]>,
    max_function_calls_count: usize,
}

impl <'a> Bobyqa <'a> {
    pub fn new() -> Bobyqa <'a> {
        const VARIABLES_COUNT: usize = 2;
        const NUMBER_OF_INTERPOLATION_CONDITIONS: usize = VARIABLES_COUNT + 2;
        static LOWER_BOUND: [f64; VARIABLES_COUNT] = [0.0, 0.0];
        static UPPER_BOUND: [f64; VARIABLES_COUNT] = [1.0, 1.0];
        Bobyqa {
            variables_count: VARIABLES_COUNT,
            number_of_interpolation_conditions: NUMBER_OF_INTERPOLATION_CONDITIONS,
            lower_bound: Some(&LOWER_BOUND),
            upper_bound: Some(&UPPER_BOUND),
            initial_trust_region_radius: 1e-6,
            final_trust_region_radius: 1e6,
            max_function_calls_count: 1000,
        }
    }

    pub fn variables_count(&mut self, value: usize) -> &mut Self {
        assert!(value >= 2);
        self.variables_count = value;
        if self.lower_bound.is_some() && self.lower_bound.unwrap().len() < self.variables_count {
            self.lower_bound = None;
        }
        if self.upper_bound.is_some() && self.upper_bound.unwrap().len() < self.variables_count {
            self.upper_bound = None;
        }
        self
    }

    pub fn number_of_interpolation_conditions(&mut self, value: usize) -> &mut Self {
        assert!(value >= 4);
        self.number_of_interpolation_conditions = value;
        self
    }

    pub fn lower_bound(&mut self, value: &'a [f64]) -> &mut Self {
        assert!(value.len() >= self.variables_count);
        self.lower_bound = Some(value);
        self
    }

    pub fn upper_bound(&mut self, value: &'a [f64]) -> &mut Self {
        assert!(value.len() >= self.variables_count);
        self.upper_bound = Some(value);
        self
    }

    pub fn initial_trust_region_radius(&mut self, value: f64) -> &mut Self {
        assert!(value <= self.final_trust_region_radius);
        self.initial_trust_region_radius = value;
        self
    }

    pub fn final_trust_region_radius(&mut self, value: f64) -> &mut Self {
        assert!(value >= self.initial_trust_region_radius);
        self.final_trust_region_radius = value;
        self
    }

    pub fn max_function_calls_count(&mut self, value: usize) -> &mut Self {
        self.max_function_calls_count = value;
        self
    }

    /// ```
    /// use bobyqa::Bobyqa;
    /// let mut x = [0.5, 0.5];
    /// let f = |x: &[f64]| -> f64 { x[0] + x[1] };
    /// assert_eq!(Bobyqa::new().perform(&mut x, &f), 0.0);
    /// assert_eq!(x, [0.0, 0.0]);
    /// ```
    pub fn perform<F>(&self, values: &mut [f64], function: &F) -> f64
            where F: Fn(&[f64]) -> f64 {
        self.check(values);
        let closure = Closure::new(function);
        let mut working_space = self.working_space();
        unsafe {
            bobyqa_closure_const(
                &closure as *const _,
                self.variables_count as i64,
                self.number_of_interpolation_conditions as i64,
                values.as_mut_ptr(),
                self.lower_bound.unwrap().as_ptr(),
                self.upper_bound.unwrap().as_ptr(),
                self.initial_trust_region_radius,
                self.final_trust_region_radius,
                self.max_function_calls_count as i64,
                working_space.as_mut_ptr(),
            )
        }
    }

    /// ```
    /// use bobyqa::Bobyqa;
    /// let mut c = Box::new(0_u64);
    /// let mut x = [0.5, 0.5];
    /// {
    ///     let mut f = |x: &[f64]| -> f64 { *c += 1; x[0] + x[1] };
    ///     assert_eq!(Bobyqa::new().perform_mut(&mut x, &mut f), 0.0);
    /// }
    /// assert_eq!(x, [0.0, 0.0]);
    /// assert_eq!(*c, 28);
    /// ```
    pub fn perform_mut<F>(&self, values: &mut [f64], function: &mut F) -> f64
            where F: FnMut(&[f64]) -> f64 {
        self.check(values);
        let mut closure = ClosureMut::new(function);
        let mut working_space = self.working_space();
        unsafe {
            bobyqa_closure(
                &mut closure as *mut _,
                self.variables_count as i64,
                self.number_of_interpolation_conditions as i64,
                values.as_mut_ptr(),
                self.lower_bound.unwrap().as_ptr(),
                self.upper_bound.unwrap().as_ptr(),
                self.initial_trust_region_radius,
                self.final_trust_region_radius,
                self.max_function_calls_count as i64,
                working_space.as_mut_ptr(),
            )
        }
    }

    fn check(&self, values: &[f64]) {
        assert!(values.len() >= self.variables_count);
        assert!(self.number_of_interpolation_conditions >= self.variables_count + 2);
        assert!(self.number_of_interpolation_conditions <=
            (self.variables_count + 1)*(self.variables_count + 2)/2);
        assert!(self.lower_bound.is_some());
        assert!(self.upper_bound.is_some());
        assert!(self.lower_bound.unwrap().len() >= self.variables_count);
        assert!(self.upper_bound.unwrap().len() >= self.variables_count);
    }

    fn working_space(&self) -> Vec<f64> {
        use std::iter::repeat;
        let working_space_size = Bobyqa::working_space_size(
            self.number_of_interpolation_conditions,
            self.variables_count);
        repeat(0.0).take(working_space_size).collect::<Vec<f64>>()
    }

    fn working_space_size(number_of_interpolation_conditions: usize, variables_count: usize) -> usize {
        3*variables_count*(variables_count + 3)/2
        + (number_of_interpolation_conditions + 13)
            *(number_of_interpolation_conditions + variables_count)
    }
}

#[test]
fn test_pefrorm_mut_with_all_settings_should_succeed() {
    let mut calls_count = Box::new(0);
    let mut values = [1.0, -1.0, 0.0];
    let lower_bound = [-3.0, -2.0, -1.0];
    let upper_bound = [1.0, 2.0, 3.0];
    let result = {
        let mut function = |x: &[f64]| -> f64 {
            assert_eq!(x.len(), 3);
            *calls_count += 1;
            x[0] + x[1] + x[2]
        };
        Bobyqa::new()
            .variables_count(values.len())
            .number_of_interpolation_conditions((values.len() + 1)*(values.len() + 2)/2)
            .initial_trust_region_radius(1e-3)
            .final_trust_region_radius(1e3)
            .lower_bound(&lower_bound)
            .upper_bound(&upper_bound)
            .max_function_calls_count(25)
            .perform_mut(&mut values, &mut function)
    };
    assert_eq!(values, lower_bound);
    assert_eq!(result, -6.0);
    assert_eq!(*calls_count, 25);
}
<|endoftext|>


<commit_before>#![cfg_attr(test, deny(warnings))]
#![cfg_attr(test, allow(unstable))]

extern crate "rustc-serialize" as rustc_serialize;

extern crate conduit;
extern crate "conduit-middleware" as middleware;
extern crate "conduit-utils" as utils;

use std::error::Error;
use rustc_serialize::Decodable;
use rustc_serialize::json::{self, Json};

use conduit::Request;
use utils::RequestDelegator;
use middleware::Middleware;

pub struct BodyReader<T>;

impl<T: Decodable + 'static> Middleware for BodyReader<T> {
    fn before(&self, req: &mut Request) -> Result<(), Box<Error+Send>> {
        let json: T = try!(decode::<T>(req.body()));

        req.mut_extensions().insert(json);
        Ok(())
    }
}

fn decode<T: Decodable>(reader: &mut Reader) -> Result<T, Box<Error+Send>> {
    let j = try!(Json::from_reader(reader).map_err(|e| Box::new(e) as Box<Error+Send>));
    let mut decoder = json::Decoder::new(j);
    Decodable::decode(&mut decoder).map_err(|e| Box::new(e) as Box<Error+Send>)
}

pub fn json_params<'a, T: Decodable + 'static>(req: &'a Request) -> Option<&'a T> {
    req.extensions().find::<T>()
}

#[cfg(test)]
mod tests {
    extern crate "conduit-test" as conduit_test;

    use {json_params, BodyReader};

    use std::collections::HashMap;
    use std::error::Error;
    use std::old_io::MemReader;
    use rustc_serialize::json;

    use conduit::{Request, Response, Handler, Method};
    use middleware::MiddlewareBuilder;

    #[derive(PartialEq, RustcDecodable, RustcEncodable, Show)]
    struct Person {
        name: String,
        location: String
    }

    fn handler(req: &mut Request) -> Result<Response, Box<Error+Send>> {
        let person = json_params::<Person>(req);
        let out = person.map(|p| json::encode(p).unwrap()).expect("No JSON");

        Ok(Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: Box::new(MemReader::new(out.into_bytes()))
        })
    }

    #[test]
    fn test_body_params() {
        let mut req = conduit_test::MockRequest::new(Method::Get, "/");
        req.with_body(br#"{ "name": "Alex Crichton", "location": "San Francisco" }"#);

        let mut middleware = MiddlewareBuilder::new(handler);
        middleware.add(BodyReader::<Person>);

        let mut res = middleware.call(&mut req).ok().expect("No response");
        let person = super::decode::<Person>(&mut *res.body).ok().expect("No JSON response");
        assert_eq!(person, Person {
            name: "Alex Crichton".to_string(),
            location: "San Francisco".to_string()
        });
    }
}
<commit_msg>Add some feature gates<commit_after>#![cfg_attr(test, feature(collections, io, core))]
#![cfg_attr(test, deny(warnings))]

extern crate "rustc-serialize" as rustc_serialize;

extern crate conduit;
extern crate "conduit-middleware" as middleware;
extern crate "conduit-utils" as utils;

use std::error::Error;
use rustc_serialize::Decodable;
use rustc_serialize::json::{self, Json};

use conduit::Request;
use utils::RequestDelegator;
use middleware::Middleware;

pub struct BodyReader<T>;

impl<T: Decodable + 'static> Middleware for BodyReader<T> {
    fn before(&self, req: &mut Request) -> Result<(), Box<Error+Send>> {
        let json: T = try!(decode::<T>(req.body()));

        req.mut_extensions().insert(json);
        Ok(())
    }
}

fn decode<T: Decodable>(reader: &mut Reader) -> Result<T, Box<Error+Send>> {
    let j = try!(Json::from_reader(reader).map_err(|e| Box::new(e) as Box<Error+Send>));
    let mut decoder = json::Decoder::new(j);
    Decodable::decode(&mut decoder).map_err(|e| Box::new(e) as Box<Error+Send>)
}

pub fn json_params<'a, T: Decodable + 'static>(req: &'a Request) -> Option<&'a T> {
    req.extensions().find::<T>()
}

#[cfg(test)]
mod tests {
    extern crate "conduit-test" as conduit_test;

    use {json_params, BodyReader};

    use std::collections::HashMap;
    use std::error::Error;
    use std::old_io::MemReader;
    use rustc_serialize::json;

    use conduit::{Request, Response, Handler, Method};
    use middleware::MiddlewareBuilder;

    #[derive(PartialEq, RustcDecodable, RustcEncodable, Show)]
    struct Person {
        name: String,
        location: String
    }

    fn handler(req: &mut Request) -> Result<Response, Box<Error+Send>> {
        let person = json_params::<Person>(req);
        let out = person.map(|p| json::encode(p).unwrap()).expect("No JSON");

        Ok(Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: Box::new(MemReader::new(out.into_bytes()))
        })
    }

    #[test]
    fn test_body_params() {
        let mut req = conduit_test::MockRequest::new(Method::Get, "/");
        req.with_body(br#"{ "name": "Alex Crichton", "location": "San Francisco" }"#);

        let mut middleware = MiddlewareBuilder::new(handler);
        middleware.add(BodyReader::<Person>);

        let mut res = middleware.call(&mut req).ok().expect("No response");
        let person = super::decode::<Person>(&mut *res.body).ok().expect("No JSON response");
        assert_eq!(person, Person {
            name: "Alex Crichton".to_string(),
            location: "San Francisco".to_string()
        });
    }
}
<|endoftext|>