<commit_before>//! A [TOML]-parsing library
//!
//! This library implements a [TOML] v0.5.0 compatible parser,
//! primarily supporting the [`serde`] library for encoding/decoding
//! various types in Rust.
//!
//! TOML itself is a simple, ergonomic, and readable configuration format:
//!
//! ```toml
//! [package]
//! name = "toml"
//! version = "0.4.2"
//! authors = ["Alex Crichton <alex@alexcrichton.com>"]
//!
//! [dependencies]
//! serde = "1.0"
//! ```
//!
//! The TOML format tends to be relatively common throughout the Rust community
//! for configuration, notably being used by [Cargo], Rust's package manager.
//!
//! ## TOML values
//!
//! A value in TOML is represented with the `Value` enum in this crate:
//!
//! ```rust,ignore
//! pub enum Value {
//!     String(String),
//!     Integer(i64),
//!     Float(f64),
//!     Boolean(bool),
//!     Datetime(Datetime),
//!     Array(Array),
//!     Table(Table),
//! }
//! ```
//!
//! TOML is similar to JSON with the notable addition of a `Datetime`
//! type. In general, TOML and JSON are interchangeable in terms of
//! formats.
//!
//! ## Parsing TOML
//!
//! The easiest way to parse a TOML document is via the `Value` type:
//!
//! ```rust
//! use toml::Value;
//!
//! let value = "foo = 'bar'".parse::<Value>().unwrap();
//!
//! assert_eq!(value["foo"].as_str(), Some("bar"));
//! ```
//!
//! The `Value` type implements a number of convenience methods and
//! traits; the example above uses `FromStr` to parse a `str` into a
//! `Value`.
//!
//! ## Deserialization and Serialization
//!
//! This crate supports [`serde`] 1.0 with a number of
//! implementations of the `Deserialize`, `Serialize`, `Deserializer`, and
//! `Serializer` traits. Namely, you'll find:
//!
//! * `Deserialize for Value`
//! * `Serialize for Value`
//! * `Deserialize for Datetime`
//! * `Serialize for Datetime`
//! * `Deserializer for de::Deserializer`
//! * `Serializer for ser::Serializer`
//! * `Deserializer for Value`
//!
//! This means that you can use Serde to deserialize/serialize the
//! `Value` type as well as the `Datetime` type in this crate. You can also
//! use the `Deserializer`, `Serializer`, or `Value` type itself to act as
//! a deserializer/serializer for arbitrary types.
//!
//! An example of deserializing with TOML is:
//!
//! ```rust
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate toml;
//!
//! #[derive(Deserialize)]
//! struct Config {
//!     ip: String,
//!     port: Option<u16>,
//!     keys: Keys,
//! }
//!
//! #[derive(Deserialize)]
//! struct Keys {
//!     github: String,
//!     travis: Option<String>,
//! }
//!
//! fn main() {
//!     let config: Config = toml::from_str(r#"
//!         ip = '127.0.0.1'
//!
//!         [keys]
//!         github = 'xxxxxxxxxxxxxxxxx'
//!         travis = 'yyyyyyyyyyyyyyyyy'
//!     "#).unwrap();
//!
//!     assert_eq!(config.ip, "127.0.0.1");
//!     assert_eq!(config.port, None);
//!     assert_eq!(config.keys.github, "xxxxxxxxxxxxxxxxx");
//!     assert_eq!(config.keys.travis.as_ref().unwrap(), "yyyyyyyyyyyyyyyyy");
//! }
//! ```
//!
//! You can serialize types in a similar fashion:
//!
//! ```rust
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate toml;
//!
//! #[derive(Serialize)]
//! struct Config {
//!     ip: String,
//!     port: Option<u16>,
//!     keys: Keys,
//! }
//!
//! #[derive(Serialize)]
//! struct Keys {
//!     github: String,
//!     travis: Option<String>,
//! }
//!
//! fn main() {
//!     let config = Config {
//!         ip: "127.0.0.1".to_string(),
//!         port: None,
//!         keys: Keys {
//!             github: "xxxxxxxxxxxxxxxxx".to_string(),
//!             travis: Some("yyyyyyyyyyyyyyyyy".to_string()),
//!         },
//!     };
//!
//!     let toml = toml::to_string(&config).unwrap();
//! }
//! ```
//!
//! [TOML]: https://github.com/toml-lang/toml
//! [Cargo]: https://crates.io/
//! [`serde`]: https://serde.rs/

#![doc(html_root_url = "https://docs.rs/toml/0.4")]
#![deny(missing_docs)]

#[macro_use]
extern crate serde;
#[cfg(feature = "preserve_order")]
extern crate linked_hash_map;

pub mod map;
pub mod value;
#[doc(no_inline)]
pub use value::Value;
mod datetime;

pub mod ser;
#[doc(no_inline)]
pub use ser::{to_string, to_string_pretty, to_vec, Serializer};
pub mod de;
#[doc(no_inline)]
pub use de::{from_slice, from_str, Deserializer};
mod tokens;

#[doc(hidden)]
pub mod macros;

mod spanned;
#[doc(no_inline)]
pub use spanned::Spanned;
<commit_msg>Bump html_root_url version.<commit_after>//! A [TOML]-parsing library
//!
//! This library implements a [TOML] v0.5.0 compatible parser,
//! primarily supporting the [`serde`] library for encoding/decoding
//! various types in Rust.
//!
//! TOML itself is a simple, ergonomic, and readable configuration format:
//!
//! ```toml
//! [package]
//! name = "toml"
//! version = "0.4.2"
//! authors = ["Alex Crichton <alex@alexcrichton.com>"]
//!
//! [dependencies]
//! serde = "1.0"
//! ```
//!
//! The TOML format tends to be relatively common throughout the Rust community
//! for configuration, notably being used by [Cargo], Rust's package manager.
//!
//! ## TOML values
//!
//! A value in TOML is represented with the `Value` enum in this crate:
//!
//! ```rust,ignore
//! pub enum Value {
//!     String(String),
//!     Integer(i64),
//!     Float(f64),
//!     Boolean(bool),
//!     Datetime(Datetime),
//!     Array(Array),
//!     Table(Table),
//! }
//! ```
//!
//! TOML is similar to JSON with the notable addition of a `Datetime`
//! type. In general, TOML and JSON are interchangeable in terms of
//! formats.
//!
//! ## Parsing TOML
//!
//! The easiest way to parse a TOML document is via the `Value` type:
//!
//! ```rust
//! use toml::Value;
//!
//! let value = "foo = 'bar'".parse::<Value>().unwrap();
//!
//! assert_eq!(value["foo"].as_str(), Some("bar"));
//! ```
//!
//! The `Value` type implements a number of convenience methods and
//! traits; the example above uses `FromStr` to parse a `str` into a
//! `Value`.
//!
//! ## Deserialization and Serialization
//!
//! This crate supports [`serde`] 1.0 with a number of
//! implementations of the `Deserialize`, `Serialize`, `Deserializer`, and
//! `Serializer` traits. Namely, you'll find:
//!
//! * `Deserialize for Value`
//! * `Serialize for Value`
//! * `Deserialize for Datetime`
//! * `Serialize for Datetime`
//! * `Deserializer for de::Deserializer`
//! * `Serializer for ser::Serializer`
//! * `Deserializer for Value`
//!
//! This means that you can use Serde to deserialize/serialize the
//! `Value` type as well as the `Datetime` type in this crate. You can also
//! use the `Deserializer`, `Serializer`, or `Value` type itself to act as
//! a deserializer/serializer for arbitrary types.
//!
//! An example of deserializing with TOML is:
//!
//! ```rust
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate toml;
//!
//! #[derive(Deserialize)]
//! struct Config {
//!     ip: String,
//!     port: Option<u16>,
//!     keys: Keys,
//! }
//!
//! #[derive(Deserialize)]
//! struct Keys {
//!     github: String,
//!     travis: Option<String>,
//! }
//!
//! fn main() {
//!     let config: Config = toml::from_str(r#"
//!         ip = '127.0.0.1'
//!
//!         [keys]
//!         github = 'xxxxxxxxxxxxxxxxx'
//!         travis = 'yyyyyyyyyyyyyyyyy'
//!     "#).unwrap();
//!
//!     assert_eq!(config.ip, "127.0.0.1");
//!     assert_eq!(config.port, None);
//!     assert_eq!(config.keys.github, "xxxxxxxxxxxxxxxxx");
//!     assert_eq!(config.keys.travis.as_ref().unwrap(), "yyyyyyyyyyyyyyyyy");
//! }
//! ```
//!
//! You can serialize types in a similar fashion:
//!
//! ```rust
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate toml;
//!
//! #[derive(Serialize)]
//! struct Config {
//!     ip: String,
//!     port: Option<u16>,
//!     keys: Keys,
//! }
//!
//! #[derive(Serialize)]
//! struct Keys {
//!     github: String,
//!     travis: Option<String>,
//! }
//!
//! fn main() {
//!     let config = Config {
//!         ip: "127.0.0.1".to_string(),
//!         port: None,
//!         keys: Keys {
//!             github: "xxxxxxxxxxxxxxxxx".to_string(),
//!             travis: Some("yyyyyyyyyyyyyyyyy".to_string()),
//!         },
//!     };
//!
//!     let toml = toml::to_string(&config).unwrap();
//! }
//! ```
//!
//! [TOML]: https://github.com/toml-lang/toml
//! [Cargo]: https://crates.io/
//! [`serde`]: https://serde.rs/

#![doc(html_root_url = "https://docs.rs/toml/0.5")]
#![deny(missing_docs)]

#[macro_use]
extern crate serde;
#[cfg(feature = "preserve_order")]
extern crate linked_hash_map;

pub mod map;
pub mod value;
#[doc(no_inline)]
pub use value::Value;
mod datetime;

pub mod ser;
#[doc(no_inline)]
pub use ser::{to_string, to_string_pretty, to_vec, Serializer};
pub mod de;
#[doc(no_inline)]
pub use de::{from_slice, from_str, Deserializer};
mod tokens;

#[doc(hidden)]
pub mod macros;

mod spanned;
#[doc(no_inline)]
pub use spanned::Spanned;
<|endoftext|>


<commit_before>//! Additional methods for Read and Write
//!
//! The additional methods implemented allow reading and writing integers and floats
//! in the specified endianness.
//!
//! # Usage
//!
//! Basically, you need to `use` the trait WritePodExt or ReadPodExt.
//!
//! # Examples
//!
//! ## Reading
//!
//! To read some value from a reader, import ReadPodExt and the needed endianness.
//!
//! ```
//! use podio::{ReadPodExt, BigEndian};
//!
//! let slice: &[u8] = &[0x10, 0x20, 0x30, 0x40];
//! let mut reader = std::io::Cursor::new(slice);
//!
//! let value = reader.read_u32::<BigEndian>().unwrap();
//!
//! assert_eq!(value, 0x10203040);
//! ```
//!
//! ## Writing
//!
//! For writing, you need to import the trait WritePodExt.
//!
//! ```
//! use podio::{WritePodExt, LittleEndian};
//!
//! let slice: &mut [u8] = &mut [0; 2];
//! let mut writer = std::io::Cursor::new(slice);
//!
//! writer.write_u16::<LittleEndian>(0x8802).unwrap();
//!
//! assert_eq!(writer.into_inner(), &[0x02, 0x88]);
//! ```
//!
//! ## Read exact
//!
//! One additional method, not really dealing with POD, is `read_exact`.
//!
//! ```
//! use podio::ReadPodExt;
//!
//! let slice: &[u8] = &[0, 1, 2, 3];
//! let mut reader = std::io::Cursor::new(slice);
//!
//! assert_eq!(reader.read_exact(1).unwrap(), [0]);
//! assert_eq!(reader.read_exact(2).unwrap(), [1,2]);
//! assert_eq!(reader.read_exact(0).unwrap(), []);
//! assert_eq!(reader.read_exact(1).unwrap(), [3]);
//! assert!(reader.read_exact(1).is_err());

#![warn(missing_docs)]

use std::io;
use std::io::prelude::*;

/// Little endian. The number `0xABCD` is stored `[0xCD, 0xAB]`
pub enum LittleEndian {}
/// Big endian. The number `0xABCD` is stored `[0xAB, 0xCD]`
pub enum BigEndian {}

/// Trait implementing conversion methods for a specific endianness
pub trait Endianness {
    /// Converts a value from the platform type to the specified endianness
    fn int_to_target<T: EndianConvert>(val: T) -> T;
    /// Converts a value from the sepcified endianness to the platform type
    fn int_from_target<T: EndianConvert>(val: T) -> T;
}

