<commit_before>// !
// Entity component system
//

extern crate fnv;
extern crate rustc_serialize;

use std::default::Default;
use std::ops::{Deref, DerefMut, Index, IndexMut};
use std::collections::{HashMap, hash_map, HashSet, hash_set};

/// Handle for an entity in the entity component system.
///
/// The internal value is the unique identifier for the entity. No two
/// entities should get the same UID during the lifetime of the ECS.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, RustcEncodable, RustcDecodable)]
pub struct Entity(pub usize);

pub trait AnyComponent {
    /// Remove an entity's component.
    fn remove(&mut self, e: Entity);
}

/// Storage for a single component type.
#[derive(RustcEncodable, RustcDecodable)]
pub struct ComponentData<C> {
    // TODO: Add reused index fields to entities and use VecMap with the
    // index field instead of HashMap with the UID here for more
    // efficient access.
    data: HashMap<Entity, C>,
}

impl<C> ComponentData<C> {
    pub fn new() -> ComponentData<C> {
        ComponentData { data: HashMap::default() }
    }

    /// Insert a component to an entity.
    pub fn insert(&mut self, e: Entity, comp: C) {
        self.data.insert(e, comp);
    }

    /// Return whether an entity contains this component.
    pub fn contains(&self, e: Entity) -> bool {
        self.data.contains_key(&e)
    }

    /// Get a reference to a component only if it exists for this entity.
    pub fn get(&self, e: Entity) -> Option<&C> {
        self.data.get(&e)
    }

    /// Get a mutable reference to a component only if it exists for this entity.
    pub fn get_mut(&mut self, e: Entity) -> Option<&mut C> {
        self.data.get_mut(&e)
    }

    /// Iterate entity-component pairs for this component.
    pub fn iter(&self) -> hash_map::Iter<Entity, C> {
        self.data.iter()
    }

    /// Iterate mutable entity-component pairs for this component.
    pub fn iter_mut(&mut self) -> hash_map::IterMut<Entity, C> {
        self.data.iter_mut()
    }
}

impl<C> Index<Entity> for ComponentData<C> {
    type Output = C;

    fn index<'a>(&'a self, e: Entity) -> &'a C {
        self.data.get(&e).unwrap()
    }
}

impl<C> IndexMut<Entity> for ComponentData<C> {
    fn index_mut<'a>(&'a mut self, e: Entity) -> &'a mut C {
        self.data.get_mut(&e).unwrap()
    }
}

impl<C> AnyComponent for ComponentData<C> {
    fn remove(&mut self, e: Entity) {
        self.data.remove(&e);
    }
}

pub trait Store {
    /// Perform an operation for each component container.
    fn for_each_component<F>(&mut self, f: F) where F: FnMut(&mut AnyComponent);
}

#[derive(RustcEncodable, RustcDecodable)]
pub struct Ecs<ST> {
    next_uid: usize,
    active: HashSet<Entity>,
    store: ST,
}

impl<ST: Default + Store> Ecs<ST> {
    pub fn new() -> Ecs<ST> {
        Ecs {
            next_uid: 1,
            active: HashSet::default(),
            store: Default::default(),
        }
    }

    /// Create a new empty entity.
    pub fn make(&mut self) -> Entity {
        let next = self.next_uid;
        self.next_uid += 1;
        let ret = Entity(next);
        self.active.insert(ret);
        ret
    }

    /// Remove an entity from the system and clear its components.
    pub fn remove(&mut self, e: Entity) {
        self.active.remove(&e);
        self.store.for_each_component(|c| c.remove(e));
    }

    /// Return whether the system contains an entity.
    pub fn contains(&self, e: Entity) -> bool {
        self.active.contains(&e)
    }

    pub fn iter(&self) -> hash_set::Iter<Entity> {
        self.active.iter()
    }
}

impl<ST> Deref for Ecs<ST> {
    type Target = ST;

    fn deref(&self) -> &ST {
        &self.store
    }
}

impl<ST> DerefMut for Ecs<ST> {
    fn deref_mut(&mut self) -> &mut ST {
        &mut self.store
    }
}

/// Entity component system builder macro.
///
/// Defines a local `Ecs` type that's parametrized with a custom component
/// store type with the component types you specify. Will also define a trait
/// `Component` which will be implemented for the component types.
#[macro_export]
macro_rules! Ecs {
    {
        // Declare the type of the (plain old data) component and the
        // identifier to use for it in the ECS.
        $($compname:ident: $comptype:ty,)+
    } => {
        mod _ecs_inner {
            // Use the enum to convert components to numbers for component bit masks etc.
            #[allow(non_camel_case_types, dead_code)]
            pub enum ComponentNum {
                $($compname,)+
            }

        }

        pub use self::_ecs_inner::ComponentNum;

        #[derive(RustcEncodable, RustcDecodable)]
        pub struct _ComponentStore {
            $(pub $compname: $crate::ComponentData<$comptype>),+
        }

        impl ::std::default::Default for _ComponentStore {
            fn default() -> _ComponentStore {
                _ComponentStore {
                    $($compname: $crate::ComponentData::new()),+
                }
            }
        }

        impl $crate::Store for _ComponentStore {
            fn for_each_component<F>(&mut self, mut f: F)
                where F: FnMut(&mut $crate::AnyComponent)
            {
                $(f(&mut self.$compname as &mut $crate::AnyComponent);)+
            }
        }

        #[allow(dead_code)]
        pub fn matches_mask(ecs: &$crate::Ecs<_ComponentStore>, e: $crate::Entity, mask: u64) -> bool {
            $(if mask & (1 << ComponentNum::$compname as u8) != 0 && !ecs.$compname.contains(e) {
                return false;
            })+
            return true;
        }

        /// Common operations for ECS component value types.
        pub trait Component {
            /// Add a clone of the component value to an entity in an ECS.
            ///
            /// Can't move the component itself since we might be using this
            /// through a trait object.
            fn add_to_ecs(&self, ecs: &mut $crate::Ecs<_ComponentStore>, e: $crate::Entity);

            /// Add a clone of the component to a loadout struct.
            fn add_to_loadout(self, loadout: &mut Loadout);
        }

        $(impl Component for $comptype {
            fn add_to_ecs(&self, ecs: &mut $crate::Ecs<_ComponentStore>, e: $crate::Entity) {
                ecs.$compname.insert(e, self.clone());
            }

            fn add_to_loadout(self, loadout: &mut Loadout) {
                loadout.$compname = Some(self);
            }
        })+

        pub type Ecs = $crate::Ecs<_ComponentStore>;

        /// A straightforward representation for the complete data of an
        /// entity.
        #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
        pub struct Loadout {
            $(pub $compname: Option<$comptype>),+
        }

        impl ::std::default::Default for Loadout {
            fn default() -> Loadout {
                Loadout {
                    $($compname: None),+
                }
            }
        }

        #[allow(dead_code)]
        impl Loadout {
            /// Create a new blank loadout.
            pub fn new() -> Loadout { Default::default() }

            /// Get the loadout that corresponds to an existing entity.
            pub fn get(ecs: &Ecs, e: $crate::Entity) -> Loadout {
                Loadout {
                    $($compname: ecs.$compname.get(e).map(|e| e.clone())),+
                }
            }

            /// Create a new entity in the ECS with this loadout.
            pub fn make(&self, ecs: &mut Ecs) -> $crate::Entity {
                let e = ecs.make();
                $(self.$compname.as_ref().map(|c| ecs.$compname.insert(e, c.clone()));)+
                e
            }

            /// Builder method for adding a component to this loadout.
            pub fn c<C: Component>(mut self, comp: C) -> Loadout {
                comp.add_to_loadout(&mut self);
                self
            }
        }
    }
}

/// Build a component type mask to match component iteration with.
///
/// You must have ComponentNum enum from the Ecs! macro expansion in scope
/// when using this.
#[macro_export]
macro_rules! build_mask {
    ( $($compname:ident),+ ) => {
        0u64 $(| (1u64 << ComponentNum::$compname as u8))+
    }
}
<commit_msg>Add rustdoc<commit_after>// !
// Entity component system
//

extern crate fnv;
extern crate rustc_serialize;

use std::default::Default;
use std::ops::{Deref, DerefMut, Index, IndexMut};
use std::collections::{HashMap, hash_map, HashSet, hash_set};

/// Handle for an entity in the entity component system.
///
/// The internal value is the unique identifier for the entity. No two
/// entities should get the same UID during the lifetime of the ECS.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, RustcEncodable, RustcDecodable)]
pub struct Entity(pub usize);

pub trait AnyComponent {
    /// Remove an entity's component.
    fn remove(&mut self, e: Entity);
}

/// Storage for a single component type.
#[derive(RustcEncodable, RustcDecodable)]
pub struct ComponentData<C> {
    // TODO: Add reused index fields to entities and use VecMap with the
    // index field instead of HashMap with the UID here for more
    // efficient access.
    data: HashMap<Entity, C>,
}

impl<C> ComponentData<C> {
    pub fn new() -> ComponentData<C> {
        ComponentData { data: HashMap::default() }
    }

    /// Insert a component to an entity.
    pub fn insert(&mut self, e: Entity, comp: C) {
        self.data.insert(e, comp);
    }

    /// Return whether an entity contains this component.
    pub fn contains(&self, e: Entity) -> bool {
        self.data.contains_key(&e)
    }

    /// Get a reference to a component only if it exists for this entity.
    pub fn get(&self, e: Entity) -> Option<&C> {
        self.data.get(&e)
    }

    /// Get a mutable reference to a component only if it exists for this entity.
    pub fn get_mut(&mut self, e: Entity) -> Option<&mut C> {
        self.data.get_mut(&e)
    }

    /// Iterate entity-component pairs for this component.
    pub fn iter(&self) -> hash_map::Iter<Entity, C> {
        self.data.iter()
    }

    /// Iterate mutable entity-component pairs for this component.
    pub fn iter_mut(&mut self) -> hash_map::IterMut<Entity, C> {
        self.data.iter_mut()
    }
}

impl<C> Index<Entity> for ComponentData<C> {
    type Output = C;

    fn index<'a>(&'a self, e: Entity) -> &'a C {
        self.data.get(&e).unwrap()
    }
}

impl<C> IndexMut<Entity> for ComponentData<C> {
    fn index_mut<'a>(&'a mut self, e: Entity) -> &'a mut C {
        self.data.get_mut(&e).unwrap()
    }
}

impl<C> AnyComponent for ComponentData<C> {
    fn remove(&mut self, e: Entity) {
        self.data.remove(&e);
    }
}

pub trait Store {
    /// Perform an operation for each component container.
    fn for_each_component<F>(&mut self, f: F) where F: FnMut(&mut AnyComponent);
}

/// Generic entity component system container
///
/// Needs to be specified with the parametrized `Store` type that has struct fields for the actual
/// components. This can be done with the `Ecs!` macro.
#[derive(RustcEncodable, RustcDecodable)]
pub struct Ecs<ST> {
    next_uid: usize,
    active: HashSet<Entity>,
    store: ST,
}

impl<ST: Default + Store> Ecs<ST> {
    pub fn new() -> Ecs<ST> {
        Ecs {
            next_uid: 1,
            active: HashSet::default(),
            store: Default::default(),
        }
    }

    /// Create a new empty entity.
    pub fn make(&mut self) -> Entity {
        let next = self.next_uid;
        self.next_uid += 1;
        let ret = Entity(next);
        self.active.insert(ret);
        ret
    }

    /// Remove an entity from the system and clear its components.
    pub fn remove(&mut self, e: Entity) {
        self.active.remove(&e);
        self.store.for_each_component(|c| c.remove(e));
    }

    /// Return whether the system contains an entity.
    pub fn contains(&self, e: Entity) -> bool {
        self.active.contains(&e)
    }

    pub fn iter(&self) -> hash_set::Iter<Entity> {
        self.active.iter()
    }
}

impl<ST> Deref for Ecs<ST> {
    type Target = ST;

    fn deref(&self) -> &ST {
        &self.store
    }
}

impl<ST> DerefMut for Ecs<ST> {
    fn deref_mut(&mut self) -> &mut ST {
        &mut self.store
    }
}

