<commit_before>
// Copyright 2017 The gltf Library Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(missing_docs)]

//! glTF 2.0 loader
//!
//! This crate is intended to load [glTF 2.0], a file format designed for the
//! efficient runtime transmission of 3D scenes. The crate aims to provide
//! rustic utilities that make working with glTF simple and intuitive.
//!
//! [glTF 2.0]: https://www.khronos.org/gltf
//!
//! ## Installation
//!
//! Add `gltf` version 0.6 to your `Cargo.toml`.
//!
//! ```toml
//! [dependencies.gltf]
//! version = "0.6"
//! ```
//!
//! ## Examples
//!
//! ### Loading glTF from the file system
//!
//! The crate provides a `from_path` method whereby one can import glTF from the
//! system.
//!
//! ```
//! extern crate gltf;
//!
//! fn main() {
//!     # #[allow(unused_variables)]
//!     let path = "path/to/asset.gltf";
//!     # let path = "./glTF-Sample-Models/2.0/Box/glTF/Box.gltf";
//!     // This creates a `Future` that drives the loading
//!     // of glTF and all of its data.
//!     let import = gltf::Import::from_path(path);
//!     // The simpliest way of working with futures is to
//!     // block the thread until the glTF is ready.
//!     match import.sync() {
//!         Ok(gltf) => println!("{:#?}", gltf),
//!         Err(err) => println!("error: {:?}", err),
//!     }
//! }
//! ```
//!
//! An [`Import`] resolves to [`Gltf`], a data structure that provides helpful utilities
//! such as iterators for working with glTF.
//!
//! [`Import`]: import/struct.Import.html
//! [`Gltf`]: gltf/struct.Gltf.html
//!
//! ### Walking the node hierarchy
//!
//! Below demonstates visiting the root [`Node`]s of every [`Scene`], printing the
//! number of children each node has.
//!
//! [`Node`]: scene/struct.Node.html
//! [`Scene`]: scene/struct.Scene.html
//! ```
//! # fn run() -> Result<(), Box<std::error::Error>> {
//! # let path = "./glTF-Sample-Models/2.0/Box/glTF/Box.gltf";
//! let gltf = gltf::Import::from_path(path).sync()?;
//! for scene in gltf.scenes() {
//!     for node in scene.nodes() {
//!         // Do something with this node
//!         println!(
//!             "Node {} has {} children",
//!             node.index(),
//!             node.children().count(),
//!         );
//!     }
//! }
//! # Ok(())
//! # }
//! # fn main() {
//! #    let _ = run().expect("No runtime errors");
//! # }
//! ```

extern crate base64;
extern crate futures;
extern crate image as image_crate;
#[macro_use]
extern crate lazy_static;

/// Contains (de)serializable data structures that match the glTF JSON text.
pub extern crate gltf_json as json;

/// Contains `Accessor` and other related data structures.
pub mod accessor;

/// Contains `Animation` and other related data structures.
pub mod animation;

/// Contains `Buffer`, `View`, and other related data structures.
pub mod buffer;

/// Contains `Camera` and other related data structures.
pub mod camera;

/// Contains extension specific data structures.
pub mod extensions;

/// Contains `Gltf`, and other related data structures.
pub mod gltf;

/// Contains `Image` and other related data structures.
pub mod image;

/// Contains functions for importing glTF 2.0 assets.
pub mod import;

/// Contains `Material` and other related data structures.
pub mod material;

/// Contains `Mesh` and other related data structures.
pub mod mesh;

/// Contains `Root`.
pub mod root;

/// Contains `Scene`, `Node`, and other related data structures.
pub mod scene;

/// Contains `Skin` and other related data structures.
pub mod skin;

/// Contains `Texture`, `Sampler`, and other related data structures.
pub mod texture;

pub use self::gltf::Gltf;
pub use self::import::{Data, DynamicImage, Import};
<commit_msg>Add Loaded and Source<commit_after>
// Copyright 2017 The gltf Library Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(missing_docs)]

//! glTF 2.0 loader
//!
//! This crate is intended to load [glTF 2.0], a file format designed for the
//! efficient runtime transmission of 3D scenes. The crate aims to provide
//! rustic utilities that make working with glTF simple and intuitive.
//!
//! [glTF 2.0]: https://www.khronos.org/gltf
//!
//! ## Installation
//!
//! Add `gltf` version 0.6 to your `Cargo.toml`.
//!
//! ```toml
//! [dependencies.gltf]
//! version = "0.6"
//! ```
//!
//! ## Examples
//!
//! ### Loading glTF from the file system
//!
//! The crate provides a `from_path` method whereby one can import glTF from the
//! system.
//!
//! ```
//! extern crate gltf;
//!
//! fn main() {
//!     # #[allow(unused_variables)]
//!     let path = "path/to/asset.gltf";
//!     # let path = "./glTF-Sample-Models/2.0/Box/glTF/Box.gltf";
//!     // This creates a `Future` that drives the loading
//!     // of glTF and all of its data.
//!     let import = gltf::Import::from_path(path);
//!     // The simpliest way of working with futures is to
//!     // block the thread until the glTF is ready.
//!     match import.sync() {
//!         Ok(gltf) => println!("{:#?}", gltf),
//!         Err(err) => println!("error: {:?}", err),
//!     }
//! }
//! ```
//!
//! An [`Import`] resolves to [`Gltf`], a data structure that provides helpful utilities
//! such as iterators for working with glTF.
//!
//! [`Import`]: import/struct.Import.html
//! [`Gltf`]: gltf/struct.Gltf.html
//!
//! ### Walking the node hierarchy
//!
//! Below demonstates visiting the root [`Node`]s of every [`Scene`], printing the
//! number of children each node has.
//!
//! [`Node`]: scene/struct.Node.html
//! [`Scene`]: scene/struct.Scene.html
//! ```
//! # fn run() -> Result<(), Box<std::error::Error>> {
//! # let path = "./glTF-Sample-Models/2.0/Box/glTF/Box.gltf";
//! let gltf = gltf::Import::from_path(path).sync()?;
//! for scene in gltf.scenes() {
//!     for node in scene.nodes() {
//!         // Do something with this node
//!         println!(
//!             "Node {} has {} children",
//!             node.index(),
//!             node.children().count(),
//!         );
//!     }
//! }
//! # Ok(())
//! # }
//! # fn main() {
//! #    let _ = run().expect("No runtime errors");
//! # }
//! ```

extern crate base64;
extern crate futures;
extern crate image as image_crate;
#[macro_use]
extern crate lazy_static;

/// Contains (de)serializable data structures that match the glTF JSON text.
pub extern crate gltf_json as json;

/// Contains `Accessor` and other related data structures.
pub mod accessor;

/// Contains `Animation` and other related data structures.
pub mod animation;

/// Contains `Buffer`, `View`, and other related data structures.
pub mod buffer;

/// Contains `Camera` and other related data structures.
pub mod camera;

/// Contains extension specific data structures.
pub mod extensions;

/// Contains `Gltf`, and other related data structures.
pub mod gltf;

/// Contains `Image` and other related data structures.
pub mod image;

/// Contains functions for importing glTF 2.0 assets.
pub mod import;

/// Contains `Material` and other related data structures.
pub mod material;

/// Contains `Mesh` and other related data structures.
pub mod mesh;

/// Contains `Root`.
pub mod root;

/// Contains `Scene`, `Node`, and other related data structures.
pub mod scene;

/// Contains `Skin` and other related data structures.
pub mod skin;

/// Contains `Texture`, `Sampler`, and other related data structures.
pub mod texture;

pub use self::animation::Animation;
pub use self::accessor::Accessor;
pub use self::buffer::Buffer;
pub use self::camera::Camera;
pub use self::gltf::Gltf;
pub use self::image::Image;
pub use self::import::{Data, DynamicImage, Import};
pub use self::material::Material;
pub use self::mesh::{Mesh, Primitive};
pub use self::scene::{Node, Scene};
pub use self::skin::Skin;
pub use self::texture::Texture;

/// Represents sources of buffer data.
pub trait Source {
    /// Return the buffer data referenced by the given `Buffer`.
    ///
    /// This method must not fail.
    fn source_buffer(&self, buffer: &Buffer) -> &[u8];
}

/// Wrapper type for data structures with their data ready.
pub struct Loaded<'a, T> {
    /// The wrapper item.
    item: T,

    /// The data source for this item.
    source: &'a Source,
}
<|endoftext|>


<commit_before>//! Crate `etcd` provides a client for [etcd](https://github.com/coreos/etcd), a distributed
//! key-value store from [CoreOS](https://coreos.com/).
//!
//! The client uses etcd's v2 APIs. Support for the v3 APIs is planned, and will be added via
//! separate types for backwards compatibility and to support both sets of APIs simultaneously.
//!
//! The client uses asynchronous I/O, backed by the `futures` and `tokio-core` crates, and requires
//! both to be used alongside. Functions that return futures currently return them boxed. As soon
//! as Rust's [impl Trait](https://github.com/rust-lang/rust/issues/34511) feature is stabilized,
//! this crate's API will be updated to use it.
//!
//! The client is thoroughly tested against etcd 2.3.7.
//!
//! # Usage
//!
//! `Client` is an HTTP client required for all API calls. It can be constructed to use HTTP or
//! HTTPS, and supports authenticating to the etcd cluster via HTTP basic authentication (username
//! and password) and/or X.509 client certificates.
//!
//! To get basic information about the versions of etcd running in a cluster, use the
//! `Client::versions` method. All other API calls are made by passing a `Client` reference to the
//! functions in the `kv` and `stats` modules. These modules contain functions for API calls to the
//! primary key-value store APIs and statistics APIs, respectively. The membership and
//! authentication APIs are not yet supported, but planned.
//!
//! # Examples
//!
//! Basic usage:
//!
//! ```no_run
//! extern crate etcd;
//! extern crate futures;
//! extern crate tokio_core;
//!
//! use etcd::Client;
//! use etcd::kv::{self, Action};
//! use futures::Future;
//! use tokio_core::reactor::Core;
//!
//! fn main() {
//!     // Create a `Core`, which is the event loop which will drive futures to completion.
//!     let mut core = Core::new().unwrap();
//!     // Get a "handle" to the event loop that the client can use to schedule work.
//!     let handle = core.handle();
//!
//!     // Create a client to access a single cluster member. Addresses of multiple cluster
//!     // members can be provided and the client will try each one in sequence until it
//!     // receives a successful response.
//!     let client = Client::new(&handle, &["http://etcd.example.com:2379"], None).unwrap();
//!
//!     // Set the key "/foo" to the value "bar" with no expiration.
//!     let work = kv::set(&client, "/foo", "bar", None).and_then(|_| {
//!         // Once the key has been set, ask for details about it.
//!         let get_request = kv::get(&client, "/foo", kv::GetOptions::default());
//!
//!         get_request.and_then(|(key_value_info, cluster_info)| {
//!             // The information returned tells you what kind of operation was performed.
//!             assert_eq!(key_value_info.action, Action::Get);
//!
//!             // The value of the key is what we set it to previously.
//!             assert_eq!(key_value_info.node.value, Some("bar".to_string()));
//!
//!             // Each API call also returns information about the etcd cluster extracted from
//!             // HTTP response headers.
//!             assert!(cluster_info.etcd_index.is_some());
//!
//!             Ok(())
//!         })
//!     });
//!
//!     // Start the event loop, driving the asynchronous code to completion.
//!     core.run(work).unwrap();
//! }
//! ```
//!
//! # Cargo features
//!
//! Crate `etcd` has one Cargo feature, `tls`, which adds HTTPS support via the `Client::https`
//! constructor. This feature is enabled by default.

#![deny(missing_debug_implementations, missing_docs, warnings)]