/// Generic trait for endian conversions on integers
pub trait EndianConvert {
    /// Convert self to a big-endian value
    fn to_be(self) -> Self;
    /// Convert self to a little-endian value
    fn to_le(self) -> Self;
    /// Convert a big-endian value to the target endianness
    fn from_be(x: Self) -> Self;
    /// Convert a little-endian value to the target endiannes
    fn from_le(x: Self) -> Self;
}

/// Additional write methods for a io::Write
pub trait WritePodExt {
    /// Write a u64
    fn write_u64<T: Endianness>(&mut self, u64) -> io::Result<()>;
    /// Write a u32
    fn write_u32<T: Endianness>(&mut self, u32) -> io::Result<()>;
    /// Write a u16
    fn write_u16<T: Endianness>(&mut self, u16) -> io::Result<()>;
    /// Write a u8
    fn write_u8(&mut self, u8) -> io::Result<()>;
    /// Write a i64
    fn write_i64<T: Endianness>(&mut self, i64) -> io::Result<()>;
    /// Write a i32
    fn write_i32<T: Endianness>(&mut self, i32) -> io::Result<()>;
    /// Write a i16
    fn write_i16<T: Endianness>(&mut self, i16) -> io::Result<()>;
    /// Write a i8
    fn write_i8(&mut self, i8) -> io::Result<()>;
    /// Write a f32
    fn write_f32<T: Endianness>(&mut self, f32) -> io::Result<()>;
    /// Write a f64
    fn write_f64<T: Endianness>(&mut self, f64) -> io::Result<()>;
}

/// Additional read methods for a io::Read
pub trait ReadPodExt {
    /// Read a u64
    fn read_u64<T: Endianness>(&mut self) -> io::Result<u64>;
    /// Read a u32
    fn read_u32<T: Endianness>(&mut self) -> io::Result<u32>;
    /// Read a u16
    fn read_u16<T: Endianness>(&mut self) -> io::Result<u16>;
    /// Read a u8
    fn read_u8(&mut self) -> io::Result<u8>;
    /// Read a i64
    fn read_i64<T: Endianness>(&mut self) -> io::Result<i64>;
    /// Read a i32
    fn read_i32<T: Endianness>(&mut self) -> io::Result<i32>;
    /// Read a i16
    fn read_i16<T: Endianness>(&mut self) -> io::Result<i16>;
    /// Read a i8
    fn read_i8(&mut self) -> io::Result<i8>;
    /// Read a f32
    fn read_f32<T: Endianness>(&mut self) -> io::Result<f32>;
    /// Read a f64
    fn read_f64<T: Endianness>(&mut self) -> io::Result<f64>;
    /// Read a specific number of bytes
    fn read_exact(&mut self, usize) -> io::Result<Vec<u8>>;
}

impl Endianness for LittleEndian {
    #[inline]
    fn int_to_target<T: EndianConvert>(val: T) -> T {
        val.to_le()
    }
    #[inline]
    fn int_from_target<T: EndianConvert>(val: T) -> T {
        <T as EndianConvert>::from_le(val)
    }
}

impl Endianness for BigEndian {
    #[inline]
    fn int_to_target<T: EndianConvert>(val: T) -> T {
        val.to_be()
    }
    #[inline]
    fn int_from_target<T: EndianConvert>(val: T) -> T {
        <T as EndianConvert>::from_be(val)
    }
}

macro_rules! impl_platform_convert {
    ($T:ty) => {
        impl EndianConvert for $T {
            #[inline]
            fn to_be(self) -> $T {
                self.to_be()
            }

            #[inline]
            fn to_le(self) -> $T {
                self.to_le()
            }

            #[inline]
            fn from_be(x: $T) -> $T {
                if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
            }

            #[inline]
            fn from_le(x: $T) -> $T {
                if cfg!(target_endian = "little") { x } else { x.swap_bytes() }
            }
        }
    };
}

impl_platform_convert!(u8);
impl_platform_convert!(u16);
impl_platform_convert!(u32);
impl_platform_convert!(u64);

macro_rules! val_to_buf {
    ($val:ident, $T:expr) => {
        {
            let mut buf = [0; $T];
            for i in 0..buf.len() {
                buf[i] = ($val >> (i * 8)) as u8;
            }
            buf
        }
    };
}

impl<W: Write> WritePodExt for W {
    fn write_u64<T: Endianness>(&mut self, val: u64) -> io::Result<()> {
        let tval = <T as Endianness>::int_to_target(val);
        let buf = val_to_buf!(tval, 8);
        self.write_all(&buf)
    }

    fn write_u32<T: Endianness>(&mut self, val: u32) -> io::Result<()> {
        let tval = <T as Endianness>::int_to_target(val);
        let buf = val_to_buf!(tval, 4);
        self.write_all(&buf)
    }

    fn write_u16<T: Endianness>(&mut self, val: u16) -> io::Result<()> {
        let tval = <T as Endianness>::int_to_target(val);
        let buf = val_to_buf!(tval, 2);
        self.write_all(&buf)
    }

    fn write_u8(&mut self, val: u8) -> io::Result<()> {
        self.write_all(&[val])
    }

    fn write_i64<T: Endianness>(&mut self, val: i64) -> io::Result<()> {
        self.write_u64::<T>(val as u64)
    }

    fn write_i32<T: Endianness>(&mut self, val: i32) -> io::Result<()> {
        self.write_u32::<T>(val as u32)
    }

    fn write_i16<T: Endianness>(&mut self, val: i16) -> io::Result<()> {
        self.write_u16::<T>(val as u16)
    }

    fn write_i8(&mut self, val: i8) -> io::Result<()> {
        self.write_u8(val as u8)
    }

    fn write_f32<T: Endianness>(&mut self, val: f32) -> io::Result<()> {
        let tval: u32 = unsafe { std::mem::transmute::<f32, u32>(val) };
        self.write_u32::<T>(tval)
    }

    fn write_f64<T: Endianness>(&mut self, val: f64) -> io::Result<()> {
        let tval: u64 = unsafe { std::mem::transmute::<f64, u64>(val) };
        self.write_u64::<T>(tval)
    }
}