/// Entity component system builder macro.
///
/// Defines a local `Ecs` type that's parametrized with a custom component
/// store type with the component types you specify. Will also define a trait
/// `Component` which will be implemented for the component types.
#[macro_export]
macro_rules! Ecs {
    {
        // Declare the type of the (plain old data) component and the
        // identifier to use for it in the ECS.
        $($compname:ident: $comptype:ty,)+
    } => {
        mod _ecs_inner {
            // Use the enum to convert components to numbers for component bit masks etc.
            #[allow(non_camel_case_types, dead_code)]
            pub enum ComponentNum {
                $($compname,)+
            }

        }

        pub use self::_ecs_inner::ComponentNum;

        #[derive(RustcEncodable, RustcDecodable)]
        pub struct _ComponentStore {
            $(pub $compname: $crate::ComponentData<$comptype>),+
        }

        impl ::std::default::Default for _ComponentStore {
            fn default() -> _ComponentStore {
                _ComponentStore {
                    $($compname: $crate::ComponentData::new()),+
                }
            }
        }

        impl $crate::Store for _ComponentStore {
            fn for_each_component<F>(&mut self, mut f: F)
                where F: FnMut(&mut $crate::AnyComponent)
            {
                $(f(&mut self.$compname as &mut $crate::AnyComponent);)+
            }
        }

        #[allow(dead_code)]
        pub fn matches_mask(ecs: &$crate::Ecs<_ComponentStore>, e: $crate::Entity, mask: u64) -> bool {
            $(if mask & (1 << ComponentNum::$compname as u8) != 0 && !ecs.$compname.contains(e) {
                return false;
            })+
            return true;
        }

        /// Common operations for ECS component value types.
        pub trait Component {
            /// Add a clone of the component value to an entity in an ECS.
            ///
            /// Can't move the component itself since we might be using this
            /// through a trait object.
            fn add_to_ecs(&self, ecs: &mut $crate::Ecs<_ComponentStore>, e: $crate::Entity);

            /// Add a clone of the component to a loadout struct.
            fn add_to_loadout(self, loadout: &mut Loadout);
        }

        $(impl Component for $comptype {
            fn add_to_ecs(&self, ecs: &mut $crate::Ecs<_ComponentStore>, e: $crate::Entity) {
                ecs.$compname.insert(e, self.clone());
            }

            fn add_to_loadout(self, loadout: &mut Loadout) {
                loadout.$compname = Some(self);
            }
        })+

        pub type Ecs = $crate::Ecs<_ComponentStore>;

        /// A straightforward representation for the complete data of an
        /// entity.
        #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
        pub struct Loadout {
            $(pub $compname: Option<$comptype>),+
        }

        impl ::std::default::Default for Loadout {
            fn default() -> Loadout {
                Loadout {
                    $($compname: None),+
                }
            }
        }

        #[allow(dead_code)]
        impl Loadout {
            /// Create a new blank loadout.
            pub fn new() -> Loadout { Default::default() }

            /// Get the loadout that corresponds to an existing entity.
            pub fn get(ecs: &Ecs, e: $crate::Entity) -> Loadout {
                Loadout {
                    $($compname: ecs.$compname.get(e).map(|e| e.clone())),+
                }
            }

            /// Create a new entity in the ECS with this loadout.
            pub fn make(&self, ecs: &mut Ecs) -> $crate::Entity {
                let e = ecs.make();
                $(self.$compname.as_ref().map(|c| ecs.$compname.insert(e, c.clone()));)+
                e
            }

            /// Builder method for adding a component to this loadout.
            pub fn c<C: Component>(mut self, comp: C) -> Loadout {
                comp.add_to_loadout(&mut self);
                self
            }
        }
    }
}

/// Build a component type mask to match component iteration with.
///
/// You must have ComponentNum enum from the Ecs! macro expansion in scope
/// when using this.
#[macro_export]
macro_rules! build_mask {
    ( $($compname:ident),+ ) => {
        0u64 $(| (1u64 << ComponentNum::$compname as u8))+
    }
}
<|endoftext|>


<commit_before>//! Bit utilities for Rust
//!
//! This will eventually expand to include Nibbles and packing them into bytes and integers.

<commit_msg>Add BitInformation and implement it for u8<commit_after>//! Bit utilities for Rust
//!
//! This will eventually expand to include Nibbles and packing them into bytes and integers.

pub trait BitInformation {

    /// Gets the number of bits contained in this type
    fn number_of_bits(&self) -> usize;

    /// Checks to see if bit X is set
    fn has_x_bit(&self, position: usize) -> bool;

    /// Checks to see if the requested bit position is in bounds
    fn is_bit_in_bounds(&self, position: usize) -> bool {
        position <= self.number_of_bits()
    }

    /// Checks to see if the most signifigant bit is set
    fn has_most_signifigant_bit(&self) -> bool {
        self.has_x_bit(self.number_of_bits() - 1) //8 bits? position 7.
    }

}

impl BitInformation for u8 {

    /// Gets the number of bits contained in this type
    fn number_of_bits(&self) -> usize {
        8
    }

    fn has_x_bit(&self, position: usize) -> bool {
        if self.is_bit_in_bounds(position) {
            return (self & (0b00000001 << position)) != 0;
        } else {
            return false; //Huh
        }
    }

}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_number_of_bits_u8() {
        assert_eq!(8, 1u8.number_of_bits());
        assert_eq!(8, 255u8.number_of_bits());
    }

    #[test]
    fn test_most_signifigant_bit_u8() {
        assert!(1u8.has_most_signifigant_bit() == false);
        assert!(0b10101010u8.has_most_signifigant_bit() == true);
        assert!(0b10111000u8.has_most_signifigant_bit() == true);
    }

    #[test]
    fn test_bit_in_bounds_u8() {
        assert!(25u8.is_bit_in_bounds(1));
        assert!(25u8.is_bit_in_bounds(9) == false);
    }

    #[test]
    fn test_has_x_bit_u8() {
        let num: u8 = 0b10101010u8;

        assert!(num.has_x_bit(0) == false);
        assert!(num.has_x_bit(1) == true);
        assert!(num.has_x_bit(2) == false);
        assert!(num.has_x_bit(3) == true);
        assert!(num.has_x_bit(4) == false);
        assert!(num.has_x_bit(5) == true);
        assert!(num.has_x_bit(6) == false);
        assert!(num.has_x_bit(7) == true);
    }

}<|endoftext|>


<commit_before>#![feature(libc)]

extern crate libc;
extern crate "glib-2_0-sys" as glib;
extern crate "gobject-2_0-sys" as gobject;

pub mod notification;

pub use notification::*;

use libc::{
    c_char
};

use glib::types::{
    gboolean,
};

use glib::GList;

extern "C" {
    pub fn notify_init(app_name: *const c_char) -> gboolean;
    pub fn notify_uninit();
    pub fn notify_is_initted() -> gboolean;

    pub fn notify_get_app_name() -> *const c_char;
    pub fn notify_set_app_name(app_name: *const c_char);

    pub fn notify_get_server_caps() -> *mut GList;

    pub fn notify_get_server_info(ret_name: *mut *mut c_char,
                                  ret_vendor: *mut *mut c_char,
                                  ret_version: *mut *mut c_char,
                                  ret_spec_version: *mut *mut c_char);
}
<commit_msg>Clean up some use declarations<commit_after>#![feature(libc)]

extern crate libc;
extern crate "glib-2_0-sys" as glib;
extern crate "gobject-2_0-sys" as gobject;

pub mod notification;

pub use notification::*;

use libc::c_char;
use glib::types::gboolean;

use glib::GList;

extern "C" {
    pub fn notify_init(app_name: *const c_char) -> gboolean;
    pub fn notify_uninit();
    pub fn notify_is_initted() -> gboolean;

    pub fn notify_get_app_name() -> *const c_char;
    pub fn notify_set_app_name(app_name: *const c_char);

    pub fn notify_get_server_caps() -> *mut GList;

    pub fn notify_get_server_info(ret_name: *mut *mut c_char,
                                  ret_vendor: *mut *mut c_char,
                                  ret_version: *mut *mut c_char,
                                  ret_spec_version: *mut *mut c_char);
}
<|endoftext|>


<commit_before>//! Bit utilities for Rust
//!
//! This will eventually expand to include Nibbles and packing them into bytes and integers.

pub trait BitInformation {

    /// Gets the number of bits contained in this type
    fn number_of_bits(&self) -> usize;

    /// Checks to see if bit X is set
    fn has_x_bit(&self, position: usize) -> bool;

    /// Checks to see if the requested bit position is in bounds
    fn is_bit_in_bounds(&self, position: usize) -> bool {
        position <= self.number_of_bits()
    }

    /// Checks to see if the most signifigant bit is set
    fn has_most_signifigant_bit(&self) -> bool {
        self.has_x_bit(self.number_of_bits() - 1) //8 bits? position 7.
    }

}

impl BitInformation for u8 {

    /// Gets the number of bits contained in this type
    fn number_of_bits(&self) -> usize {
        8
    }

    fn has_x_bit(&self, position: usize) -> bool {
        if self.is_bit_in_bounds(position) {
            return (self & (0b00000001 << position)) != 0;
        } else {
            return false; //Huh
        }
    }

}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_number_of_bits_u8() {
        assert_eq!(8, 1u8.number_of_bits());
        assert_eq!(8, 255u8.number_of_bits());
    }

    #[test]
    fn test_most_signifigant_bit_u8() {
        assert!(1u8.has_most_signifigant_bit() == false);
        assert!(0b10101010u8.has_most_signifigant_bit() == true);
        assert!(0b10111000u8.has_most_signifigant_bit() == true);
    }

    #[test]
    fn test_bit_in_bounds_u8() {
        assert!(25u8.is_bit_in_bounds(1));
        assert!(25u8.is_bit_in_bounds(9) == false);
    }

    #[test]
    fn test_has_x_bit_u8() {
        let num: u8 = 0b10101010u8;

        assert!(num.has_x_bit(0) == false);
        assert!(num.has_x_bit(1) == true);
        assert!(num.has_x_bit(2) == false);
        assert!(num.has_x_bit(3) == true);
        assert!(num.has_x_bit(4) == false);
        assert!(num.has_x_bit(5) == true);
        assert!(num.has_x_bit(6) == false);
        assert!(num.has_x_bit(7) == true);
    }

}<commit_msg>Remove unneeded dupe in test<commit_after>//! Bit utilities for Rust
//!
//! This will eventually expand to include Nibbles and packing them into bytes and integers.

pub trait BitInformation {

    /// Gets the number of bits contained in this type
    fn number_of_bits(&self) -> usize;

    /// Checks to see if bit X is set
    fn has_x_bit(&self, position: usize) -> bool;

    /// Checks to see if the requested bit position is in bounds
    fn is_bit_in_bounds(&self, position: usize) -> bool {
        position <= self.number_of_bits()
    }

    /// Checks to see if the most signifigant bit is set
    fn has_most_signifigant_bit(&self) -> bool {
        self.has_x_bit(self.number_of_bits() - 1) //8 bits? position 7.
    }

}

impl BitInformation for u8 {

    /// Gets the number of bits contained in this type
    fn number_of_bits(&self) -> usize {
        8
    }

    fn has_x_bit(&self, position: usize) -> bool {
        if self.is_bit_in_bounds(position) {
            return (self & (0b00000001 << position)) != 0;
        } else {
            return false; //Huh
        }
    }

}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_number_of_bits_u8() {
        assert_eq!(8, 1u8.number_of_bits());
    }

    #[test]
    fn test_most_signifigant_bit_u8() {
        assert!(1u8.has_most_signifigant_bit() == false);
        assert!(0b10101010u8.has_most_signifigant_bit() == true);
        assert!(0b10111000u8.has_most_signifigant_bit() == true);
    }

    #[test]
    fn test_bit_in_bounds_u8() {
        assert!(25u8.is_bit_in_bounds(1));
        assert!(25u8.is_bit_in_bounds(9) == false);
    }

    #[test]
    fn test_has_x_bit_u8() {
        let num: u8 = 0b10101010u8;

        assert!(num.has_x_bit(0) == false);
        assert!(num.has_x_bit(1) == true);
        assert!(num.has_x_bit(2) == false);
        assert!(num.has_x_bit(3) == true);
        assert!(num.has_x_bit(4) == false);
        assert!(num.has_x_bit(5) == true);
        assert!(num.has_x_bit(6) == false);
        assert!(num.has_x_bit(7) == true);
    }

}<|endoftext|>