extern crate futures;
#[macro_use]
extern crate hyper;
#[cfg(feature = "tls")]
extern crate hyper_tls;
#[cfg(feature = "tls")]
extern crate native_tls;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tokio_core;
extern crate tokio_timer;
extern crate url;

pub use client::{BasicAuth, Client, ClusterInfo};
pub use error::{ApiError, Error};
pub use version::VersionInfo;

pub mod kv;
pub mod stats;

mod async;
mod client;
mod error;
mod http;
mod member;
mod options;
mod version;
<commit_msg>APIs --> API<commit_after>//! Crate `etcd` provides a client for [etcd](https://github.com/coreos/etcd), a distributed
//! key-value store from [CoreOS](https://coreos.com/).
//!
//! The client uses etcd's v2 API. Support for the v3 API is planned, and will be added via
//! separate types for backwards compatibility and to support both APIs simultaneously.
//!
//! The client uses asynchronous I/O, backed by the `futures` and `tokio-core` crates, and requires
//! both to be used alongside. Functions that return futures currently return them boxed. As soon
//! as Rust's [impl Trait](https://github.com/rust-lang/rust/issues/34511) feature is stabilized,
//! this crate's API will be updated to use it.
//!
//! The client is thoroughly tested against etcd 2.3.7.
//!
//! # Usage
//!
//! `Client` is an HTTP client required for all API calls. It can be constructed to use HTTP or
//! HTTPS, and supports authenticating to the etcd cluster via HTTP basic authentication (username
//! and password) and/or X.509 client certificates.
//!
//! To get basic information about the versions of etcd running in a cluster, use the
//! `Client::versions` method. All other API calls are made by passing a `Client` reference to the
//! functions in the `kv` and `stats` modules. These modules contain functions for API calls to the
//! primary key-value store API and statistics API, respectively. The membership and
//! authentication APIs are not yet supported, but planned.
//!
//! # Examples
//!
//! Basic usage:
//!
//! ```no_run
//! extern crate etcd;
//! extern crate futures;
//! extern crate tokio_core;
//!
//! use etcd::Client;
//! use etcd::kv::{self, Action};
//! use futures::Future;
//! use tokio_core::reactor::Core;
//!
//! fn main() {
//!     // Create a `Core`, which is the event loop which will drive futures to completion.
//!     let mut core = Core::new().unwrap();
//!     // Get a "handle" to the event loop that the client can use to schedule work.
//!     let handle = core.handle();
//!
//!     // Create a client to access a single cluster member. Addresses of multiple cluster
//!     // members can be provided and the client will try each one in sequence until it
//!     // receives a successful response.
//!     let client = Client::new(&handle, &["http://etcd.example.com:2379"], None).unwrap();
//!
//!     // Set the key "/foo" to the value "bar" with no expiration.
//!     let work = kv::set(&client, "/foo", "bar", None).and_then(|_| {
//!         // Once the key has been set, ask for details about it.
//!         let get_request = kv::get(&client, "/foo", kv::GetOptions::default());
//!
//!         get_request.and_then(|(key_value_info, cluster_info)| {
//!             // The information returned tells you what kind of operation was performed.
//!             assert_eq!(key_value_info.action, Action::Get);
//!
//!             // The value of the key is what we set it to previously.
//!             assert_eq!(key_value_info.node.value, Some("bar".to_string()));
//!
//!             // Each API call also returns information about the etcd cluster extracted from
//!             // HTTP response headers.
//!             assert!(cluster_info.etcd_index.is_some());
//!
//!             Ok(())
//!         })
//!     });
//!
//!     // Start the event loop, driving the asynchronous code to completion.
//!     core.run(work).unwrap();
//! }
//! ```
//!
//! # Cargo features
//!
//! Crate `etcd` has one Cargo feature, `tls`, which adds HTTPS support via the `Client::https`
//! constructor. This feature is enabled by default.

#![deny(missing_debug_implementations, missing_docs, warnings)]

extern crate futures;
#[macro_use]
extern crate hyper;
#[cfg(feature = "tls")]
extern crate hyper_tls;
#[cfg(feature = "tls")]
extern crate native_tls;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tokio_core;
extern crate tokio_timer;
extern crate url;

pub use client::{BasicAuth, Client, ClusterInfo};
pub use error::{ApiError, Error};
pub use version::VersionInfo;

pub mod kv;
pub mod stats;

mod async;
mod client;
mod error;
mod http;
mod member;
mod options;
mod version;
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate serde;

use std::io;

use byteorder::{WriteBytesExt};

pub struct Serializer<W> {
    writer: W,
}

impl<W> Serializer<W> where W: io::Write {
    pub fn new(writer: W) -> Self {
        return Serializer {
            writer: writer,
        }
    }

    fn _write_length(&mut self, length: isize) -> Result<(), io::Error> {
        assert!(length < 128);
        try!(self.writer.write_u8(length as u8));
        return Ok(());
    }

    fn _int_length(&self, v: i64) -> isize {
        let mut num_bytes = 1;
        let mut i = v;

        while i > 127 || i < -128 {
            num_bytes += 1;
            i >>= 8;
        }
        return num_bytes;
    }
}

impl<W> serde::Serializer for Serializer<W> where W: io::Write {
    type Error = io::Error;

    fn visit_bool(&mut self, v: bool) -> Result<(), Self::Error> {
        if v {
            try!(self.writer.write_all(b"\xff"));
        } else {
            try!(self.writer.write_all(b"\x00"));
        }
        return Ok(());
    }

    fn visit_i64(&mut self, v: i64) -> Result<(), Self::Error> {
        try!(self.writer.write_all(b"\x02"));

        let n = self._int_length(v);
        try!(self._write_length(n));
        for i in (1..n+1).rev() {
            try!(self.writer.write_u8((v >> ((i - 1) * 8)) as u8))
        }

        return Ok(());
    }