#[inline]
fn fill_buf<R: Read>(reader: &mut R, buf: &mut [u8]) -> io::Result<()> {
    let mut idx = 0;
    while idx != buf.len() {
        match reader.read(&mut buf[idx..]) {
            Ok(0) => return Err(io::Error::new(io::ErrorKind::Other, "Could not read enough bytes")),
            Ok(v) => { idx += v; }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    Ok(())
}

macro_rules! buf_to_val {
    ($buf:ident, $T:ty) => {
        {
            let mut val: $T = 0;
            for i in 0..$buf.len() {
                val |= ($buf[i] as $T) << (i * 8);
            }
            val
        }
    };
}

impl<R: Read> ReadPodExt for R {
    fn read_u64<T: Endianness>(&mut self) -> io::Result<u64> {
        let buf = &mut [0u8; 8];
        try!(fill_buf(self, buf));
        let tval = buf_to_val!(buf, u64);
        Ok(<T as Endianness>::int_from_target(tval))
    }
    fn read_u32<T: Endianness>(&mut self) -> io::Result<u32> {
        let buf = &mut [0u8; 4];
        try!(fill_buf(self, buf));
        let tval = buf_to_val!(buf, u32);
        Ok(<T as Endianness>::int_from_target(tval))
    }
    fn read_u16<T: Endianness>(&mut self) -> io::Result<u16> {
        let buf = &mut [0u8; 2];
        try!(fill_buf(self, buf));
        let tval = buf_to_val!(buf, u16);
        Ok(<T as Endianness>::int_from_target(tval))
    }
    fn read_u8(&mut self) -> io::Result<u8> {
        let buf = &mut [0u8; 1];
        try!(fill_buf(self, buf));
        Ok(buf[0])
    }
    fn read_i64<T: Endianness>(&mut self) -> io::Result<i64> {
        self.read_u64::<T>().map(|v| v as i64)
    }
    fn read_i32<T: Endianness>(&mut self) -> io::Result<i32> {
        self.read_u32::<T>().map(|v| v as i32)
    }
    fn read_i16<T: Endianness>(&mut self) -> io::Result<i16> {
        self.read_u16::<T>().map(|v| v as i16)
    }
    fn read_i8(&mut self) -> io::Result<i8> {
        self.read_u8().map(|v| v as i8)
    }
    fn read_f64<T: Endianness>(&mut self) -> io::Result<f64> {
        self.read_u64::<T>().map(|v| unsafe { std::mem::transmute::<u64, f64>(v) })
    }
    fn read_f32<T: Endianness>(&mut self) -> io::Result<f32> {
        self.read_u32::<T>().map(|v| unsafe { std::mem::transmute::<u32, f32>(v) })
    }
    fn read_exact(&mut self, len: usize) -> io::Result<Vec<u8>> {
        let mut res = vec![0; len];
        try!(fill_buf(self, &mut res));
        Ok(res)
    }
}
<commit_msg>Add newlines<commit_after>//! Additional methods for Read and Write
//!
//! The additional methods implemented allow reading and writing integers and floats
//! in the specified endianness.
//!
//! # Usage
//!
//! Basically, you need to `use` the trait WritePodExt or ReadPodExt.
//!
//! # Examples
//!
//! ## Reading
//!
//! To read some value from a reader, import ReadPodExt and the needed endianness.
//!
//! ```
//! use podio::{ReadPodExt, BigEndian};
//!
//! let slice: &[u8] = &[0x10, 0x20, 0x30, 0x40];
//! let mut reader = std::io::Cursor::new(slice);
//!
//! let value = reader.read_u32::<BigEndian>().unwrap();
//!
//! assert_eq!(value, 0x10203040);
//! ```
//!
//! ## Writing
//!
//! For writing, you need to import the trait WritePodExt.
//!
//! ```
//! use podio::{WritePodExt, LittleEndian};
//!
//! let slice: &mut [u8] = &mut [0; 2];
//! let mut writer = std::io::Cursor::new(slice);
//!
//! writer.write_u16::<LittleEndian>(0x8802).unwrap();
//!
//! assert_eq!(writer.into_inner(), &[0x02, 0x88]);
//! ```
//!
//! ## Read exact
//!
//! One additional method, not really dealing with POD, is `read_exact`.
//!
//! ```
//! use podio::ReadPodExt;
//!
//! let slice: &[u8] = &[0, 1, 2, 3];
//! let mut reader = std::io::Cursor::new(slice);
//!
//! assert_eq!(reader.read_exact(1).unwrap(), [0]);
//! assert_eq!(reader.read_exact(2).unwrap(), [1,2]);
//! assert_eq!(reader.read_exact(0).unwrap(), []);
//! assert_eq!(reader.read_exact(1).unwrap(), [3]);
//! assert!(reader.read_exact(1).is_err());

#![warn(missing_docs)]

use std::io;
use std::io::prelude::*;

/// Little endian. The number `0xABCD` is stored `[0xCD, 0xAB]`
pub enum LittleEndian {}
/// Big endian. The number `0xABCD` is stored `[0xAB, 0xCD]`
pub enum BigEndian {}

/// Trait implementing conversion methods for a specific endianness
pub trait Endianness {
    /// Converts a value from the platform type to the specified endianness
    fn int_to_target<T: EndianConvert>(val: T) -> T;
    /// Converts a value from the sepcified endianness to the platform type
    fn int_from_target<T: EndianConvert>(val: T) -> T;
}

/// Generic trait for endian conversions on integers
pub trait EndianConvert {
    /// Convert self to a big-endian value
    fn to_be(self) -> Self;
    /// Convert self to a little-endian value
    fn to_le(self) -> Self;
    /// Convert a big-endian value to the target endianness
    fn from_be(x: Self) -> Self;
    /// Convert a little-endian value to the target endiannes
    fn from_le(x: Self) -> Self;
}

/// Additional write methods for a io::Write
pub trait WritePodExt {
    /// Write a u64
    fn write_u64<T: Endianness>(&mut self, u64) -> io::Result<()>;
    /// Write a u32
    fn write_u32<T: Endianness>(&mut self, u32) -> io::Result<()>;
    /// Write a u16
    fn write_u16<T: Endianness>(&mut self, u16) -> io::Result<()>;
    /// Write a u8
    fn write_u8(&mut self, u8) -> io::Result<()>;
    /// Write a i64
    fn write_i64<T: Endianness>(&mut self, i64) -> io::Result<()>;
    /// Write a i32
    fn write_i32<T: Endianness>(&mut self, i32) -> io::Result<()>;
    /// Write a i16
    fn write_i16<T: Endianness>(&mut self, i16) -> io::Result<()>;
    /// Write a i8
    fn write_i8(&mut self, i8) -> io::Result<()>;
    /// Write a f32
    fn write_f32<T: Endianness>(&mut self, f32) -> io::Result<()>;
    /// Write a f64
    fn write_f64<T: Endianness>(&mut self, f64) -> io::Result<()>;
}

/// Additional read methods for a io::Read
pub trait ReadPodExt {
    /// Read a u64
    fn read_u64<T: Endianness>(&mut self) -> io::Result<u64>;
    /// Read a u32
    fn read_u32<T: Endianness>(&mut self) -> io::Result<u32>;
    /// Read a u16
    fn read_u16<T: Endianness>(&mut self) -> io::Result<u16>;
    /// Read a u8
    fn read_u8(&mut self) -> io::Result<u8>;
    /// Read a i64
    fn read_i64<T: Endianness>(&mut self) -> io::Result<i64>;
    /// Read a i32
    fn read_i32<T: Endianness>(&mut self) -> io::Result<i32>;
    /// Read a i16
    fn read_i16<T: Endianness>(&mut self) -> io::Result<i16>;
    /// Read a i8
    fn read_i8(&mut self) -> io::Result<i8>;
    /// Read a f32
    fn read_f32<T: Endianness>(&mut self) -> io::Result<f32>;
    /// Read a f64
    fn read_f64<T: Endianness>(&mut self) -> io::Result<f64>;
    /// Read a specific number of bytes
    fn read_exact(&mut self, usize) -> io::Result<Vec<u8>>;
}

impl Endianness for LittleEndian {
    #[inline]
    fn int_to_target<T: EndianConvert>(val: T) -> T {
        val.to_le()
    }
    #[inline]
    fn int_from_target<T: EndianConvert>(val: T) -> T {
        <T as EndianConvert>::from_le(val)
    }
}

impl Endianness for BigEndian {
    #[inline]
    fn int_to_target<T: EndianConvert>(val: T) -> T {
        val.to_be()
    }
    #[inline]
    fn int_from_target<T: EndianConvert>(val: T) -> T {
        <T as EndianConvert>::from_be(val)
    }
}

macro_rules! impl_platform_convert {
    ($T:ty) => {
        impl EndianConvert for $T {
            #[inline]
            fn to_be(self) -> $T {
                self.to_be()
            }

            #[inline]
            fn to_le(self) -> $T {
                self.to_le()
            }

            #[inline]
            fn from_be(x: $T) -> $T {
                if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
            }

            #[inline]
            fn from_le(x: $T) -> $T {
                if cfg!(target_endian = "little") { x } else { x.swap_bytes() }
            }
        }
    };
}

impl_platform_convert!(u8);
impl_platform_convert!(u16);
impl_platform_convert!(u32);
impl_platform_convert!(u64);

macro_rules! val_to_buf {
    ($val:ident, $T:expr) => {
        {
            let mut buf = [0; $T];
            for i in 0..buf.len() {
                buf[i] = ($val >> (i * 8)) as u8;
            }
            buf
        }
    };
}

impl<W: Write> WritePodExt for W {
    fn write_u64<T: Endianness>(&mut self, val: u64) -> io::Result<()> {
        let tval = <T as Endianness>::int_to_target(val);
        let buf = val_to_buf!(tval, 8);
        self.write_all(&buf)
    }

    fn write_u32<T: Endianness>(&mut self, val: u32) -> io::Result<()> {
        let tval = <T as Endianness>::int_to_target(val);
        let buf = val_to_buf!(tval, 4);
        self.write_all(&buf)
    }

    fn write_u16<T: Endianness>(&mut self, val: u16) -> io::Result<()> {
        let tval = <T as Endianness>::int_to_target(val);
        let buf = val_to_buf!(tval, 2);
        self.write_all(&buf)
    }

    fn write_u8(&mut self, val: u8) -> io::Result<()> {
        self.write_all(&[val])
    }

    fn write_i64<T: Endianness>(&mut self, val: i64) -> io::Result<()> {
        self.write_u64::<T>(val as u64)
    }

    fn write_i32<T: Endianness>(&mut self, val: i32) -> io::Result<()> {
        self.write_u32::<T>(val as u32)
    }

    fn write_i16<T: Endianness>(&mut self, val: i16) -> io::Result<()> {
        self.write_u16::<T>(val as u16)
    }

    fn write_i8(&mut self, val: i8) -> io::Result<()> {
        self.write_u8(val as u8)
    }

    fn write_f32<T: Endianness>(&mut self, val: f32) -> io::Result<()> {
        let tval: u32 = unsafe { std::mem::transmute::<f32, u32>(val) };
        self.write_u32::<T>(tval)
    }

    fn write_f64<T: Endianness>(&mut self, val: f64) -> io::Result<()> {
        let tval: u64 = unsafe { std::mem::transmute::<f64, u64>(val) };
        self.write_u64::<T>(tval)
    }
}

#[inline]
fn fill_buf<R: Read>(reader: &mut R, buf: &mut [u8]) -> io::Result<()> {
    let mut idx = 0;
    while idx != buf.len() {
        match reader.read(&mut buf[idx..]) {
            Ok(0) => return Err(io::Error::new(io::ErrorKind::Other, "Could not read enough bytes")),
            Ok(v) => { idx += v; }
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    Ok(())
}

macro_rules! buf_to_val {
    ($buf:ident, $T:ty) => {
        {
            let mut val: $T = 0;
            for i in 0..$buf.len() {
                val |= ($buf[i] as $T) << (i * 8);
            }
            val
        }
    };
}

impl<R: Read> ReadPodExt for R {
    fn read_u64<T: Endianness>(&mut self) -> io::Result<u64> {
        let buf = &mut [0u8; 8];
        try!(fill_buf(self, buf));
        let tval = buf_to_val!(buf, u64);
        Ok(<T as Endianness>::int_from_target(tval))
    }

    fn read_u32<T: Endianness>(&mut self) -> io::Result<u32> {
        let buf = &mut [0u8; 4];
        try!(fill_buf(self, buf));
        let tval = buf_to_val!(buf, u32);
        Ok(<T as Endianness>::int_from_target(tval))
    }

    fn read_u16<T: Endianness>(&mut self) -> io::Result<u16> {
        let buf = &mut [0u8; 2];
        try!(fill_buf(self, buf));
        let tval = buf_to_val!(buf, u16);
        Ok(<T as Endianness>::int_from_target(tval))
    }

    fn read_u8(&mut self) -> io::Result<u8> {
        let buf = &mut [0u8; 1];
        try!(fill_buf(self, buf));
        Ok(buf[0])
    }

    fn read_i64<T: Endianness>(&mut self) -> io::Result<i64> {
        self.read_u64::<T>().map(|v| v as i64)
    }

    fn read_i32<T: Endianness>(&mut self) -> io::Result<i32> {
        self.read_u32::<T>().map(|v| v as i32)
    }

    fn read_i16<T: Endianness>(&mut self) -> io::Result<i16> {
        self.read_u16::<T>().map(|v| v as i16)
    }

    fn read_i8(&mut self) -> io::Result<i8> {
        self.read_u8().map(|v| v as i8)
    }

    fn read_f64<T: Endianness>(&mut self) -> io::Result<f64> {
        self.read_u64::<T>().map(|v| unsafe { std::mem::transmute::<u64, f64>(v) })
    }

    fn read_f32<T: Endianness>(&mut self) -> io::Result<f32> {
        self.read_u32::<T>().map(|v| unsafe { std::mem::transmute::<u32, f32>(v) })
    }

    fn read_exact(&mut self, len: usize) -> io::Result<Vec<u8>> {
        let mut res = vec![0; len];
        try!(fill_buf(self, &mut res));
        Ok(res)
    }
}
<|endoftext|>


<commit_before>pub mod env_reader;
pub mod sleeper;
pub mod tcp;

pub struct Config {
    pub hosts: String,
    pub timeout: u64,
    pub wait_before: u64,
    pub wait_after: u64,
    pub wait_sleep_interval: u64,
}

pub fn wait(sleep: &sleeper::Sleeper, config: &Config, on_timeout: &mut FnMut()) {
    println!("Docker-compose-wait starting with configuration:");
    println!("------------------------------------------------");
    println!(" - Hosts to be waiting for: [{}]", config.hosts);
    println!(" - Timeout before failure: {} seconds ", config.timeout);
    println!(
        " - Sleeping time before checking for hosts availability: {} seconds",
        config.wait_before
    );
    println!(
        " - Sleeping time once all hosts are available: {} seconds",
        config.wait_after
    );
    println!("------------------------------------------------");

    if config.wait_before > 0 {
        println!(
            "Waiting {} seconds before checking for hosts availability",
            config.wait_before
        );
        sleep.sleep(config.wait_before);
    }

    if !config.hosts.trim().is_empty() {
        let mut count = 0;
        //let start = Instant::now();
        for host in config.hosts.trim().split(',') {
            println!("Checking availability of {}", host);
            while !tcp::is_reachable(&host.trim().to_string()) {
                println!("Host {} not yet available", host);
                count += 1;
                if count > config.timeout {
                    //if (start.elapsed().as_secs() > wait_timeout) {
                    println!(
                        "Timeout! After {} seconds some hosts are still not reachable",
                        config.timeout
                    );
                    on_timeout();
                    return;
                }
                sleep.sleep(config.wait_sleep_interval);
            }
            println!("Host {} is now available", host);
        }
    }

    if config.wait_after > 0 {
        println!(
            "Waiting {} seconds after hosts availability",
            config.wait_after
        );
        sleep.sleep(config.wait_after);
    }
}

pub fn config_from_env() -> Config {
    Config {
        hosts: env_reader::env_var(&"WAIT_HOSTS".to_string(), "".to_string()),
        timeout: to_int(
            &env_reader::env_var(&"WAIT_HOSTS_TIMEOUT".to_string(), "".to_string()),
            30,
        ),
        wait_before: to_int(
            &env_reader::env_var(&"WAIT_BEFORE_HOSTS".to_string(), "".to_string()),
            0,
        ),
        wait_after: to_int(
            &env_reader::env_var(&"WAIT_AFTER_HOSTS".to_string(), "".to_string()),
            0,
        ),
        wait_sleep_interval: to_int(
            &env_reader::env_var(&"WAIT_SLEEP_INTERVAL".to_string(), "".to_string()),
            1,
        ),
    }
}

fn to_int(number: &str, default: u64) -> u64 {
    match number.parse::<u64>() {
        Ok(value) => value,
        Err(_e) => default,
    }
}

#[cfg(test)]
mod test {

    use super::*;
    use std::env;

    #[test]
    fn should_return_int_value() {
        let value = to_int("32", 0);
        assert_eq!(32, value)
    }

    #[test]
    fn should_return_zero_when_negative_value() {
        let value = to_int("-32", 10);
        assert_eq!(10, value)
    }

    #[test]
    fn should_return_zero_when_invalid_value() {
        let value = to_int("hello", 0);
        assert_eq!(0, value)
    }

    #[test]
    fn should_return_zero_when_empty_value() {
        let value = to_int("", 11);
        assert_eq!(11, value)
    }

    /*
        #[test]
        fn default_timeout_should_be_30() {
            set_env("", "", "10o", "10");
            let config = config_from_env();
            assert_eq!("".to_string(), config.hosts);
            assert_eq!(30, config.timeout);
            assert_eq!(0, config.wait_before);
            assert_eq!(10, config.wait_after);
        }
    */

    #[test]
    fn should_get_config_values_from_env() {
        set_env("localhost:1234", "20", "2", "3", "4");
        let config = config_from_env();
        assert_eq!("localhost:1234".to_string(), config.hosts);
        assert_eq!(20, config.timeout);
        assert_eq!(2, config.wait_before);
        assert_eq!(3, config.wait_after);
        assert_eq!(4, config.wait_sleep_interval);
    }

    /*     #[test]
       fn should_get_default_config_values() {
           set_env("localhost:1234", "", "", "", "");
           let config = config_from_env();
           assert_eq!("localhost:1234".to_string(), config.hosts);
           assert_eq!(30, config.timeout);
           assert_eq!(0, config.wait_before);
           assert_eq!(0, config.wait_after);
           assert_eq!(1, config.wait_sleep_interval);
       }
    */
    fn set_env(hosts: &str, timeout: &str, before: &str, after: &str, sleep: &str) {
        env::set_var("WAIT_BEFORE_HOSTS", before.to_string());
        env::set_var("WAIT_AFTER_HOSTS", after.to_string());
        env::set_var("WAIT_HOSTS_TIMEOUT", timeout.to_string());
        env::set_var("WAIT_HOSTS", hosts.to_string());
        env::set_var("WAIT_SLEEP_INTERVAL", sleep.to_string());
    }
}
<commit_msg>use crate mod prefix<commit_after>pub mod env_reader;
pub mod sleeper;
pub mod tcp;

pub struct Config {
    pub hosts: String,
    pub timeout: u64,
    pub wait_before: u64,
    pub wait_after: u64,
    pub wait_sleep_interval: u64,
}

pub fn wait(sleep: &crate::sleeper::Sleeper, config: &Config, on_timeout: &mut FnMut()) {
    println!("Docker-compose-wait starting with configuration:");
    println!("------------------------------------------------");
    println!(" - Hosts to be waiting for: [{}]", config.hosts);
    println!(" - Timeout before failure: {} seconds ", config.timeout);
    println!(
        " - Sleeping time before checking for hosts availability: {} seconds",
        config.wait_before
    );
    println!(
        " - Sleeping time once all hosts are available: {} seconds",
        config.wait_after
    );
    println!("------------------------------------------------");

    if config.wait_before > 0 {
        println!(
            "Waiting {} seconds before checking for hosts availability",
            config.wait_before
        );
        sleep.sleep(config.wait_before);
    }

    if !config.hosts.trim().is_empty() {
        let mut count = 0;
        //let start = Instant::now();
        for host in config.hosts.trim().split(',') {
            println!("Checking availability of {}", host);
            while !tcp::is_reachable(&host.trim().to_string()) {
                println!("Host {} not yet available", host);
                count += 1;
                if count > config.timeout {
                    //if (start.elapsed().as_secs() > wait_timeout) {
                    println!(
                        "Timeout! After {} seconds some hosts are still not reachable",
                        config.timeout
                    );
                    on_timeout();
                    return;
                }
                sleep.sleep(config.wait_sleep_interval);
            }
            println!("Host {} is now available", host);
        }
    }

    if config.wait_after > 0 {
        println!(
            "Waiting {} seconds after hosts availability",
            config.wait_after
        );
        sleep.sleep(config.wait_after);
    }
}

pub fn config_from_env() -> Config {
    Config {
        hosts: crate::env_reader::env_var(&"WAIT_HOSTS".to_string(), "".to_string()),
        timeout: to_int(
            &crate::env_reader::env_var(&"WAIT_HOSTS_TIMEOUT".to_string(), "".to_string()),
            30,
        ),
        wait_before: to_int(
            &crate::env_reader::env_var(&"WAIT_BEFORE_HOSTS".to_string(), "".to_string()),
            0,
        ),
        wait_after: to_int(
            &crate::env_reader::env_var(&"WAIT_AFTER_HOSTS".to_string(), "".to_string()),
            0,
        ),
        wait_sleep_interval: to_int(
            &crate::env_reader::env_var(&"WAIT_SLEEP_INTERVAL".to_string(), "".to_string()),
            1,
        ),
    }
}

fn to_int(number: &str, default: u64) -> u64 {
    match number.parse::<u64>() {
        Ok(value) => value,
        Err(_e) => default,
    }
}

#[cfg(test)]
mod test {

    use super::*;
    use std::env;

    #[test]
    fn should_return_int_value() {
        let value = to_int("32", 0);
        assert_eq!(32, value)
    }

    #[test]
    fn should_return_zero_when_negative_value() {
        let value = to_int("-32", 10);
        assert_eq!(10, value)
    }

    #[test]
    fn should_return_zero_when_invalid_value() {
        let value = to_int("hello", 0);
        assert_eq!(0, value)
    }

    #[test]
    fn should_return_zero_when_empty_value() {
        let value = to_int("", 11);
        assert_eq!(11, value)
    }

    /*
        #[test]
        fn default_timeout_should_be_30() {
            set_env("", "", "10o", "10");
            let config = config_from_env();
            assert_eq!("".to_string(), config.hosts);
            assert_eq!(30, config.timeout);
            assert_eq!(0, config.wait_before);
            assert_eq!(10, config.wait_after);
        }
    */

    #[test]
    fn should_get_config_values_from_env() {
        set_env("localhost:1234", "20", "2", "3", "4");
        let config = config_from_env();
        assert_eq!("localhost:1234".to_string(), config.hosts);
        assert_eq!(20, config.timeout);
        assert_eq!(2, config.wait_before);
        assert_eq!(3, config.wait_after);
        assert_eq!(4, config.wait_sleep_interval);
    }

    /*     #[test]
       fn should_get_default_config_values() {
           set_env("localhost:1234", "", "", "", "");
           let config = config_from_env();
           assert_eq!("localhost:1234".to_string(), config.hosts);
           assert_eq!(30, config.timeout);
           assert_eq!(0, config.wait_before);
           assert_eq!(0, config.wait_after);
           assert_eq!(1, config.wait_sleep_interval);
       }
    */
    fn set_env(hosts: &str, timeout: &str, before: &str, after: &str, sleep: &str) {
        env::set_var("WAIT_BEFORE_HOSTS", before.to_string());
        env::set_var("WAIT_AFTER_HOSTS", after.to_string());
        env::set_var("WAIT_HOSTS_TIMEOUT", timeout.to_string());
        env::set_var("WAIT_HOSTS", hosts.to_string());
        env::set_var("WAIT_SLEEP_INTERVAL", sleep.to_string());
    }
}
<|endoftext|>


<commit_before>extern crate logi_lcd_sys as sys;
extern crate widestring;
extern crate winapi;

use widestring::WideCString;
use self::winapi::{c_int};
use sys::*;

pub const MONO_WIDTH: usize   = sys::MONO_WIDTH;
pub const MONO_HEIGHT: usize  = sys::MONO_HEIGHT;
pub const COLOR_WIDTH: usize  = sys::COLOR_WIDTH;
pub const COLOR_HEIGHT: usize = sys::COLOR_HEIGHT;

pub struct MonoLcd;

#[allow(dead_code)]
#[derive(Debug)]
pub enum ColorButton {
    ButtonLeft,
    ButtonRight,
    ButtonOk,
    ButtonCancel,
    ButtonUp,
    ButtonDown,
    BttonMenu,
}

#[derive(Debug)]
pub enum MonoButton {
    Button0,
    Button1,
    Button2,
    Button3,
}

impl ColorButton {
    #[allow(dead_code)]
    fn lcd_button(self) -> LcdButton {
        match self {
            ColorButton::ButtonLeft   => LcdButton::COLOR_BUTTON_LEFT,
            ColorButton::ButtonRight  => LcdButton::COLOR_BUTTON_RIGHT,
            ColorButton::ButtonOk     => LcdButton::COLOR_BUTTON_OK,
            ColorButton::ButtonCancel => LcdButton::COLOR_BUTTON_CANCEL,
            ColorButton::ButtonUp     => LcdButton::COLOR_BUTTON_UP,
            ColorButton::ButtonDown   => LcdButton::COLOR_BUTTON_DOWN,
            ColorButton::BttonMenu    => LcdButton::COLOR_BUTTON_MENU,
        }
    }
}

impl MonoButton {
    fn lcd_button(self) -> LcdButton {
        match self {
            MonoButton::Button0 => LcdButton::MONO_BUTTON_0,
            MonoButton::Button1 => LcdButton::MONO_BUTTON_1,
            MonoButton::Button2 => LcdButton::MONO_BUTTON_2,
            MonoButton::Button3 => LcdButton::MONO_BUTTON_3,
        }
    }
}

impl MonoLcd {
    pub fn connect(app_name: &str) -> Result<MonoLcd, ()> {
        let ws = WideCString::from_str(app_name).unwrap();
        unsafe {
            match LogiLcdInit(ws.as_ptr(), LcdType::MONO) {
                Bool::TRUE => {
                    match LogiLcdIsConnected(LcdType::MONO) {
                        Bool::TRUE => Ok(MonoLcd),
                        Bool::FALSE => Err(()),
                    }
                },
                Bool::FALSE => Err(()),
            }
        }
    }

    pub fn is_button_pressed(&self, button: MonoButton) -> bool {
        unsafe {
            LogiLcdIsButtonPressed(button.lcd_button()).into()
        }
    }

    pub fn update(&mut self) {
        unsafe {
            LogiLcdUpdate();
        }
    }

    pub fn set_background(&mut self, bytemap: &[u8]) -> Result<(), ()> {
        assert_eq!(bytemap.len(), MONO_WIDTH * MONO_HEIGHT);
        unsafe {
            match LogiLcdMonoSetBackground(bytemap.as_ptr()) {
                Bool::TRUE  => Ok(()),
                Bool::FALSE => Err(()),
            }
        }
    }

    pub fn set_text(&mut self, line_number: usize, text: &str) -> Result<(), ()> {
        let ws = WideCString::from_str(text).unwrap();
        assert!(line_number < 4);
        unsafe {
            match LogiLcdMonoSetText(line_number as c_int, ws.as_ptr()) {
                Bool::TRUE  => Ok(()),
                Bool::FALSE => Err(()),
            }
        }
    }
}

impl Drop for MonoLcd {
    fn drop(&mut self) {
        unsafe {
            LogiLcdShutdown();
        }
    }
}
<commit_msg>Add error type and restrict to one instance<commit_after>extern crate logi_lcd_sys as sys;
extern crate widestring;
extern crate winapi;

use widestring::WideCString;
use self::winapi::{c_int};
use sys::*;

use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT};
use std::error::Error;
use std::fmt::{Display, Formatter};

pub const MONO_WIDTH: usize   = sys::MONO_WIDTH;
pub const MONO_HEIGHT: usize  = sys::MONO_HEIGHT;
pub const COLOR_WIDTH: usize  = sys::COLOR_WIDTH;
pub const COLOR_HEIGHT: usize = sys::COLOR_HEIGHT;

static INITIALIZED: AtomicBool = ATOMIC_BOOL_INIT;

pub struct MonoLcd;

#[allow(dead_code)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum ColorButton {
    ButtonLeft,
    ButtonRight,
    ButtonOk,
    ButtonCancel,
    ButtonUp,
    ButtonDown,
    BttonMenu,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum MonoButton {
    Button0,
    Button1,
    Button2,
    Button3,
}

#[derive(Debug)]
pub enum LcdError {
    NotConnected,
    Initialization,
    MonoBackground,
    MonoText,
    ColorBackground,
    ColorTitle,
    ColorText,
}

impl Error for LcdError {
    fn description(&self) -> &str {
        match *self {
            LcdError::NotConnected    => "LCD is not connected",
            LcdError::Initialization  => "A FFI call to LogiLcdInit() has failed",
            LcdError::MonoBackground  => "A FFI call to LogiLcdMonoSetBackground() has failed",
            LcdError::MonoText        => "A FFI call to LogiLcdMonoSetText() has failed",
            LcdError::ColorBackground => "A FFI call to LogiLcdColorSetBackground() has failed",
            LcdError::ColorTitle      => "A FFI call to LogiLcdColorSetTitle() has failed",
            LcdError::ColorText       => "A FFI call to LogiLcdColorSetText() has failed",
        }
    }
}

impl Display for LcdError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "LcdError: {}", self.description())
    }
}