<commit_before>#[allow(dead_code)]
#[allow(non_camel_case_types)]

/**
 * Abstraction of libnl core functionality
 */
#[link(name="nl-3")]
extern "C" {
	// Exposed socket functions
	fn nl_socket_alloc() -> *const nl_sock;
	fn nl_socket_free(socket: *const nl_sock);
	fn nl_socket_get_fd(socket: *const nl_sock) -> i32;
	fn nl_socket_set_buffer_size(socket: *const nl_sock, rxbuf: int, txbuf: int) -> i32;

	fn nl_socket_set_local_port(socket: *const nl_sock, port: u32);
	fn nl_socket_get_local_port(socket: *const nl_sock);

	fn nl_connect(socket: *const nl_sock, protocol: u32) -> i32;
	fn nl_close(socket: *const nl_sock);

	fn nl_socket_set_cb(socket: *const nl_sock, cb: *const nl_cb);
	fn nl_socket_get_cb(socket: *const nl_sock) -> nl_cb;

	// Exposed msg functions
	fn nlmsg_alloc() -> *const nl_msg;
	fn nlmsg_free(msg: *const nl_msg);
}

// exposed structures - these are wrapped
struct nl_sock;
struct nl_msg;
struct nl_cb;

// RSNL datatypes wrapping the libnl data structures
pub struct socket {
	ptr: *const nl_sock
}

/* library version of nlmsghdr
 * the name is altered to differentiate
 * between the native libnl and rsnl
 */
pub struct rsnl_msghdr {
	nlmsg_len: u32,
	nlmsg_type: u16,
	nlmsg_flags: u16,
	nlmsg_seq: u32,
	nlmsg_pid: u32
}

pub struct msg {
	ptr: *const nl_msg
}

pub enum NetlinkProtocol {
	route,
	unused,
	usersock,
	firewall,
	sock_diag,
	nflog,
	xfrm,
	selinux,
	iscsi,
	audit,
	fib_lookup,
	connector,
	netfilter,
	ip6_fw,
	dnrtmsg,
	kobject_uevent,
	DMEVENTS,
	scsitransport,
	ecryptfs,
	rdma,
	crypto
}

impl socket {
	pub fn new() -> socket {
		unsafe {
			let nlptr = nl_socket_alloc();
			socket {
				ptr: nlptr
			}
		}
	}

	pub fn free(&self) {
		unsafe {
			nl_socket_free(self.ptr)
		}
	}

	pub fn set_buffer_size(&self, rxbuf: int, txbuf: int) -> i32 {
		unsafe {
			nl_socket_set_buffer_size(self.ptr, rxbuf, txbuf)
		}
	}

	pub fn connect(&self, protocol: NetlinkProtocol) -> i32 {
		unsafe { nl_connect(self.ptr, protocol as u32) }
	}

	pub fn close(&self) {
		unsafe{ nl_close(self.ptr) }
	}

	pub fn get_fd(&self) -> i32 {
		unsafe { nl_socket_get_fd(self.ptr) }
	}
}

impl msg {
	pub fn new() -> msg {
	unsafe {
		let nlmsg = nlmsg_alloc();
		msg {
			ptr: nlmsg
		}
	}
	}

	pub fn free(&self) {
		unsafe{ nlmsg_free(self.ptr); }
	}
}
<commit_msg>Added local port gtr/str to socket<commit_after>#[allow(dead_code)]
#[allow(non_camel_case_types)]

/**
 * Abstraction of libnl core functionality
 */
#[link(name="nl-3")]
extern "C" {
	// Exposed socket functions
	fn nl_socket_alloc() -> *const nl_sock;
	fn nl_socket_free(socket: *const nl_sock);
	fn nl_socket_get_fd(socket: *const nl_sock) -> i32;
	fn nl_socket_set_buffer_size(socket: *const nl_sock, rxbuf: int, txbuf: int) -> i32;

	fn nl_socket_set_local_port(socket: *const nl_sock, port: u32);
	fn nl_socket_get_local_port(socket: *const nl_sock);

	fn nl_connect(socket: *const nl_sock, protocol: u32) -> i32;
	fn nl_close(socket: *const nl_sock);

	fn nl_socket_set_cb(socket: *const nl_sock, cb: *const nl_cb);
	fn nl_socket_get_cb(socket: *const nl_sock) -> nl_cb;

	// Exposed msg functions
	fn nlmsg_alloc() -> *const nl_msg;
	fn nlmsg_free(msg: *const nl_msg);
}

// exposed structures - these are wrapped
struct nl_sock;
struct nl_msg;
struct nl_cb;

// RSNL datatypes wrapping the libnl data structures
pub struct socket {
	ptr: *const nl_sock
}

/* library version of nlmsghdr
 * the name is altered to differentiate
 * between the native libnl and rsnl
 */
pub struct rsnl_msghdr {
	nlmsg_len: u32,
	nlmsg_type: u16,
	nlmsg_flags: u16,
	nlmsg_seq: u32,
	nlmsg_pid: u32
}

pub struct msg {
	ptr: *const nl_msg
}

pub enum NetlinkProtocol {
	route,
	unused,
	usersock,
	firewall,
	sock_diag,
	nflog,
	xfrm,
	selinux,
	iscsi,
	audit,
	fib_lookup,
	connector,
	netfilter,
	ip6_fw,
	dnrtmsg,
	kobject_uevent,
	DMEVENTS,
	scsitransport,
	ecryptfs,
	rdma,
	crypto
}

impl socket {
	pub fn new() -> socket {
		unsafe {
			let nlptr = nl_socket_alloc();
			socket {
				ptr: nlptr
			}
		}
	}

	pub fn free(&self) {
		unsafe {
			nl_socket_free(self.ptr)
		}
	}

	pub fn set_buffer_size(&self, rxbuf: int, txbuf: int) -> i32 {
		unsafe {
			nl_socket_set_buffer_size(self.ptr, rxbuf, txbuf)
		}
	}

	pub fn connect(&self, protocol: NetlinkProtocol) -> i32 {
		unsafe { nl_connect(self.ptr, protocol as u32) }
	}

	pub fn close(&self) {
		unsafe{ nl_close(self.ptr) }
	}

	pub fn get_fd(&self) -> i32 {
		unsafe { nl_socket_get_fd(self.ptr) }
	}

	pub fn get_local_port(&self) -> u32 {
		unsafe { nl_socket_get_local_port(self.ptr) }
	}

	pub fn set_local_port(&self, port: u32) {
		unsafe { nl_socket_set_local_port(self.ptr, port) }
	}
}

impl msg {
	pub fn new() -> msg {
	unsafe {
		let nlmsg = nlmsg_alloc();
		msg {
			ptr: nlmsg
		}
	}
	}

	pub fn free(&self) {
		unsafe{ nlmsg_free(self.ptr); }
	}
}
<|endoftext|>


<commit_before>//! Isbfc is an optimizing brainfuck compiler targeting x86_64 Linux
//!
//! # Examples
//! ```
//! extern crate isbfc;
//!
//! fn main() {
//!     // 2048 is the tape length to use
//!     let assembly = isbfc::parse(",[.,]").optimize().compile(2048);
//!     print!("{}", assembly);
//! }
//! ```

use std::fmt;

mod token;
mod parser;
mod optimizer;
mod compiler;

pub use token::Token;
pub use parser::parse;

/// Intermediate representation used by isbfc
pub struct IsbfcIR {
    /// Syntax tree of tokens
    pub tokens: Vec<Token>
}

impl fmt::Debug for IsbfcIR {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.tokens.fmt(f)
    }
}
<commit_msg>Update example<commit_after>//! Isbfc is an optimizing brainfuck compiler targeting x86_64 Linux
//!
//! # Examples
//! ```
//! extern crate isbfc;
//!
//! fn main() {
//!     // 2048 is the tape length to use
//!     let assembly = isbfc::parse(",[.,]").unwrap().optimize().compile(2048);
//!     print!("{}", assembly);
//! }
//! ```

use std::fmt;

mod token;
mod parser;
mod optimizer;
mod compiler;

pub use token::Token;
pub use parser::parse;

/// Intermediate representation used by isbfc
pub struct IsbfcIR {
    /// Syntax tree of tokens
    pub tokens: Vec<Token>
}

impl fmt::Debug for IsbfcIR {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.tokens.fmt(f)
    }
}
<|endoftext|>


<commit_before>//! # Shamir's Secret Sharing algorithm over GF( 2^8 ).
//!
//! Shamir's Secret Sharing algorithm allows you to securely share a secret with
//! `N` people, allowing the recovery of that secret if `K` of those people
//! combine their shares.
//!
//! ## Example
//!
//! ```
//! extern crate rand;
//! extern crate sss;
//!
//! // we start with a secret value
//! let secret = "this is a super secret";
//! println!("Secret: {}", secret);
//!
//! // and a cryptographically secure RNG
//! let mut rng = rand::thread_rng();
//!
//! // we generate 5 shares of which 3 are required
//! let shares = sss::split(5, 3, secret.as_bytes(), &mut rng);
//! println!("Shares: {:?}", shares);
//!
//! // we select 3 of those shares
//! let mut selected = std::collections::HashMap::new();
//! for &id in shares.keys().take(3) {
//!     selected.insert(id, shares[&id].clone());
//! }
//!
//! // we combine them to recover the secret
//! let recovered = sss::combine(&selected);
//! println!("Recovered: {}", String::from_utf8(recovered).unwrap());
//! ```
//!
//! ## How It Works
//!
//! It begins by encoding a secret as a number (e.g., 42), and generating `N`
//! random polynomial equations of degree `K`-1 which have an Y-intercept equal
//! to the secret. Given `K=3`, the following equations might be generated:
//!
//! ```ignore
//! f1(x) =  78x^2 +  19x + 42
//! f2(x) = 128x^2 + 171x + 42
//! f3(x) = 121x^2 +   3x + 42
//! f4(x) =  91x^2 +  95x + 42
//! etc.
//! ```
//!
//! These polynomials are then evaluated for values of X > 0:
//!
//! ```ignore
//! f1(1) =  139
//! f2(2) =  896
//! f3(3) = 1140
//! f4(4) = 1783
//! etc.
//! ```
//!
//! These (x, y) pairs are the shares given to the parties. In order to combine
//! shares to recover the secret, these (x, y) pairs are used as the input
//! points for Lagrange interpolation, which produces a polynomial which matches
//! the given points. This polynomial can be evaluated for f(0), producing the
//! secret value--the common Y-intercept for all the generated polynomials.
//!
//! If fewer than K shares are combined, the interpolated polynomial will be
//! wrong, and the result of f(0) will not be the secret.
//!
//! This package constructs polynomials over the field GF( 2^8 ) for each byte
//! of the secret, allowing for fast splitting and combining of anything which
//! can be encoded as bytes.
//!
//! This package has not been audited by cryptography or security professionals.

extern crate rand;

mod gf256;
mod poly;

use std::collections::HashMap;
use std::hash::BuildHasher;

use rand::{CryptoRng, Rng};

use poly::{eval, generate, y_intercept};

/// Split a secret into N shares, of which K are required to re-combine. Returns
/// a map of share IDs to share values.
pub fn split<R>(n: u8, k: u8, secret: &[u8], rng: &mut R) -> HashMap<u8, Vec<u8>>
where
    R: Rng + CryptoRng,
{
    // Generate a random K-degree polynomial for each byte of the secret.
    let polys = secret
        .iter()
        .map(|&b| generate((k - 1) as usize, b, rng))
        .collect::<Vec<Vec<u8>>>();

    // Collect the evaluation of each polynomial with the share ID as the input.
    (1..=n)
        .map(|id| (id, polys.iter().map(|p| eval(p, id)).collect()))
        .collect()
}

/// Combine a map of share IDs into the original secret.
///
/// N.B.: There is no way to know if this is successful or not.
pub fn combine<S>(shares: &HashMap<u8, Vec<u8>, S>) -> Vec<u8>
where
    S: BuildHasher,
{
    let len = shares.values().next().unwrap().len();
    if shares.values().any(|v| v.len() != len) {
        panic!("mismatched share lengths")
    }

    (0..len)
        .map(|i| y_intercept(shares.iter().map(|(&id, v)| (id, v[i])).collect()))
        .collect()
}

#[cfg(test)]
mod test {
    extern crate itertools;
    extern crate proptest;
    extern crate rand_chacha;