    #[allow(unused_variables)]
    fn visit_u64(&mut self, v: u64) -> Result<(), Self::Error> {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_f64(&mut self, v: f64) -> Result<(), Self::Error> {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_str(&mut self, value: &str) -> Result<(), Self::Error> {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_unit(&mut self) -> Result<(), Self::Error> {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_none(&mut self) -> Result<(), Self::Error> {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_some<V>(&mut self, value: V) -> Result<(), Self::Error> where V: serde::Serialize {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_seq<V>(&mut self, visitor: V) -> Result<(), Self::Error>
        where V: serde::ser::SeqVisitor {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error> where T: serde::Serialize {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_map<V>(&mut self, visitor: V) -> Result<(), Self::Error>
            where V: serde::ser::MapVisitor {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
            where K: serde::Serialize, V: serde::Serialize {
        panic!("not implemented");
    }
}

pub fn to_writer<W, T>(writer: &mut W, value: &T) -> io::Result<()>
        where W: io::Write, T: serde::Serialize {
    let mut ser = Serializer::new(writer);
    try!(value.serialize(&mut ser));
    return Ok(());
}

pub fn to_vec<T>(value: &T) -> Vec<u8> where T: serde::Serialize {
    let mut writer = Vec::new();
    to_writer(&mut writer, value).unwrap();
    return writer;
}

#[cfg(test)]
mod tests {
    use serde;

    use super::{to_vec};

    fn assert_serializes<T>(values: Vec<(T, Vec<u8>)>) where T: serde::Serialize {
        for (value, expected) in values {
            let result = to_vec(&value);
            assert_eq!(result, expected);
        }
    }

    #[test]
    fn test_serialize_bool() {
        assert_serializes(vec![
            (true, b"\xff".to_vec()),
            (false, b"\x00".to_vec()),
        ]);
    }

    #[test]
    fn test_serialize_int() {
        assert_serializes(vec![
            (0, b"\x02\x01\x00".to_vec()),
            (127, b"\x02\x01\x7f".to_vec()),
            (128, b"\x02\x02\x00\x80".to_vec()),
            (256, b"\x02\x02\x01\x00".to_vec()),
            (-128, b"\x02\x01\x80".to_vec()),
            (-129, b"\x02\x02\xff\x7f".to_vec()),
        ])
    }
}
<commit_msg>refactor to always include the tag<commit_after>extern crate byteorder;
extern crate serde;

use std::io;

use byteorder::{WriteBytesExt};

pub struct Serializer<W> {
    writer: W,
}

impl<W> Serializer<W> where W: io::Write {
    pub fn new(writer: W) -> Self {
        return Serializer {
            writer: writer,
        }
    }

    fn _write_length(&mut self, length: usize) -> Result<(), io::Error> {
        assert!(length < 128);
        try!(self.writer.write_u8(length as u8));
        return Ok(());
    }

    fn _int_length(&self, v: i64) -> usize {
        let mut num_bytes = 1;
        let mut i = v;

        while i > 127 || i < -128 {
            num_bytes += 1;
            i >>= 8;
        }
        return num_bytes;
    }

    fn _write_with_tag<F>(&mut self, tag: u8, body: F) -> Result<(), io::Error>
            where F: Fn() -> Vec<u8> {
        try!(self.writer.write_u8(tag));

        let body = body();
        try!(self._write_length(body.len()));
        try!(self.writer.write_all(&body));
        return Ok(());
    }
}

impl<W> serde::Serializer for Serializer<W> where W: io::Write {
    type Error = io::Error;

    fn visit_bool(&mut self, v: bool) -> Result<(), Self::Error> {
        return self._write_with_tag(1, || {
            if v {
                return b"\xff".to_vec();
            } else {
                return b"\x00".to_vec();
            }
        })
    }

    fn visit_i64(&mut self, v: i64) -> Result<(), Self::Error> {
        let n = self._int_length(v);
        return self._write_with_tag(2, || {
            let mut result = Vec::with_capacity(n);
            for i in (1..n+1).rev() {
                result.push((v >> ((i - 1) * 8)) as u8);
            }
            return result;
        });
    }

    #[allow(unused_variables)]
    fn visit_u64(&mut self, v: u64) -> Result<(), Self::Error> {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_f64(&mut self, v: f64) -> Result<(), Self::Error> {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_str(&mut self, value: &str) -> Result<(), Self::Error> {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_unit(&mut self) -> Result<(), Self::Error> {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_none(&mut self) -> Result<(), Self::Error> {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_some<V>(&mut self, value: V) -> Result<(), Self::Error> where V: serde::Serialize {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_seq<V>(&mut self, visitor: V) -> Result<(), Self::Error>
        where V: serde::ser::SeqVisitor {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error> where T: serde::Serialize {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_map<V>(&mut self, visitor: V) -> Result<(), Self::Error>
            where V: serde::ser::MapVisitor {
        panic!("not implemented");
    }

    #[allow(unused_variables)]
    fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
            where K: serde::Serialize, V: serde::Serialize {
        panic!("not implemented");
    }
}

pub fn to_writer<W, T>(writer: &mut W, value: &T) -> io::Result<()>
        where W: io::Write, T: serde::Serialize {
    let mut ser = Serializer::new(writer);
    try!(value.serialize(&mut ser));
    return Ok(());
}

pub fn to_vec<T>(value: &T) -> Vec<u8> where T: serde::Serialize {
    let mut writer = Vec::new();
    to_writer(&mut writer, value).unwrap();
    return writer;
}

#[cfg(test)]
mod tests {
    use serde;

    use super::{to_vec};

    fn assert_serializes<T>(values: Vec<(T, Vec<u8>)>) where T: serde::Serialize {
        for (value, expected) in values {
            let result = to_vec(&value);
            assert_eq!(result, expected);
        }
    }

    #[test]
    fn test_serialize_bool() {
        assert_serializes(vec![
            (true, b"\x01\x01\xff".to_vec()),
            (false, b"\x01\x01\x00".to_vec()),
        ]);
    }

    #[test]
    fn test_serialize_int() {
        assert_serializes(vec![
            (0, b"\x02\x01\x00".to_vec()),
            (127, b"\x02\x01\x7f".to_vec()),
            (128, b"\x02\x02\x00\x80".to_vec()),
            (256, b"\x02\x02\x01\x00".to_vec()),
            (-128, b"\x02\x01\x80".to_vec()),
            (-129, b"\x02\x02\xff\x7f".to_vec()),
        ])
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(core, unsafe_no_drop_flag, filling_drop, nonzero)]
#![cfg_attr(test, feature(test, str_char))]
#![deny(warnings)]

extern crate core;
#[macro_use] extern crate mac;
extern crate futf;
extern crate encoding;

#[cfg(test)]
extern crate test;

pub use tendril::{Tendril, ByteTendril, StrTendril, SliceExt, ReadExt, SubtendrilError};
pub use fmt::Format;

pub mod fmt;
pub mod stream;

mod util;
mod buf32;
mod tendril;

static OFLOW: &'static str = "tendril: overflow in buffer arithmetic";
<commit_msg>Only make warnings fatal when testing.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(core, unsafe_no_drop_flag, filling_drop, nonzero)]
#![cfg_attr(test, feature(test, str_char))]
#![cfg_attr(test, deny(warnings))]

extern crate core;
#[macro_use] extern crate mac;
extern crate futf;
extern crate encoding;

#[cfg(test)]
extern crate test;

pub use tendril::{Tendril, ByteTendril, StrTendril, SliceExt, ReadExt, SubtendrilError};
pub use fmt::Format;

pub mod fmt;
pub mod stream;

mod util;
mod buf32;
mod tendril;

static OFLOW: &'static str = "tendril: overflow in buffer arithmetic";
<|endoftext|>


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

#[cfg(target_os = "macos")]
pub fn user_data_dir(app: Option<&str>, _: Option<&str>, _: bool) -> PathBuf {
    let mut data_dir = env::home_dir().unwrap();
    data_dir.push("Library/Application Support");
    if app.is_some() {
        data_dir.push(app.unwrap());
    }
    data_dir
}

#[cfg(target_os = "macos")]
pub fn site_data_dir(app: Option<&str>, _: Option<&str>) -> PathBuf {
    let mut data_dir = PathBuf::new();
    data_dir.push("/Library/Application Support");
    if app.is_some() {
        data_dir.push(app.unwrap());
    }
    data_dir
}

#[cfg(target_os = "macos")]
pub fn user_config_dir(app: Option<&str>, author: Option<&str>, roaming: bool) -> PathBuf {
    user_data_dir(app, author, roaming)
}

#[cfg(target_os = "macos")]
pub fn site_config_dir(app: Option<&str>, author: Option<&str>) -> PathBuf {
    site_data_dir(app, author)
}

#[cfg(target_os = "macos")]
pub fn user_cache_dir(app: Option<&str>, _: Option<&str>) -> PathBuf {
    let mut cache_dir = env::home_dir().unwrap();
    cache_dir.push("Library/Caches");
    if app.is_some() {
        cache_dir.push(app.unwrap());
    }
    cache_dir
}

#[cfg(target_os = "macos")]
pub fn user_log_dir(app: Option<&str>, _: Option<&str>) -> PathBuf {
    let mut log_dir = env::home_dir().unwrap();
    log_dir.push("Library/Logs");
    if app.is_some() {
        log_dir.push(app.unwrap());
    }
    log_dir
}

#[cfg(test)]
mod tests {

    use std::io::{self, Write};
    use std::path::PathBuf;

    fn to_stderr(name: &str, value: PathBuf) {
        let _ = io::stderr().write(format!("{}: {}\n", name,
                                           value.to_str().unwrap()).as_bytes());
    }

    #[test]
    fn output_dirs() {
        to_stderr("user data dir",
                  super::user_data_dir(Some("AppDirs"), None, false));
        to_stderr("site data dir",
                  super::site_data_dir(Some("AppDirs"), None));
        to_stderr("user config dir",
                  super::user_config_dir(Some("AppDirs"), None, false));
        to_stderr("site config dir",
                  super::site_config_dir(Some("AppDirs"), None));
        to_stderr("user cache dir",
                  super::user_cache_dir(Some("AppDirs"), None));
        to_stderr("user log dir",
                  super::user_log_dir(Some("AppDirs"), None));
    }

}
<commit_msg>Add support for non-iOS/macOS/Android Unices<commit_after>use std::env;
use std::path::PathBuf;

#[cfg(target_os = "macos")]
pub fn user_data_dir(app: Option<&str>, _: Option<&str>, _: bool) -> PathBuf {
    let mut data_dir = env::home_dir().unwrap();
    data_dir.push("Library/Application Support");
    if app.is_some() {
        data_dir.push(app.unwrap());
    }
    data_dir
}

#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))]
pub fn user_data_dir(app: Option<&str>, _: Option<&str>, _: bool) -> PathBuf {
    let mut data_dir = PathBuf::new();
    match env::var_os("XDG_DATA_HOME") {
        Some(dir) => { data_dir.push(dir); },
        None => {
            data_dir.push(env::home_dir().unwrap());
            data_dir.push(".local/share");
        },
    };
    if app.is_some() {
        data_dir.push(app.unwrap());
    }
    data_dir
}

#[cfg(target_os = "macos")]
pub fn site_data_dir(app: Option<&str>, _: Option<&str>) -> PathBuf {
    let mut data_dir = PathBuf::new();
    data_dir.push("/Library/Application Support");
    if app.is_some() {
        data_dir.push(app.unwrap());
    }
    data_dir
}

#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))]
pub fn site_data_dir(app: Option<&str>, _: Option<&str>) -> PathBuf {
    let mut data_dir = PathBuf::new();
    let default = "/usr/local/share";
    match env::var_os("XDG_DATA_DIRS") {
        Some(joined) => {
            let first = env::split_paths(&joined).next();
            match first {
                Some(dir) => { data_dir.push(dir); },
                None => { data_dir.push(default); },
            };
        },
        None => { data_dir.push(default); },
    };
    if app.is_some() {
        data_dir.push(app.unwrap());
    }
    data_dir
}

#[cfg(target_os = "macos")]
pub fn user_config_dir(app: Option<&str>, author: Option<&str>, roaming: bool) -> PathBuf {
    user_data_dir(app, author, roaming)
}

#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))]
pub fn user_config_dir(app: Option<&str>, _: Option<&str>, _: bool) -> PathBuf {
    let mut config_dir = PathBuf::new();
    match env::var_os("XDG_CONFIG_HOME") {
        Some(dir) => { config_dir.push(dir); },
        None => {
            config_dir.push(env::home_dir().unwrap());
            config_dir.push(".config");
        },
    };
    if app.is_some() {
        config_dir.push(app.unwrap());
    }
    config_dir
}

#[cfg(target_os = "macos")]
pub fn site_config_dir(app: Option<&str>, author: Option<&str>) -> PathBuf {
    site_data_dir(app, author)
}

#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))]
pub fn site_config_dir(app: Option<&str>, _: Option<&str>) -> PathBuf {
    let mut data_dir = PathBuf::new();
    let default = "/etc/xdg";
    match env::var_os("XDG_CONFIG_DIRS") {
        Some(joined) => {
            let first = env::split_paths(&joined).next();
            match first {
                Some(dir) => { data_dir.push(dir); },
                None => { data_dir.push(default); },
            };
        },
        None => { data_dir.push(default); },
    };
    if app.is_some() {
        data_dir.push(app.unwrap());
    }
    data_dir
}

#[cfg(target_os = "macos")]
pub fn user_cache_dir(app: Option<&str>, _: Option<&str>) -> PathBuf {
    let mut cache_dir = env::home_dir().unwrap();
    cache_dir.push("Library/Caches");
    if app.is_some() {
        cache_dir.push(app.unwrap());
    }
    cache_dir
}

#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))]
pub fn user_cache_dir(app: Option<&str>, _: Option<&str>) -> PathBuf {
    let mut cache_dir = PathBuf::new();
    match env::var_os("XDG_CACHE_HOME") {
        Some(dir) => { cache_dir.push(dir); },
        None => {
            cache_dir.push(env::home_dir().unwrap());
            cache_dir.push(".cache");
        },
    };
    if app.is_some() {
        cache_dir.push(app.unwrap());
    }
    cache_dir
}

#[cfg(target_os = "macos")]
pub fn user_log_dir(app: Option<&str>, _: Option<&str>) -> PathBuf {
    let mut log_dir = env::home_dir().unwrap();
    log_dir.push("Library/Logs");
    if app.is_some() {
        log_dir.push(app.unwrap());
    }
    log_dir
}

#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))]
pub fn user_log_dir(app: Option<&str>, author: Option<&str>) -> PathBuf {
    let mut log_dir = user_cache_dir(app, author);
    log_dir.push("log");
    log_dir
}

#[cfg(test)]
mod tests {

    use std::io::{self, Write};
    use std::path::PathBuf;

    fn to_stderr(name: &str, value: PathBuf) {
        let _ = io::stderr().write(format!("{}: {}\n", name,
                                           value.to_str().unwrap()).as_bytes());
    }

    #[test]
    fn output_dirs() {
        to_stderr("user data dir",
                  super::user_data_dir(Some("AppDirs"), None, false));
        to_stderr("site data dir",
                  super::site_data_dir(Some("AppDirs"), None));
        to_stderr("user config dir",
                  super::user_config_dir(Some("AppDirs"), None, false));
        to_stderr("site config dir",
                  super::site_config_dir(Some("AppDirs"), None));
        to_stderr("user cache dir",
                  super::user_cache_dir(Some("AppDirs"), None));
        to_stderr("user log dir",
                  super::user_log_dir(Some("AppDirs"), None));
    }

}
<|endoftext|>


<commit_before>//! # Terminal progress bar for Rust
//!
//! Console progress bar for Rust Inspired from [pb](http://github.com/cheggaaa/pb), support and
//! tested on MacOS, Linux and Windows
//!
//! ![Screenshot](https://github.com/a8m/pb/blob/master/gif/rec_v3.gif)
//!
//! [Documentation](http://a8m.github.io/pb/doc/pbr/index.html)
//!
//! ### Examples
//! 1. simple example
//!
//! ```ignore
//! extern crate pbr;
//!
//! use pbr::ProgressBar;
//! use std::thread;
//!
//! fn main() {
//!     let count = 1000;
//!     let mut pb = ProgressBar::new(count);
//!     pb.format("╢▌▌░╟");
//!     for _ in 0..count {
//!         pb.inc();
//!         thread::sleep_ms(200);
//!     }
//!     pb.finish_print("done");
//! }
//! ```
//!
//! 2. MultiBar example. see full example [here](https://github.com/a8m/pb/blob/master/examples/multi.rs)
//! ```ignore
//! extern crate pbr;
//!
//! use std::thread;
//! use pbr::MultiBar;
//! use std::time::Duration;
//!
//! fn main() {
//!     let mut mb = MultiBar::new();
//!     let count = 100;
//!     mb.println("Application header:");
//!
//!     let mut p1 = mb.create_bar(count);
//!     let _ = thread::spawn(move || {
//!         for _ in 0..count {
//!             p1.inc();
//!             thread::sleep(Duration::from_millis(100));
//!         }
//!         // notify the multibar that this bar finished.
//!         p1.finish();
//!     });
//!
//!     mb.println("add a separator between the two bars");
//!
//!     let mut p2 = mb.create_bar(count * 2);
//!     let _ = thread::spawn(move || {
//!         for _ in 0..count * 2 {
//!             p2.inc();
//!             thread::sleep(Duration::from_millis(100));
//!         }
//!         // notify the multibar that this bar finished.
//!         p2.finish();
//!     });
//!
//!     // start listen to all bars changes.
//!     // this is a blocking operation, until all bars will finish.
//!     // to ignore blocking, you can run it in a different thread.
//!     mb.listen();
//! }
//! ```
//!
//! 3. Broadcast writing(simple file copying)
//!
//! ```ignore
//! #![feature(io)]
//! extern crate pbr;
//!
//! use std::io::copy;
//! use std::io::prelude::*;
//! use std::fs::File;
//! use pbr::{ProgressBar, Units};
//!
//! fn main() {
//!     let mut file = File::open("/usr/share/dict/words").unwrap();
//!     let n_bytes = file.metadata().unwrap().len() as usize;
//!     let mut pb = ProgressBar::new(n_bytes);
//!     pb.set_units(Units::Bytes);
//!     let mut handle = File::create("copy-words").unwrap().broadcast(&mut pb);
//!     copy(&mut file, &mut handle).unwrap();
//!     pb.finish_print("done");
//! }
//! ```

// Macro for writing to the giving writer.
// Used in both pb.rs and multi.rs modules.
//
// # Examples
//
// ```
// let w = io::stdout();
// printfl!(w, "");
// printfl!(w, "\r{}", out);
//
// ```
macro_rules! printfl {
   ($w:expr, $($tt:tt)*) => {{
        $w.write(&format!($($tt)*).as_bytes()).ok().expect("write() fail");
        $w.flush().ok().expect("flush() fail");
    }}
}

#[macro_use]
extern crate time;
mod tty;
mod pb;
mod multi;
pub use pb::{ProgressBar, Units};
pub use multi::MultiBar;
use std::io::{Write, Stdout, stdout};

pub struct PbIter<T, I>
    where I: Iterator,
          T: Write
{
    iter: I,
    progress_bar: ProgressBar<T>,
}

impl<I> PbIter<Stdout, I>
    where I: Iterator
{
    pub fn new(iter: I) -> Self {
        Self::on(stdout(), iter)
    }
}

impl<T, I> PbIter<T, I>
    where I: Iterator,
          T: Write
{
    pub fn on(handle: T, iter: I) -> Self {
        let size = iter.size_hint().0;
        PbIter {
            iter: iter,
            progress_bar: ProgressBar::on(handle, size as u64),
        }
    }
}

impl<T, I> Iterator for PbIter<T, I>
    where I: Iterator,
          T: Write
{
    type Item = I::Item;

    fn next(&mut self) -> Option<I::Item> {
        match self.iter.next() {
            Some(i) => {
                self.progress_bar.inc();
                Some(i)
            }
            None => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}
<commit_msg>docs: fix gif url<commit_after>//! # Terminal progress bar for Rust
//!
//! Console progress bar for Rust Inspired from [pb](http://github.com/cheggaaa/pb), support and
//! tested on MacOS, Linux and Windows
//!
//! ![Screenshot](https://raw.githubusercontent.com/a8m/pb/master/gif/rec_v3.gif)
//!
//! [Documentation](http://a8m.github.io/pb/doc/pbr/index.html)
//!
//! ### Examples
//! 1. simple example
//!
//! ```ignore
//! extern crate pbr;
//!
//! use pbr::ProgressBar;
//! use std::thread;
//!
//! fn main() {
//!     let count = 1000;
//!     let mut pb = ProgressBar::new(count);
//!     pb.format("╢▌▌░╟");
//!     for _ in 0..count {
//!         pb.inc();
//!         thread::sleep_ms(200);
//!     }
//!     pb.finish_print("done");
//! }
//! ```
//!
//! 2. MultiBar example. see full example [here](https://github.com/a8m/pb/blob/master/examples/multi.rs)
//! ```ignore
//! extern crate pbr;
//!
//! use std::thread;
//! use pbr::MultiBar;
//! use std::time::Duration;
//!
//! fn main() {
//!     let mut mb = MultiBar::new();
//!     let count = 100;
//!     mb.println("Application header:");
//!
//!     let mut p1 = mb.create_bar(count);
//!     let _ = thread::spawn(move || {
//!         for _ in 0..count {
//!             p1.inc();
//!             thread::sleep(Duration::from_millis(100));
//!         }
//!         // notify the multibar that this bar finished.
//!         p1.finish();
//!     });
//!
//!     mb.println("add a separator between the two bars");
//!
//!     let mut p2 = mb.create_bar(count * 2);
//!     let _ = thread::spawn(move || {
//!         for _ in 0..count * 2 {
//!             p2.inc();
//!             thread::sleep(Duration::from_millis(100));
//!         }
//!         // notify the multibar that this bar finished.
//!         p2.finish();
//!     });
//!
//!     // start listen to all bars changes.
//!     // this is a blocking operation, until all bars will finish.
//!     // to ignore blocking, you can run it in a different thread.
//!     mb.listen();
//! }
//! ```
//!
//! 3. Broadcast writing(simple file copying)
//!
//! ```ignore
//! #![feature(io)]
//! extern crate pbr;
//!
//! use std::io::copy;
//! use std::io::prelude::*;
//! use std::fs::File;
//! use pbr::{ProgressBar, Units};
//!
//! fn main() {
//!     let mut file = File::open("/usr/share/dict/words").unwrap();
//!     let n_bytes = file.metadata().unwrap().len() as usize;
//!     let mut pb = ProgressBar::new(n_bytes);
//!     pb.set_units(Units::Bytes);
//!     let mut handle = File::create("copy-words").unwrap().broadcast(&mut pb);
//!     copy(&mut file, &mut handle).unwrap();
//!     pb.finish_print("done");
//! }
//! ```

// Macro for writing to the giving writer.
// Used in both pb.rs and multi.rs modules.
//
// # Examples
//
// ```
// let w = io::stdout();
// printfl!(w, "");
// printfl!(w, "\r{}", out);
//
// ```
macro_rules! printfl {
   ($w:expr, $($tt:tt)*) => {{
        $w.write(&format!($($tt)*).as_bytes()).ok().expect("write() fail");
        $w.flush().ok().expect("flush() fail");
    }}
}

#[macro_use]
extern crate time;
mod tty;
mod pb;
mod multi;
pub use pb::{ProgressBar, Units};
pub use multi::MultiBar;
use std::io::{Write, Stdout, stdout};

pub struct PbIter<T, I>
    where I: Iterator,
          T: Write
{
    iter: I,
    progress_bar: ProgressBar<T>,
}

impl<I> PbIter<Stdout, I>
    where I: Iterator
{
    pub fn new(iter: I) -> Self {
        Self::on(stdout(), iter)
    }
}

impl<T, I> PbIter<T, I>
    where I: Iterator,
          T: Write
{
    pub fn on(handle: T, iter: I) -> Self {
        let size = iter.size_hint().0;
        PbIter {
            iter: iter,
            progress_bar: ProgressBar::on(handle, size as u64),
        }
    }
}

impl<T, I> Iterator for PbIter<T, I>
    where I: Iterator,
          T: Write
{
    type Item = I::Item;

    fn next(&mut self) -> Option<I::Item> {
        match self.iter.next() {
            Some(i) => {
                self.progress_bar.inc();
                Some(i)
            }
            None => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}
<|endoftext|>


<commit_before>#![feature(alloc, core)]
#![cfg_attr(test, feature(test, step_by))]

extern crate alloc;

use self::alloc::arc;

use std::fmt::{Formatter, Debug};
use std::fmt::Error as FmtError;
use std::raw::Slice as RawSlice;
use std::sync::Arc;
use std::mem;
use std::ops;

/// A vector that can be operated on concurrently via non-overlapping slices.
struct RacyCell<T>(T);
unsafe impl<T: Send> Sync for RacyCell<T> {}
///
/// Get a `ParVec` and a vector of slices via `new()`, send the slices to other threads
/// and mutate them, then get the mutated vector with `into_inner()` when finished.
pub struct ParVec<T> {
    data: Arc<RacyCell<Vec<T>>>,
}

impl<T: Send> ParVec<T> {
    /// Create a new `ParVec`, returning it and a vector of slices that can be sent
    /// to other threads and mutated concurrently.
    pub fn new(vec: Vec<T>, slices: usize) -> (ParVec<T>, Vec<ParSlice<T>>) {
        let slices = sub_slices(&vec, slice_count);
        let data = Arc::new(RacyCell(vec));

        let par_slices = slices.into_iter().map(|slice|
                ParSlice {
                    _vec: data.clone(),
                    data: slice,
                }
            ).collect();

        let par_vec = ParVec {
            data: data,
        };

        (par_vec, par_slices)
    }

    /// Take the inner `Vec` if there are no slices remaining.
    /// Returns `Err(self)` if there are still slices out there.
    pub fn into_inner_opt(self) -> Result<Vec<T>, ParVec<T>> {
        // Unwrap if we hold a unique reference
        // (we don't use weak refs so ignore those)
        if arc::strong_count(&self.data) == 1 {
            let vec_ptr: &mut Vec<T> = unsafe { mem::transmute(&*self.data) };
            Ok(mem::replace(vec_ptr, Vec::new()))
        } else {
            Err(self)
        }
    }

    /// Take the inner `Vec`, waiting until all slices have been freed.
    pub fn into_inner(mut self) -> Vec<T> {
        loop {
            match self.into_inner_opt() {
                Ok(vec) => return vec,
                Err(new_self) => self = new_self,
            }
        }
    }
}

fn sub_slices<T>(parent: &[T], slice_count: usize) -> Vec<RawSlice<T>> {
    use std::cmp;
    use std::raw::Repr;

    let mut start = 0;

    (1 .. slice_count + 1).rev().map(|curr| {
        let slice_len = (len - start) / curr;
        let end = cmp::min(start + slice_len, len);

        let slice = parent[start..end].repr();
        start += slice_len;

        slice
    }).collect()
}

/// A slice of `ParVec` that can be sent to another task for processing.
/// Automatically releases the slice on drop.
pub struct ParSlice<T: Send> {
    // Just to keep the source vector alive while the slice is,
    // since the ParVec can die asynchronously.
    _vec: Arc<RacyCell<Vec<T>>>,
    data: RawSlice<T>,
}

unsafe impl<T: Send> Send for ParSlice<T> {}

impl<T: Send> ops::Deref for ParSlice<T> {
    type Target = [T];

    fn deref<'a>(&'a self) -> &'a [T] {
        unsafe { mem::transmute(self.data) }
    }
}

impl<T: Send> ops::DerefMut for ParSlice<T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut [T] {
        unsafe { mem::transmute(self.data) }
    }
}

impl<T: Send> Debug for ParSlice<T> where T: Debug {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{:?}", &*self)
    }
}

#[cfg(test)]
mod test {
    extern crate rand;
    extern crate threadpool;
    extern crate test;

    use super::ParVec;

    use std::mem;

    use self::rand::{thread_rng, Rng};
    use self::test::Bencher;
    use self::threadpool::ThreadPool;

    const TEST_SLICES: usize = 8;
    const TEST_MAX: u32 = 1000;

    #[test]
    fn test_unwrap_safely() {
        let (vec, slices) = ParVec::new([5u32; TEST_MAX as usize].to_vec(), TEST_SLICES);
        mem::drop(slices);

        let vec = vec.into_inner();

        assert_eq!(&*vec, &[5u32; TEST_MAX as usize][..]);
    }

    #[test]
    fn test_slices() {
        let (_, slices) = ParVec::new((1u32 .. TEST_MAX).collect(), TEST_SLICES);

        assert_eq!(slices.len(), TEST_SLICES);
    }

    #[bench]
    fn seq_prime_factors_1000(b: &mut Bencher) {
        let vec: Vec<u32> = (1 .. TEST_MAX).collect();

        b.iter(|| {
            let _: Vec<(u32, Vec<u32>)> = vec.iter()
                .map(|&x| (x, get_prime_factors(x)))
                .collect();
        });
    }

    #[bench]
    fn par_prime_factors_1000(b: &mut Bencher) {
        let mut rng = thread_rng();
        let pool = ThreadPool::new(TEST_SLICES);

        b.iter(|| {
            let mut vec: Vec<(u32, Vec<u32>)> = (1 .. TEST_MAX)
                .map(|x| (x, Vec::new())).collect();

            // Shuffle so each thread gets an even distribution of work.
            // Otherwise, the lower threads will quit early.
            rng.shuffle(&mut *vec);

            let (par_vec, par_slices) = ParVec::new(vec, TEST_SLICES);

            for mut slice in par_slices.into_iter() {
                pool.execute(move ||
                    for pair in slice.iter_mut() {
                        let (x, ref mut x_primes) = *pair;
                        *x_primes = get_prime_factors(x);
                    }
                );
            }

            let mut vec = par_vec.into_inner();
            // Sort so they're in the same order as sequential.
            vec.sort();
        });
    }

    fn get_prime_factors(x: u32) -> Vec<u32> {
        (1 .. x).filter(|&y| x % y == 0 && is_prime(y)).collect()
    }

    fn is_prime(x: u32) -> bool {
        if x < 3 { return true; }

        if x & 1 == 0 { return false; }

        for i in (3 .. x).step_by(2) {
            if x % i == 0 { return false; }
        }

        true
    }

}

<commit_msg>`into_inner` -> `unwrap`, use safer implementation<commit_after>#![feature(alloc, core)]
#![cfg_attr(test, feature(test, step_by))]

extern crate alloc;

use self::alloc::arc;

use std::fmt::{Formatter, Debug};
use std::fmt::Error as FmtError;
use std::raw::Slice as RawSlice;
use std::sync::Arc;
use std::mem;
use std::ops;

/// A vector that can be operated on concurrently via non-overlapping slices.
struct RacyCell<T>(T);
unsafe impl<T: Send> Sync for RacyCell<T> {}
///
/// Get a `ParVec` and a vector of slices via `new()`, send the slices to other threads
/// and mutate them, then get the mutated vector with `into_inner()` when finished.
pub struct ParVec<T> {
    data: Arc<RacyCell<Vec<T>>>,
}

impl<T: Send> ParVec<T> {
    /// Create a new `ParVec`, returning it and a vector of slices that can be sent
    /// to other threads and mutated concurrently.
    pub fn new(vec: Vec<T>, slices: usize) -> (ParVec<T>, Vec<ParSlice<T>>) {
        let slices = sub_slices(&vec, slice_count);
        let data = Arc::new(RacyCell(vec));

        let par_slices = slices.into_iter().map(|slice|
                ParSlice {
                    _vec: data.clone(),
                    data: slice,
                }
            ).collect();

        let par_vec = ParVec {
            data: data,
        };

        (par_vec, par_slices)
    }

    /// Take the inner `Vec` if there are no slices remaining.
    /// Returns `Err(self)` if there are still slices out there.
        // Unwrap if we hold a unique reference
        // (we don't use weak refs so ignore those)
    pub fn try_unwrap(mut self) -> Result<Vec<T>, ParVec<T>> {
        if let Some(data) = arc::get_mut(&mut self.data) {
             return Ok(mem::replace(&mut data.0, Vec::new()));
        }

        Err(self)
    }

    /// Take the inner `Vec`, waiting until all slices have been freed.
    pub fn unwrap(mut self) -> Vec<T> {
        loop {
            match self.try_unwrap() {
                Ok(vec) => return vec,
                Err(new_self) => self = new_self,
            }
            ::std::thread::yield_now();
        }
    }
}

fn sub_slices<T>(parent: &[T], slice_count: usize) -> Vec<RawSlice<T>> {
    use std::cmp;
    use std::raw::Repr;

    let mut start = 0;

    (1 .. slice_count + 1).rev().map(|curr| {
        let slice_len = (len - start) / curr;
        let end = cmp::min(start + slice_len, len);

        let slice = parent[start..end].repr();
        start += slice_len;

        slice
    }).collect()
}

/// A slice of `ParVec` that can be sent to another task for processing.
/// Automatically releases the slice on drop.
pub struct ParSlice<T: Send> {
    // Just to keep the source vector alive while the slice is,
    // since the ParVec can die asynchronously.
    _vec: Arc<RacyCell<Vec<T>>>,
    data: RawSlice<T>,
}

unsafe impl<T: Send> Send for ParSlice<T> {}

impl<T: Send> ops::Deref for ParSlice<T> {
    type Target = [T];

    fn deref<'a>(&'a self) -> &'a [T] {
        unsafe { mem::transmute(self.data) }
    }
}

impl<T: Send> ops::DerefMut for ParSlice<T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut [T] {
        unsafe { mem::transmute(self.data) }
    }
}

impl<T: Send> Debug for ParSlice<T> where T: Debug {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{:?}", &*self)
    }
}

#[cfg(test)]
mod test {
    extern crate rand;
    extern crate threadpool;
    extern crate test;

    use super::ParVec;

    use std::mem;

    use self::rand::{thread_rng, Rng};
    use self::test::Bencher;
    use self::threadpool::ThreadPool;

    const TEST_SLICES: usize = 8;
    const TEST_MAX: u32 = 1000;

    #[test]
    fn test_unwrap_safely() {
        let (vec, slices) = ParVec::new([5u32; TEST_MAX as usize].to_vec(), TEST_SLICES);
        mem::drop(slices);

        let vec = vec.unwrap();

        assert_eq!(&*vec, &[5u32; TEST_MAX as usize][..]);
    }

    #[test]
    fn test_slices() {
        let (_, slices) = ParVec::new((1u32 .. TEST_MAX).collect(), TEST_SLICES);

        assert_eq!(slices.len(), TEST_SLICES);
    }

    #[bench]
    fn seq_prime_factors_1000(b: &mut Bencher) {
        let vec: Vec<u32> = (1 .. TEST_MAX).collect();

        b.iter(|| {
            let _: Vec<(u32, Vec<u32>)> = vec.iter()
                .map(|&x| (x, get_prime_factors(x)))
                .collect();
        });
    }

    #[bench]
    fn par_prime_factors_1000(b: &mut Bencher) {
        let mut rng = thread_rng();
        let pool = ThreadPool::new(TEST_SLICES);

        b.iter(|| {
            let mut vec: Vec<(u32, Vec<u32>)> = (1 .. TEST_MAX)
                .map(|x| (x, Vec::new())).collect();

            // Shuffle so each thread gets an even distribution of work.
            // Otherwise, the lower threads will quit early.
            rng.shuffle(&mut *vec);

            let (par_vec, par_slices) = ParVec::new(vec, TEST_SLICES);

            for mut slice in par_slices.into_iter() {
                pool.execute(move ||
                    for pair in slice.iter_mut() {
                        let (x, ref mut x_primes) = *pair;
                        *x_primes = get_prime_factors(x);
                    }
                );
            }

            let mut vec = par_vec.unwrap();
            // Sort so they're in the same order as sequential.
            vec.sort();
        });
    }

    fn get_prime_factors(x: u32) -> Vec<u32> {
        (1 .. x).filter(|&y| x % y == 0 && is_prime(y)).collect()
    }

    fn is_prime(x: u32) -> bool {
        if x < 3 { return true; }

        if x & 1 == 0 { return false; }

        for i in (3 .. x).step_by(2) {
            if x % i == 0 { return false; }
        }

        true
    }

}

<|endoftext|>


<commit_before>//! This package contains just four macros, which enable the creation
//! of array references to portions of arrays or slices (or things
//! that can be sliced).
//!
//! # Examples
//!
//! Here is a simple example of slicing and dicing a slice into array
//! references with these macros.  Here we implement a simple
//! little-endian conversion from bytes to `u16`, and demonstrate code
//! that uses `array_ref!` to extract an array reference from a larger
//! array.  Note that the documentation for each macro also has an
//! example of its use.
//!
//! ```
//! #[macro_use]
//! extern crate arrayref;
//!
//! fn read_u16(bytes: &[u8; 2]) -> u16 {
//!      bytes[0] as u16 + ((bytes[1] as u16) << 8)
//! }
//! // ...
//! # fn main() {
//! let data = [0,1,2,3,4,0,6,7,8,9];
//! assert_eq!(256, read_u16(array_ref![data,0,2]));
//! assert_eq!(4, read_u16(array_ref![data,4,2]));
//! # }
//! ```
#![deny(warnings)]

#[cfg(test)]
extern crate quickcheck;

/// You can use `array_ref` to generate an array reference to a subset
/// of a sliceable bit of data (which could be an array, or a slice,
/// or a Vec).
///
/// **Panics** if the slice is out of bounds.
///
/// ```
/// #[macro_use]
/// extern crate arrayref;
///
/// fn read_u16(bytes: &[u8; 2]) -> u16 {
///      bytes[0] as u16 + ((bytes[1] as u16) << 8)
/// }
/// // ...
/// # fn main() {
/// let data = [0,1,2,3,4,0,6,7,8,9];
/// assert_eq!(256, read_u16(array_ref![data,0,2]));
/// assert_eq!(4, read_u16(array_ref![data,4,2]));
/// # }
/// ```

#[macro_export]
macro_rules! array_ref {
    ($arr:expr, $offset:expr, $len:expr) => {{
        {
            #[inline]
            unsafe fn as_array<T>(slice: &[T]) -> &[T; $len] {
                &*(slice.as_ptr() as *const [_; $len])
            }
            let offset = $offset;
            let slice = & $arr[offset..offset + $len];
            unsafe {
                as_array(slice)
            }
        }
    }}
}

/// You can use `array_refs` to generate a series of array references
/// to an input array reference.  The idea is if you want to break an
/// array into a series of contiguous and non-overlapping arrays.
/// `array_refs` is a bit funny in that it insists on slicing up the
/// *entire* array.  This is intentional, as I find it handy to make
/// me ensure that my sub-arrays add up to the entire array.  This
/// macro will *never* panic, since the sizes are all checked at
/// compile time.
///
/// Note that unlike `array_ref!`, `array_refs` *requires* that the
/// first argument be an array reference.  The following arguments are
/// the lengths of each subarray you wish a reference to.  The total
/// of these arguments *must* equal the size of the array itself.
///
/// ```
/// #[macro_use]
/// extern crate arrayref;
///
/// fn read_u16(bytes: &[u8; 2]) -> u16 {
///      bytes[0] as u16 + ((bytes[1] as u16) << 8)
/// }
/// // ...
/// # fn main() {
/// let data = [0,1,2,3,4,0,6,7];
/// let (a,b,c) = array_refs![&data,2,2,4];
/// assert_eq!(read_u16(a), 256);
/// assert_eq!(read_u16(b), 3*256+2);
/// assert_eq!(*c, [4,0,6,7]);
/// # }
/// ```
#[macro_export]
macro_rules! array_refs {
    ( $arr:expr, $( $len:expr ),* ) => {{
        {
            #[inline]
            #[allow(unused_assignments)]
            unsafe fn as_arrays<T>(a: &[T; $( $len + )* 0 ]) -> ( $( &[T; $len], )* ) {
                let mut p = a.as_ptr();
                ( $( {
                    let aref = &*(p as *const [T; $len]);
                    p = p.offset($len as isize);
                    aref
                } ),* )
            }
            let input = $arr;
            unsafe {
                as_arrays(input)
            }
        }
    }}
}

/// You can use `mut_array_refs` to generate a series of mutable array
/// references to an input mutable array reference.  The idea is if
/// you want to break an array into a series of contiguous and
/// non-overlapping mutable array references.  Like `array_refs!`,
/// `mut_array_refs!` is a bit funny in that it insists on slicing up
/// the *entire* array.  This is intentional, as I find it handy to
/// make me ensure that my sub-arrays add up to the entire array.
/// This macro will *never* panic, since the sizes are all checked at
/// compile time.
///
/// Note that unlike `array_mut_ref!`, `mut_array_refs` *requires*
/// that the first argument be a mutable array reference.  The
/// following arguments are the lengths of each subarray you wish a
/// reference to.  The total of these arguments *must* equal the size
/// of the array itself.  Also note that this macro allows you to take
/// out multiple mutable references to a single object, which is both
/// weird and powerful.
///
/// ```
/// #[macro_use]
/// extern crate arrayref;
///
/// fn write_u16(bytes: &mut [u8; 2], num: u16) {
///      bytes[0] = num as u8;
///      bytes[1] = (num >> 8) as u8;
/// }
/// fn write_u32(bytes: &mut [u8; 4], num: u32) {
///      bytes[0] = num as u8;
///      bytes[1] = (num >> 8) as u8; // this is buggy to save space...
/// }
/// // ...
/// # fn main() {
/// let mut data = [0,1,2,3,4,0,6,7];
/// let (a,b,c) = mut_array_refs![&mut data,2,2,4];
/// // let's write out some nice prime numbers!
/// write_u16(a, 37);
/// write_u16(b, 73);
/// write_u32(c, 137); // approximate inverse of the fine structure constant!
/// # }
/// ```
#[macro_export]
macro_rules! mut_array_refs {
    ( $arr:expr, $( $len:expr ),* ) => {{
        {
            #[inline]
            #[allow(unused_assignments)]
            unsafe fn as_arrays<T>(a: &mut [T; $( $len + )* 0 ]) -> ( $( &mut [T; $len], )* ) {
                let mut p = a.as_mut_ptr();
                ( $( {
                    let aref = &mut *(p as *mut [T; $len]);
                    p = p.offset($len as isize);
                    aref
                } ),* )
            }
            let input = $arr;
            unsafe {
                as_arrays(input)
            }
        }
    }}
}

/// You can use `array_mut_ref` to generate a mutable array reference
/// to a subset of a sliceable bit of data (which could be an array,
/// or a slice, or a Vec).
///
/// **Panics** if the slice is out of bounds.
///
/// ```
/// #[macro_use]
/// extern crate arrayref;
///
/// fn write_u16(bytes: &mut [u8; 2], num: u16) {
///      bytes[0] = num as u8;
///      bytes[1] = (num >> 8) as u8;
/// }
/// // ...
/// # fn main() {
/// let mut data = [0,1,2,3,4,0,6,7,8,9];
/// write_u16(array_mut_ref![data,0,2], 1);
/// write_u16(array_mut_ref![data,2,2], 5);
/// assert_eq!(*array_ref![data,0,4], [1,0,5,0]);
/// *array_mut_ref![data,4,5] = [4,3,2,1,0];
/// assert_eq!(data, [1,0,5,0,4,3,2,1,0,9]);
/// # }
/// ```
#[macro_export]
macro_rules! array_mut_ref {
    ($arr:expr, $offset:expr, $len:expr) => {{
        {
            #[inline]
            unsafe fn as_array<T>(slice: &mut [T]) -> &mut [T; $len] {
                &mut *(slice.as_mut_ptr() as *mut [_; $len])
            }
            let offset = $offset;
            let slice = &mut $arr[offset..offset + $len];
            unsafe {
                as_array(slice)
            }
        }
    }}
}

#[test]
#[should_panic]
fn checks_bounds() {
    let foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let bar = array_ref!(foo, 1, 11);
    println!("I am checking that I can dereference bar[0] = {}", bar[0]);
}

#[test]
fn simple_case_works() {
    fn check(expected: [u8; 3], actual: &[u8; 3]) {
        for (e, a) in (&expected).iter().zip(actual.iter()) {
            assert_eq!(e, a)
        }
    }
    let mut foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    {
        let bar = array_ref!(foo, 2, 3);
        check([2, 3, 4], bar);
    }
    check([0, 1, 2], array_ref!(foo, 0, 3));
    fn zero2(x: &mut [u8; 2]) {
        x[0] = 0;
        x[1] = 0;
    }
    zero2(array_mut_ref!(foo, 8, 2));
    check([0, 0, 10], array_ref!(foo, 8, 3));
}

#[test]
fn check_array_ref_5() {
    fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() < offset + 5 {
            return quickcheck::TestResult::discard();
        }
        let out = array_ref!(data, offset, 5);
        quickcheck::TestResult::from_bool(out.len() == 5)
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn check_array_ref_out_of_bounds_5() {
    fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() >= offset + 5 {
            return quickcheck::TestResult::discard();
        }
        quickcheck::TestResult::must_fail(move || {
            array_ref!(data, offset, 5);
        })
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn check_array_mut_ref_7() {
    fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() < offset + 7 {
            return quickcheck::TestResult::discard();
        }
        let out = array_mut_ref!(data, offset, 7);
        out[6] = 3;
        quickcheck::TestResult::from_bool(out.len() == 7)
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn check_array_mut_ref_out_of_bounds_32() {
    fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() >= offset + 32 {
            return quickcheck::TestResult::discard();
        }
        quickcheck::TestResult::must_fail(move || {
            array_mut_ref!(data, offset, 32);
        })
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn test_5_array_refs() {
    let mut data: [usize; 128] = [0; 128];
    for i in 0..128 {
        data[i] = i;
    }
    let data = data;
    let (a,b,c,d,e) = array_refs!(&data, 1, 14, 3, 100, 10);
    assert_eq!(a.len(), 1 as usize);
    assert_eq!(b.len(), 14 as usize);
    assert_eq!(c.len(), 3 as usize);
    assert_eq!(d.len(), 100 as usize);
    assert_eq!(e.len(), 10 as usize);
    assert_eq!(a, array_ref![data, 0, 1]);
    assert_eq!(b, array_ref![data, 1, 14]);
    assert_eq!(c, array_ref![data, 15, 3]);
    assert_eq!(e, array_ref![data, 118, 10]);
}

#[test]
fn test_5_mut_xarray_refs() {
    let mut data: [usize; 128] = [0; 128];
    {
        // temporarily borrow the data to modify it.
        let (a,b,c,d,e) = mut_array_refs!(&mut data, 1, 14, 3, 100, 10);
        assert_eq!(a.len(), 1 as usize);
        assert_eq!(b.len(), 14 as usize);
        assert_eq!(c.len(), 3 as usize);
        assert_eq!(d.len(), 100 as usize);
        assert_eq!(e.len(), 10 as usize);
        *a = [1; 1];
        *b = [14; 14];
        *c = [3; 3];
        *d = [100; 100];
        *e = [10; 10];
    }
    assert_eq!(&[1;1], array_ref![data, 0, 1]);
    assert_eq!(&[14;14], array_ref![data, 1, 14]);
    assert_eq!(&[3;3], array_ref![data, 15, 3]);
    assert_eq!(&[10;10], array_ref![data, 118, 10]);
}
<commit_msg>Add test module<commit_after>//! This package contains just four macros, which enable the creation
//! of array references to portions of arrays or slices (or things
//! that can be sliced).
//!
//! # Examples
//!
//! Here is a simple example of slicing and dicing a slice into array
//! references with these macros.  Here we implement a simple
//! little-endian conversion from bytes to `u16`, and demonstrate code
//! that uses `array_ref!` to extract an array reference from a larger
//! array.  Note that the documentation for each macro also has an
//! example of its use.
//!
//! ```
//! #[macro_use]
//! extern crate arrayref;
//!
//! fn read_u16(bytes: &[u8; 2]) -> u16 {
//!      bytes[0] as u16 + ((bytes[1] as u16) << 8)
//! }
//! // ...
//! # fn main() {
//! let data = [0,1,2,3,4,0,6,7,8,9];
//! assert_eq!(256, read_u16(array_ref![data,0,2]));
//! assert_eq!(4, read_u16(array_ref![data,4,2]));
//! # }
//! ```
#![deny(warnings)]

/// You can use `array_ref` to generate an array reference to a subset
/// of a sliceable bit of data (which could be an array, or a slice,
/// or a Vec).
///
/// **Panics** if the slice is out of bounds.
///
/// ```
/// #[macro_use]
/// extern crate arrayref;
///
/// fn read_u16(bytes: &[u8; 2]) -> u16 {
///      bytes[0] as u16 + ((bytes[1] as u16) << 8)
/// }
/// // ...
/// # fn main() {
/// let data = [0,1,2,3,4,0,6,7,8,9];
/// assert_eq!(256, read_u16(array_ref![data,0,2]));
/// assert_eq!(4, read_u16(array_ref![data,4,2]));
/// # }
/// ```

#[macro_export]
macro_rules! array_ref {
    ($arr:expr, $offset:expr, $len:expr) => {{
        {
            #[inline]
            unsafe fn as_array<T>(slice: &[T]) -> &[T; $len] {
                &*(slice.as_ptr() as *const [_; $len])
            }
            let offset = $offset;
            let slice = & $arr[offset..offset + $len];
            unsafe {
                as_array(slice)
            }
        }
    }}
}

/// You can use `array_refs` to generate a series of array references
/// to an input array reference.  The idea is if you want to break an
/// array into a series of contiguous and non-overlapping arrays.
/// `array_refs` is a bit funny in that it insists on slicing up the
/// *entire* array.  This is intentional, as I find it handy to make
/// me ensure that my sub-arrays add up to the entire array.  This
/// macro will *never* panic, since the sizes are all checked at
/// compile time.
///
/// Note that unlike `array_ref!`, `array_refs` *requires* that the
/// first argument be an array reference.  The following arguments are
/// the lengths of each subarray you wish a reference to.  The total
/// of these arguments *must* equal the size of the array itself.
///
/// ```
/// #[macro_use]
/// extern crate arrayref;
///
/// fn read_u16(bytes: &[u8; 2]) -> u16 {
///      bytes[0] as u16 + ((bytes[1] as u16) << 8)
/// }
/// // ...
/// # fn main() {
/// let data = [0,1,2,3,4,0,6,7];
/// let (a,b,c) = array_refs![&data,2,2,4];
/// assert_eq!(read_u16(a), 256);
/// assert_eq!(read_u16(b), 3*256+2);
/// assert_eq!(*c, [4,0,6,7]);
/// # }
/// ```
#[macro_export]
macro_rules! array_refs {
    ( $arr:expr, $( $len:expr ),* ) => {{
        {
            #[inline]
            #[allow(unused_assignments)]
            unsafe fn as_arrays<T>(a: &[T; $( $len + )* 0 ]) -> ( $( &[T; $len], )* ) {
                let mut p = a.as_ptr();
                ( $( {
                    let aref = &*(p as *const [T; $len]);
                    p = p.offset($len as isize);
                    aref
                } ),* )
            }
            let input = $arr;
            unsafe {
                as_arrays(input)
            }
        }
    }}
}

/// You can use `mut_array_refs` to generate a series of mutable array
/// references to an input mutable array reference.  The idea is if
/// you want to break an array into a series of contiguous and
/// non-overlapping mutable array references.  Like `array_refs!`,
/// `mut_array_refs!` is a bit funny in that it insists on slicing up
/// the *entire* array.  This is intentional, as I find it handy to
/// make me ensure that my sub-arrays add up to the entire array.
/// This macro will *never* panic, since the sizes are all checked at
/// compile time.
///
/// Note that unlike `array_mut_ref!`, `mut_array_refs` *requires*
/// that the first argument be a mutable array reference.  The
/// following arguments are the lengths of each subarray you wish a
/// reference to.  The total of these arguments *must* equal the size
/// of the array itself.  Also note that this macro allows you to take
/// out multiple mutable references to a single object, which is both
/// weird and powerful.
///
/// ```
/// #[macro_use]
/// extern crate arrayref;
///
/// fn write_u16(bytes: &mut [u8; 2], num: u16) {
///      bytes[0] = num as u8;
///      bytes[1] = (num >> 8) as u8;
/// }
/// fn write_u32(bytes: &mut [u8; 4], num: u32) {
///      bytes[0] = num as u8;
///      bytes[1] = (num >> 8) as u8; // this is buggy to save space...
/// }
/// // ...
/// # fn main() {
/// let mut data = [0,1,2,3,4,0,6,7];
/// let (a,b,c) = mut_array_refs![&mut data,2,2,4];
/// // let's write out some nice prime numbers!
/// write_u16(a, 37);
/// write_u16(b, 73);
/// write_u32(c, 137); // approximate inverse of the fine structure constant!
/// # }
/// ```
#[macro_export]
macro_rules! mut_array_refs {
    ( $arr:expr, $( $len:expr ),* ) => {{
        {
            #[inline]
            #[allow(unused_assignments)]
            unsafe fn as_arrays<T>(a: &mut [T; $( $len + )* 0 ]) -> ( $( &mut [T; $len], )* ) {
                let mut p = a.as_mut_ptr();
                ( $( {
                    let aref = &mut *(p as *mut [T; $len]);
                    p = p.offset($len as isize);
                    aref
                } ),* )
            }
            let input = $arr;
            unsafe {
                as_arrays(input)
            }
        }
    }}
}

/// You can use `array_mut_ref` to generate a mutable array reference
/// to a subset of a sliceable bit of data (which could be an array,
/// or a slice, or a Vec).
///
/// **Panics** if the slice is out of bounds.
///
/// ```
/// #[macro_use]
/// extern crate arrayref;
///
/// fn write_u16(bytes: &mut [u8; 2], num: u16) {
///      bytes[0] = num as u8;
///      bytes[1] = (num >> 8) as u8;
/// }
/// // ...
/// # fn main() {
/// let mut data = [0,1,2,3,4,0,6,7,8,9];
/// write_u16(array_mut_ref![data,0,2], 1);
/// write_u16(array_mut_ref![data,2,2], 5);
/// assert_eq!(*array_ref![data,0,4], [1,0,5,0]);
/// *array_mut_ref![data,4,5] = [4,3,2,1,0];
/// assert_eq!(data, [1,0,5,0,4,3,2,1,0,9]);
/// # }
/// ```
#[macro_export]
macro_rules! array_mut_ref {
    ($arr:expr, $offset:expr, $len:expr) => {{
        {
            #[inline]
            unsafe fn as_array<T>(slice: &mut [T]) -> &mut [T; $len] {
                &mut *(slice.as_mut_ptr() as *mut [_; $len])
            }
            let offset = $offset;
            let slice = &mut $arr[offset..offset + $len];
            unsafe {
                as_array(slice)
            }
        }
    }}
}

#[cfg(test)]
mod test {

extern crate quickcheck;

// use super::*;

#[test]
#[should_panic]
fn checks_bounds() {
    let foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let bar = array_ref!(foo, 1, 11);
    println!("I am checking that I can dereference bar[0] = {}", bar[0]);
}

#[test]
fn simple_case_works() {
    fn check(expected: [u8; 3], actual: &[u8; 3]) {
        for (e, a) in (&expected).iter().zip(actual.iter()) {
            assert_eq!(e, a)
        }
    }
    let mut foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    {
        let bar = array_ref!(foo, 2, 3);
        check([2, 3, 4], bar);
    }
    check([0, 1, 2], array_ref!(foo, 0, 3));
    fn zero2(x: &mut [u8; 2]) {
        x[0] = 0;
        x[1] = 0;
    }
    zero2(array_mut_ref!(foo, 8, 2));
    check([0, 0, 10], array_ref!(foo, 8, 3));
}

#[test]
fn check_array_ref_5() {
    fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() < offset + 5 {
            return quickcheck::TestResult::discard();
        }
        let out = array_ref!(data, offset, 5);
        quickcheck::TestResult::from_bool(out.len() == 5)
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn check_array_ref_out_of_bounds_5() {
    fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() >= offset + 5 {
            return quickcheck::TestResult::discard();
        }
        quickcheck::TestResult::must_fail(move || {
            array_ref!(data, offset, 5);
        })
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn check_array_mut_ref_7() {
    fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() < offset + 7 {
            return quickcheck::TestResult::discard();
        }
        let out = array_mut_ref!(data, offset, 7);
        out[6] = 3;
        quickcheck::TestResult::from_bool(out.len() == 7)
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn check_array_mut_ref_out_of_bounds_32() {
    fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
        if data.len() >= offset + 32 {
            return quickcheck::TestResult::discard();
        }
        quickcheck::TestResult::must_fail(move || {
            array_mut_ref!(data, offset, 32);
        })
    }
    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
}

#[test]
fn test_5_array_refs() {
    let mut data: [usize; 128] = [0; 128];
    for i in 0..128 {
        data[i] = i;
    }
    let data = data;
    let (a,b,c,d,e) = array_refs!(&data, 1, 14, 3, 100, 10);
    assert_eq!(a.len(), 1 as usize);
    assert_eq!(b.len(), 14 as usize);
    assert_eq!(c.len(), 3 as usize);
    assert_eq!(d.len(), 100 as usize);
    assert_eq!(e.len(), 10 as usize);
    assert_eq!(a, array_ref![data, 0, 1]);
    assert_eq!(b, array_ref![data, 1, 14]);
    assert_eq!(c, array_ref![data, 15, 3]);
    assert_eq!(e, array_ref![data, 118, 10]);
}

#[test]
fn test_5_mut_xarray_refs() {
    let mut data: [usize; 128] = [0; 128];
    {
        // temporarily borrow the data to modify it.
        let (a,b,c,d,e) = mut_array_refs!(&mut data, 1, 14, 3, 100, 10);
        assert_eq!(a.len(), 1 as usize);
        assert_eq!(b.len(), 14 as usize);
        assert_eq!(c.len(), 3 as usize);
        assert_eq!(d.len(), 100 as usize);
        assert_eq!(e.len(), 10 as usize);
        *a = [1; 1];
        *b = [14; 14];
        *c = [3; 3];
        *d = [100; 100];
        *e = [10; 10];
    }
    assert_eq!(&[1;1], array_ref![data, 0, 1]);
    assert_eq!(&[14;14], array_ref![data, 1, 14]);
    assert_eq!(&[3;3], array_ref![data, 15, 3]);
    assert_eq!(&[10;10], array_ref![data, 118, 10]);
}

} // mod test
<|endoftext|>


<commit_before>#![cfg(target_arch="x86_64")]

#![feature(const_fn)]
#![feature(asm)]
#![feature(associated_consts)]
#![no_std]
#![cfg_attr(test, allow(unused_features))]

pub use address::{VirtualAddress, PhysicalAddress};

#[macro_use]
extern crate bitflags;

#[macro_use]
extern crate raw_cpuid;

pub mod address;

macro_rules! bit {
    ( $x:expr ) => {
        1 << $x
    };
}

macro_rules! check_flag {
    ($doc:meta, $fun:ident, $flag:ident) => (
        #[$doc]
        pub fn $fun(&self) -> bool {
            self.contains($flag)
        }
    )
}

macro_rules! is_bit_set {
    ($field:expr, $bit:expr) => (
        $field & (1 << $bit) > 0
    )
}

macro_rules! check_bit_fn {
    ($doc:meta, $fun:ident, $field:ident, $bit:expr) => (
        #[$doc]
        pub fn $fun(&self) -> bool {
            is_bit_set!(self.$field, $bit)
        }
    )
}

pub mod time;
pub mod irq;
pub mod paging;
pub mod task;
pub mod syscall;
pub mod sgx;
pub mod control_regs;
pub mod descriptor;
pub mod dtables;
pub mod io;
pub mod msr;
pub mod flags;
pub mod segmentation;
pub mod tlb;

pub mod cpuid {
    pub use raw_cpuid::*;
}

#[derive(Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum PrivilegeLevel {
    Ring0 = 0,
    Ring1 = 1,
    Ring2 = 2,
    Ring3 = 3,
}

#[inline(always)]
pub unsafe fn halt() {
    asm!("hlt" :::: "volatile");
}

mod std {
    pub use core::fmt;
    pub use core::ops;
    pub use core::option;
}
<commit_msg>Remove dummy std module<commit_after>#![cfg(target_arch="x86_64")]

#![feature(const_fn)]
#![feature(asm)]
#![feature(associated_consts)]
#![no_std]
#![cfg_attr(test, allow(unused_features))]

pub use address::{VirtualAddress, PhysicalAddress};

#[macro_use]
extern crate bitflags;

#[macro_use]
extern crate raw_cpuid;

pub mod address;

macro_rules! bit {
    ( $x:expr ) => {
        1 << $x
    };
}

macro_rules! check_flag {
    ($doc:meta, $fun:ident, $flag:ident) => (
        #[$doc]
        pub fn $fun(&self) -> bool {
            self.contains($flag)
        }
    )
}

macro_rules! is_bit_set {
    ($field:expr, $bit:expr) => (
        $field & (1 << $bit) > 0
    )
}

macro_rules! check_bit_fn {
    ($doc:meta, $fun:ident, $field:ident, $bit:expr) => (
        #[$doc]
        pub fn $fun(&self) -> bool {
            is_bit_set!(self.$field, $bit)
        }
    )
}

pub mod time;
pub mod irq;
pub mod paging;
pub mod task;
pub mod syscall;
pub mod sgx;
pub mod control_regs;
pub mod descriptor;
pub mod dtables;
pub mod io;
pub mod msr;
pub mod flags;
pub mod segmentation;
pub mod tlb;

pub mod cpuid {
    pub use raw_cpuid::*;
}

#[derive(Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum PrivilegeLevel {
    Ring0 = 0,
    Ring1 = 1,
    Ring2 = 2,
    Ring3 = 3,
}

#[inline(always)]
pub unsafe fn halt() {
    asm!("hlt" :::: "volatile");
}
<|endoftext|>


<commit_before>#![feature(zero_one)]

extern crate libc;

use std::io::{self, Read, Write};
use std::num::One;
use std::ops::Neg;

mod ffi;

macro_rules! unsafe_try {
    ( $x:expr ) => {
        try!($crate::to_result(unsafe { $x }))
    };
}

pub struct Child {
    pid: libc::pid_t
}

impl Child {
    pub fn pid(&self) -> libc::pid_t { self.pid }

    pub fn wait(&self) {
        unsafe { libc::waitpid(self.pid, std::ptr::null(), 0) };
    }
}

pub struct Master {
    fd: libc::c_int
}

impl Master {
    pub fn fd(&self) -> libc::c_int { self.fd }

    pub fn close(&self) {
        unsafe { libc::close(self.fd) };
    }
}

impl Read for Master {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match to_result(unsafe {
            libc::read(self.fd,
                       buf.as_mut_ptr() as *mut libc::c_void,
                       buf.len() as libc::size_t)
        }) {
            Ok(nread) => Ok(nread as usize),
            Err(_)    => Ok(0 as usize)
        }
    }
}

impl Write for Master {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let ret = unsafe_try!(
            libc::write(self.fd,
                        buf.as_ptr() as *const libc::c_void,
                        buf.len() as libc::size_t)
        );

        Ok(ret as usize)
    }

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

impl Copy for Master {}

impl Clone for Master {
    fn clone(&self) -> Master { *self }
}

pub fn fork() -> io::Result<(Child, Master)>
{
    let pty_master = try!(open_ptm());
    let pid        = unsafe_try!(libc::fork());

    if pid == 0 {
        try!(attach_pts(pty_master));

        Ok((Child { pid: pid }, Master { fd: -1 }))
    }
    else {
        Ok((Child { pid: pid }, Master { fd: pty_master }))
    }
}

fn open_ptm() -> io::Result<libc::c_int> {
    let pty_master = unsafe_try!(ffi::posix_openpt(libc::O_RDWR));

    unsafe_try!(ffi::grantpt(pty_master));
    unsafe_try!(ffi::unlockpt(pty_master));

    Ok(pty_master)
}

fn attach_pts(pty_master: libc::c_int) -> io::Result<()> {
    let pts_name = unsafe { ffi::ptsname(pty_master) };

    if (pts_name as *const i32) == std::ptr::null() {
        return Err(io::Error::last_os_error())
    }

    unsafe_try!(libc::close(pty_master));
    unsafe_try!(libc::setsid());

    let pty_slave = unsafe_try!(libc::open(pts_name, libc::O_RDWR, 0));

    unsafe_try!(libc::dup2(pty_slave, libc::STDIN_FILENO));
    unsafe_try!(libc::dup2(pty_slave, libc::STDOUT_FILENO));
    unsafe_try!(libc::dup2(pty_slave, libc::STDERR_FILENO));

    unsafe_try!(libc::close(pty_slave));

    Ok(())
}

#[inline]
fn to_result<T: One + PartialEq + Neg<Output=T>>(t: T) -> io::Result<T> {
    let one: T = T::one();

    if t == -one {
        Err(io::Error::last_os_error())
    } else {
        Ok(t)
    }
}

#[cfg(test)]
mod tests {
    extern crate libc;

    use std::ffi::CString;
    use std::io::{Read, Write};
    use std::process::{Command, Stdio};
    use std::ptr;
    use std::string::String;
    use super::fork;

    #[test]
    fn it_fork_with_new_pty() {
        let (child, mut master) = fork().unwrap();

        if child.pid() == 0 {
            let mut ptrs = [CString::new("tty").unwrap().as_ptr(), ptr::null()];

            unsafe { libc::execvp(*ptrs.as_ptr(), ptrs.as_mut_ptr()) };
        }
        else {
            let mut string = String::new();

            match master.read_to_string(&mut string) {
                Ok(_)  => {
                    let output = Command::new("tty").stdin(Stdio::inherit()).output().unwrap().stdout;

                    let parent_tty = String::from_utf8_lossy(&output);
                    let child_tty  = string.trim();

                    assert!(child_tty != "");
                    assert!(child_tty != parent_tty);

                    let mut parent_tty_dir: Vec<&str> = parent_tty.split("/").collect();
                    let mut child_tty_dir:  Vec<&str> = child_tty.split("/").collect();

                    parent_tty_dir.pop();
                    child_tty_dir.pop();

                    assert_eq!(parent_tty_dir, child_tty_dir);
                },
                Err(e) => panic!("{}", e)
            }

            child.wait();
            master.close();
        }
    }

    #[test]
    fn it_can_read_write() {
        let (child, mut master) = fork().unwrap();

        if child.pid() == 0 {
            let mut ptrs = [CString::new("bash").unwrap().as_ptr(), ptr::null()];

            print!(" "); // FIXME I'm not sure but this is needed to prevent read-block.

            unsafe { libc::execvp(*ptrs.as_ptr(), ptrs.as_mut_ptr()) };
        }
        else {
            let _ = master.write("echo readme!\n".to_string().as_bytes());

            let mut string = String::new();

            match master.read_to_string(&mut string) {
                Ok(_)  => {
                    assert!(string.contains("readme!"));
                },
                Err(e) => panic!("{}", e)
            }

            let _ = master.write("exit\n".to_string().as_bytes());

            child.wait();
            master.close();
        }
    }
}
<commit_msg>Support stable rust<commit_after>extern crate libc;

use std::io::{self, Read, Write};

mod ffi;

macro_rules! unsafe_try {
    ( $x:expr ) => {
        try!($crate::to_result(unsafe { $x }))
    };
}

pub struct Child {
    pid: libc::pid_t
}

impl Child {
    pub fn pid(&self) -> libc::pid_t { self.pid }

    pub fn wait(&self) {
        unsafe { libc::waitpid(self.pid, std::ptr::null(), 0) };
    }
}

pub struct Master {
    fd: libc::c_int
}

impl Master {
    pub fn fd(&self) -> libc::c_int { self.fd }

    pub fn close(&self) {
        unsafe { libc::close(self.fd) };
    }
}

impl Read for Master {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match to_result(unsafe {
            libc::read(self.fd,
                       buf.as_mut_ptr() as *mut libc::c_void,
                       buf.len() as libc::size_t)
        }) {
            Ok(nread) => Ok(nread as usize),
            Err(_)    => Ok(0 as usize)
        }
    }
}

impl Write for Master {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let ret = unsafe_try!(
            libc::write(self.fd,
                        buf.as_ptr() as *const libc::c_void,
                        buf.len() as libc::size_t)
        );

        Ok(ret as usize)
    }

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

impl Copy for Master {}

impl Clone for Master {
    fn clone(&self) -> Master { *self }
}

pub fn fork() -> io::Result<(Child, Master)>
{
    let pty_master = try!(open_ptm());
    let pid        = unsafe_try!(libc::fork());

    if pid == 0 {
        try!(attach_pts(pty_master));

        Ok((Child { pid: pid }, Master { fd: -1 }))
    }
    else {
        Ok((Child { pid: pid }, Master { fd: pty_master }))
    }
}

fn open_ptm() -> io::Result<libc::c_int> {
    let pty_master = unsafe_try!(ffi::posix_openpt(libc::O_RDWR));

    unsafe_try!(ffi::grantpt(pty_master));
    unsafe_try!(ffi::unlockpt(pty_master));

    Ok(pty_master)
}

fn attach_pts(pty_master: libc::c_int) -> io::Result<()> {
    let pts_name = unsafe { ffi::ptsname(pty_master) };

    if (pts_name as *const i32) == std::ptr::null() {
        return Err(io::Error::last_os_error())
    }

    unsafe_try!(libc::close(pty_master));
    unsafe_try!(libc::setsid());

    let pty_slave = unsafe_try!(libc::open(pts_name, libc::O_RDWR, 0));

    unsafe_try!(libc::dup2(pty_slave, libc::STDIN_FILENO));
    unsafe_try!(libc::dup2(pty_slave, libc::STDOUT_FILENO));
    unsafe_try!(libc::dup2(pty_slave, libc::STDERR_FILENO));

    unsafe_try!(libc::close(pty_slave));

    Ok(())
}

// XXX use <T: Neg<Output=T> + One + PartialEq> trait instead
trait CReturnValue { fn as_c_return_value_is_error(&self) -> bool; }

macro_rules! impl_as_c_return_value_is_error {
    () => {
        fn as_c_return_value_is_error(&self) -> bool { *self == -1 }
    }
}

impl CReturnValue for i32 { impl_as_c_return_value_is_error!(); }
impl CReturnValue for i64 { impl_as_c_return_value_is_error!(); }

#[inline]
fn to_result<T: CReturnValue>(r: T) -> io::Result<T> {
    if r.as_c_return_value_is_error() {
        Err(io::Error::last_os_error())
    } else {
        Ok(r)
    }
}

#[cfg(test)]
mod tests {
    extern crate libc;

    use std::ffi::CString;
    use std::io::{Read, Write};
    use std::process::{Command, Stdio};
    use std::ptr;
    use std::string::String;
    use super::fork;

    #[test]
    fn it_fork_with_new_pty() {
        let (child, mut master) = fork().unwrap();

        if child.pid() == 0 {
            let mut ptrs = [CString::new("tty").unwrap().as_ptr(), ptr::null()];

            unsafe { libc::execvp(*ptrs.as_ptr(), ptrs.as_mut_ptr()) };
        }
        else {
            let mut string = String::new();

            match master.read_to_string(&mut string) {
                Ok(_)  => {
                    let output = Command::new("tty").stdin(Stdio::inherit()).output().unwrap().stdout;

                    let parent_tty = String::from_utf8_lossy(&output);
                    let child_tty  = string.trim();

                    assert!(child_tty != "");
                    assert!(child_tty != parent_tty);

                    let mut parent_tty_dir: Vec<&str> = parent_tty.split("/").collect();
                    let mut child_tty_dir:  Vec<&str> = child_tty.split("/").collect();

                    parent_tty_dir.pop();
                    child_tty_dir.pop();

                    assert_eq!(parent_tty_dir, child_tty_dir);
                },
                Err(e) => panic!("{}", e)
            }

            child.wait();
            master.close();
        }
    }

    #[test]
    fn it_can_read_write() {
        let (child, mut master) = fork().unwrap();

        if child.pid() == 0 {
            let mut ptrs = [CString::new("bash").unwrap().as_ptr(), ptr::null()];

            print!(" "); // FIXME I'm not sure but this is needed to prevent read-block.

            unsafe { libc::execvp(*ptrs.as_ptr(), ptrs.as_mut_ptr()) };
        }
        else {
            let _ = master.write("echo readme!\n".to_string().as_bytes());

            let mut string = String::new();

            match master.read_to_string(&mut string) {
                Ok(_)  => {
                    assert!(string.contains("readme!"));
                },
                Err(e) => panic!("{}", e)
            }

            let _ = master.write("exit\n".to_string().as_bytes());

            child.wait();
            master.close();
        }
    }
}
<|endoftext|>


<commit_before>#![feature(proc_macro_non_items)]

pub mod app;
pub mod time;
pub mod render;
<commit_msg>Fix the procedural macro hygiene stuff.<commit_after>#![feature(proc_macro_hygiene)]

pub mod app;
pub mod time;
pub mod render;
<|endoftext|>


<commit_before>extern crate regex;
use std::path::Path;
use std::fs::File;
use std::io::Read;

mod event;
mod output;
mod sass;
mod tokenizer;
mod top_level_event;
mod variable_mapper;

use tokenizer::Tokenizer;

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug)]
pub struct Error {
    pub message: String,
    pub kind: ErrorKind,
}

impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Error {
        Error { message: format!("IO error! {}", err), kind: ErrorKind::IoError }
    }
}

#[derive(Debug)]
pub enum ErrorKind {
    IoError,
    InvalidStyle,
}

pub fn compile(inputfile: &str, style: &str) -> Result<String> {
    let mut file = try!(File::open(&Path::new(inputfile)));
    let mut sass = String::new();

    try!(file.read_to_string(&mut sass));
    let mut st = Tokenizer::new(&sass);
    match style {
        "nested"     => Ok(output::nested(&mut st)),
        "compressed" => Ok(output::compressed(&mut st)),
        "expanded"   => Ok(output::expanded(&mut st)),
        "compact"    => Ok(output::compact(&mut st)),
        "debug"      => Ok(output::debug(&mut st)),
        _            => {
            Err(Error {
                kind: ErrorKind::InvalidStyle,
                message: format!("Unknown style {:?}. Please specify one of nested, compressed, expanded, or compact.", style),
            })
        },
    }
}
<commit_msg>Rename st to tokenizer<commit_after>extern crate regex;
use std::path::Path;
use std::fs::File;
use std::io::Read;

mod event;
mod output;
mod sass;
mod tokenizer;
mod top_level_event;
mod variable_mapper;

use tokenizer::Tokenizer;

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug)]
pub struct Error {
    pub message: String,
    pub kind: ErrorKind,
}

impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Error {
        Error { message: format!("IO error! {}", err), kind: ErrorKind::IoError }
    }
}

#[derive(Debug)]
pub enum ErrorKind {
    IoError,
    InvalidStyle,
}

pub fn compile(inputfile: &str, style: &str) -> Result<String> {
    let mut file = try!(File::open(&Path::new(inputfile)));
    let mut sass = String::new();

    try!(file.read_to_string(&mut sass));
    let mut tokenizer = Tokenizer::new(&sass);
    match style {
        "nested"     => Ok(output::nested(&mut tokenizer)),
        "compressed" => Ok(output::compressed(&mut tokenizer)),
        "expanded"   => Ok(output::expanded(&mut tokenizer)),
        "compact"    => Ok(output::compact(&mut tokenizer)),
        "debug"      => Ok(output::debug(&mut tokenizer)),
        _            => {
            Err(Error {
                kind: ErrorKind::InvalidStyle,
                message: format!("Unknown style {:?}. Please specify one of nested, compressed, expanded, or compact.", style),
            })
        },
    }
}
<|endoftext|>