impl ColorButton {
    #[allow(dead_code)]
    fn lcd_button(self) -> LcdButton {
        match self {
            ColorButton::ButtonLeft   => LcdButton::COLOR_BUTTON_LEFT,
            ColorButton::ButtonRight  => LcdButton::COLOR_BUTTON_RIGHT,
            ColorButton::ButtonOk     => LcdButton::COLOR_BUTTON_OK,
            ColorButton::ButtonCancel => LcdButton::COLOR_BUTTON_CANCEL,
            ColorButton::ButtonUp     => LcdButton::COLOR_BUTTON_UP,
            ColorButton::ButtonDown   => LcdButton::COLOR_BUTTON_DOWN,
            ColorButton::BttonMenu    => LcdButton::COLOR_BUTTON_MENU,
        }
    }
}

impl MonoButton {
    fn lcd_button(self) -> LcdButton {
        match self {
            MonoButton::Button0 => LcdButton::MONO_BUTTON_0,
            MonoButton::Button1 => LcdButton::MONO_BUTTON_1,
            MonoButton::Button2 => LcdButton::MONO_BUTTON_2,
            MonoButton::Button3 => LcdButton::MONO_BUTTON_3,
        }
    }
}

impl MonoLcd {
    pub fn connect(app_name: &str) -> Result<MonoLcd, LcdError> {
        assert_eq!(INITIALIZED.swap(true, Ordering::SeqCst), false);

        let ws = WideCString::from_str(app_name).unwrap();
        let ret = unsafe {
            match LogiLcdInit(ws.as_ptr(), LcdType::MONO) {
                Bool::TRUE => {
                    match LogiLcdIsConnected(LcdType::MONO) {
                        Bool::TRUE => Ok(MonoLcd),
                        Bool::FALSE => Err(LcdError::NotConnected),
                    }
                },
                Bool::FALSE => Err(LcdError::Initialization),
            }
        };
        if ret.is_err() {
            INITIALIZED.store(false, Ordering::SeqCst);
        }
        ret
    }