    use rand::SeedableRng;

    use super::*;

    use self::itertools::Itertools;
    use self::proptest::prelude::*;
    use self::rand_chacha::ChaChaRng;

    proptest! {
        #[test]
        fn test_split(secret: Vec<u8>, seed: [u8; 32]) {
            let mut rng = ChaChaRng::from_seed(seed);
            let splits = split(5, 3, &secret, &mut rng);

            for i in 5..=3 {
                for keys in splits.keys().combinations(i) {
                    let mut subset = HashMap::new();
                    for &key in keys {
                        subset.insert(key, splits.get(&key).unwrap().to_vec());
                    }
                    assert_eq!(combine(&subset), secret);
                }
            }

            for i in 2..=1 {
                for keys in splits.keys().combinations(i) {
                    let mut subset = HashMap::new();
                    for &key in keys {
                        subset.insert(key, splits.get(&key).unwrap().to_vec());
                    }
                    assert_ne!(combine(&subset), secret);
                }
            }
        }
    }

    #[test]
    fn test_combine() {
        let mut shares = HashMap::new();
        shares.insert(1, vec![64, 163, 216, 189, 193]);
        shares.insert(3, vec![194, 250, 117, 212, 82]);
        shares.insert(5, vec![95, 17, 153, 111, 252]);

        assert_eq!(combine(&shares), vec![1, 2, 3, 4, 5])
    }
}
<commit_msg>Forbid unsafe and warnings in this lib.<commit_after>#![forbid(unsafe_code)]
#![forbid(warnings)]

//! # Shamir's Secret Sharing algorithm over GF( 2^8 ).
//!
//! Shamir's Secret Sharing algorithm allows you to securely share a secret with
//! `N` people, allowing the recovery of that secret if `K` of those people
//! combine their shares.
//!
//! ## Example
//!
//! ```
//! extern crate rand;
//! extern crate sss;
//!
//! // we start with a secret value
//! let secret = "this is a super secret";
//! println!("Secret: {}", secret);
//!
//! // and a cryptographically secure RNG
//! let mut rng = rand::thread_rng();
//!
//! // we generate 5 shares of which 3 are required
//! let shares = sss::split(5, 3, secret.as_bytes(), &mut rng);
//! println!("Shares: {:?}", shares);
//!
//! // we select 3 of those shares
//! let mut selected = std::collections::HashMap::new();
//! for &id in shares.keys().take(3) {
//!     selected.insert(id, shares[&id].clone());
//! }
//!
//! // we combine them to recover the secret
//! let recovered = sss::combine(&selected);
//! println!("Recovered: {}", String::from_utf8(recovered).unwrap());
//! ```
//!
//! ## How It Works
//!
//! It begins by encoding a secret as a number (e.g., 42), and generating `N`
//! random polynomial equations of degree `K`-1 which have an Y-intercept equal
//! to the secret. Given `K=3`, the following equations might be generated:
//!
//! ```ignore
//! f1(x) =  78x^2 +  19x + 42
//! f2(x) = 128x^2 + 171x + 42
//! f3(x) = 121x^2 +   3x + 42
//! f4(x) =  91x^2 +  95x + 42
//! etc.
//! ```
//!
//! These polynomials are then evaluated for values of X > 0:
//!
//! ```ignore
//! f1(1) =  139
//! f2(2) =  896
//! f3(3) = 1140
//! f4(4) = 1783
//! etc.
//! ```
//!
//! These (x, y) pairs are the shares given to the parties. In order to combine
//! shares to recover the secret, these (x, y) pairs are used as the input
//! points for Lagrange interpolation, which produces a polynomial which matches
//! the given points. This polynomial can be evaluated for f(0), producing the
//! secret value--the common Y-intercept for all the generated polynomials.
//!
//! If fewer than K shares are combined, the interpolated polynomial will be
//! wrong, and the result of f(0) will not be the secret.
//!
//! This package constructs polynomials over the field GF( 2^8 ) for each byte
//! of the secret, allowing for fast splitting and combining of anything which
//! can be encoded as bytes.
//!
//! This package has not been audited by cryptography or security professionals.

extern crate rand;

mod gf256;
mod poly;

use std::collections::HashMap;
use std::hash::BuildHasher;

use rand::{CryptoRng, Rng};

use poly::{eval, generate, y_intercept};

/// Split a secret into N shares, of which K are required to re-combine. Returns
/// a map of share IDs to share values.
pub fn split<R>(n: u8, k: u8, secret: &[u8], rng: &mut R) -> HashMap<u8, Vec<u8>>
where
    R: Rng + CryptoRng,
{
    // Generate a random K-degree polynomial for each byte of the secret.
    let polys = secret
        .iter()
        .map(|&b| generate((k - 1) as usize, b, rng))
        .collect::<Vec<Vec<u8>>>();

    // Collect the evaluation of each polynomial with the share ID as the input.
    (1..=n)
        .map(|id| (id, polys.iter().map(|p| eval(p, id)).collect()))
        .collect()
}

/// Combine a map of share IDs into the original secret.
///
/// N.B.: There is no way to know if this is successful or not.
pub fn combine<S>(shares: &HashMap<u8, Vec<u8>, S>) -> Vec<u8>
where
    S: BuildHasher,
{
    let len = shares.values().next().unwrap().len();
    if shares.values().any(|v| v.len() != len) {
        panic!("mismatched share lengths")
    }

    (0..len)
        .map(|i| y_intercept(shares.iter().map(|(&id, v)| (id, v[i])).collect()))
        .collect()
}

#[cfg(test)]
mod test {
    extern crate itertools;
    extern crate proptest;
    extern crate rand_chacha;

    use rand::SeedableRng;

    use super::*;

    use self::itertools::Itertools;
    use self::proptest::prelude::*;
    use self::rand_chacha::ChaChaRng;

    proptest! {
        #[test]
        fn test_split(secret: Vec<u8>, seed: [u8; 32]) {
            let mut rng = ChaChaRng::from_seed(seed);
            let splits = split(5, 3, &secret, &mut rng);

            for i in 5..=3 {
                for keys in splits.keys().combinations(i) {
                    let mut subset = HashMap::new();
                    for &key in keys {
                        subset.insert(key, splits.get(&key).unwrap().to_vec());
                    }
                    assert_eq!(combine(&subset), secret);
                }
            }

            for i in 2..=1 {
                for keys in splits.keys().combinations(i) {
                    let mut subset = HashMap::new();
                    for &key in keys {
                        subset.insert(key, splits.get(&key).unwrap().to_vec());
                    }
                    assert_ne!(combine(&subset), secret);
                }
            }
        }
    }

    #[test]
    fn test_combine() {
        let mut shares = HashMap::new();
        shares.insert(1, vec![64, 163, 216, 189, 193]);
        shares.insert(3, vec![194, 250, 117, 212, 82]);
        shares.insert(5, vec![95, 17, 153, 111, 252]);

        assert_eq!(combine(&shares), vec![1, 2, 3, 4, 5])
    }
}
<|endoftext|>


<commit_before>mod crypt;

use std::path::Path;

extern crate rustc_serialize;
use rustc_serialize::json;

extern crate uuid;
use uuid::Uuid;

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

#[derive(RustcDecodable, RustcEncodable)]
struct StorableKey {
    key: Box<[u8]>,
    iv: Box<[u8]>
}

#[derive(RustcDecodable, RustcEncodable)]
struct StorableData {
    ciphertext: Vec<u8>
}

#[derive(RustcDecodable, RustcEncodable)]
struct StorableMap {
    key_id: Uuid,
    data_id: Uuid,
    tag: Box<[u8]>
}

pub fn dump(external_id: String, data: Vec<u8>) -> Result<(), String>  {
    let data_path = "/home/andrey/Documents/storages/data".to_string();
    let keys_path = "/home/andrey/Documents/storages/keys".to_string();
    let maps_path = "/home/andrey/Documents/storages/maps".to_string();

    let result = crypt::encrypt(external_id.as_bytes(), &data);

    let key_id = store_key(keys_path, StorableKey { key: result.key, iv: result.iv }).unwrap();
    let data_id = store_data(data_path, StorableData { ciphertext: result.ciphertext }).unwrap();
    let external_uuid = Uuid::parse_str(&external_id).unwrap();
    store_map(maps_path, StorableMap { key_id: key_id, data_id: data_id, tag: result.tag })
}

fn store_data(path_prefix: String, storable: StorableData) -> Result<Uuid, String> {
    let id = Uuid::new_v4();
    let encoded_storable = json::encode(&storable).unwrap();

    let mut file = File::create(Path::new(&format!("{}/{}.json", path_prefix, id.to_string()))).ok().expect("Cannot create file");
    match file.write_all(encoded_storable.as_bytes()) {
        Ok(_) => Ok(id),
        Err(error) => Err(format!("Error: {}", error))
    }
}

fn store_key(path_prefix: String, storable: StorableKey) -> Result<Uuid, String> {
    let id = Uuid::new_v4();
    let encoded_storable = json::encode(&storable).unwrap();

    let mut file = File::create(Path::new(&format!("{}/{}.json", path_prefix, id.to_string()))).ok().expect("Cannot create file");
    match file.write_all(encoded_storable.as_bytes()) {
        Ok(_) => Ok(id),
        Err(error) => Err(format!("Error: {}", error))
    }
}

fn store_map(path_prefix: String, storable: StorableMap) -> Result<(), String> {
    let id = Uuid::new_v4();
    let encoded_storable = json::encode(&storable).unwrap();

    let mut file = File::create(Path::new(&format!("{}/{}.json", path_prefix, id.to_string()))).ok().expect("Cannot create file");
    match file.write_all(encoded_storable.as_bytes()) {
        Ok(_) => Ok(()),
        Err(error) => Err(format!("Error: {}", error))
    }
}

pub struct LoadResult {
    pub data: Vec<u8>
}

trait FakeLoadResult {
    fn new(data: &'static str) -> Self;
    fn data(&self) -> Vec<u8> { self.data() }
}

impl FakeLoadResult for LoadResult {
    fn new(data: &'static str) -> LoadResult {
        LoadResult { data: data.to_string().into_bytes() }
    }
}

pub fn load(external_id: &String) -> LoadResult {
    LoadResult::new("fakevalue")
}
<commit_msg>Code compacted.<commit_after>mod crypt;

use std::path::Path;

extern crate rustc_serialize;
use rustc_serialize::json;

extern crate uuid;
use uuid::Uuid;

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

#[derive(RustcDecodable, RustcEncodable)]
struct StorableKey {
    key: Box<[u8]>,
    iv: Box<[u8]>
}

#[derive(RustcDecodable, RustcEncodable)]
struct StorableData {
    ciphertext: Vec<u8>
}

#[derive(RustcDecodable, RustcEncodable)]
struct StorableMap {
    key_id: Uuid,
    data_id: Uuid,
    tag: Box<[u8]>
}

pub fn dump(external_id: String, data: Vec<u8>) -> Result<(), String>  {
    let data_path = "/home/andrey/Documents/storages/data".to_string();
    let keys_path = "/home/andrey/Documents/storages/keys".to_string();
    let maps_path = "/home/andrey/Documents/storages/maps".to_string();

    let result = crypt::encrypt(external_id.as_bytes(), &data);

    let key_id = store_key(keys_path, StorableKey { key: result.key, iv: result.iv }).unwrap();
    let data_id = store_data(data_path, StorableData { ciphertext: result.ciphertext }).unwrap();
    let external_uuid = Uuid::parse_str(&external_id).unwrap();
    store_map(maps_path, external_uuid, StorableMap { key_id: key_id, data_id: data_id, tag: result.tag })
}

fn store_json_string(path_prefix: String, path_key: Uuid, json: String) -> Result<(), String> {
    let mut file = File::create(Path::new(&format!("{}/{}.json", path_prefix, path_key.to_string()))).ok().expect("Cannot create file");
    match file.write_all(json.as_bytes()) {
        Ok(_) => Ok(()),
        Err(error) => Err(format!("Error: {}", error))
    }
}

fn store_data(path_prefix: String, storable: StorableData) -> Result<Uuid, String> {
    let id = Uuid::new_v4();
    let json = json::encode(&storable).unwrap();
    store_json_string(path_prefix, id, json).ok();
    Ok(id)
}

fn store_key(path_prefix: String, storable: StorableKey) -> Result<Uuid, String> {
    let id = Uuid::new_v4();
    let json = json::encode(&storable).unwrap();
    store_json_string(path_prefix, id, json).ok();
    Ok(id)
}

fn store_map(path_prefix: String, external_id: Uuid, storable: StorableMap) -> Result<(), String> {
    let id = external_id;
    let json = json::encode(&storable).unwrap();
    store_json_string(path_prefix, id, json).ok();
    Ok(())
}

pub struct LoadResult {
    pub data: Vec<u8>
}

trait FakeLoadResult {
    fn new(data: &'static str) -> Self;
    fn data(&self) -> Vec<u8> { self.data() }
}

impl FakeLoadResult for LoadResult {
    fn new(data: &'static str) -> LoadResult {
        LoadResult { data: data.to_string().into_bytes() }
    }
}

pub fn load(external_id: &String) -> LoadResult {
    LoadResult::new("fakevalue")
}
<|endoftext|>


<commit_before>extern crate regex;

use regex::Regex;

pub fn puzzle(input: &str) -> u32 {
    0
}

pub struct Room {
    name: String,
    sector_id: u32,
    checksum: String,
}

impl Room {
    fn new(description: &str) -> Room {
        let regex = Regex::new(r"
(?P<name>[a-z-])
-
(?P<sector_id>[0-9]+)
\[(?P<checksum>[a-z]{5})\]
").expect("Regex is invalid");

        let caps = regex.captures(description).expect("Can't capture");

        Room {
            name: caps.name("name").expect("No name").to_string(),
            sector_id: caps.name("sector_id").expect("No sector id").parse().expect("Can't parse"),
            checksum: caps.name("checksum").expect("No checksum").to_string(),
        }
    }
}

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