    pub fn is_connected() -> bool {
        unsafe {
            LogiLcdIsConnected(LcdType::MONO).into()
        }
    }

    pub fn is_button_pressed(&self, button: MonoButton) -> bool {
        unsafe {
            LogiLcdIsButtonPressed(button.lcd_button()).into()
        }
    }

    pub fn update(&mut self) {
        unsafe {
            LogiLcdUpdate();
        }
    }

    pub fn set_background(&mut self, bytemap: &[u8]) -> Result<(), LcdError> {
        assert_eq!(bytemap.len(), MONO_WIDTH * MONO_HEIGHT);
        unsafe {
            match LogiLcdMonoSetBackground(bytemap.as_ptr()) {
                Bool::TRUE  => Ok(()),
                Bool::FALSE => Err(LcdError::MonoBackground),
            }
        }
    }

    pub fn set_text(&mut self, line_number: usize, text: &str) -> Result<(), LcdError> {
        let ws = WideCString::from_str(text).unwrap();
        assert!(line_number < 4);
        unsafe {
            match LogiLcdMonoSetText(line_number as c_int, ws.as_ptr()) {
                Bool::TRUE  => Ok(()),
                Bool::FALSE => Err(LcdError::MonoText),
            }
        }
    }
}

impl Drop for MonoLcd {
    fn drop(&mut self) {
        unsafe {
            LogiLcdShutdown();
        }
    }
}
<|endoftext|>


<commit_before>#![feature(collections)]
#![feature(core)]
#![feature(plugin)]
extern crate "rustc-serialize" as serialize;

#[plugin]
extern crate regex_macros;
extern crate regex;

extern crate collections;
extern crate url;

pub use parser::{parse, ParseResult, ParseError, ParseErrorKind};

mod merge;
mod mutable_json;
mod helpers;
mod parser;

<commit_msg>(fix) use new plugin syntax<commit_after>#![feature(collections)]
#![feature(core)]
#![feature(plugin)]
#![plugin(regex_macros)]
extern crate "rustc-serialize" as serialize;

extern crate regex_macros;
extern crate regex;

extern crate collections;
extern crate url;

pub use parser::{parse, ParseResult, ParseError, ParseErrorKind};

mod merge;
mod mutable_json;
mod helpers;
mod parser;

<|endoftext|>


<commit_before>#![cfg_attr(test, feature(plugin))]
#![cfg_attr(test, plugin(stainless))]

//! A repeating-key XOR functions.
//!
//! This functions might be useful to play with
//! [the matasano crypto challenges](http://cryptopals.com).

/// Returns result of a XOR operation applied to a `source` byte sequence.
///
/// `key` will be an infinitely repeating byte sequence.
pub fn xor(source: &[u8], key: &[u8]) -> Vec<u8> {
    match key.len() {
        0 => source.to_vec(),
        1 => xor_with_byte(source, key[0]),
        _ => {
            let key_iter = InfiniteByteIterator::new(key);
            source.iter().zip(key_iter).map(|(&a, b)| a ^ b).collect()
        },
    }
}

/// Returns result of a XOR operation applied to a `source` byte sequence.
///
/// `byte` will be an infinitely repeating byte sequence.
pub fn xor_with_byte(source: &[u8], byte: u8) -> Vec<u8> {
    source.iter().map(|&a| a ^ byte).collect()
}

struct InfiniteByteIterator<'a> {
    bytes: &'a [u8],
    index: usize
}

impl<'a> InfiniteByteIterator<'a> {
    pub fn new(bytes: &'a [u8]) -> InfiniteByteIterator<'a> {
        InfiniteByteIterator {
            bytes: bytes,
            index: 0
        }
    }
}

impl<'a> Iterator for InfiniteByteIterator<'a> {
    type Item = u8;
    fn next(&mut self) -> Option<u8> {
        let byte = self.bytes[self.index];
        self.index = next_index(self.index, self.bytes.len());
        Some(byte)
    }
}

fn next_index(index: usize, count: usize) -> usize {
    if index + 1 < count { index + 1 } else { 0 }
}

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

    describe! xor {
        it "should return valid result" {
            let source = &[0, 1, 2, 3];
            let key = &[34, 52];
            assert!(xor(source, key) == [34, 53, 32, 55]);
        }

        it "should return valid result with one byte" {
            let source = &[0, 1, 2, 3];
            let key = &[47];
            assert!(xor(source, key) == [47, 46, 45, 44]);
        }

        it "should return source if key is empty" {
            let source = &[0, 1, 2, 3];
            let key = &[];
            assert!(xor(source, key) == [0, 1, 2, 3]);
        }

        it "should return empty result if source is empty" {
            let source = &[];
            let key = &[45, 32, 56];
            assert!(xor(source, key) == []);
        }
    }

    describe! xor_with_byte {
        it "should return valid result" {
            let source = &[0, 1, 2, 3];
            assert!(xor_with_byte(source, 23) == [23, 22, 21, 20]);
        }
    }
}
<commit_msg>Minor fix in tests.<commit_after>#![cfg_attr(test, feature(plugin))]
#![cfg_attr(test, plugin(stainless))]

//! A repeating-key XOR functions.
//!
//! This functions might be useful to play with
//! [the matasano crypto challenges](http://cryptopals.com).

/// Returns result of a XOR operation applied to a `source` byte sequence.
///
/// `key` will be an infinitely repeating byte sequence.
pub fn xor(source: &[u8], key: &[u8]) -> Vec<u8> {
    match key.len() {
        0 => source.to_vec(),
        1 => xor_with_byte(source, key[0]),
        _ => {
            let key_iter = InfiniteByteIterator::new(key);
            source.iter().zip(key_iter).map(|(&a, b)| a ^ b).collect()
        },
    }
}

/// Returns result of a XOR operation applied to a `source` byte sequence.
///
/// `byte` will be an infinitely repeating byte sequence.
pub fn xor_with_byte(source: &[u8], byte: u8) -> Vec<u8> {
    source.iter().map(|&a| a ^ byte).collect()
}

struct InfiniteByteIterator<'a> {
    bytes: &'a [u8],
    index: usize
}

impl<'a> InfiniteByteIterator<'a> {
    pub fn new(bytes: &'a [u8]) -> InfiniteByteIterator<'a> {
        InfiniteByteIterator {
            bytes: bytes,
            index: 0
        }
    }
}

impl<'a> Iterator for InfiniteByteIterator<'a> {
    type Item = u8;
    fn next(&mut self) -> Option<u8> {
        let byte = self.bytes[self.index];
        self.index = next_index(self.index, self.bytes.len());
        Some(byte)
    }
}

fn next_index(index: usize, count: usize) -> usize {
    if index + 1 < count { index + 1 } else { 0 }
}

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

    describe! xor {
        it "should return valid result" {
            let source = &[0, 1, 2, 3];
            let key = &[34, 52];
            assert!(xor(source, key) == [34, 53, 32, 55]);
        }

        it "should return valid result with one byte" {
            let source = &[0, 1, 2, 3];
            let key = &[47];
            assert!(xor(source, key) == [47, 46, 45, 44]);
        }

        it "should return source if key is empty" {
            let source = &[0, 1, 2, 3];
            let key = &[];
            assert!(xor(source, key) == source);
        }

        it "should return empty result if source is empty" {
            let source = &[];
            let key = &[45, 32, 56];
            assert!(xor(source, key) == []);
        }
    }

    describe! xor_with_byte {
        it "should return valid result" {
            let source = &[0, 1, 2, 3];
            assert!(xor_with_byte(source, 23) == [23, 22, 21, 20]);
        }
    }
}
<|endoftext|>


<commit_before>// (c) 2015 Joost Yervante Damad <joost@damad.be>

// loosely based on https://github.com/cgaebel/sexp

use std::fmt;
use std::str::FromStr;

use std::fs::File;
use std::io::prelude::*;

pub enum Atom {
  S(String),
  Q(String),
  I(i64),
  F(f64),
}

pub enum Sexp {
  Atom(Atom),
  Empty,
  List(Vec<Sexp>),
}

struct ParseState {
    pos: usize,
    line: usize,
    lpos: usize,
    vec: Vec<char>,
}

pub struct Error {
    msg: String,
    line: usize,
    lpos: usize,
}

type Err = Box<Error>;
type ERes<T> = Result<T, Err>;

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}:{}: {}", self.line, self.lpos, self.msg)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}:{}: {}", self.line, self.lpos, self.msg)
    }
}

impl fmt::Display for Atom {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
      Atom::S(ref s) => write!(f, "{}", s),
      Atom::Q(ref s) => write!(f, "\"{}\"", s),
      Atom::I(i)     => write!(f, "{}", i),
      Atom::F(d)     => write!(f, "{}", d),
    }
  }
}

impl fmt::Display for Sexp {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
      Sexp::Atom(ref a) => write!(f, "{}", a),
      Sexp::List(ref xs) => {
        try!(write!(f, "("));
        for (i, x) in xs.iter().enumerate() {
          let s = if i == 0 { "" } else { " " };
          try!(write!(f, "{}{}", s, x));
        }
        write!(f, ")")
      },
      Sexp::Empty => write!(f, ""),
    }
  }
}

fn parse_list(state: &mut ParseState) -> ERes<Sexp> {
    println!("list");
    state.pos += 1;
    state.lpos += 1;
    let mut l: Vec<Sexp> = Vec::new();
    loop {
        match state.vec[state.pos] {
            ')' => {
                state.pos += 1;
                state.lpos += 1;
                break;
            }
            _ => {
                l.push(try!(parse_sexp(state)));
            }
        }
    }
    println!("Found list");
    Ok(Sexp::List(l))
}

fn parse_quoted_string(state: &mut ParseState) -> ERes<Atom> {
    println!("qstring");
    state.pos += 1;
    state.lpos += 1;
    let mut s = String::new();
    loop {
        match state.vec[state.pos] {
            '"' => {
                state.pos += 1;
                state.lpos += 1;
                break
            }
            '\r' | '\n' => {
                s.push(state.vec[state.pos]);
                state.pos += 1;
                state.lpos = 0;
                state.line += 1;
                }
            x => {
                s.push(x);
                state.pos += 1;
                state.lpos += 1;
            }
        }
    }
    println!("Found quoted string {}", s);
    Ok(Atom::Q(s))
}

fn parse_string(state: &mut ParseState) -> ERes<Atom> {
    println!("string");
    let mut s = String::new();
    loop {
        match state.vec[state.pos] {
            ' ' | '\t' | '\r' | '\n' | ')' => break,
            '"' => panic!("quote in unquoted string {}", s),
            x => s.push(x)
        }
        state.pos += 1;
        state.lpos += 1;
    }
    println!("Found string {}", s);
    Ok(Atom::S(s))
}

fn parse_number(state: &mut ParseState) -> ERes<Atom> {
    println!("number");
    let mut s = String::new();
    loop {
        match state.vec[state.pos] {
            ' ' | '\r' | '\n' | '\t' | ')' => {
                break
            },
            '0' ... '9' | '.' | '-' => {
                s.push(state.vec[state.pos])
            },
            _ => {
                panic!("unexpected char in number")
            },
        }
        state.pos += 1;
        state.lpos += 1;
    }
    println!("Found number {}", s);
    let s2: &str = &s[..];
    if s.contains('.') {
        Ok(Atom::F(f64::from_str(s2).unwrap()))
    } else {
        Ok(Atom::I(i64::from_str(s2).unwrap()))
    }
}

fn parse_atom(state: &mut ParseState) -> ERes<Sexp> {
    println!("atom");
    let a = match state.vec[state.pos] {
        '"' => {
            try!(parse_quoted_string(state))
        }
        '0' ... '9' | '.' | '-' => {
            try!(parse_number(state))
        }
        _ => {
            try!(parse_string(state))
        }
    };
    Ok(Sexp::Atom(a))
}

fn parse_sexp(state: &mut ParseState) -> ERes<Sexp> {
    loop {
        match state.vec[state.pos] {
            '(' => {
                return parse_list(state)
            }
            '\n' => {
                state.pos += 1;
                state.lpos = 0;
                state.line += 1;
            }
            ' ' | '\t' => {
                state.pos += 1;
                state.lpos += 1;
            }
            ')' => {
                panic!("unmatched )")
            }
            _ => {
                return parse_atom(state)
            }
        }
    }
}

fn parse(data: &str) -> Sexp {
    if data.len() == 0 {
        Sexp::Empty
    } else {
        let vec: Vec<char> = data.chars().collect();
        let state = &mut ParseState { pos: 0, line: 1, lpos: 0, vec: vec };
        let res = parse_sexp(state).unwrap();
        res
    }
}

fn read_file(name: &str) -> Result<String,std::io::Error> {
    let mut f = try!(File::open(name));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_str(s: &str) -> Sexp {
    parse(s)
}

pub fn parse_file(name: &str) -> Sexp {
    let s = read_file(name).unwrap();
    parse(&s[..])
}

#[allow(dead_code)]
fn check_parse(s: &str) {
    let e = parse_str(s);
    let t = format!("{}", e);
    assert_eq!(s, t);
}

#[test]
fn test_empty() { check_parse("") }
#[test]
fn test_minimal() { check_parse("()") }
#[test]
fn test_invalid1() { check_parse("(") }
#[test]
fn test_invalid2() { check_parse(")") }
<commit_msg>more error handing and unit testing<commit_after>// (c) 2015 Joost Yervante Damad <joost@damad.be>

// loosely based on https://github.com/cgaebel/sexp

use std::fmt;
use std::str::FromStr;

use std::fs::File;
use std::io::prelude::*;

pub enum Atom {
  S(String),
  Q(String),
  I(i64),
  F(f64),
}

pub enum Sexp {
  Atom(Atom),
  Empty,
  List(Vec<Sexp>),
}

struct ParseState {
    pos: usize,
    line: usize,
    lpos: usize,
    vec: Vec<char>,
}

pub struct Error {
    msg: &'static str,
    line: usize,
    lpos: usize,
}

type Err = Box<Error>;
type ERes<T> = Result<T, Err>;

fn err<T>(msg: &'static str, state: &ParseState) -> ERes<T> {
    Err(Box::new(Error { msg: msg, line: state.line, lpos: state.lpos }))
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Parse Error {}:{}: {}", self.line, self.lpos, self.msg)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Parse Error {}:{}: {}", self.line, self.lpos, self.msg)
    }
}

impl fmt::Display for Atom {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
      Atom::S(ref s) => write!(f, "{}", s),
      Atom::Q(ref s) => write!(f, "\"{}\"", s),
      Atom::I(i)     => write!(f, "{}", i),
      Atom::F(d)     => write!(f, "{}", d),
    }
  }
}

impl fmt::Display for Sexp {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
      Sexp::Atom(ref a) => write!(f, "{}", a),
      Sexp::List(ref xs) => {
        try!(write!(f, "("));
        for (i, x) in xs.iter().enumerate() {
          let s = if i == 0 { "" } else { " " };
          try!(write!(f, "{}{}", s, x));
        }
        write!(f, ")")
      },
      Sexp::Empty => write!(f, ""),
    }
  }
}

fn parse_list(state: &mut ParseState) -> ERes<Sexp> {
    println!("list");
    state.pos += 1;
    state.lpos += 1;
    let mut l: Vec<Sexp> = Vec::new();
    loop {
        match state.vec[state.pos] {
            ')' => {
                state.pos += 1;
                state.lpos += 1;
                break;
            }
            _ => {
                l.push(try!(parse_sexp(state)));
            }
        }
    }
    println!("Found list");
    Ok(Sexp::List(l))
}

fn parse_quoted_string(state: &mut ParseState) -> ERes<Atom> {
    println!("qstring");
    state.pos += 1;
    state.lpos += 1;
    let mut s = String::new();
    loop {
        match state.vec[state.pos] {
            '"' => {
                state.pos += 1;
                state.lpos += 1;
                break
            }
            '\r' | '\n' => {
                s.push(state.vec[state.pos]);
                state.pos += 1;
                state.lpos = 0;
                state.line += 1;
                }
            x => {
                s.push(x);
                state.pos += 1;
                state.lpos += 1;
            }
        }
    }
    println!("Found quoted string {}", s);
    Ok(Atom::Q(s))
}

fn parse_string(state: &mut ParseState) -> ERes<Atom> {
    println!("string");
    let mut s = String::new();
    loop {
        match state.vec[state.pos] {
            ' ' | '\t' | '\r' | '\n' | ')' => break,
            '"' => return err("unexpected \" in string", state),
            x => s.push(x),
        }
        state.pos += 1;
        state.lpos += 1;
    }
    println!("Found string {}", s);
    Ok(Atom::S(s))
}

fn parse_number(state: &mut ParseState) -> ERes<Atom> {
    println!("number");
    let mut s = String::new();
    loop {
        match state.vec[state.pos] {
            ' ' | '\r' | '\n' | '\t' | ')' => {
                break
            },
            '0' ... '9' | '.' | '-' => {
                s.push(state.vec[state.pos])
            },
            _ => {
                return err("unexpected char in number", state)
            },
        }
        state.pos += 1;
        state.lpos += 1;
    }
    println!("Found number {}", s);
    let s2: &str = &s[..];
    if s.contains('.') {
        Ok(Atom::F(f64::from_str(s2).unwrap()))
    } else {
        Ok(Atom::I(i64::from_str(s2).unwrap()))
    }
}

fn parse_atom(state: &mut ParseState) -> ERes<Sexp> {
    println!("atom");
    let a = match state.vec[state.pos] {
        '"' => {
            try!(parse_quoted_string(state))
        }
        '0' ... '9' | '.' | '-' => {
            try!(parse_number(state))
        }
        _ => {
            try!(parse_string(state))
        }
    };
    Ok(Sexp::Atom(a))
}

fn parse_sexp(state: &mut ParseState) -> ERes<Sexp> {
    loop {
        match state.vec[state.pos] {
            '(' => {
                return parse_list(state)
            }
            '\n' => {
                state.pos += 1;
                state.lpos = 0;
                state.line += 1;
            }
            ' ' | '\t' => {
                state.pos += 1;
                state.lpos += 1;
            }
            ')' => {
                return err("unmatched )", state)
            }
            _ => {
                return parse_atom(state)
            }
        }
    }
}

fn parse(data: &str) -> ERes<Sexp> {
    if data.len() == 0 {
        Ok(Sexp::Empty)
    } else {
        let vec: Vec<char> = data.chars().collect();
        let state = &mut ParseState { pos: 0, line: 1, lpos: 0, vec: vec };
        parse_sexp(state)
    }
}