    #[test]
    fn test_extraction() {
        let description = "aaaaa-bbb-z-y-x-123[abxyz]";
        let room = Room::new(description);

        assert_eq!(room.name, "aaaaa-bbb-z-y-x");
        assert_eq!(room.sector_id, 123);
        assert_eq!(room.checksum, "abxyz");
    }
}
<commit_msg>Aha, that (?x) is important to enable insignificant whitespace mode<commit_after>extern crate regex;

use regex::Regex;

pub fn puzzle(input: &str) -> u32 {
    0
}

pub struct Room {
    name: String,
    sector_id: u32,
    checksum: String,
}

impl Room {
    fn new(description: &str) -> Room {
        let regex = Regex::new(r"(?x)
(?P<name>[a-z-]+)
-
(?P<sector_id>[0-9]+)
\[(?P<checksum>[a-z]{5})\]
").expect("Regex is invalid");

        let caps = regex.captures(description).expect("Can't capture");

        Room {
            name: caps.name("name").expect("No name").to_string(),
            sector_id: 3, //caps.name("sector_id").expect("No sector id").parse().expect("Can't parse"),
            checksum: String::from("hi"), //caps.name("checksum").expect("No checksum").to_string(),
        }
    }
}

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

    #[test]
    fn test_extraction() {
        let description = "aaaaa-bbb-z-y-x-123[abxyz]";
        let room = Room::new(description);

        assert_eq!(room.name, "aaaaa-bbb-z-y-x");
        assert_eq!(room.sector_id, 123);
        assert_eq!(room.checksum, "abxyz");
    }
}
<|endoftext|>


<commit_before>//! nom, eating data byte by byte
//!
//! nom is a parser combinator library with a focus on safe parsing,
//! streaming patterns, and as much as possible zero copy.
//!
//! The code is available on [Github](https://github.com/Geal/nom)
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate nom;
//!
//! use nom::{IResult,digit};
//! use nom::IResult::*;
//!
//! // Parser definition
//!
//! use std::str;
//! use std::str::FromStr;
//!
//! named!(parens<i64>, delimited!(
//!     char!('('),
//!     expr,
//!     char!(')')
//!   )
//! );
//!
//! named!(i64_digit<i64>,
//!   map_res!(
//!     map_res!(
//!       digit,
//!       str::from_utf8
//!     ),
//!     FromStr::from_str
//!   )
//! );
//!
//! // We transform an integer string into a i64
//! // we look for a digit suite, and try to convert it.
//! // if either str::from_utf8 or FromStr::from_str fail,
//! // the parser will fail
//! named!(factor<i64>,
//!   alt!(
//!     i64_digit
//!   | parens
//!   )
//! );
//!
//! // we define acc as mutable to update its value whenever a new term is found
//! named!(term <i64>,
//!   chain!(
//!     mut acc: factor  ~
//!              many0!(
//!                alt!(
//!                  tap!(mul: preceded!(tag!("*"), factor) => acc = acc * mul) |
//!                  tap!(div: preceded!(tag!("/"), factor) => acc = acc / div)
//!                )
//!              ),
//!     || { return acc }
//!   )
//! );
//!
//! named!(expr <i64>,
//!   chain!(
//!     mut acc: term  ~
//!              many0!(
//!                alt!(
//!                  tap!(add: preceded!(tag!("+"), term) => acc = acc + add) |
//!                  tap!(sub: preceded!(tag!("-"), term) => acc = acc - sub)
//!                )
//!              ),
//!     || { return acc }
//!   )
//! );
//!
//! fn main() {
//!   assert_eq!(expr(b"1+2"),         IResult::Done(&b""[..], 3));
//!   assert_eq!(expr(b"12+6-4+3"),    IResult::Done(&b""[..], 17));
//!   assert_eq!(expr(b"1+2*3+4"),     IResult::Done(&b""[..], 11));
//!
//!   assert_eq!(expr(b"(2)"),         IResult::Done(&b""[..], 2));
//!   assert_eq!(expr(b"2*(3+4)"),     IResult::Done(&b""[..], 14));
//!   assert_eq!(expr(b"2*2/(5-1)+3"), IResult::Done(&b""[..], 4));
//! }
//! ```
#![cfg_attr(feature = "core", feature(no_std))]
#![cfg_attr(feature = "core", feature(collections))]
#![cfg_attr(feature = "core", no_std)]
#![cfg_attr(feature = "nightly", feature(test))]
#![cfg_attr(feature = "nightly", feature(const_fn))]
#![warn(missing_docs)]

#[cfg(feature = "core")]
extern crate collections;
#[cfg(feature = "regexp")]
extern crate regex;
#[cfg(feature = "regexp_macros")]
#[macro_use] extern crate lazy_static;
#[cfg(feature = "nightly")]
extern crate test;

#[cfg(feature = "core")]
mod std {
#[macro_use]
  pub use core::{fmt, iter, option, ops, slice, mem};
  pub use collections::{boxed, vec, string};
  pub mod prelude {
    pub use core::prelude as v1;
  }
}

pub use self::util::*;
pub use self::traits::*;

#[cfg(feature = "verbose-errors")]
pub use self::verbose_errors::*;

#[cfg(not(feature = "verbose-errors"))]
pub use self::simple_errors::*;

pub use self::internal::*;
pub use self::macros::*;
pub use self::branch::*;
pub use self::sequence::*;
pub use self::multi::*;
pub use self::methods::*;
pub use self::bytes::*;
pub use self::bits::*;

pub use self::nom::*;
pub use self::character::*;

#[cfg(not(feature = "core"))]
pub use self::whitespace::*;

#[cfg(feature = "regexp")]
pub use self::regexp::*;

#[cfg(not(feature = "core"))]
#[cfg(feature = "stream")]
pub use self::stream::*;

#[cfg(not(feature = "core"))]
pub use self::str::*;

#[macro_use] mod util;
mod traits;

#[cfg(feature = "verbose-errors")] #[macro_use] mod verbose_errors;

#[cfg(not(feature = "verbose-errors"))] #[macro_use] mod simple_errors;

#[macro_use] mod internal;
#[macro_use] mod macros;
#[macro_use] mod branch;
#[macro_use] mod sequence;
#[macro_use] mod multi;
#[macro_use] pub mod methods;
#[macro_use] mod bytes;
#[macro_use] pub mod bits;

#[macro_use] mod nom;
#[macro_use] mod character;

#[macro_use]
#[cfg(not(feature = "core"))]
pub mod whitespace;

#[cfg(feature = "regexp")]
#[macro_use] mod regexp;

#[macro_use]
#[cfg(not(feature = "core"))]
#[cfg(feature = "stream")]
mod stream;

#[cfg(not(feature = "core"))]
mod str;
<commit_msg>add links to the articles<commit_after>//! nom, eating data byte by byte
//!
//! nom is a parser combinator library with a focus on safe parsing,
//! streaming patterns, and as much as possible zero copy.
//!
//! The code is available on [Github](https://github.com/Geal/nom)
//!
//! There are a few [guides](home.html) with more details
//! about [the design of nom](how_nom_macros_work.html),
//! [how to write parsers](making_a_new_parser_from_scratch.html),
//! or the [error management system](error_management.html).
//!
//! See also the [FAQ](FAQ.html).
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate nom;
//!
//! use nom::{IResult,digit};
//! use nom::IResult::*;
//!
//! // Parser definition
//!
//! use std::str;
//! use std::str::FromStr;
//!
//! named!(parens<i64>, delimited!(
//!     char!('('),
//!     expr,
//!     char!(')')
//!   )
//! );
//!
//! named!(i64_digit<i64>,
//!   map_res!(
//!     map_res!(
//!       digit,
//!       str::from_utf8
//!     ),
//!     FromStr::from_str
//!   )
//! );
//!
//! // We transform an integer string into a i64
//! // we look for a digit suite, and try to convert it.
//! // if either str::from_utf8 or FromStr::from_str fail,
//! // the parser will fail
//! named!(factor<i64>,
//!   alt!(
//!     i64_digit
//!   | parens
//!   )
//! );
//!
//! // we define acc as mutable to update its value whenever a new term is found
//! named!(term <i64>,
//!   chain!(
//!     mut acc: factor  ~
//!              many0!(
//!                alt!(
//!                  tap!(mul: preceded!(tag!("*"), factor) => acc = acc * mul) |
//!                  tap!(div: preceded!(tag!("/"), factor) => acc = acc / div)
//!                )
//!              ),
//!     || { return acc }
//!   )
//! );
//!
//! named!(expr <i64>,
//!   chain!(
//!     mut acc: term  ~
//!              many0!(
//!                alt!(
//!                  tap!(add: preceded!(tag!("+"), term) => acc = acc + add) |
//!                  tap!(sub: preceded!(tag!("-"), term) => acc = acc - sub)
//!                )
//!              ),
//!     || { return acc }
//!   )
//! );
//!
//! fn main() {
//!   assert_eq!(expr(b"1+2"),         IResult::Done(&b""[..], 3));
//!   assert_eq!(expr(b"12+6-4+3"),    IResult::Done(&b""[..], 17));
//!   assert_eq!(expr(b"1+2*3+4"),     IResult::Done(&b""[..], 11));
//!
//!   assert_eq!(expr(b"(2)"),         IResult::Done(&b""[..], 2));
//!   assert_eq!(expr(b"2*(3+4)"),     IResult::Done(&b""[..], 14));
//!   assert_eq!(expr(b"2*2/(5-1)+3"), IResult::Done(&b""[..], 4));
//! }
//! ```
#![cfg_attr(feature = "core", feature(no_std))]
#![cfg_attr(feature = "core", feature(collections))]
#![cfg_attr(feature = "core", no_std)]
#![cfg_attr(feature = "nightly", feature(test))]
#![cfg_attr(feature = "nightly", feature(const_fn))]
#![warn(missing_docs)]

#[cfg(feature = "core")]
extern crate collections;
#[cfg(feature = "regexp")]
extern crate regex;
#[cfg(feature = "regexp_macros")]
#[macro_use] extern crate lazy_static;
#[cfg(feature = "nightly")]
extern crate test;

#[cfg(feature = "core")]
mod std {
#[macro_use]
  pub use core::{fmt, iter, option, ops, slice, mem};
  pub use collections::{boxed, vec, string};
  pub mod prelude {
    pub use core::prelude as v1;
  }
}

pub use self::util::*;
pub use self::traits::*;

#[cfg(feature = "verbose-errors")]
pub use self::verbose_errors::*;

#[cfg(not(feature = "verbose-errors"))]
pub use self::simple_errors::*;

pub use self::internal::*;
pub use self::macros::*;
pub use self::branch::*;
pub use self::sequence::*;
pub use self::multi::*;
pub use self::methods::*;
pub use self::bytes::*;
pub use self::bits::*;

pub use self::nom::*;
pub use self::character::*;

#[cfg(not(feature = "core"))]
pub use self::whitespace::*;

#[cfg(feature = "regexp")]
pub use self::regexp::*;

#[cfg(not(feature = "core"))]
#[cfg(feature = "stream")]
pub use self::stream::*;

#[cfg(not(feature = "core"))]
pub use self::str::*;

#[macro_use] mod util;
mod traits;

#[cfg(feature = "verbose-errors")] #[macro_use] mod verbose_errors;

#[cfg(not(feature = "verbose-errors"))] #[macro_use] mod simple_errors;

#[macro_use] mod internal;
#[macro_use] mod macros;
#[macro_use] mod branch;
#[macro_use] mod sequence;
#[macro_use] mod multi;
#[macro_use] pub mod methods;
#[macro_use] mod bytes;
#[macro_use] pub mod bits;

#[macro_use] mod nom;
#[macro_use] mod character;

#[macro_use]
#[cfg(not(feature = "core"))]
pub mod whitespace;

#[cfg(feature = "regexp")]
#[macro_use] mod regexp;

#[macro_use]
#[cfg(not(feature = "core"))]
#[cfg(feature = "stream")]
mod stream;

#[cfg(not(feature = "core"))]
mod str;
<|endoftext|>


<commit_before>//! # urlshortener
//!
//! An easy library for retrieving short urls.
//!
//! ## Installation
//!
//! Add the following dependency to your project's `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! urlshortener = "0.6"
//! ```
//!
//! And add this to your root file:
//!
//! ```no_run
//! extern crate urlshortener;
//! ```
//!
//! ## Usage
//!
//! Creating a short URL via a specified provider is very simple:
//!
//! ```no_run
//! use urlshortener::{Provider, UrlShortener};
//!
//! let us = UrlShortener::new();
//! let short_url = us.generate("https://my-long-url.com", Provider::IsGd);
//! assert!(short_url.is_ok());
//! ```
//!
//! Or attempting all URL shorteners until one is successfully generated:
//!
//! ```no_run
//! use urlshortener::UrlShortener;
//!
//! let us = UrlShortener::new();
//! let short_url = us.try_generate("https://my-long-url.com");
//! assert!(short_url.is_ok());
//! ```
//! In order to use service with authentication use the appropriate provider directly:
//!
//! ```no_run
//! use urlshortener::{ UrlShortener, Provider };
//!
//! let us = UrlShortener::new();
//! let key = "MY_API_KEY";
//! let short_url = us.generate("https://my-long-url.com", Provider::GooGl { api_key:
//! key.to_owned() });
//! assert!(short_url.is_ok());
//! ```

#[macro_use]
extern crate log;
extern crate hyper;
extern crate url;

mod providers;

pub use providers::{Provider, providers};

use providers::{parse, request};
use hyper::Client;
use std::io::{Error, ErrorKind, Read};
use std::time::Duration;

/// Url shortener: the way to retrieve a short url.
#[derive(Debug, Default)]
pub struct UrlShortener {
    client: Client,
}

impl UrlShortener {
    /// Creates new `UrlShortener` with default (3 seconds) timeout.
    pub fn new() -> UrlShortener {
        UrlShortener::with_timeout(3)
    }