fn read_file(name: &str) -> Result<String,std::io::Error> {
    let mut f = try!(File::open(name));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_str(s: &str) -> Sexp {
    parse(s).unwrap()
}

pub fn parse_file(name: &str) -> Sexp {
    let s = read_file(name).unwrap();
    parse(&s[..]).unwrap()
}

#[allow(dead_code)]
fn check_parse(s: &str) {
    let e = parse_str(s);
    let t = format!("{}", e);
    assert_eq!(s, t);
}

#[test]
fn test_empty() { check_parse("") }

#[test]
fn test_minimal() { check_parse("()") }

#[test]
#[should_panic(expected="foo")]
fn test_invalid1() { parse_str("("); }

#[test]
#[should_panic(expected="Parse Error 1:0")]
fn test_invalid2() { parse_str(")"); }
<|endoftext|>


<commit_before>/*!

*/

/*!

## Declarative feature configuration

The primary motivation of this library is to create a mechanism
that helps to separate concerns of a project from tools.

For example, my project will need X, Y and Z features. Idealy,
I should be able to simply declare a list of them, and they should
discover each other themselves.

## Dependency injection as a method

First of all, while __dependency injection__ term is just a fancy name for
"passing arguments to constructor", it also communicates a specific
intent: __the user of these arguments does not care about
the way they were created__.

The simpliest form of dependency abstraction is use of trait objects
as construction arguments.

For example, there is an argument for something that implements "Logger"
trait. Our library depends on "logger", and it does not care how the
actual "logger" logs the messages.

## Aggregate construction

Sometimes some dependency might be optional. Or maybe there
are multiple valid dependencies for the same interface.

Let's suppose there can be multiple "logger" backends. It would be
great if we could depend on any amount of "loggers" and get them
collected into one list. This library can do that.

## Features can be libraries

When project feature list grows, different features must use the same
resources and respond to the same events. So, this needs some kind of
mechanism to __plug-in__ our feature into them. And then another feature.
And then yet another.

This becomes a problem when the addition or removal of a feature
requires developer to go all over the code and mechanically modify
countless if/match statements. It is a symptom that it is possible
to make a mechanism for plugging this and similar features in, and
move the feature itself to another library.

## Dependency validation

Currently this library validates dependencies at startup.
There is an error printer that can output all errors into the terminal.

## Example

Let's say there is a `Logger` object that can log to any backend that implements
`Backend` trait, and if `redis_logs` feature is enabled, it will log to
`RedisBackend`.

Also, the `RedisBackend` requires `Redis` as a direct dependency.

```rust
use di::registry::Registry;
# struct Redis;
# impl Redis { fn new() -> Redis { Redis } }
# struct RedisBackend { runner: Redis };
# impl RedisBackend {
#     fn new(runner: Redis) -> RedisBackend {
#         RedisBackend { runner: runner }
#     }
# }
# impl Backend for RedisBackend {}
# trait Backend {}
# struct Logger { backends: Vec<Box<Backend + 'static>> }
# impl Logger {
#     fn new(backends: Vec<Box<Backend + 'static>>) -> Logger {
#         Logger {
#             backends: backends
#         }
#     }
#     fn log(&self, _m: &str) {}
# }

fn enable_redis_logs(registry: &mut Registry) {
    registry
        .one_of("backends", |redis| {
            box RedisBackend::new(redis) as Box<Backend>
        })
        .add_arg("redis") // It will need "redis"
        .insert();

    registry
        .one("redis", || Redis::new())
        .insert();
}

fn enable_logger(registry: &mut Registry) {
    registry
        .one("logger", |backends| {
            Logger::new(backends)
        })
        .add_arg("backends")
        .insert();

    registry.may_be_empty::<Box<Backend>>("backends");
}

let mut registry = Registry::new();

// List of features in our application.
enable_redis_logs(&mut registry);
enable_logger(&mut registry);

// The compilation phase is going to validate the registry
// definitions when the application is started.
match registry.compile() {
    Ok(container) => {
        //let view_factory = container.get("logger").unwrap();
        //let view = view_factory.take();

        // Use view:
        //view.show();
    },
    Err(errors) => {
        di::error_printer::pretty_print(&errors);
        panic!("expected no errors");
    }
}
```

Obviously, the above is equivalent to this simple code:

```rust
# struct Redis;
# impl Redis { fn new() -> Redis { Redis } }
# struct RedisBackend { runner: Redis };
# impl RedisBackend {
#     fn new(runner: Redis) -> RedisBackend {
#         RedisBackend { runner: runner }
#     }
# }
# impl Backend for RedisBackend {}
# trait Backend {}
# struct Logger { backends: Vec<Box<Backend + 'static>> }
# impl Logger {
#     fn new(backends: Vec<Box<Backend + 'static>>) -> Logger {
#         Logger {
#             backends: backends
#         }
#     }
#     fn log(&self, _m: &str) {}
# }

fn get_logger_factory() -> Logger {
    // Regis logs feature
    let redis = Redis::new();
    let redis_backend = box RedisBackend::new(redis) as Box<Backend>;

    // Logger feature
    let logger = Logger::new(vec![redis_backend]);

    logger
}

// Use logger:
let logger = get_logger_factory();
logger.log("hello");
```

In fact, `registry.compile` constructs internal execution structure
that is very similar to `get_logger_factory`, but it is done at
runtime.

If the "redis logs" is not enabled, the `enable_logger` code does not
need re-compilation, and constructed `get_logger_factory` won't
have any code related to redis:

```ignore
fn get_logger_factory() -> Logger {
    // Logger feature
    let logger = Logger::new(Vec::new());

    logger
}
```

## The roles of `Registry` and `Container`

`Registry` is mutable, `Container` is immutable.
`Registry` is changed on initialization, then it validates all definitions and
"compiles" the `Container`, which is used at runtime.
Further changes to `Registry` can be used to produce a new, different
`Container`.

HashMap and Any are used only on `Registry` configuration phase.
If there are any mistakes, the validator should produce error messages
that pinpoint problems accurately.

The compiled container contains initialization trees constructed from
registry definitions. If the `Container` construction succeeds, factories
returned by container should never fail. If they do, it is a bug.

## The true cost of a factory

`Container` will return copies of constructed factories,
which are nothing more than object-initialization trees that can be invoked.

While it was certainly possible to eliminate a lot of indirection in this
tree using unsafe hacks, this library currently uses __no__ unsafe code.

This is a approximate example of calls the
`Logger` construction with `redis_logs` enabled would make:

 - `Factory<Logger>.take()` - wraps `Logger` getter mechanism in struct
 - `Closure_ManyArg_1<Vec<Box<Backend>>, Logger>.take()` - closure dependency scope
     - `AggregateGetter<Vec<Box<Backend>>>.take()` - aggregates ("one_of") dependencies
        - `Factory<Box<Backend>>.take()` - wraps getter mechanism in struct
        - `Closure_ManyArg_1<Redis, Box<Backend>>.take()` - closure dependency scope
            - `Factory<Redis>.take()`
            - `Closure_ZeroArg<Redis>.take()` - call Redis construction closure
            - `Rc<RefCell<|| -> Redis>>.call()`
        - `Rc<RefCell<|Redis| -> Box<Backend>>>.call()` - call `RedisBackend` construction closure
 - `Rc<RefCell<|Vec<Box<Redis>>| -> Logger>>.call()` - call `Logger` construction closure

The constly point here is probably a `Rc<RefCell>` and allocation of
`Vec<Box<Backends>>`, though this is just a guess at this point.
But it shouldn't be a problem, especially when compared to `registry.compile`.
*/

#![feature(slicing_syntax)]
#![feature(default_type_params)]

extern crate term;
extern crate typedef;
extern crate metafactory;

pub mod registry;
pub mod error_printer;
pub mod container;
<commit_msg>Add more doc and some history.<commit_after>/*!

*/

/*!

# Dependency Injection container for Rust

This page contains an abstract (although with few examples) overview
of this dependency injection container. To see more fine-grained
usage examples without much prose, browse the [Registry](registry/index.html)
documentation.

# Overview

## Declarative feature configuration

The primary motivation of this library is to create a mechanism
that helps to separate concept of a "feature" from libraries used.

For example, if a project needs X, Y and Z features, it should be
possible to declare a list of these features, and the features should
discover each other and configure themselves.

## Dependency injection (DI) as a method

First of all, while __dependency injection__ term is just a fancy name for
"passing arguments to constructor", it also communicates a specific
intent: __the user of these arguments does not care about
the way they were created__.

The simpliest form of dependency abstraction is use of trait objects
as construction arguments.

As an example, a `Logger` trait can be passed as an argument to something
that needs a `Logger`. Our library would depend on the abstraction,
and it would not need to care how this actual `Logger` logs the messages.

Without using this "di" library:

```rust
trait Logger { fn log(&self, m: &str); }

struct ConsoleLogger;
impl Logger for ConsoleLogger {
    fn log(&self, m: &str) {
        println!("{}", m);
    }
}

struct OurLibrary;
impl OurLibrary {
    fn new(logger: Box<Logger>) -> OurLibrary {
        logger.log("Library created!");
        OurLibrary
    }
}

OurLibrary::new(box ConsoleLogger); // will print "Library created!"
```

Pluging it into "di" looks like this:

```rust
# trait Logger { fn log(&self, m: &str); }
# struct ConsoleLogger;
# impl Logger for ConsoleLogger {
#     fn log(&self, m: &str) {
#         println!("{}", m);
#     }
# }
# struct OurLibrary;
# impl OurLibrary {
#     fn new(logger: Box<Logger>) -> OurLibrary {
#         logger.log("Library created!");
#         OurLibrary
#     }
# }
let mut registry = di::Registry::new();

registry.insert_one("logger", || box ConsoleLogger as Box<Logger>);

registry
    .one("our_library", |logger: Box<Logger + 'static>| {
        logger.log("Hello world!");
        OurLibrary
    })
    .with_arg("logger")
    .insert();

// The compilation phase is going to validate the registry
// definitions when the application is started.
match registry.compile() {
    Ok(container) => {
        container.get::<OurLibrary>("our_library").unwrap()
            .take(); // will print "Library created!"
    },
    Err(errors) => di::error_printer::pretty_print(&errors),
}
```

## Aggregate construction

Sometimes some dependency might be optional. Or maybe there
are multiple valid dependencies for the same interface.

Let's say there can be multiple `Backend` implementations for `Logger`.
It would be great if our `Logger` could depend on any amount of `Backend`
abstractions (without actually depending on implementations)
and get them collected into one list which could be injected as
an argument. This library can do that.

In this example, the concrete implementation would be `RedisBackend`, which
would also require some kind of `Redis` as another dependency.

```rust
use di::Registry;
# struct Redis;
# impl Redis { fn new() -> Redis { Redis } }
# struct RedisBackend { runner: Redis };
# impl RedisBackend {
#     fn new(runner: Redis) -> RedisBackend {
#         RedisBackend { runner: runner }
#     }
# }
# impl Backend for RedisBackend {}
# trait Backend {}
# struct Logger { backends: Vec<Box<Backend + 'static>> }
# impl Logger {
#     fn new(backends: Vec<Box<Backend + 'static>>) -> Logger {
#         Logger {
#             backends: backends
#         }
#     }
#     fn log(&self, _m: &str) {}
# }

fn enable_redis_logs(registry: &mut Registry) {
    registry
        .one_of("backends", |redis| {
            box RedisBackend::new(redis) as Box<Backend>
        })
        .add_arg("redis") // It will need "redis"
        .insert();

    registry
        .one("redis", || Redis::new())
        .insert();
}

fn enable_logger(registry: &mut Registry) {
    registry
        .one("logger", |backends| {
            Logger::new(backends)
        })
        .add_arg("backends")
        .insert();

    registry.may_be_empty::<Box<Backend>>("backends");
}

let mut registry = Registry::new();

// List of features in our application.
enable_redis_logs(&mut registry);
enable_logger(&mut registry);

match registry.compile() {
    Ok(container) => {
        // Get a factory that constructs the logger object.
        let logger_factory = container.get::<Logger>("logger").unwrap();
        // Actually invoke construction.
        let logger = logger_factory.take();

        logger.log("Loaded!");
    },
    Err(errors) => {
        di::error_printer::pretty_print(&errors);
        panic!("expected no errors");
    }
}
```

Obviously, the above is equivalent to this simple code:

```rust
# struct Redis;
# impl Redis { fn new() -> Redis { Redis } }
# struct RedisBackend { runner: Redis };
# impl RedisBackend {
#     fn new(runner: Redis) -> RedisBackend {
#         RedisBackend { runner: runner }
#     }
# }
# impl Backend for RedisBackend {}
# trait Backend {}
# struct Logger { backends: Vec<Box<Backend + 'static>> }
# impl Logger {
#     fn new(backends: Vec<Box<Backend + 'static>>) -> Logger {
#         Logger {
#             backends: backends
#         }
#     }
#     fn log(&self, _m: &str) {}
# }
fn get_logger_factory() -> Logger {
    // Regis logs feature
    let redis = Redis::new();
    let redis_backend = box RedisBackend::new(redis) as Box<Backend>;

    // Logger feature
    let logger = Logger::new(vec![redis_backend]);

    logger
}

// Use logger:
let logger = get_logger_factory();
logger.log("hello");
```

In fact, `registry.compile` constructs internal execution structure
that is very similar to `get_logger_factory`, but it is done at
runtime.

If the "redis logs" is not enabled, the `enable_logger` code does not
need re-compilation, and constructed `get_logger_factory` won't
have any code related to redis:

```ignore
fn get_logger_factory() -> Logger {
    // Logger feature
    let logger = Logger::new(Vec::new());

    logger
}
```

## The roles of `Registry` and `Container`

`Registry` is mutable, `Container` is immutable.
`Registry` is changed on initialization, then it validates all definitions and
"compiles" the `Container`, which is used at runtime.
Further changes to `Registry` can be used to produce a new, different
`Container`.

HashMap and Any are used only on `Registry` configuration phase.
If there are any mistakes, the validator should produce error messages
that pinpoint problems accurately.

The compiled container contains initialization trees constructed from
registry definitions. If the `Container` construction succeeds, factories
returned by container should never fail. If they do, it is a bug.

# Discussion

## Why did this library happen

I wanted to implement DI mechanism for Rust because I had great success
with it before. The idea of "container" and "registering" definitions to
it [comes from Symfony2][symfony2-container-component] framework.

However, I intentionaly chose to avoid implementing things the same way
Symfony2 does.

For example, the factories do not return singletons. This `di` library
will always return a new value. If you really, really need them singletons,
well, you will find out how to work around that. What? You need MUTABLE
SINGLETONS? Go away.

The initialization mechanism requires a closure. If you do not like
that, well, it is possible to implement `metafactory::ToMetafactory` trait
for anything you would like to use as definition.

There is no lazy loading. Frankly, this is not PHP.

There is one other pattern that is a bit burried in Symfony2 di: it is the
ability to "tag" services and then have the container inject all of them
based on that "tag". [Using that is not straightforward][symfony2-tagged-services].
However, I found that it was the key of decoupling features properly, so I chose
to make them __very__ easy to use equivalent functionality in this library.
That's where `one_of` method came from.

[symfony2-container-component]: http://symfony.com/doc/current/components/dependency_injection/introduction.html
[symfony2-tagged-services]: http://symfony.com/doc/current/components/dependency_injection/tags.html

## Features can be libraries

When project feature list grows, different features must use the same
resources and respond to the same events. So, there needs to be some kind of
mechanism to __plug-in__ our feature into them. And then another feature.
And then yet another.

This becomes a problem when the addition or removal of a feature
requires developer to go all over the code and mechanically modify
countless if/match statements. It is a symptom that it is possible
to make a mechanism for plugging this and similar features in, and
move the feature itself to another library.

Note that no special DI tool is needed to acomplish that: but it might be
necessary if you need to put your development on highly configurable "rails"
of same implementation mechanism. What I mean, learn it once, use
everywhere.

## The true cost of a factory

`Container` will return copies of constructed factories,
which are nothing more than object-initialization trees that can be invoked.

While it was certainly possible to eliminate a lot of indirection in this
tree using unsafe hacks, this library currently uses __no__ unsafe code.

This is a approximate example of calls the
`Logger` construction with `redis_logs` enabled would make:

 - `Factory<Logger>.take()` - wraps `Logger` getter mechanism in struct
 - `Closure_ManyArg_1<Vec<Box<Backend>>, Logger>.take()` - closure dependency scope
     - `AggregateGetter<Vec<Box<Backend>>>.take()` - aggregates ("one_of") dependencies
        - `Factory<Box<Backend>>.take()` - wraps getter mechanism in struct
        - `Closure_ManyArg_1<Redis, Box<Backend>>.take()` - closure dependency scope
            - `Factory<Redis>.take()`
            - `Closure_ZeroArg<Redis>.take()` - call Redis construction closure
            - `Rc<RefCell<|| -> Redis>>.call()`
        - `Rc<RefCell<|Redis| -> Box<Backend>>>.call()` - call `RedisBackend` construction closure
 - `Rc<RefCell<|Vec<Box<Redis>>| -> Logger>>.call()` - call `Logger` construction closure

The constly point here is probably a `Rc<RefCell>` and allocation of
`Vec<Box<Backends>>`, though this is just a guess at this point.

## Further ideas

Currently registry definitions are initialized from clonable values or closures.
It is possible to extend it with unboxed closures and channels by implementing
`ToMetafactory` trait for them in `metafactory` library.

It might be possible to compile the `Container` at actual compilation instead of
runtime. That would probably require a compiler plugin.
*/

#![feature(slicing_syntax)]
#![feature(default_type_params)]

extern crate term;
extern crate typedef;
extern crate metafactory;

pub use registry::Registry;
pub use container::Container;

pub mod registry;
pub mod error_printer;
pub mod container;
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! The official Piston window back-end for the Piston game engine

extern crate piston;
extern crate gfx;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate graphics;

use std::cell::RefCell;
use std::rc::Rc;
use std::any::Any;

use piston::{ event, window };
use gfx::traits::*;
use gfx_graphics::{ Gfx2d, GfxGraphics };
use graphics::Context;

/// Contains everything required for controlling window, graphics, event loop.
pub struct PistonWindow<W: window::Window, T = ()> {
    /// The window.
    pub window: Rc<RefCell<W>>,
    /// The gfx Canvas
    pub canvas: Rc<RefCell<gfx::Canvas<gfx_device_gl::Output, gfx_device_gl::Device, gfx_device_gl::Factory>>>,
    /// Gfx2d
    pub g2d: Rc<RefCell<Gfx2d<gfx_device_gl::Resources>>>,
    /// The event loop.
    pub events: Rc<RefCell<event::events::Events<W, event::Event<W::Event>>>>,
    /// The event.
    pub event: Option<event::Event<W::Event>>,
    /// Application structure.
    pub app: Rc<RefCell<T>>,
}

impl<W, T> Clone for PistonWindow<W, T>
    where W: window::Window, W::Event: Clone
{
    fn clone(&self) -> Self {
        PistonWindow {
            window: self.window.clone(),
            canvas: self.canvas.clone(),
            g2d: self.g2d.clone(),
            events: self.events.clone(),
            event: self.event.clone(),
            app: self.app.clone(),
        }
    }
}

impl<W, T> PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    /// Creates a new piston object.
    pub fn new(window: Rc<RefCell<W>>, app: Rc<RefCell<T>>) -> Self
        where W: window::OpenGLWindow
    {
        use piston::event::Events;
        use piston::window::{ OpenGLWindow, Window };

        let (mut device, mut factory) = gfx_device_gl::create(|s| window.borrow_mut().get_proc_address(s));

        let size = window.borrow().size();
        let output = factory.make_fake_output(size.width as u16, size.height as u16);

        let g2d = Gfx2d::new(&mut device, &mut factory);

        let canvas = (output, device, factory).into_canvas();

        PistonWindow {
            window: window.clone(),
            canvas: Rc::new(RefCell::new(canvas)),
            g2d: Rc::new(RefCell::new(g2d)),
            events: Rc::new(RefCell::new(window.events())),
            event: None,
            app: app,
        }
    }

    /// Changes application structure.
    pub fn app<U>(self, app: Rc<RefCell<U>>) -> PistonWindow<W, U> {
        PistonWindow {
            window: self.window,
            canvas: self.canvas,
            g2d: self.g2d,
            events: self.events,
            event: self.event,
            app: app,
        }
    }

    /// Renders 2D graphics.
    pub fn draw_2d<F>(&self, f: F)
        where F: FnMut(Context, &mut GfxGraphics<
            gfx_device_gl::Resources, gfx_device_gl::CommandBuffer,
            gfx_device_gl::Output>)
    {
        use piston::event::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(args) = e.render_args() {

                let &mut gfx::Canvas {
                    ref mut device,
                    ref mut renderer,
                    ref mut output,
                    ..
                } = &mut *self.canvas.borrow_mut();

                self.g2d.borrow_mut().draw(renderer, output, args.viewport(), f);
                device.submit(renderer.as_buffer());
                renderer.reset();
            }
        }
    }

    /// Renders 3D graphics.
    pub fn draw_3d<F>(&self, mut f: F)
        where F: FnMut(&mut gfx::Canvas<gfx_device_gl::Output, gfx_device_gl::Device, gfx_device_gl::Factory>)
    {
        use piston::event::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(_) = e.render_args() {
                f(&mut *self.canvas.borrow_mut())
            }
        }
    }
}