    /// Creates new `UrlShortener` with custom read timeout.
    pub fn with_timeout(seconds: u64) -> UrlShortener {
        let mut client = hyper::Client::new();
        client.set_read_timeout(Some(Duration::from_secs(seconds)));

        UrlShortener { client: client }
    }

    /// Try to generate a short URL from each provider, iterating over each
    /// provider until a short URL is successfully generated.
    /// If you wish to override the list or providers or their priority,
    /// provide your own list of providers as second argument.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use urlshortener::UrlShortener;
    ///
    /// let us = UrlShortener::new();
    /// let long_url = "https://rust-lang.org";
    /// let _short_url = us.try_generate(long_url, None);
    /// ```
    ///
    /// ```no_run
    /// use urlshortener::UrlShortener;
    ///
    /// let us = UrlShortener::new();
    /// let providers = vec![
    ///     Provider::GooGl { api_key: "MY_API_KEY".to_owned() },
    ///     Provider::IsGd,
    /// ];
    /// let long_url = "https://rust-lang.org";
    /// let _short_url = us.try_generate(long_url, Some(providers));
    /// ```
    ///
    /// # Errors
    ///
    /// Returns an `Error<ErrorKind::Other>` if there is an error generating a
    /// short URL from all providers.
    pub fn try_generate<S: Into<String>>(&self,
                                         url: S,
                                         use_providers: Option<Vec<Provider>>)
        -> Result<String, Error> {

        let url = &url.into()[..];
        let mut chosen_providers;
        if let Some(chosen) = use_providers {
            chosen_providers = chosen;
        } else {
            chosen_providers = providers();
        }

        loop {
            if chosen_providers.is_empty() {
                break;
            }

            // This would normally have the potential to panic, except that a
            // check to ensure there is an element at this index is performed.
            let res = self.generate(url, chosen_providers.remove(0));

            if let Ok(s) = res {
                return Ok(s);
            } else {
                warn!("Failed to get short link from service: {}",
                      res.unwrap_err());
            }
        }
        error!("Failed to get short link from any service");
        Err(Error::new(ErrorKind::Other,
                       "Failed to get short link from any service"))
    }

    /// Attempts to get a short URL using the specified provider.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use urlshortener::{Provider, UrlShortener};
    ///
    /// let us = UrlShortener::new();
    /// let long_url = "http://rust-lang.org";
    /// let _short_url = us.generate(long_url, Provider::IsGd);
    /// ```
    ///
    /// ```no_run
    /// use urlshortener::{Provider, UrlShortener};
    ///
    /// let us = UrlShortener::new();
    /// let api_key = "MY_API_KEY".to_owned();
    /// let long_url = "http://rust-lang.org";
    /// let _short_url = us.generate(long_url, Provider::GooGl { api_key: api_key });
    /// ```
    ///
    /// # Errors
    ///
    /// Returns an `std::io::Error` if there is an error generating a
    /// short URL from the given provider due to either:
    ///
    /// a. a decode error (ErrorKind::Other);
    /// b. the service being unavailable (ErrorKind::ConnectionAborted)
    pub fn generate<S: Into<String>>(&self,
                                     url: S,
                                     provider: Provider)
                                     -> Result<String, Error> {
        let response_opt = request(&url.into(), &self.client, provider.clone());

        if let Some(mut response) = response_opt {
            if response.status.is_success() {
                let mut short_url = String::new();

                if try!(response.read_to_string(&mut short_url)) > 0 {
                    return parse(&short_url, provider)
                        .ok_or(Error::new(ErrorKind::Other, "Decode error"));
                }
            }
        }

        Err(Error::new(ErrorKind::ConnectionAborted, "Service is unavailable"))
    }
}

#[cfg(test)]
mod tests {
    use std::io::ErrorKind;

    /// This test does not cover services which require authentication for obvious reasons.
    #[test]
    fn providers() {
        let us = ::UrlShortener::with_timeout(5);
        let url = "http://stackoverflow.com";

        for provider in ::providers() {
            if let Some(err) = us.generate(url, provider).err() {
                assert!(err.kind() == ErrorKind::ConnectionAborted);
            }
        }
    }
}
<commit_msg>build fix again<commit_after>//! # urlshortener
//!
//! An easy library for retrieving short urls.
//!
//! ## Installation
//!
//! Add the following dependency to your project's `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! urlshortener = "0.6"
//! ```
//!
//! And add this to your root file:
//!
//! ```no_run
//! extern crate urlshortener;
//! ```
//!
//! ## Usage
//!
//! Creating a short URL via a specified provider is very simple:
//!
//! ```no_run
//! use urlshortener::{Provider, UrlShortener};
//!
//! let us = UrlShortener::new();
//! let short_url = us.generate("https://my-long-url.com", Provider::IsGd);
//! assert!(short_url.is_ok());
//! ```
//!
//! Or attempting all URL shorteners until one is successfully generated:
//!
//! ```no_run
//! use urlshortener::UrlShortener;
//!
//! let us = UrlShortener::new();
//! let short_url = us.try_generate("https://my-long-url.com", None);
//! assert!(short_url.is_ok());
//! ```
//! In order to use service with authentication use the appropriate provider directly:
//!
//! ```no_run
//! use urlshortener::{ UrlShortener, Provider };
//!
//! let us = UrlShortener::new();
//! let key = "MY_API_KEY";
//! let short_url = us.generate("https://my-long-url.com", Provider::GooGl { api_key:
//! key.to_owned() });
//! assert!(short_url.is_ok());
//! ```

#[macro_use]
extern crate log;
extern crate hyper;
extern crate url;

mod providers;

pub use providers::{Provider, providers};

use providers::{parse, request};
use hyper::Client;
use std::io::{Error, ErrorKind, Read};
use std::time::Duration;

/// Url shortener: the way to retrieve a short url.
#[derive(Debug, Default)]
pub struct UrlShortener {
    client: Client,
}

impl UrlShortener {
    /// Creates new `UrlShortener` with default (3 seconds) timeout.
    pub fn new() -> UrlShortener {
        UrlShortener::with_timeout(3)
    }

    /// Creates new `UrlShortener` with custom read timeout.
    pub fn with_timeout(seconds: u64) -> UrlShortener {
        let mut client = hyper::Client::new();
        client.set_read_timeout(Some(Duration::from_secs(seconds)));

        UrlShortener { client: client }
    }

    /// Try to generate a short URL from each provider, iterating over each
    /// provider until a short URL is successfully generated.
    /// If you wish to override the list or providers or their priority,
    /// provide your own list of providers as second argument.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use urlshortener::UrlShortener;
    ///
    /// let us = UrlShortener::new();
    /// let long_url = "https://rust-lang.org";
    /// let _short_url = us.try_generate(long_url, None);
    /// ```
    ///
    /// ```no_run
    /// use urlshortener::{UrlShortener, Provider};
    ///
    /// let us = UrlShortener::new();
    /// let providers = vec![
    ///     Provider::GooGl { api_key: "MY_API_KEY".to_owned() },
    ///     Provider::IsGd,
    /// ];
    /// let long_url = "https://rust-lang.org";
    /// let _short_url = us.try_generate(long_url, Some(providers));
    /// ```
    ///
    /// # Errors
    ///
    /// Returns an `Error<ErrorKind::Other>` if there is an error generating a
    /// short URL from all providers.
    pub fn try_generate<S: Into<String>>(&self,
                                         url: S,
                                         use_providers: Option<Vec<Provider>>)
        -> Result<String, Error> {

        let url = &url.into()[..];
        let mut chosen_providers;
        if let Some(chosen) = use_providers {
            chosen_providers = chosen;
        } else {
            chosen_providers = providers();
        }

        loop {
            if chosen_providers.is_empty() {
                break;
            }

            // This would normally have the potential to panic, except that a
            // check to ensure there is an element at this index is performed.
            let res = self.generate(url, chosen_providers.remove(0));

            if let Ok(s) = res {
                return Ok(s);
            } else {
                warn!("Failed to get short link from service: {}",
                      res.unwrap_err());
            }
        }
        error!("Failed to get short link from any service");
        Err(Error::new(ErrorKind::Other,
                       "Failed to get short link from any service"))
    }

    /// Attempts to get a short URL using the specified provider.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use urlshortener::{Provider, UrlShortener};
    ///
    /// let us = UrlShortener::new();
    /// let long_url = "http://rust-lang.org";
    /// let _short_url = us.generate(long_url, Provider::IsGd);
    /// ```
    ///
    /// ```no_run
    /// use urlshortener::{Provider, UrlShortener};
    ///
    /// let us = UrlShortener::new();
    /// let api_key = "MY_API_KEY".to_owned();
    /// let long_url = "http://rust-lang.org";
    /// let _short_url = us.generate(long_url, Provider::GooGl { api_key: api_key });
    /// ```
    ///
    /// # Errors
    ///
    /// Returns an `std::io::Error` if there is an error generating a
    /// short URL from the given provider due to either:
    ///
    /// a. a decode error (ErrorKind::Other);
    /// b. the service being unavailable (ErrorKind::ConnectionAborted)
    pub fn generate<S: Into<String>>(&self,
                                     url: S,
                                     provider: Provider)
                                     -> Result<String, Error> {
        let response_opt = request(&url.into(), &self.client, provider.clone());

        if let Some(mut response) = response_opt {
            if response.status.is_success() {
                let mut short_url = String::new();

                if try!(response.read_to_string(&mut short_url)) > 0 {
                    return parse(&short_url, provider)
                        .ok_or(Error::new(ErrorKind::Other, "Decode error"));
                }
            }
        }

        Err(Error::new(ErrorKind::ConnectionAborted, "Service is unavailable"))
    }
}

#[cfg(test)]
mod tests {
    use std::io::ErrorKind;