impl<W, T> Iterator for PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    type Item = PistonWindow<W, T>;

    fn next(&mut self) -> Option<PistonWindow<W, T>> {
        use piston::event::*;

        if let Some(e) = self.events.borrow_mut().next() {
            if let Some(_) = e.after_render_args() {
                // After swapping buffers.

                let &mut gfx::Canvas {
                    ref mut device,
                    ref mut factory,
                    ..
                } = &mut *self.canvas.borrow_mut();

                device.after_frame();
                factory.cleanup();

            }

            if let Some(size) = e.resize_args() {

                let &mut gfx::Canvas {
                    ref mut output,
                    ref mut factory,
                    ..
                } = &mut *self.canvas.borrow_mut();

                *output = factory.make_fake_output(size[0] as u16, size[1] as u16);
            }

            Some(PistonWindow {
                window: self.window.clone(),
                canvas: self.canvas.clone(),
                g2d: self.g2d.clone(),
                events: self.events.clone(),
                event: Some(e),
                app: self.app.clone(),
            })
        } else { None }
    }
}

impl<W, T> event::GenericEvent for PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    fn event_id(&self) -> event::EventId {
        match self.event {
            Some(ref e) => e.event_id(),
            None => event::EventId("")
        }
    }

    fn with_args<'a, F, U>(&'a self, f: F) -> U
       where F: FnMut(&Any) -> U
    {
        self.event.as_ref().unwrap().with_args(f)
    }

    fn from_args(event_id: event::EventId, any: &Any, old_event: &Self) -> Option<Self> {
        if let Some(ref e) = old_event.event {
            match event::GenericEvent::from_args(event_id, any, e) {
                Some(e) => {
                    Some(PistonWindow {
                        window: old_event.window.clone(),
                        canvas: old_event.canvas.clone(),
                        g2d: old_event.g2d.clone(),
                        events: old_event.events.clone(),
                        event: Some(e),
                        app: old_event.app.clone(),
                    })
                }
                None => None
            }
        } else { None }
    }
}

impl<W, T> window::Window for PistonWindow<W, T>
    where W: window::Window
{
    type Event = <W as window::Window>::Event;

    fn should_close(&self) -> bool { self.window.borrow().should_close() }
    fn size(&self) -> window::Size { self.window.borrow().size() }
    fn draw_size(&self) -> window::Size { self.window.borrow().draw_size() }
    fn swap_buffers(&mut self) { self.window.borrow_mut().swap_buffers() }
    fn poll_event(&mut self) -> Option<Self::Event> {
        window::Window::poll_event(&mut *self.window.borrow_mut())
    }
}

impl<W, T> window::AdvancedWindow for PistonWindow<W, T>
    where W: window::AdvancedWindow
{
    fn get_title(&self) -> String { self.window.borrow().get_title() }
    fn set_title(&mut self, title: String) {
        self.window.borrow_mut().set_title(title)
    }
    fn get_exit_on_esc(&self) -> bool { self.window.borrow().get_exit_on_esc() }
    fn set_exit_on_esc(&mut self, value: bool) {
        self.window.borrow_mut().set_exit_on_esc(value)
    }
    fn set_capture_cursor(&mut self, value: bool) {
        self.window.borrow_mut().set_capture_cursor(value)
    }
}

/// Creates a new empty application.
pub fn empty_app() -> Rc<RefCell<()>> { Rc::new(RefCell::new(())) }
<commit_msg>draw_3d submits render buffer and resets renderer<commit_after>#![deny(missing_docs)]

//! The official Piston window back-end for the Piston game engine

extern crate piston;
extern crate gfx;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate graphics;

use std::cell::RefCell;
use std::rc::Rc;
use std::any::Any;

use piston::{ event, window };
use gfx::traits::*;
use gfx_graphics::{ Gfx2d, GfxGraphics };
use graphics::Context;

/// Contains everything required for controlling window, graphics, event loop.
pub struct PistonWindow<W: window::Window, T = ()> {
    /// The window.
    pub window: Rc<RefCell<W>>,
    /// The gfx Canvas
    pub canvas: Rc<RefCell<gfx::Canvas<gfx_device_gl::Output, gfx_device_gl::Device, gfx_device_gl::Factory>>>,
    /// Gfx2d
    pub g2d: Rc<RefCell<Gfx2d<gfx_device_gl::Resources>>>,
    /// The event loop.
    pub events: Rc<RefCell<event::events::Events<W, event::Event<W::Event>>>>,
    /// The event.
    pub event: Option<event::Event<W::Event>>,
    /// Application structure.
    pub app: Rc<RefCell<T>>,
}

impl<W, T> Clone for PistonWindow<W, T>
    where W: window::Window, W::Event: Clone
{
    fn clone(&self) -> Self {
        PistonWindow {
            window: self.window.clone(),
            canvas: self.canvas.clone(),
            g2d: self.g2d.clone(),
            events: self.events.clone(),
            event: self.event.clone(),
            app: self.app.clone(),
        }
    }
}

impl<W, T> PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    /// Creates a new piston object.
    pub fn new(window: Rc<RefCell<W>>, app: Rc<RefCell<T>>) -> Self
        where W: window::OpenGLWindow
    {
        use piston::event::Events;
        use piston::window::{ OpenGLWindow, Window };

        let (mut device, mut factory) = gfx_device_gl::create(|s| window.borrow_mut().get_proc_address(s));

        let size = window.borrow().size();
        let output = factory.make_fake_output(size.width as u16, size.height as u16);

        let g2d = Gfx2d::new(&mut device, &mut factory);

        let canvas = (output, device, factory).into_canvas();

        PistonWindow {
            window: window.clone(),
            canvas: Rc::new(RefCell::new(canvas)),
            g2d: Rc::new(RefCell::new(g2d)),
            events: Rc::new(RefCell::new(window.events())),
            event: None,
            app: app,
        }
    }

    /// Changes application structure.
    pub fn app<U>(self, app: Rc<RefCell<U>>) -> PistonWindow<W, U> {
        PistonWindow {
            window: self.window,
            canvas: self.canvas,
            g2d: self.g2d,
            events: self.events,
            event: self.event,
            app: app,
        }
    }

    /// Renders 2D graphics.
    pub fn draw_2d<F>(&self, f: F)
        where F: FnMut(Context, &mut GfxGraphics<
            gfx_device_gl::Resources, gfx_device_gl::CommandBuffer,
            gfx_device_gl::Output>)
    {
        use piston::event::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(args) = e.render_args() {

                let &mut gfx::Canvas {
                    ref mut device,
                    ref mut renderer,
                    ref mut output,
                    ..
                } = &mut *self.canvas.borrow_mut();

                self.g2d.borrow_mut().draw(renderer, output, args.viewport(), f);
                device.submit(renderer.as_buffer());
                renderer.reset();
            }
        }
    }

    /// Renders 3D graphics.
    pub fn draw_3d<F>(&self, mut f: F)
        where F: FnMut(&mut gfx::Canvas<gfx_device_gl::Output, gfx_device_gl::Device, gfx_device_gl::Factory>)
    {
        use piston::event::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(_) = e.render_args() {
                f(&mut *self.canvas.borrow_mut());
                let &mut gfx::Canvas {
                    ref mut device,
                    ref mut renderer,
                    ..
                } = &mut *self.canvas.borrow_mut();
                device.submit(renderer.as_buffer());
                renderer.reset();
            }
        }
    }
}

impl<W, T> Iterator for PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    type Item = PistonWindow<W, T>;

    fn next(&mut self) -> Option<PistonWindow<W, T>> {
        use piston::event::*;

        if let Some(e) = self.events.borrow_mut().next() {
            if let Some(_) = e.after_render_args() {
                // After swapping buffers.

                let &mut gfx::Canvas {
                    ref mut device,
                    ref mut factory,
                    ..
                } = &mut *self.canvas.borrow_mut();

                device.after_frame();
                factory.cleanup();

            }

            if let Some(size) = e.resize_args() {

                let &mut gfx::Canvas {
                    ref mut output,
                    ref mut factory,
                    ..
                } = &mut *self.canvas.borrow_mut();

                *output = factory.make_fake_output(size[0] as u16, size[1] as u16);
            }

            Some(PistonWindow {
                window: self.window.clone(),
                canvas: self.canvas.clone(),
                g2d: self.g2d.clone(),
                events: self.events.clone(),
                event: Some(e),
                app: self.app.clone(),
            })
        } else { None }
    }
}

impl<W, T> event::GenericEvent for PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    fn event_id(&self) -> event::EventId {
        match self.event {
            Some(ref e) => e.event_id(),
            None => event::EventId("")
        }
    }

    fn with_args<'a, F, U>(&'a self, f: F) -> U
       where F: FnMut(&Any) -> U
    {
        self.event.as_ref().unwrap().with_args(f)
    }

    fn from_args(event_id: event::EventId, any: &Any, old_event: &Self) -> Option<Self> {
        if let Some(ref e) = old_event.event {
            match event::GenericEvent::from_args(event_id, any, e) {
                Some(e) => {
                    Some(PistonWindow {
                        window: old_event.window.clone(),
                        canvas: old_event.canvas.clone(),
                        g2d: old_event.g2d.clone(),
                        events: old_event.events.clone(),
                        event: Some(e),
                        app: old_event.app.clone(),
                    })
                }
                None => None
            }
        } else { None }
    }
}

impl<W, T> window::Window for PistonWindow<W, T>
    where W: window::Window
{
    type Event = <W as window::Window>::Event;

    fn should_close(&self) -> bool { self.window.borrow().should_close() }
    fn size(&self) -> window::Size { self.window.borrow().size() }
    fn draw_size(&self) -> window::Size { self.window.borrow().draw_size() }
    fn swap_buffers(&mut self) { self.window.borrow_mut().swap_buffers() }
    fn poll_event(&mut self) -> Option<Self::Event> {
        window::Window::poll_event(&mut *self.window.borrow_mut())
    }
}

impl<W, T> window::AdvancedWindow for PistonWindow<W, T>
    where W: window::AdvancedWindow
{
    fn get_title(&self) -> String { self.window.borrow().get_title() }
    fn set_title(&mut self, title: String) {
        self.window.borrow_mut().set_title(title)
    }
    fn get_exit_on_esc(&self) -> bool { self.window.borrow().get_exit_on_esc() }
    fn set_exit_on_esc(&mut self, value: bool) {
        self.window.borrow_mut().set_exit_on_esc(value)
    }
    fn set_capture_cursor(&mut self, value: bool) {
        self.window.borrow_mut().set_capture_cursor(value)
    }
}

/// Creates a new empty application.
pub fn empty_app() -> Rc<RefCell<()>> { Rc::new(RefCell::new(())) }
<|endoftext|>