    /// This test does not cover services which require authentication for obvious reasons.
    #[test]
    fn providers() {
        let us = ::UrlShortener::with_timeout(5);
        let url = "http://stackoverflow.com";

        for provider in ::providers() {
            if let Some(err) = us.generate(url, provider).err() {
                assert!(err.kind() == ErrorKind::ConnectionAborted);
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://docs.rs/tempdir/0.3.5")]
#![cfg_attr(test, deny(warnings))]

//! Temporary directories of files.
//!
//! The [`TempDir`] type creates a directory on the file system that
//! is deleted once it goes out of scope. At construction, the
//! `TempDir` creates a new directory with a randomly generated name
//! and a prefix of your choosing.
//!
//! [`TempDir`]: struct.TempDir.html
//! [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html
//!
//! # Examples
//!
//! ```
//! extern crate tempdir;
//!
//! use std::fs::File;
//! use std::io::{self, Write};
//! use tempdir::TempDir;
//!
//! fn main() {
//!     if let Err(_) = run() {
//!         ::std::process::exit(1);
//!     }
//! }
//!
//! fn run() -> Result<(), io::Error> {
//!     // Create a directory inside of `std::env::temp_dir()`, named with
//!     // the prefix "example".
//!     let tmp_dir = TempDir::new("example")?;
//!     let file_path = tmp_dir.path().join("my-temporary-note.txt");
//!     let mut tmp_file = File::create(file_path)?;
//!     writeln!(tmp_file, "Brian was here. Briefly.")?;
//!
//!     // By closing the `TempDir` explicitly, we can check that it has
//!     // been deleted successfully. If we don't close it explicitly,
//!     // the directory will still be deleted when `tmp_dir` goes out
//!     // of scope, but we won't know whether deleting the directory
//!     // succeeded.
//!     drop(tmp_file);
//!     tmp_dir.close()?;
//!     Ok(())
//! }
//! ```

extern crate rand;
extern crate remove_dir_all;

use std::env;
use std::io::{self, Error, ErrorKind};
use std::fmt;
use std::fs;
use std::path::{self, PathBuf, Path};
use rand::{thread_rng, Rng};
use remove_dir_all::remove_dir_all;

/// A directory in the filesystem that is automatically deleted when
/// it goes out of scope.
///
/// The [`TempDir`] type creates a directory on the file system that
/// is deleted once it goes out of scope. At construction, the
/// `TempDir` creates a new directory with a randomly generated name,
/// and with a prefix of your choosing.
///
/// The default constructor, [`TempDir::new`], creates directories in
/// the location returned by [`std::env::temp_dir()`], but `TempDir`
/// can be configured to manage a temporary directory in any location
/// by constructing with [`TempDir::new_in`].
///
/// After creating a `TempDir`, work with the file system by doing
/// standard [`std::fs`] file system operations on its [`Path`],
/// which can be retrieved with [`TempDir::path`]. Once the `TempDir`
/// value is dropped, the directory at the path will be deleted, along
/// with any files and directories it contains. It is your responsibility
/// to ensure that no further file system operations are attempted
/// inside the temporary directory once it has been deleted.
///
/// Various platform-specific conditions may cause `TempDir` to fail
/// to delete the underlying directory. It's important to ensure that
/// handles (like [`File`] and [`ReadDir`]) to files inside the
/// directory are dropped before the `TempDir` goes out of scope. The
/// `TempDir` destructor will silently ignore any errors in deleting
/// the directory; to instead handle errors call [`TempDir::close`].
///
/// Note that if the program exits before the `TempDir` destructor is
/// run, such as via [`std::process::exit`], by segfaulting, or by
/// receiving a signal like `SIGINT`, then the temporary directory
/// will not be deleted.
///
/// [`File`]: http://doc.rust-lang.org/std/fs/struct.File.html
/// [`Path`]: http://doc.rust-lang.org/std/path/struct.Path.html
/// [`ReadDir`]: http://doc.rust-lang.org/std/fs/struct.ReadDir.html
/// [`TempDir::close`]: struct.TempDir.html#method.close
/// [`TempDir::new`]: struct.TempDir.html#method.new
/// [`TempDir::new_in`]: struct.TempDir.html#method.new_in
/// [`TempDir::path`]: struct.TempDir.html#method.path
/// [`TempDir`]: struct.TempDir.html
/// [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html
/// [`std::fs`]: http://doc.rust-lang.org/std/fs/index.html
/// [`std::process::exit`]: http://doc.rust-lang.org/std/process/fn.exit.html
pub struct TempDir {
    path: Option<PathBuf>,
}

// How many times should we (re)try finding an unused random name? It should be
// enough that an attacker will run out of luck before we run out of patience.
const NUM_RETRIES: u32 = 1 << 31;
// How many characters should we include in a random file name? It needs to
// be enough to dissuade an attacker from trying to preemptively create names
// of that length, but not so huge that we unnecessarily drain the random number
// generator of entropy.
const NUM_RAND_CHARS: usize = 12;

impl TempDir {
    /// Attempts to make a temporary directory inside of `env::temp_dir()` whose
    /// name will have the prefix, `prefix`. The directory and
    /// everything inside it will be automatically deleted once the
    /// returned `TempDir` is destroyed.
    ///
    /// # Errors
    ///
    /// If the directory can not be created, `Err` is returned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs::File;
    /// use std::io::Write;
    /// use tempdir::TempDir;
    ///
    /// # use std::io;
    /// # fn run() -> Result<(), io::Error> {
    /// // Create a directory inside of `std::env::temp_dir()`, named with
    /// // the prefix, "example".
    /// let tmp_dir = TempDir::new("example")?;
    /// let file_path = tmp_dir.path().join("my-temporary-note.txt");
    /// let mut tmp_file = File::create(file_path)?;
    /// writeln!(tmp_file, "Brian was here. Briefly.")?;
    ///
    /// // `tmp_dir` goes out of scope, the directory as well as
    /// // `tmp_file` will be deleted here.
    /// # Ok(())
    /// # }
    /// ```
    pub fn new(prefix: &str) -> io::Result<TempDir> {
        TempDir::new_in(&env::temp_dir(), prefix)
    }

    /// Attempts to make a temporary directory inside of `tmpdir`
    /// whose name will have the prefix `prefix`. The directory and
    /// everything inside it will be automatically deleted once the
    /// returned `TempDir` is destroyed.
    ///
    /// # Errors
    ///
    /// If the directory can not be created, `Err` is returned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs::{self, File};
    /// use std::io::Write;
    /// use tempdir::TempDir;
    ///
    /// # use std::io;
    /// # fn run() -> Result<(), io::Error> {
    /// // Create a directory inside of the current directory, named with
    /// // the prefix, "example".
    /// let tmp_dir = TempDir::new_in(".", "example")?;
    /// let file_path = tmp_dir.path().join("my-temporary-note.txt");
    /// let mut tmp_file = File::create(file_path)?;
    /// writeln!(tmp_file, "Brian was here. Briefly.")?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn new_in<P: AsRef<Path>>(tmpdir: P, prefix: &str) -> io::Result<TempDir> {
        let storage;
        let mut tmpdir = tmpdir.as_ref();
        if !tmpdir.is_absolute() {
            let cur_dir = env::current_dir()?;
            storage = cur_dir.join(tmpdir);
            tmpdir = &storage;
            // return TempDir::new_in(&cur_dir.join(tmpdir), prefix);
        }

        let mut rng = thread_rng();
        for _ in 0..NUM_RETRIES {
            let suffix: String = rng.gen_ascii_chars().take(NUM_RAND_CHARS).collect();
            let leaf = if prefix.len() > 0 {
                format!("{}.{}", prefix, suffix)
            } else {
                // If we're given an empty string for a prefix, then creating a
                // directory starting with "." would lead to it being
                // semi-invisible on some systems.
                suffix
            };
            let path = tmpdir.join(&leaf);
            match fs::create_dir(&path) {
                Ok(_) => return Ok(TempDir { path: Some(path) }),
                Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {}
                Err(e) => return Err(e),
            }
        }

        Err(Error::new(ErrorKind::AlreadyExists,
                       "too many temporary directories already exist"))
    }

    /// Accesses the [`Path`] to the temporary directory.
    ///
    /// [`Path`]: http://doc.rust-lang.org/std/path/struct.Path.html
    ///
    /// # Examples
    ///
    /// ```
    /// use tempdir::TempDir;
    ///
    /// # use std::io;
    /// # fn run() -> Result<(), io::Error> {
    /// let tmp_path;
    ///
    /// {
    ///    let tmp_dir = TempDir::new("example")?;
    ///    tmp_path = tmp_dir.path().to_owned();
    ///
    ///    // Check that the temp directory actually exists.
    ///    assert!(tmp_path.exists());
    ///
    ///    // End of `tmp_dir` scope, directory will be deleted
    /// }
    ///
    /// // Temp directory should be deleted by now
    /// assert_eq!(tmp_path.exists(), false);
    /// # Ok(())
    /// # }
    /// ```
    pub fn path(&self) -> &path::Path {
        self.path.as_ref().unwrap()
    }

    /// Unwraps the [`Path`] contained in the `TempDir` and
    /// returns it. This destroys the `TempDir` without deleting the
    /// directory represented by the returned `Path`.
    ///
    /// [`Path`]: http://doc.rust-lang.org/std/path/struct.Path.html
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use tempdir::TempDir;
    ///
    /// # use std::io;
    /// # fn run() -> Result<(), io::Error> {
    /// let tmp_dir = TempDir::new("example")?;
    ///
    /// // Convert `tmp_dir` into a `Path`, destroying the `TempDir`
    /// // without deleting the directory.
    /// let tmp_path = tmp_dir.into_path();
    ///
    /// // Delete the temporary directory ourselves.
    /// fs::remove_dir_all(tmp_path)?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn into_path(mut self) -> PathBuf {
        self.path.take().unwrap()
    }

    /// Closes and removes the temporary directory, returing a `Result`.
    ///
    /// Although `TempDir` removes the directory on drop, in the destructor
    /// any errors are ignored. To detect errors cleaning up the temporary
    /// directory, call `close` instead.
    ///
    /// # Errors
    ///
    /// This function may return a variety of [`std::io::Error`]s that result from deleting
    /// the files and directories contained with the temporary directory,
    /// as well as from deleting the temporary directory itself. These errors
    /// may be platform specific.
    ///
    /// [`std::io::Error`]: http://doc.rust-lang.org/std/io/struct.Error.html
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs::File;
    /// use std::io::Write;
    /// use tempdir::TempDir;
    ///
    /// # use std::io;
    /// # fn run() -> Result<(), io::Error> {
    /// // Create a directory inside of `std::env::temp_dir()`, named with
    /// // the prefix, "example".
    /// let tmp_dir = TempDir::new("example")?;
    /// let file_path = tmp_dir.path().join("my-temporary-note.txt");
    /// let mut tmp_file = File::create(file_path)?;
    /// writeln!(tmp_file, "Brian was here. Briefly.")?;
    ///
    /// // By closing the `TempDir` explicitly we can check that it has
    /// // been deleted successfully. If we don't close it explicitly,
    /// // the directory will still be deleted when `tmp_dir` goes out
    /// // of scope, but we won't know whether deleting the directory
    /// // succeeded.
    /// drop(tmp_file);
    /// tmp_dir.close()?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn close(mut self) -> io::Result<()> {
        let result = remove_dir_all(self.path());

        // Prevent the Drop impl from removing the dir a second time.
        self.path = None;

        result
    }
}

impl AsRef<Path> for TempDir {
    fn as_ref(&self) -> &Path {
        self.path()
    }
}

impl fmt::Debug for TempDir {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("TempDir")
            .field("path", &self.path())
            .finish()
    }
}

impl Drop for TempDir {
    fn drop(&mut self) {
        // Path is `None` if `close()` or `into_path()` has been called.
        if let Some(ref p) = self.path {
            let _ =  remove_dir_all(p);
        }
    }
}

// the tests for this module need to change the path using change_dir,
// and this doesn't play nicely with other tests so these unit tests are located
// in src/test/run-pass/tempfile.rs
<commit_msg>Clean compiler warning<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://docs.rs/tempdir/0.3.5")]
#![cfg_attr(test, deny(warnings))]

//! Temporary directories of files.
//!
//! The [`TempDir`] type creates a directory on the file system that
//! is deleted once it goes out of scope. At construction, the
//! `TempDir` creates a new directory with a randomly generated name
//! and a prefix of your choosing.
//!
//! [`TempDir`]: struct.TempDir.html
//! [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html
//!
//! # Examples
//!
//! ```
//! extern crate tempdir;
//!
//! use std::fs::File;
//! use std::io::{self, Write};
//! use tempdir::TempDir;
//!
//! fn main() {
//!     if let Err(_) = run() {
//!         ::std::process::exit(1);
//!     }
//! }
//!
//! fn run() -> Result<(), io::Error> {
//!     // Create a directory inside of `std::env::temp_dir()`, named with
//!     // the prefix "example".
//!     let tmp_dir = TempDir::new("example")?;
//!     let file_path = tmp_dir.path().join("my-temporary-note.txt");
//!     let mut tmp_file = File::create(file_path)?;
//!     writeln!(tmp_file, "Brian was here. Briefly.")?;
//!
//!     // By closing the `TempDir` explicitly, we can check that it has
//!     // been deleted successfully. If we don't close it explicitly,
//!     // the directory will still be deleted when `tmp_dir` goes out
//!     // of scope, but we won't know whether deleting the directory
//!     // succeeded.
//!     drop(tmp_file);
//!     tmp_dir.close()?;
//!     Ok(())
//! }
//! ```

extern crate rand;
extern crate remove_dir_all;

use std::env;
use std::io::{self, Error, ErrorKind};
use std::fmt;
use std::fs;
use std::path::{self, PathBuf, Path};
use rand::{thread_rng, Rng};
use remove_dir_all::remove_dir_all;

/// A directory in the filesystem that is automatically deleted when
/// it goes out of scope.
///
/// The [`TempDir`] type creates a directory on the file system that
/// is deleted once it goes out of scope. At construction, the
/// `TempDir` creates a new directory with a randomly generated name,
/// and with a prefix of your choosing.
///
/// The default constructor, [`TempDir::new`], creates directories in
/// the location returned by [`std::env::temp_dir()`], but `TempDir`
/// can be configured to manage a temporary directory in any location
/// by constructing with [`TempDir::new_in`].
///
/// After creating a `TempDir`, work with the file system by doing
/// standard [`std::fs`] file system operations on its [`Path`],
/// which can be retrieved with [`TempDir::path`]. Once the `TempDir`
/// value is dropped, the directory at the path will be deleted, along
/// with any files and directories it contains. It is your responsibility
/// to ensure that no further file system operations are attempted
/// inside the temporary directory once it has been deleted.
///
/// Various platform-specific conditions may cause `TempDir` to fail
/// to delete the underlying directory. It's important to ensure that
/// handles (like [`File`] and [`ReadDir`]) to files inside the
/// directory are dropped before the `TempDir` goes out of scope. The
/// `TempDir` destructor will silently ignore any errors in deleting
/// the directory; to instead handle errors call [`TempDir::close`].
///
/// Note that if the program exits before the `TempDir` destructor is
/// run, such as via [`std::process::exit`], by segfaulting, or by
/// receiving a signal like `SIGINT`, then the temporary directory
/// will not be deleted.
///
/// [`File`]: http://doc.rust-lang.org/std/fs/struct.File.html
/// [`Path`]: http://doc.rust-lang.org/std/path/struct.Path.html
/// [`ReadDir`]: http://doc.rust-lang.org/std/fs/struct.ReadDir.html
/// [`TempDir::close`]: struct.TempDir.html#method.close
/// [`TempDir::new`]: struct.TempDir.html#method.new
/// [`TempDir::new_in`]: struct.TempDir.html#method.new_in
/// [`TempDir::path`]: struct.TempDir.html#method.path
/// [`TempDir`]: struct.TempDir.html
/// [`std::env::temp_dir()`]: https://doc.rust-lang.org/std/env/fn.temp_dir.html
/// [`std::fs`]: http://doc.rust-lang.org/std/fs/index.html
/// [`std::process::exit`]: http://doc.rust-lang.org/std/process/fn.exit.html
pub struct TempDir {
    path: Option<PathBuf>,
}

// How many times should we (re)try finding an unused random name? It should be
// enough that an attacker will run out of luck before we run out of patience.
const NUM_RETRIES: u32 = 1 << 31;
// How many characters should we include in a random file name? It needs to
// be enough to dissuade an attacker from trying to preemptively create names
// of that length, but not so huge that we unnecessarily drain the random number
// generator of entropy.
const NUM_RAND_CHARS: usize = 12;

impl TempDir {
    /// Attempts to make a temporary directory inside of `env::temp_dir()` whose
    /// name will have the prefix, `prefix`. The directory and
    /// everything inside it will be automatically deleted once the
    /// returned `TempDir` is destroyed.
    ///
    /// # Errors
    ///
    /// If the directory can not be created, `Err` is returned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs::File;
    /// use std::io::Write;
    /// use tempdir::TempDir;
    ///
    /// # use std::io;
    /// # fn run() -> Result<(), io::Error> {
    /// // Create a directory inside of `std::env::temp_dir()`, named with
    /// // the prefix, "example".
    /// let tmp_dir = TempDir::new("example")?;
    /// let file_path = tmp_dir.path().join("my-temporary-note.txt");
    /// let mut tmp_file = File::create(file_path)?;
    /// writeln!(tmp_file, "Brian was here. Briefly.")?;
    ///
    /// // `tmp_dir` goes out of scope, the directory as well as
    /// // `tmp_file` will be deleted here.
    /// # Ok(())
    /// # }
    /// ```
    pub fn new(prefix: &str) -> io::Result<TempDir> {
        TempDir::new_in(&env::temp_dir(), prefix)
    }

    /// Attempts to make a temporary directory inside of `tmpdir`
    /// whose name will have the prefix `prefix`. The directory and
    /// everything inside it will be automatically deleted once the
    /// returned `TempDir` is destroyed.
    ///
    /// # Errors
    ///
    /// If the directory can not be created, `Err` is returned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs::{self, File};
    /// use std::io::Write;
    /// use tempdir::TempDir;
    ///
    /// # use std::io;
    /// # fn run() -> Result<(), io::Error> {
    /// // Create a directory inside of the current directory, named with
    /// // the prefix, "example".
    /// let tmp_dir = TempDir::new_in(".", "example")?;
    /// let file_path = tmp_dir.path().join("my-temporary-note.txt");
    /// let mut tmp_file = File::create(file_path)?;
    /// writeln!(tmp_file, "Brian was here. Briefly.")?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn new_in<P: AsRef<Path>>(tmpdir: P, prefix: &str) -> io::Result<TempDir> {
        let storage;
        let mut tmpdir = tmpdir.as_ref();
        if !tmpdir.is_absolute() {
            let cur_dir = env::current_dir()?;
            storage = cur_dir.join(tmpdir);
            tmpdir = &storage;
            // return TempDir::new_in(&cur_dir.join(tmpdir), prefix);
        }

        let mut rng = thread_rng();
        for _ in 0..NUM_RETRIES {
            let suffix: String = rng.gen_ascii_chars().take(NUM_RAND_CHARS).collect();
            let leaf = if !prefix.is_empty() {
                format!("{}.{}", prefix, suffix)
            } else {
                // If we're given an empty string for a prefix, then creating a
                // directory starting with "." would lead to it being
                // semi-invisible on some systems.
                suffix
            };
            let path = tmpdir.join(&leaf);
            match fs::create_dir(&path) {
                Ok(_) => return Ok(TempDir { path: Some(path) }),
                Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {}
                Err(e) => return Err(e),
            }
        }

        Err(Error::new(ErrorKind::AlreadyExists,
                       "too many temporary directories already exist"))
    }

    /// Accesses the [`Path`] to the temporary directory.
    ///
    /// [`Path`]: http://doc.rust-lang.org/std/path/struct.Path.html
    ///
    /// # Examples
    ///
    /// ```
    /// use tempdir::TempDir;
    ///
    /// # use std::io;
    /// # fn run() -> Result<(), io::Error> {
    /// let tmp_path;
    ///
    /// {
    ///    let tmp_dir = TempDir::new("example")?;
    ///    tmp_path = tmp_dir.path().to_owned();
    ///
    ///    // Check that the temp directory actually exists.
    ///    assert!(tmp_path.exists());
    ///
    ///    // End of `tmp_dir` scope, directory will be deleted
    /// }
    ///
    /// // Temp directory should be deleted by now
    /// assert_eq!(tmp_path.exists(), false);
    /// # Ok(())
    /// # }
    /// ```
    pub fn path(&self) -> &path::Path {
        self.path.as_ref().unwrap()
    }

    /// Unwraps the [`Path`] contained in the `TempDir` and
    /// returns it. This destroys the `TempDir` without deleting the
    /// directory represented by the returned `Path`.
    ///
    /// [`Path`]: http://doc.rust-lang.org/std/path/struct.Path.html
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use tempdir::TempDir;
    ///
    /// # use std::io;
    /// # fn run() -> Result<(), io::Error> {
    /// let tmp_dir = TempDir::new("example")?;
    ///
    /// // Convert `tmp_dir` into a `Path`, destroying the `TempDir`
    /// // without deleting the directory.
    /// let tmp_path = tmp_dir.into_path();
    ///
    /// // Delete the temporary directory ourselves.
    /// fs::remove_dir_all(tmp_path)?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn into_path(mut self) -> PathBuf {
        self.path.take().unwrap()
    }

    /// Closes and removes the temporary directory, returing a `Result`.
    ///
    /// Although `TempDir` removes the directory on drop, in the destructor
    /// any errors are ignored. To detect errors cleaning up the temporary
    /// directory, call `close` instead.
    ///
    /// # Errors
    ///
    /// This function may return a variety of [`std::io::Error`]s that result from deleting
    /// the files and directories contained with the temporary directory,
    /// as well as from deleting the temporary directory itself. These errors
    /// may be platform specific.
    ///
    /// [`std::io::Error`]: http://doc.rust-lang.org/std/io/struct.Error.html
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs::File;
    /// use std::io::Write;
    /// use tempdir::TempDir;
    ///
    /// # use std::io;
    /// # fn run() -> Result<(), io::Error> {
    /// // Create a directory inside of `std::env::temp_dir()`, named with
    /// // the prefix, "example".
    /// let tmp_dir = TempDir::new("example")?;
    /// let file_path = tmp_dir.path().join("my-temporary-note.txt");
    /// let mut tmp_file = File::create(file_path)?;
    /// writeln!(tmp_file, "Brian was here. Briefly.")?;
    ///
    /// // By closing the `TempDir` explicitly we can check that it has
    /// // been deleted successfully. If we don't close it explicitly,
    /// // the directory will still be deleted when `tmp_dir` goes out
    /// // of scope, but we won't know whether deleting the directory
    /// // succeeded.
    /// drop(tmp_file);
    /// tmp_dir.close()?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn close(mut self) -> io::Result<()> {
        let result = remove_dir_all(self.path());

        // Prevent the Drop impl from removing the dir a second time.
        self.path = None;

        result
    }
}

impl AsRef<Path> for TempDir {
    fn as_ref(&self) -> &Path {
        self.path()
    }
}

impl fmt::Debug for TempDir {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("TempDir")
            .field("path", &self.path())
            .finish()
    }
}

impl Drop for TempDir {
    fn drop(&mut self) {
        // Path is `None` if `close()` or `into_path()` has been called.
        if let Some(ref p) = self.path {
            let _ =  remove_dir_all(p);
        }
    }
}

// the tests for this module need to change the path using change_dir,
// and this doesn't play nicely with other tests so these unit tests are located
// in src/test/run-pass/tempfile.rs
<|endoftext|>