<commit_before>//! `Scene` and `SyncGuard` structures.

use node;
use color::Color;
use hub::{Hub, HubPtr, SubNode};
use object::{Base, DowncastObject, Group, Object};
use texture::{CubeMap, Texture};

use std::mem;
use std::marker::PhantomData;
use std::sync::MutexGuard;

/// Background type.
#[derive(Clone, Debug, PartialEq)]
pub enum Background {
    /// Basic solid color background.
    Color(Color),
    /// Texture background, covers the whole screen.
    // TODO: different wrap modes?
    Texture(Texture<[f32; 4]>),
    /// Skybox
    Skybox(CubeMap<[f32; 4]>),
}

/// The root node of a tree of game objects that may be rendered by a [`Camera`].
///
/// [`Camera`]: ../camera/struct.Camera.html
pub struct Scene {
    pub(crate) hub: HubPtr,
    pub(crate) first_child: Option<node::NodePointer>,
    /// See [`Background`](struct.Background.html).
    pub background: Background,
}

impl Scene {
    /// Add new [`Base`](struct.Base.html) to the scene.
    pub fn add<P>(
        &mut self,
        child_base: P,
    ) where
        P: AsRef<Base>,
    {
        let mut hub = self.hub.lock().unwrap();
        let node_ptr = child_base.as_ref().node.clone();
        let child = &mut hub[child_base];

        if child.next_sibling.is_some() {
            error!("Element {:?} is added to a scene while still having old parent - {}",
                child.sub_node, "discarding siblings");
        }

        child.next_sibling = mem::replace(&mut self.first_child, Some(node_ptr));
    }

    /// Remove a previously added [`Base`](struct.Base.html) from the scene.
    pub fn remove<P>(
        &mut self,
        child_base: P,
    ) where
        P: AsRef<Base>,
    {
        let target_maybe = Some(child_base.as_ref().node.clone());
        let mut hub = self.hub.lock().unwrap();
        let next_sibling = hub[child_base].next_sibling.clone();

        if self.first_child == target_maybe {
            self.first_child = next_sibling;
            return;
        }

        let mut cur_ptr = self.first_child.clone();
        while let Some(ptr) = cur_ptr.take() {
            let node = &mut hub.nodes[&ptr];
            if node.next_sibling == target_maybe {
                node.next_sibling = next_sibling;
                return;
            }
            cur_ptr = node.next_sibling.clone(); //TODO: avoid clone
        }

        error!("Unable to find child for removal");
    }
}

/// `SyncGuard` is used to obtain information about scene nodes in the most effective way.
///
/// # Examples
///
/// Imagine that you have your own helper type `Enemy`:
///
/// ```rust
/// # extern crate three;
/// struct Enemy {
///     mesh: three::Mesh,
///     is_visible: bool,
/// }
/// # fn main() {}
/// ```
///
/// You need this wrapper around `three::Mesh` to cache some information - in our case, visibility.
///
/// In your game you contain all your enemy objects in `Vec<Enemy>`. In the main loop you need
/// to iterate over all the enemies and make them visible or not, basing on current position.
/// The most obvious way is to use [`object::Base::sync`], but it's not the best idea from the side of
/// performance. Instead, you can create `SyncGuard` and use its `resolve` method to effectively
/// walk through every enemy in your game:
///
/// ```rust,no_run
/// # #[macro_use]
/// # extern crate three;
/// # #[derive(Clone)]
/// # struct Enemy {
/// #     mesh: three::Mesh,
/// #     is_visible: bool,
/// # }
/// #
/// # three_object!(Enemy::mesh);
/// #
/// # fn main() {
/// # use three::Object;
/// # let mut win = three::Window::new("SyncGuard example");
/// # let geometry = three::Geometry::default();
/// # let material = three::material::Basic { color: three::color::RED, map: None };
/// # let mesh = win.factory.mesh(geometry, material);
/// # let enemy = Enemy { mesh, is_visible: true };
/// # win.scene.add(&enemy);
/// # let mut enemies = vec![enemy];
/// # loop {
/// let mut sync = win.scene.sync_guard();
/// for mut enemy in &mut enemies {
///     let node = sync.resolve(enemy);
///     let position = node.transform.position;
///     if position.x > 10.0 {
///         enemy.is_visible = false;
///         enemy.set_visible(false);
///     } else {
///         enemy.is_visible = true;
///         enemy.set_visible(true);
///     }
/// }
/// # }}
/// ```
///
/// [`object::Base::sync`]: ../object/struct.Base.html#method.sync
pub struct SyncGuard<'a> {
    pub(crate) scene: &'a Scene,
    pub(crate) hub: MutexGuard<'a, Hub>,
}

impl<'a> SyncGuard<'a> {
    /// Obtains `objects`'s local space [`Node`] in an effective way.
    ///
    /// # Panics
    /// Panics if `scene` doesn't have this `object::Base`.
    ///
    /// [`Node`]: ../node/struct.Node.html
    pub fn resolve<T: 'a + Object>(
        &self,
        object: &T,
    ) -> node::Node<node::Local> {
        self.hub[object].to_node()
    }

    /// Obtains `objects`'s world [`Node`] by traversing the scene graph.
    /// *Note*: this can be slow.
    ///
    /// # Panics
    /// Panics if the scene doesn't have this `object::Base`.
    ///
    /// [`Node`]: ../node/struct.Node.html
    pub fn resolve_world<T: 'a + Object>(
        &self,
        object: &T,
    ) -> node::Node<node::World> {
        let internal = &self.hub[object] as *const _;
        let wn = self.hub
            .walk_all(&self.scene.first_child)
            .find(|wn| wn.node as *const _ == internal)
            .expect("Unable to find objects for world resolve!");
        node::Node {
            visible: wn.world_visible,
            name: wn.node.name.clone(),
            transform: wn.world_transform.into(),
            material: match wn.node.sub_node {
                SubNode::Visual(ref mat, _, _) => Some(mat.clone()),
                _ => None,
            },
            _space: PhantomData,
        }
    }

    /// Obtains internal state data for `object`.
    ///
    /// Three-rs objects normally expose a write-only interface, making it possible to change
    /// an object's internal values but not possible to read those values. `SyncGuard` allows
    /// for that data to be read in a controlled way.
    ///
    /// Each object type has its own internal data, and not all object types can provide access
    /// to meaningful data. The following types provide specific data you can use:
    ///
    /// * [`Base`]: Returns an [`ObjectType`], which provides access to the concrete object type
    ///   for `object`.
    /// * [`Group`]: Returns a list of the group's direct children.
    /// * [`Camera`]: Returns the [`Projection`] for the camera.
    /// * [`Ambient`]: Returns the [`LightData`] for the light.
    /// * [`Point`]: Returns the [`LightData`] for the light.
    /// * [`Directional`]: Returns the [`LightData`] for the light.
    /// * [`Hemisphere`]: Returns the [`HemisphereLightData`] for the light.
    ///
    /// The other object types do not have a user-facing way to represent their internal data,
    /// and so return `()`.
    ///
    /// [`Base`]: ../object/struct.Base.html
    /// [`ObjectType`]: ../object/enum.ObjectType.html
    /// [`Group`]: ../struct.Group.html
    /// [`Camera`]: ../camera/struct.Camera.html
    /// [`Projection`]: ../camera/enum.Projection.html
    /// [`LightData`]: ../light/struct.LightData.html
    /// [`Ambient`]: ../light/struct.Ambient.html
    /// [`Point`]: ../light/struct.Point.html
    /// [`Directional`]: ../light/struct.Directional.html
    /// [`Hemisphere`]: ../light/struct.Hemisphere.html
    /// [`HemisphereLightData`]: ../light/struct.HemisphereLightData.html
    pub fn resolve_data<T: 'a + Object>(
        &self,
        object: &T,
    ) -> T::Data {
        object.resolve_data(self)
    }

    /// Returns an iterator that walks all the objects in `root`'s hierarchy.
    ///
    /// Walks the children of `root`, recursively walking the children of any [`Group`] objects
    /// found until all objects in the hierarchy have been visited. The hierarchy is walked
    /// depth-first, and objects are yielded in the order they are visited.
    ///
    /// [`Group`]: ../struct.Group.html
    pub fn walk_hierarchy(&'a self, root: &Group) -> impl Iterator<Item = Base> + 'a {
        let root = root.as_ref().node.clone();
        let guard = &*self;
        self
            .hub
            .walk_all(&Some(root))
            .map(move |walked| guard.hub.upgrade_ptr(walked.node_ptr.clone()))
    }

    /// Finds a node in a group, or any of its children, by name.
    ///
    /// Performs a depth-first search starting with `root` looking for an object with `name`.
    /// Returns the [`Base`] for the first object found with a matching name, otherwise returns
    /// `None` if no such object is found. Note that if more than one such object exists in the
    /// hierarchy, then only the first one discovered will be returned.
    ///
    /// [`Base`]: ../object/struct.Base.html
    pub fn find_child_by_name(&self, root: &Group, name: &str) -> Option<Base> {
        let root = root.as_ref().node.clone();
        self
            .hub
            .walk_all(&Some(root))
            .find(|walked| walked.node.name.as_ref().map(|node_name| node_name == name).unwrap_or(false))
            .map(|walked| self.hub.upgrade_ptr(walked.node_ptr.clone()))
    }

    /// Returns an iterator of all objects under `root` with the specified name.
    ///
    /// Performs a depth-first search starting with `root`, yielding each object in the hierarchy
    /// matching `name`.
    ///
    /// [`Group`]: ../struct.Group.html
    pub fn find_children_by_name(
        &'a self,
        root: &Group,
        name: &'a str,
    ) -> impl Iterator<Item = Base> + 'a {
        let root = root.as_ref().node.clone();
        let guard = &*self;
        self
            .hub
            .walk_all(&Some(root))
            .filter(move |walked| {
                walked
                    .node
                    .name
                    .as_ref()
                    .map(|node_name| node_name == name)
                    .unwrap_or(false)
            })
            .map(move |walked| guard.hub.upgrade_ptr(walked.node_ptr.clone()))
    }

    /// Finds the first object in a group, or any of its children, of type `T`.
    ///
    /// Performs a depth-first search starting with `root`, recusively descending into any
    /// [`Group`] objects found. Returns the first object of type `T` encountered in the
    /// hierarchy.
    ///
    /// [`Group`]: ../struct.Group.html
    pub fn find_child_of_type<T: DowncastObject>(&'a self, root: &Group) -> Option<T> {
        self.find_children_of_type::<T>(root).next()
    }

    /// Returns an iterator yielding all objects in the hierarchy of `root` of type `T`.
    ///
    /// Performs a depth-first search starting with `root`, recursively descending into any
    /// [`Group`] objects found, yielding each object of type `T` found in the hierarchy.
    ///
    /// [`Group`]: ../struct.Group.html
    pub fn find_children_of_type<T: DowncastObject>(
        &'a self,
        root: &Group,
    ) -> impl Iterator<Item = T> + 'a {
        let root = root.as_ref().node.clone();
        let guard = &*self;
        self
            .hub
            .walk_all(&Some(root))
            .map(move |walked| guard.hub.upgrade_ptr(walked.node_ptr.clone()))
            .filter_map(move |base| guard.downcast(&base))
    }

    /// Attempts to find an object of type `T` in the group or any of its children.
    ///
    /// Performs a depth-first search starting with `root`, recursively searching [`Group`]
    /// objects, until an object of type `T` that matches `name` is found. Note that if `T` is
    /// [`Group`] and `root` matches `name`, then it will be returned.
    ///
    /// [`Group`]: ../struct.Group.html
    pub fn find_child_of_type_by_name<T: DowncastObject>(
        &'a self,
        root: &Group,
        name: &'a str,
    ) -> Option<T> {
        self.find_children_of_type_by_name(root, name).next()
    }

    /// Returns an iterator yielding all children of `root` of type `T` named `name`.
    ///
    /// Performs a depth-first search starting with `root`, recursively searching [`Group`]
    /// objects, yielding any objects of `T` that match `name`. Note that if `T` is [`Group`]
    /// and `root` matches `name`, then it will be the first object yielded by the iterator.
    ///
    /// [`Group`]: ../struct.Group.html
    pub fn find_children_of_type_by_name<T: DowncastObject>(
        &'a self,
        root: &Group,
        name: &'a str,
    ) -> impl Iterator<Item = T> + 'a {
        let guard = &*self;
        self
            .find_children_by_name(root, name)
            .filter_map(move |base| guard.downcast(&base))
    }

    /// Attempts to downcast a [`Base`] to its concrete object type.
    ///
    /// If the downcast succeeds, the concrete object is returned. Returns `None` if the
    /// downcast fails.
    ///
    /// [`Base`]: ../object/struct.Base.html
    pub fn downcast<T: DowncastObject>(&self, base: &Base) -> Option<T> {
        let object_type = self.resolve_data(base);
        T::downcast(object_type)
    }
}

impl Scene {
    /// Create new [`SyncGuard`](struct.SyncGuard.html).
    ///
    /// This is performance-costly operation, you should not use it many times per frame.
    pub fn sync_guard(&mut self) -> SyncGuard {
        let mut hub = self.hub.lock().unwrap();
        hub.process_messages();
        SyncGuard { scene: self, hub }
    }
}
<commit_msg>Implement find_child_by_name in terms of find_children_by_name<commit_after>//! `Scene` and `SyncGuard` structures.

use node;
use color::Color;
use hub::{Hub, HubPtr, SubNode};
use object::{Base, DowncastObject, Group, Object};
use texture::{CubeMap, Texture};

use std::mem;
use std::marker::PhantomData;
use std::sync::MutexGuard;

/// Background type.
#[derive(Clone, Debug, PartialEq)]
pub enum Background {
    /// Basic solid color background.
    Color(Color),
    /// Texture background, covers the whole screen.
    // TODO: different wrap modes?
    Texture(Texture<[f32; 4]>),
    /// Skybox
    Skybox(CubeMap<[f32; 4]>),
}

/// The root node of a tree of game objects that may be rendered by a [`Camera`].
///
/// [`Camera`]: ../camera/struct.Camera.html
pub struct Scene {
    pub(crate) hub: HubPtr,
    pub(crate) first_child: Option<node::NodePointer>,
    /// See [`Background`](struct.Background.html).
    pub background: Background,
}

impl Scene {
    /// Add new [`Base`](struct.Base.html) to the scene.
    pub fn add<P>(
        &mut self,
        child_base: P,
    ) where
        P: AsRef<Base>,
    {
        let mut hub = self.hub.lock().unwrap();
        let node_ptr = child_base.as_ref().node.clone();
        let child = &mut hub[child_base];

        if child.next_sibling.is_some() {
            error!("Element {:?} is added to a scene while still having old parent - {}",
                child.sub_node, "discarding siblings");
        }

        child.next_sibling = mem::replace(&mut self.first_child, Some(node_ptr));
    }

    /// Remove a previously added [`Base`](struct.Base.html) from the scene.
    pub fn remove<P>(
        &mut self,
        child_base: P,
    ) where
        P: AsRef<Base>,
    {
        let target_maybe = Some(child_base.as_ref().node.clone());
        let mut hub = self.hub.lock().unwrap();
        let next_sibling = hub[child_base].next_sibling.clone();

        if self.first_child == target_maybe {
            self.first_child = next_sibling;
            return;
        }

        let mut cur_ptr = self.first_child.clone();
        while let Some(ptr) = cur_ptr.take() {
            let node = &mut hub.nodes[&ptr];
            if node.next_sibling == target_maybe {
                node.next_sibling = next_sibling;
                return;
            }
            cur_ptr = node.next_sibling.clone(); //TODO: avoid clone
        }

        error!("Unable to find child for removal");
    }
}

/// `SyncGuard` is used to obtain information about scene nodes in the most effective way.
///
/// # Examples
///
/// Imagine that you have your own helper type `Enemy`:
///
/// ```rust
/// # extern crate three;
/// struct Enemy {
///     mesh: three::Mesh,
///     is_visible: bool,
/// }
/// # fn main() {}
/// ```
///
/// You need this wrapper around `three::Mesh` to cache some information - in our case, visibility.
///
/// In your game you contain all your enemy objects in `Vec<Enemy>`. In the main loop you need
/// to iterate over all the enemies and make them visible or not, basing on current position.
/// The most obvious way is to use [`object::Base::sync`], but it's not the best idea from the side of
/// performance. Instead, you can create `SyncGuard` and use its `resolve` method to effectively
/// walk through every enemy in your game:
///
/// ```rust,no_run
/// # #[macro_use]
/// # extern crate three;
/// # #[derive(Clone)]
/// # struct Enemy {
/// #     mesh: three::Mesh,
/// #     is_visible: bool,
/// # }
/// #
/// # three_object!(Enemy::mesh);
/// #
/// # fn main() {
/// # use three::Object;
/// # let mut win = three::Window::new("SyncGuard example");
/// # let geometry = three::Geometry::default();
/// # let material = three::material::Basic { color: three::color::RED, map: None };
/// # let mesh = win.factory.mesh(geometry, material);
/// # let enemy = Enemy { mesh, is_visible: true };
/// # win.scene.add(&enemy);
/// # let mut enemies = vec![enemy];
/// # loop {
/// let mut sync = win.scene.sync_guard();
/// for mut enemy in &mut enemies {
///     let node = sync.resolve(enemy);
///     let position = node.transform.position;
///     if position.x > 10.0 {
///         enemy.is_visible = false;
///         enemy.set_visible(false);
///     } else {
///         enemy.is_visible = true;
///         enemy.set_visible(true);
///     }
/// }
/// # }}
/// ```
///
/// [`object::Base::sync`]: ../object/struct.Base.html#method.sync
pub struct SyncGuard<'a> {
    pub(crate) scene: &'a Scene,
    pub(crate) hub: MutexGuard<'a, Hub>,
}

impl<'a> SyncGuard<'a> {
    /// Obtains `objects`'s local space [`Node`] in an effective way.
    ///
    /// # Panics
    /// Panics if `scene` doesn't have this `object::Base`.
    ///
    /// [`Node`]: ../node/struct.Node.html
    pub fn resolve<T: 'a + Object>(
        &self,
        object: &T,
    ) -> node::Node<node::Local> {
        self.hub[object].to_node()
    }

    /// Obtains `objects`'s world [`Node`] by traversing the scene graph.
    /// *Note*: this can be slow.
    ///
    /// # Panics
    /// Panics if the scene doesn't have this `object::Base`.
    ///
    /// [`Node`]: ../node/struct.Node.html
    pub fn resolve_world<T: 'a + Object>(
        &self,
        object: &T,
    ) -> node::Node<node::World> {
        let internal = &self.hub[object] as *const _;
        let wn = self.hub
            .walk_all(&self.scene.first_child)
            .find(|wn| wn.node as *const _ == internal)
            .expect("Unable to find objects for world resolve!");
        node::Node {
            visible: wn.world_visible,
            name: wn.node.name.clone(),
            transform: wn.world_transform.into(),
            material: match wn.node.sub_node {
                SubNode::Visual(ref mat, _, _) => Some(mat.clone()),
                _ => None,
            },
            _space: PhantomData,
        }
    }

    /// Obtains internal state data for `object`.
    ///
    /// Three-rs objects normally expose a write-only interface, making it possible to change
    /// an object's internal values but not possible to read those values. `SyncGuard` allows
    /// for that data to be read in a controlled way.
    ///
    /// Each object type has its own internal data, and not all object types can provide access
    /// to meaningful data. The following types provide specific data you can use:
    ///
    /// * [`Base`]: Returns an [`ObjectType`], which provides access to the concrete object type
    ///   for `object`.
    /// * [`Group`]: Returns a list of the group's direct children.
    /// * [`Camera`]: Returns the [`Projection`] for the camera.
    /// * [`Ambient`]: Returns the [`LightData`] for the light.
    /// * [`Point`]: Returns the [`LightData`] for the light.
    /// * [`Directional`]: Returns the [`LightData`] for the light.
    /// * [`Hemisphere`]: Returns the [`HemisphereLightData`] for the light.
    ///
    /// The other object types do not have a user-facing way to represent their internal data,
    /// and so return `()`.
    ///
    /// [`Base`]: ../object/struct.Base.html
    /// [`ObjectType`]: ../object/enum.ObjectType.html
    /// [`Group`]: ../struct.Group.html
    /// [`Camera`]: ../camera/struct.Camera.html
    /// [`Projection`]: ../camera/enum.Projection.html
    /// [`LightData`]: ../light/struct.LightData.html
    /// [`Ambient`]: ../light/struct.Ambient.html
    /// [`Point`]: ../light/struct.Point.html
    /// [`Directional`]: ../light/struct.Directional.html
    /// [`Hemisphere`]: ../light/struct.Hemisphere.html
    /// [`HemisphereLightData`]: ../light/struct.HemisphereLightData.html
    pub fn resolve_data<T: 'a + Object>(
        &self,
        object: &T,
    ) -> T::Data {
        object.resolve_data(self)
    }

    /// Returns an iterator that walks all the objects in `root`'s hierarchy.
    ///
    /// Walks the children of `root`, recursively walking the children of any [`Group`] objects
    /// found until all objects in the hierarchy have been visited. The hierarchy is walked
    /// depth-first, and objects are yielded in the order they are visited.
    ///
    /// [`Group`]: ../struct.Group.html
    pub fn walk_hierarchy(&'a self, root: &Group) -> impl Iterator<Item = Base> + 'a {
        let root = root.as_ref().node.clone();
        let guard = &*self;
        self
            .hub
            .walk_all(&Some(root))
            .map(move |walked| guard.hub.upgrade_ptr(walked.node_ptr.clone()))
    }

    /// Finds a node in a group, or any of its children, by name.
    ///
    /// Performs a depth-first search starting with `root` looking for an object with `name`.
    /// Returns the [`Base`] for the first object found with a matching name, otherwise returns
    /// `None` if no such object is found. Note that if more than one such object exists in the
    /// hierarchy, then only the first one discovered will be returned.
    ///
    /// [`Base`]: ../object/struct.Base.html
    pub fn find_child_by_name(&self, root: &Group, name: &str) -> Option<Base> {
        self.find_children_by_name(root, name).next()
    }

    /// Returns an iterator of all objects under `root` with the specified name.
    ///
    /// Performs a depth-first search starting with `root`, yielding each object in the hierarchy
    /// matching `name`.
    ///
    /// [`Group`]: ../struct.Group.html
    pub fn find_children_by_name(
        &'a self,
        root: &Group,
        name: &'a str,
    ) -> impl Iterator<Item = Base> + 'a {
        let root = root.as_ref().node.clone();
        let guard = &*self;
        self
            .hub
            .walk_all(&Some(root))
            .filter(move |walked| {
                walked
                    .node
                    .name
                    .as_ref()
                    .map(|node_name| node_name == name)
                    .unwrap_or(false)
            })
            .map(move |walked| guard.hub.upgrade_ptr(walked.node_ptr.clone()))
    }

    /// Finds the first object in a group, or any of its children, of type `T`.
    ///
    /// Performs a depth-first search starting with `root`, recusively descending into any
    /// [`Group`] objects found. Returns the first object of type `T` encountered in the
    /// hierarchy.
    ///
    /// [`Group`]: ../struct.Group.html
    pub fn find_child_of_type<T: DowncastObject>(&'a self, root: &Group) -> Option<T> {
        self.find_children_of_type::<T>(root).next()
    }

    /// Returns an iterator yielding all objects in the hierarchy of `root` of type `T`.
    ///
    /// Performs a depth-first search starting with `root`, recursively descending into any
    /// [`Group`] objects found, yielding each object of type `T` found in the hierarchy.
    ///
    /// [`Group`]: ../struct.Group.html
    pub fn find_children_of_type<T: DowncastObject>(
        &'a self,
        root: &Group,
    ) -> impl Iterator<Item = T> + 'a {
        let root = root.as_ref().node.clone();
        let guard = &*self;
        self
            .hub
            .walk_all(&Some(root))
            .map(move |walked| guard.hub.upgrade_ptr(walked.node_ptr.clone()))
            .filter_map(move |base| guard.downcast(&base))
    }

    /// Attempts to find an object of type `T` in the group or any of its children.
    ///
    /// Performs a depth-first search starting with `root`, recursively searching [`Group`]
    /// objects, until an object of type `T` that matches `name` is found. Note that if `T` is
    /// [`Group`] and `root` matches `name`, then it will be returned.
    ///
    /// [`Group`]: ../struct.Group.html
    pub fn find_child_of_type_by_name<T: DowncastObject>(
        &'a self,
        root: &Group,
        name: &'a str,
    ) -> Option<T> {
        self.find_children_of_type_by_name(root, name).next()
    }

    /// Returns an iterator yielding all children of `root` of type `T` named `name`.
    ///
    /// Performs a depth-first search starting with `root`, recursively searching [`Group`]
    /// objects, yielding any objects of `T` that match `name`. Note that if `T` is [`Group`]
    /// and `root` matches `name`, then it will be the first object yielded by the iterator.
    ///
    /// [`Group`]: ../struct.Group.html
    pub fn find_children_of_type_by_name<T: DowncastObject>(
        &'a self,
        root: &Group,
        name: &'a str,
    ) -> impl Iterator<Item = T> + 'a {
        let guard = &*self;
        self
            .find_children_by_name(root, name)
            .filter_map(move |base| guard.downcast(&base))
    }

    /// Attempts to downcast a [`Base`] to its concrete object type.
    ///
    /// If the downcast succeeds, the concrete object is returned. Returns `None` if the
    /// downcast fails.
    ///
    /// [`Base`]: ../object/struct.Base.html
    pub fn downcast<T: DowncastObject>(&self, base: &Base) -> Option<T> {
        let object_type = self.resolve_data(base);
        T::downcast(object_type)
    }
}

impl Scene {
    /// Create new [`SyncGuard`](struct.SyncGuard.html).
    ///
    /// This is performance-costly operation, you should not use it many times per frame.
    pub fn sync_guard(&mut self) -> SyncGuard {
        let mut hub = self.hub.lock().unwrap();
        hub.process_messages();
        SyncGuard { scene: self, hub }
    }
}
<|endoftext|>


<commit_before>
use core::str::StrExt;
use regex;

pub fn score(choice: &String, query: &String) -> f32 {
    if choice.len() == 0 || query.len() > choice.len() {
        0.0
    } else if query.len() == 0 {
        1.0
    } else {
        let match_length = compute_match_length(choice, query);

        if match_length > 0 {
            1.0 / choice.len() as f32
        } else {
            0.0
        }
    }
}

// Find the length of the shortest substring matching the given characters.
fn compute_match_length(string: &String, query: &String) -> usize {
    let re_string = &make_query_regex(query);
    let re = match regex::Regex::new(re_string.as_slice()) {
        Ok(re)   => re,
        Err(err) => panic!("{}", err.msg),
    };

    // TODO: remove the outer if
    if re.is_match(string.as_slice()) {
        let caps = re.captures(string.as_slice()).unwrap();
        match caps.at(0) {
            Some(s) => return s.char_len() as usize,
            None    => return 0us
        };
    } else {
        0us
    }
}

// Creates a regex for performing a case-insensitive non-greedy fuzzy match.
// Turns "abc" into "(?i)a.*?b.*?c.*?".
fn make_query_regex(query: &String) -> String {
    let mut parts = query
        .chars()
        .map(|ch| regex::quote(ch.to_string().as_slice()))
        .collect::<Vec<String>>();

    parts.insert(0, "(?i)".to_string());

    parts.connect(".*?")
}

#[cfg(test)]
mod test {

    use score::score;
    use core::str::StrExt;

    pub fn do_score(choice: &str, query: &str) -> f32 {
       let choice_string = choice.to_string();
       let query_string = query.to_string();
       score(&choice_string,  &query_string)
    }

    #[test]
    fn scores_zero_when_the_choice_is_empty() {
        assert_eq!(do_score("", ""), 0.0);
    }

    #[test]
    fn scores_one_when_the_query_is_empty() {
        assert_eq!(do_score("a", ""), 1.0);
    }

    #[test]
    fn scores_zero_when_the_query_is_longer_than_the_choice() {
        assert_eq!(do_score("short", "longer"), 0.0);
    }

    #[test]
    fn scores_zero_when_only_a_prefix_of_the_query_matches() {
        assert_eq!(do_score("ab", "ac"), 0.0);
    }

    #[test]
    fn scores_greater_than_zero_when_it_matches() {
        assert!(do_score("a", "a") > 0.0);
        assert!(do_score("ab", "a") > 0.0);
        assert!(do_score("ba", "a") > 0.0);
        assert!(do_score("bab", "a") > 0.0);
        assert!(do_score("babababab", "aaaa") > 0.0);
    }

    #[test]
    fn scores_one_normalized_to_length_when_the_query_equals_the_choice() {
        assert_eq!(do_score("a", "a"), 1.0);
        assert_eq!(do_score("ab", "ab"), 0.5f32);
        assert_eq!(do_score("a long string", "a long string"),
            1.0 / ("a long string".char_len() as f32));

        assert_eq!(do_score("spec/search_spec.rb", "sear"),
            1.0 / ("spec/search_spec.rb".char_len() as f32));
    }

    // Character matching

    #[test]
    fn it_matches_punctuation() {
        assert!(do_score("/! symbols $^", "/!$^") > 0.0);
    }

    #[test]
    fn it_is_case_insensitive() {
        assert_eq!(do_score("a", "A"), 1.0);
        assert_eq!(do_score("A", "a"), 1.0);
    }

    #[test]
    fn it_doesnt_match_when_the_same_letter_is_repeated_in_the_choice() {
        assert_eq!(do_score("a", "aa"), 0.0);
    }

    #[test]
    fn it_scores_higher_for_better_matches() {
        assert!(do_score("selecta.gemspec", "asp")
                > do_score("algorithm4_spec.rb", "asp"));
        assert!(do_score("README.md", "em")
                > do_score("benchmark.rb", "em"));
        assert!(do_score("search.rb", "sear")
                > do_score("spec/search_spec.rb", "sear"));
    }
}

<commit_msg>Simplify regexp matching<commit_after>
use core::str::StrExt;
use regex;

pub fn score(choice: &String, query: &String) -> f32 {
    if choice.len() == 0 || query.len() > choice.len() {
        0.0
    } else if query.len() == 0 {
        1.0
    } else {
        let match_length = compute_match_length(choice, query);

        if match_length > 0 {
            1.0 / choice.len() as f32
        } else {
            0.0
        }
    }
}

// Find the length of the shortest substring matching the given characters.
fn compute_match_length(string: &String, query: &String) -> usize {
    let re_string = &make_query_regex(query);
    let re = match regex::Regex::new(re_string.as_slice()) {
        Ok(re)   => re,
        Err(err) => panic!("{}", err.msg),
    };
    match re.captures(string.as_slice()) {
        Some(caps) => caps.at(0).unwrap_or("").char_len(),
        None       => 0
    }
}

// Creates a regex for performing a case-insensitive non-greedy fuzzy match.
// Turns "abc" into "(?i)a.*?b.*?c.*?".
fn make_query_regex(query: &String) -> String {
    let mut parts = query
        .chars()
        .map(|ch| regex::quote(ch.to_string().as_slice()))
        .collect::<Vec<String>>();

    parts.insert(0, "(?i)".to_string());

    parts.connect(".*?")
}

#[cfg(test)]
mod test {

    use score::score;
    use core::str::StrExt;

    pub fn do_score(choice: &str, query: &str) -> f32 {
       let choice_string = choice.to_string();
       let query_string = query.to_string();
       score(&choice_string,  &query_string)
    }

    #[test]
    fn scores_zero_when_the_choice_is_empty() {
        assert_eq!(do_score("", ""), 0.0);
    }

    #[test]
    fn scores_one_when_the_query_is_empty() {
        assert_eq!(do_score("a", ""), 1.0);
    }

    #[test]
    fn scores_zero_when_the_query_is_longer_than_the_choice() {
        assert_eq!(do_score("short", "longer"), 0.0);
    }

    #[test]
    fn scores_zero_when_only_a_prefix_of_the_query_matches() {
        assert_eq!(do_score("ab", "ac"), 0.0);
    }

    #[test]
    fn scores_greater_than_zero_when_it_matches() {
        assert!(do_score("a", "a") > 0.0);
        assert!(do_score("ab", "a") > 0.0);
        assert!(do_score("ba", "a") > 0.0);
        assert!(do_score("bab", "a") > 0.0);
        assert!(do_score("babababab", "aaaa") > 0.0);
    }

    #[test]
    fn scores_one_normalized_to_length_when_the_query_equals_the_choice() {
        assert_eq!(do_score("a", "a"), 1.0);
        assert_eq!(do_score("ab", "ab"), 0.5f32);
        assert_eq!(do_score("a long string", "a long string"),
            1.0 / ("a long string".char_len() as f32));

        assert_eq!(do_score("spec/search_spec.rb", "sear"),
            1.0 / ("spec/search_spec.rb".char_len() as f32));
    }

    // Character matching

    #[test]
    fn it_matches_punctuation() {
        assert!(do_score("/! symbols $^", "/!$^") > 0.0);
    }

    #[test]
    fn it_is_case_insensitive() {
        assert_eq!(do_score("a", "A"), 1.0);
        assert_eq!(do_score("A", "a"), 1.0);
    }

    #[test]
    fn it_doesnt_match_when_the_same_letter_is_repeated_in_the_choice() {
        assert_eq!(do_score("a", "aa"), 0.0);
    }

    #[test]
    fn it_scores_higher_for_better_matches() {
        assert!(do_score("selecta.gemspec", "asp")
                > do_score("algorithm4_spec.rb", "asp"));
        assert!(do_score("README.md", "em")
                > do_score("benchmark.rb", "em"));
        assert!(do_score("search.rb", "sear")
                > do_score("spec/search_spec.rb", "sear"));
    }
}

<|endoftext|>


<commit_before>use std::process::{Command, Output};
use std::io::Error;
use configuration;
use output;
use file;

pub fn provision(configuration: &configuration::Configuration) -> i32 {
    let mut packages = Vec::new();

    if !configuration.is_valid() {
        output::print_message(format!("==> Configuration invalid! Abort provisioning."), output::MessageType::Stderr);
        return 1;
    }

    packages.extend(configuration.packages.iter().cloned());

    packages.reverse();

    let mut exit_codes = Vec::new();

    let package_exit_codes = install_packages(&packages);
    exit_codes.extend(&package_exit_codes[..]);

    let results = handle_file_resources(&configuration.files);
    exit_codes.extend(&results[..]);

    exit_codes.sort();

    match exit_codes.last() {
        Some(&0) => return 0,
        None     => return 0,
        _        => return 1
    }
}

fn install_packages(package_list: &Vec<String>) -> Vec<i32> {
    let mut exit_codes = Vec::new();
    let mut packages = package_list.clone();

    while let Some(package) = packages.pop() {
        if is_package_installed(&package) {
            continue;
        }
        let shellout = install_package(&package);
        output::print_shellout::<String>(&package, &shellout);
        let exit_status = shellout.status.clone();
        if exit_status.success() == false {
            exit_codes.push(exit_status.code().unwrap());
        }
    }
    exit_codes
}

fn handle_file_resources(resources: &Vec<file::FileResource>) -> Vec<i32> {
    let mut results = Vec::new();
    for resource in resources {
        let result = resource.write_file();
        match result {
            Ok(_) =>  {
                let msg = format!("==> Wrote file {}", resource.path);
                output::print_message(msg, output::MessageType::Stdout);
                results.push(0);
            },
            Err(err) => {
                let msg = format!("==> Error while writing file {}", resource.path);
                output::print_message(msg, output::MessageType::Stderr);
                output::print_message(format!("==> {}", err), output::MessageType::Stderr);
                results.push(1);
            }
        }
    }
    results
}

fn is_package_installed(package_name: &String) -> bool {
    let command_str = format!("yum list installed {}", package_name);
    let output = Command::new(command_str).output();
    output.is_ok()
}

fn install_package(package: &String) -> Output {
    Command::new("yum")
        .args(&vec!["install", "-y", package])
        .output()
        .unwrap()
}
<commit_msg>Print configuration error messages<commit_after>use std::process::{Command, Output};
use std::io::Error;
use configuration;
use output;
use file;

pub fn provision(configuration: &configuration::Configuration) -> i32 {
    let mut packages = Vec::new();

    if !configuration.is_valid() {
        for error_message in configuration.error_messages() {
            output::print_message(error_message, output::MessageType::Stderr);
        }
        return 1;
    }

    packages.extend(configuration.packages.iter().cloned());

    packages.reverse();

    let mut exit_codes = Vec::new();

    let package_exit_codes = install_packages(&packages);
    exit_codes.extend(&package_exit_codes[..]);

    let results = handle_file_resources(&configuration.files);
    exit_codes.extend(&results[..]);

    exit_codes.sort();

    match exit_codes.last() {
        Some(&0) => return 0,
        None     => return 0,
        _        => return 1
    }
}

fn install_packages(package_list: &Vec<String>) -> Vec<i32> {
    let mut exit_codes = Vec::new();
    let mut packages = package_list.clone();

    while let Some(package) = packages.pop() {
        if is_package_installed(&package) {
            continue;
        }
        let shellout = install_package(&package);
        output::print_shellout::<String>(&package, &shellout);
        let exit_status = shellout.status.clone();
        if exit_status.success() == false {
            exit_codes.push(exit_status.code().unwrap());
        }
    }
    exit_codes
}

fn handle_file_resources(resources: &Vec<file::FileResource>) -> Vec<i32> {
    let mut results = Vec::new();
    for resource in resources {
        let result = resource.write_file();
        match result {
            Ok(_) =>  {
                let msg = format!("==> Wrote file {}", resource.path);
                output::print_message(msg, output::MessageType::Stdout);
                results.push(0);
            },
            Err(err) => {
                let msg = format!("==> Error while writing file {}", resource.path);
                output::print_message(msg, output::MessageType::Stderr);
                output::print_message(format!("==> {}", err), output::MessageType::Stderr);
                results.push(1);
            }
        }
    }
    results
}

fn is_package_installed(package_name: &String) -> bool {
    let command_str = format!("yum list installed {}", package_name);
    let output = Command::new(command_str).output();
    output.is_ok()
}

fn install_package(package: &String) -> Output {
    Command::new("yum")
        .args(&vec!["install", "-y", package])
        .output()
        .unwrap()
}
<|endoftext|>


<commit_before>use ::*;

pub fn sound_loop(sound_rx : mpsc::Receiver<&str>, stop : Arc<Mutex<bool>>) {
    let mut monster_dies = Sound::new("monster_dies.wav").unwrap();
    let mut monster_spawns = Sound::new("monster_spawns.wav").unwrap();
    let mut player_dies = Sound::new("player_dies.wav").unwrap();
    loop {
        {
            if *stop.lock().unwrap() {
                break;
            }
        }
        while let Ok(choice) = sound_rx.try_recv() {
            match choice {
                "monster_dies" => monster_dies.play(),
                "monster_spawns" => monster_spawns.play(),
                "player_dies" => player_dies.play(),
                _ => {},
            }
        }
    }
    while player_dies.is_playing() {}
}
<commit_msg>Don't run the sound thread so hot.<commit_after>use ::*;

pub fn sound_loop(sound_rx : mpsc::Receiver<&str>, stop : Arc<Mutex<bool>>) {
    let mut monster_dies = Sound::new("monster_dies.wav").unwrap();
    let mut monster_spawns = Sound::new("monster_spawns.wav").unwrap();
    let mut player_dies = Sound::new("player_dies.wav").unwrap();
    loop {
        sleep(Duration::from_millis(10));
        {
            if *stop.lock().unwrap() {
                break;
            }
        }
        while let Ok(choice) = sound_rx.try_recv() {
            match choice {
                "monster_dies" => monster_dies.play(),
                "monster_spawns" => monster_spawns.play(),
                "player_dies" => player_dies.play(),
                _ => {},
            }
        }
    }
    while player_dies.is_playing() {}
}
<|endoftext|>


<commit_before>
/*
returned from the peg parser
we'll need to take each of the steps
and use them to construct an actual GraphQuery
*/
pub struct ParsedGraphQuery {
    pub scope: Scope,
    pub steps: Vec<RawStep>
}

/*
scope of the query.  determines if we're looking at the
entire graph or just from a handful of vertices
*/
pub enum Scope {
    Global,
    Vertex(Vec<i64>),
}

/*
generic step used in ParsedGraphQuery
will be turned into specific steps
*/
pub struct RawStep {
    pub name: String,
    pub args: Vec<Arg>,
}

#[derive(Debug, Display)]
pub enum Arg {
    Integer(i64),
    Float(f64),
    String(String),
}

impl RawStep {
    pub fn new(name: String, args: Vec<Arg>) -> RawStep {
        RawStep{name:name, args:args}
    }
}

struct GraphQueryResult;

impl ParsedGraphQuery {
    fn execute(&self) -> Result<GraphQueryResult, &str> {
        // execute each of the steps sequentially
        Result::Err("meh")
    }
}
<commit_msg>iteration over steps<commit_after>
/*
returned from the peg parser
we'll need to take each of the steps
and use them to construct an actual GraphQuery
*/
pub struct ParsedGraphQuery {
    pub scope: Scope,
    pub steps: Vec<RawStep>
}

/*
scope of the query.  determines if we're looking at the
entire graph or just from a handful of vertices
*/
pub enum Scope {
    Global,
    Vertex(Vec<i64>),
}

/*
generic step used in ParsedGraphQuery
will be turned into specific steps
*/
pub struct RawStep {
    pub name: String,
    pub args: Vec<Arg>,
}

#[derive(Debug, Display)]
pub enum Arg {
    Integer(i64),
    Float(f64),
    String(String),
}

impl RawStep {
    pub fn new(name: String, args: Vec<Arg>) -> RawStep {
        RawStep{name:name, args:args}
    }
}

struct GraphQueryResult;

impl ParsedGraphQuery {
    fn execute(&self) -> Result<GraphQueryResult, &str> {
        // execute each of the steps sequentially
        for step in self.steps.iter() {
            // lookup step in hash table
            // execute function, passing step args
        }
        Result::Err("meh")
    }
}
<|endoftext|>


<commit_before>use dom::{ElementData};
use css::{Stylesheet, Rule};
use css::{Selector, Simple, SimpleSelector};

pub fn matching_rules<'a>(elem: &ElementData, stylesheet: &'a Stylesheet) -> Vec<&'a Rule> {
    stylesheet.rules.iter()
        .filter(|rule| rule.selectors.iter().any(|s| matches_selector(elem, s)))
        .collect()
}

fn matches_selector(elem: &ElementData, selector: &Selector) -> bool {
    match *selector {
        Simple(ref simple_selector) => matches_simple_selector(elem, simple_selector)
    }
}

fn matches_simple_selector(elem: &ElementData, selector: &SimpleSelector) -> bool {
    // Check type selector
    if selector.local_name.iter().any(|name| elem.local_name != *name) {
        return false;
    }

    // Check ID selector
    if selector.id.iter().any(|id| {
        elem.id().iter().any(|elem_id| {
            *elem_id != id
    })}) {
        return false;
    }

    // Check class selectors
    let elem_classes = elem.classes();
    if selector.class.iter().any(|class| !elem_classes.contains(class)) {
        return false;
    }

    // We didn't find any non-matching selector components.
    return true;
}
<commit_msg>Add some comments to the style module<commit_after>//! Code for applying CSS styles to the DOM.
//!
//! This is not very interesting at the moment.  It will get much more
//! complicated if I add support for compound selectors.

use dom::{ElementData};
use css::{Stylesheet, Rule, Selector, Simple, SimpleSelector};

/// Find all CSS rules that match the given element.
pub fn matching_rules<'a>(elem: &ElementData, stylesheet: &'a Stylesheet) -> Vec<&'a Rule> {
    // For now, we just do a linear scan of all the rules.  For large
    // documents, it would be more efficient to store the rules in hash tables
    // based on tag name, id, class, etc.
    stylesheet.rules.iter()
        .filter(|rule| rule.selectors.iter().any(|s| matches_selector(elem, s)))
        .collect()
}

fn matches_selector(elem: &ElementData, selector: &Selector) -> bool {
    match *selector {
        Simple(ref simple_selector) => matches_simple_selector(elem, simple_selector)
    }
}

fn matches_simple_selector(elem: &ElementData, selector: &SimpleSelector) -> bool {
    // Check type selector
    if selector.local_name.iter().any(|name| elem.local_name != *name) {
        return false;
    }

    // Check ID selector
    if selector.id.iter().any(|id| {
        elem.id().iter().any(|elem_id| {
            *elem_id != id
    })}) {
        return false;
    }

    // Check class selectors
    let elem_classes = elem.classes();
    if selector.class.iter().any(|class| !elem_classes.contains(class)) {
        return false;
    }

    // We didn't find any non-matching selector components.
    return true;
}
<|endoftext|>


<commit_before>use config::{Benchmark, parse_config};
use repo::Workspace;

use std::collections::HashMap;
use std::io;
use std::path::Path;
use std::process::{Command, ExitStatus};
use std::str;

/// `(val, percentage_change)`
#[derive(Debug, Clone)]
pub enum BenchmarkResult<T> {
    Improvement(T, f64),
    Regression(T, f64),
    Neutral(T, f64),
}

#[derive(Debug, Clone)]
pub struct TastingResult {
    pub branch: String,
    pub commit_id: String,
    pub commit_msg: String,
    pub commit_url: String,
    pub build: bool,
    pub test: bool,
    pub bench: bool,
    pub results: Option<Vec<HashMap<String, BenchmarkResult<f64>>>>,
}

fn benchmark(workdir: &str,
             cfg: &Benchmark,
             previous_result: Option<&HashMap<String, BenchmarkResult<f64>>>)
             -> (ExitStatus, HashMap<String, BenchmarkResult<f64>>) {
    let mut cmd = Command::new("cargo");
    cmd.current_dir(workdir)
        .env("RUST_BACKTRACE", "1")
        .arg(&cfg.cmd)
        .args(cfg.args.as_slice());

    let output = cmd.output()
        .expect(&format!("Failed to execute benchmark '{}'!", cfg.name));

    let lines = str::from_utf8(output.stdout.as_slice()).unwrap().lines();
    let mut res = HashMap::new();

    // Don't try parsing the output if we didn't succeed
    if !output.status.success() {
        return (output.status, res);
    }

    // Success, so let's look for the results
    for l in lines {
        for (i, regex) in cfg.result_expr.iter().enumerate() {
            for cap in regex.captures_iter(l) {
                let (metric, value) = if cap.len() > 2 {
                    (String::from(cap.at(1).unwrap()), cap.at(2))
                } else {
                    (format!("{}", i), cap.at(1))
                };
                let bm_name = format!("{}/{}", cfg.name, &metric);
                if let Some(c) = value {
                    use std::str::FromStr;
                    let val = match f64::from_str(&c) {
                        Ok(f) => f,
                        Err(_) => {
                            println!("failed to parse value '{}' for {} into f64 number, ignoring",
                                     c,
                                     bm_name);
                            continue;
                        }
                    };
                    let new_result = match previous_result {
                        None => BenchmarkResult::Neutral(val, 0.0),
                        Some(prev_res) => {
                            let old_val = match *prev_res.get(&bm_name).unwrap() {
                                BenchmarkResult::Improvement(v, _) => v,
                                BenchmarkResult::Regression(v, _) => v,
                                BenchmarkResult::Neutral(v, _) => v,
                            };
                            let new_result = if val >= old_val * 1.1 {
                                BenchmarkResult::Improvement(val, (val / old_val) - 1.0)
                            } else if val < old_val * 0.9 {
                                BenchmarkResult::Regression(val, (val / old_val) - 1.0)
                            } else {
                                BenchmarkResult::Neutral(val, (val / old_val) - 1.0)
                            };
                            new_result
                        }
                    };
                    res.insert(bm_name, new_result);
                }
            }
        }
    }
    (output.status, res)
}

fn build(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("build")
        .arg("--release")
        .env("RUST_BACKTRACE", "1")
        .status()
        .expect("Failed to execute 'cargo build'!")
}

pub fn taste_commit(ws: &Workspace,
                    history: &mut HashMap<String,
                                          HashMap<String, HashMap<String, BenchmarkResult<f64>>>>,
                    commit_ref: &str,
                    id: &str,
                    msg: &str,
                    url: &str)
                    -> Result<TastingResult, String> {
    println!("Tasting commit {}", id);
    ws.checkout_commit(id)?;

    let branch = match commit_ref.rfind("/") {
        None => String::from(""),
        Some(i) => String::from(&commit_ref[i + 1..]),
    };

    let build_success = update(&ws.path).success() && build(&ws.path).success();
    let test_success = test(&ws.path).success();

    let cfg = match parse_config(Path::new(&format!("{}/taster.toml", ws.path))) {
        Ok(c) => c,
        Err(e) => {
            match e.kind() {
                io::ErrorKind::NotFound => {
                    println!("Skipping commit {} which doesn't have a Taster config.", id);
                    return Ok(TastingResult {
                        branch: branch,
                        commit_id: String::from(id),
                        commit_msg: String::from(msg),
                        commit_url: String::from(url),
                        build: build_success,
                        test: test_success,
                        bench: false,
                        results: None,
                    });
                }
                _ => unimplemented!(),
            }
        }
    };

    let branch_history = history.entry(branch.clone()).or_insert(HashMap::new());
    let bench_out = cfg.iter()
        .map(|b| {
            let new_result = benchmark(&ws.path, b, branch_history.get(&b.name));
            branch_history.insert(b.name.clone(), new_result.1.clone());
            new_result
        })
        .collect::<Vec<(ExitStatus, HashMap<String, BenchmarkResult<f64>>)>>();
    let bench_success = bench_out.iter().all(|x| x.0.success());
    let bench_results = bench_out.iter().map(|x| x.1.clone()).collect();

    Ok(TastingResult {
        branch: branch,
        commit_id: String::from(id),
        commit_msg: String::from(msg),
        commit_url: String::from(url),
        build: build_success,
        test: test_success,
        bench: bench_success,
        results: Some(bench_results),
    })
}

fn test(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("test")
        .env("RUST_BACKTRACE", "1")
        .env("RUST_TEST_THREADS", "1")
        .status()
        .expect("Failed to execute 'cargo test'!")
}

fn update(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("update")
        .status()
        .expect("Failed to execute 'cargo update'!")
}
<commit_msg>Treat new benchmarks as improvement<commit_after>use config::{Benchmark, parse_config};
use repo::Workspace;

use std::collections::HashMap;
use std::io;
use std::path::Path;
use std::process::{Command, ExitStatus};
use std::str;

/// `(val, percentage_change)`
#[derive(Debug, Clone)]
pub enum BenchmarkResult<T> {
    Improvement(T, f64),
    Regression(T, f64),
    Neutral(T, f64),
}

#[derive(Debug, Clone)]
pub struct TastingResult {
    pub branch: String,
    pub commit_id: String,
    pub commit_msg: String,
    pub commit_url: String,
    pub build: bool,
    pub test: bool,
    pub bench: bool,
    pub results: Option<Vec<HashMap<String, BenchmarkResult<f64>>>>,
}

fn benchmark(workdir: &str,
             cfg: &Benchmark,
             previous_result: Option<&HashMap<String, BenchmarkResult<f64>>>)
             -> (ExitStatus, HashMap<String, BenchmarkResult<f64>>) {
    let mut cmd = Command::new("cargo");
    cmd.current_dir(workdir)
        .env("RUST_BACKTRACE", "1")
        .arg(&cfg.cmd)
        .args(cfg.args.as_slice());

    let output = cmd.output()
        .expect(&format!("Failed to execute benchmark '{}'!", cfg.name));

    let lines = str::from_utf8(output.stdout.as_slice()).unwrap().lines();
    let mut res = HashMap::new();

    // Don't try parsing the output if we didn't succeed
    if !output.status.success() {
        return (output.status, res);
    }

    // Success, so let's look for the results
    for l in lines {
        for (i, regex) in cfg.result_expr.iter().enumerate() {
            for cap in regex.captures_iter(l) {
                let (metric, value) = if cap.len() > 2 {
                    (String::from(cap.at(1).unwrap()), cap.at(2))
                } else {
                    (format!("{}", i), cap.at(1))
                };
                let bm_name = format!("{}/{}", cfg.name, &metric);
                if let Some(c) = value {
                    use std::str::FromStr;
                    let val = match f64::from_str(&c) {
                        Ok(f) => f,
                        Err(_) => {
                            println!("failed to parse value '{}' for {} into f64 number, ignoring",
                                     c,
                                     bm_name);
                            continue;
                        }
                    };
                    let new_result = match previous_result {
                        None => BenchmarkResult::Improvement(val, 0.0),
                        Some(prev_res) => {
                            let old_val = match *prev_res.get(&bm_name).unwrap() {
                                BenchmarkResult::Improvement(v, _) => v,
                                BenchmarkResult::Regression(v, _) => v,
                                BenchmarkResult::Neutral(v, _) => v,
                            };
                            let new_result = if val >= old_val * 1.1 {
                                BenchmarkResult::Improvement(val, (val / old_val) - 1.0)
                            } else if val < old_val * 0.9 {
                                BenchmarkResult::Regression(val, (val / old_val) - 1.0)
                            } else {
                                BenchmarkResult::Neutral(val, (val / old_val) - 1.0)
                            };
                            new_result
                        }
                    };
                    res.insert(bm_name, new_result);
                }
            }
        }
    }
    (output.status, res)
}

fn build(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("build")
        .arg("--release")
        .env("RUST_BACKTRACE", "1")
        .status()
        .expect("Failed to execute 'cargo build'!")
}

pub fn taste_commit(ws: &Workspace,
                    history: &mut HashMap<String,
                                          HashMap<String, HashMap<String, BenchmarkResult<f64>>>>,
                    commit_ref: &str,
                    id: &str,
                    msg: &str,
                    url: &str)
                    -> Result<TastingResult, String> {
    println!("Tasting commit {}", id);
    ws.checkout_commit(id)?;

    let branch = match commit_ref.rfind("/") {
        None => String::from(""),
        Some(i) => String::from(&commit_ref[i + 1..]),
    };

    let build_success = update(&ws.path).success() && build(&ws.path).success();
    let test_success = test(&ws.path).success();

    let cfg = match parse_config(Path::new(&format!("{}/taster.toml", ws.path))) {
        Ok(c) => c,
        Err(e) => {
            match e.kind() {
                io::ErrorKind::NotFound => {
                    println!("Skipping commit {} which doesn't have a Taster config.", id);
                    return Ok(TastingResult {
                        branch: branch,
                        commit_id: String::from(id),
                        commit_msg: String::from(msg),
                        commit_url: String::from(url),
                        build: build_success,
                        test: test_success,
                        bench: false,
                        results: None,
                    });
                }
                _ => unimplemented!(),
            }
        }
    };

    let branch_history = history.entry(branch.clone()).or_insert(HashMap::new());
    let bench_out = cfg.iter()
        .map(|b| {
            let new_result = benchmark(&ws.path, b, branch_history.get(&b.name));
            branch_history.insert(b.name.clone(), new_result.1.clone());
            new_result
        })
        .collect::<Vec<(ExitStatus, HashMap<String, BenchmarkResult<f64>>)>>();
    let bench_success = bench_out.iter().all(|x| x.0.success());
    let bench_results = bench_out.iter().map(|x| x.1.clone()).collect();

    Ok(TastingResult {
        branch: branch,
        commit_id: String::from(id),
        commit_msg: String::from(msg),
        commit_url: String::from(url),
        build: build_success,
        test: test_success,
        bench: bench_success,
        results: Some(bench_results),
    })
}

fn test(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("test")
        .env("RUST_BACKTRACE", "1")
        .env("RUST_TEST_THREADS", "1")
        .status()
        .expect("Failed to execute 'cargo test'!")
}

fn update(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("update")
        .status()
        .expect("Failed to execute 'cargo update'!")
}
<|endoftext|>


<commit_before>use rs_es::query::Filter;
use rs_es::units::JsonVal;

pub trait VectorOfTerms<T> {
  fn build_terms(key: &str, values: &Vec<T>) -> Vec<Filter>;
}

macro_rules! build_vector_of_terms_impl {
  ($t:ty) => {
    impl VectorOfTerms<$t> for Filter {
      /// Extract all given items into multiple filters (if present)
      /// i.e. build_terms("field", vec![1, 2]) => vec![Filter(1), Filter(2)]
      /// This enable us to operate on these values with boolean values
      fn build_terms(key: &str, values: &Vec<$t>) -> Vec<Filter> {
        if values.is_empty() {
          return vec![];
        }

        vec![
          Filter::build_terms(key, values.iter()
                                         .map(|v| JsonVal::from(v.clone()))
                                         .collect::<Vec<JsonVal>>()).build()
        ]
      }
    }
  }
}

build_vector_of_terms_impl!(i32);
build_vector_of_terms_impl!(String);

#[cfg(test)]
mod tests {
  use terms::*;
  use rs_es::query::Filter;
  use rustc_serialize::json::ToJson;

  #[test]
  fn test_vector_of_terms() {
    assert!(<Filter as VectorOfTerms<String>>::build_terms("work_roles", &vec![])
                                              .is_empty());

    {
      let filters = <Filter as VectorOfTerms<String>>::build_terms(
                  "work_roles", &vec![String::from("Fullstack")]);
      assert_eq!(filters[0].to_json().to_string(),
        String::from("{\"terms\":{\"work_roles\":[\"Fullstack\"]}}"));
    }

    {
      let filters = <Filter as VectorOfTerms<i32>>::build_terms(
                  "work_roles", &vec![1]);
      assert_eq!(filters[0].to_json().to_string(),
        String::from("{\"terms\":{\"work_roles\":[1]}}"));
    }
  }
}
<commit_msg>terms: document VectorOfTerms<T>::build_terms()<commit_after>use rs_es::query::Filter;
use rs_es::units::JsonVal;

pub trait VectorOfTerms<T> {
  /// Extract the elements inside `Vec<T>` into `Vec<Filter>`, if present.
  /// Every element will be mapped into a `JsonVal`.
  fn build_terms(key: &str, values: &Vec<T>) -> Vec<Filter>;
}

macro_rules! build_vector_of_terms_impl {
  ($t:ty) => {
    impl VectorOfTerms<$t> for Filter {
      fn build_terms(key: &str, values: &Vec<$t>) -> Vec<Filter> {
        if values.is_empty() {
          return vec![];
        }

        vec![
          Filter::build_terms(key, values.iter()
                                         .map(|v| JsonVal::from(v.clone()))
                                         .collect::<Vec<JsonVal>>()).build()
        ]
      }
    }
  }
}

build_vector_of_terms_impl!(i32);
build_vector_of_terms_impl!(String);

#[cfg(test)]
mod tests {
  use terms::*;
  use rs_es::query::Filter;
  use rustc_serialize::json::ToJson;

  #[test]
  fn test_vector_of_terms() {
    assert!(<Filter as VectorOfTerms<String>>::build_terms("work_roles", &vec![])
                                              .is_empty());

    {
      let filters = <Filter as VectorOfTerms<String>>::build_terms(
                      "work_roles", &vec![String::from("Fullstack")]);
      assert_eq!(filters[0].to_json().to_string(),
                  String::from("{\"terms\":{\"work_roles\":[\"Fullstack\"]}}"));
    }

    {
      let filters = <Filter as VectorOfTerms<i32>>::build_terms(
                  "work_roles", &vec![1]);
      assert_eq!(filters[0].to_json().to_string(),
                  String::from("{\"terms\":{\"work_roles\":[1]}}"));
    }
  }
}
<|endoftext|>


<commit_before>use super::Checked;

// Test a unary operator
macro_rules! test_unop {
    ($name:ident $t:ty: $op:tt $expr1:tt == $expr2:tt) => {
        #[test]
        fn $name() {
            let x = Checked::<$t>::from($expr1);
            let y = Checked::<$t>::from($expr2);
            assert_eq!($op x, y);
            assert_eq!($op &x, y);
        }
    };
}

// Test a binary operator
macro_rules! test_binop {
    ($name:ident $t:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$t>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $t;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty, $v:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$v>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };
}

// These tests use None to indicate over/underflow.
test_binop! (add1 u8: 5 + 6 == 11);
test_binop! (add2 u32: 3_000_000_000 + 2_000_000_000 == None);
test_binop! (add3 i32: (-2_000_000_000) + (-2_000_000_000) == None);
test_binop! (sub u8: 5 - 6 == None);
test_binop! (mul1 u8: 5 * 6 == 30);
test_binop! (mul2 i32: 2_000_000_000 * 3 == None);
test_binop! (div1 u8: 10 / 3 == 3);
test_binop! (div2 u8: 10 / 0 == None);
test_binop! (and u8: 5 & 6 == 4);
test_binop! (xor u8: 5 ^ 6 == 3);
test_binop! (or u8: 5 | 6 == 7);
test_binop! (rem u8: 10 % 3 == 1);
test_binop! (shl u8, u32: 10 << 3 == 80);
test_binop! (shr u8, u32: 80 >> 3 == 10);
test_unop! (neg1 u8: - 5 == None);
test_unop! (neg2 i8: - 5 == (-5));
test_unop! (not i8: ! 5 == (-6));

#[test]
fn order() {
    assert!(Checked::from(1_000_u32) <= Checked::from(10_000_u32));
    assert!(!(Checked::from(1_000_u32) <= Checked::from(None)));
    assert!((Checked::from(None) <= Checked::from(1_000_u32)));
}

#[test]
fn new_checked() {
    assert_eq(Checked::new(100) == Checked(Some(100)))
}
<commit_msg>add test for Checked::from<commit_after>use super::Checked;

// Test a unary operator
macro_rules! test_unop {
    ($name:ident $t:ty: $op:tt $expr1:tt == $expr2:tt) => {
        #[test]
        fn $name() {
            let x = Checked::<$t>::from($expr1);
            let y = Checked::<$t>::from($expr2);
            assert_eq!($op x, y);
            assert_eq!($op &x, y);
        }
    };
}

// Test a binary operator
macro_rules! test_binop {
    ($name:ident $t:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$t>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $t;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty, $v:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$v>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };
}

// These tests use None to indicate over/underflow.
test_binop! (add1 u8: 5 + 6 == 11);
test_binop! (add2 u32: 3_000_000_000 + 2_000_000_000 == None);
test_binop! (add3 i32: (-2_000_000_000) + (-2_000_000_000) == None);
test_binop! (sub u8: 5 - 6 == None);
test_binop! (mul1 u8: 5 * 6 == 30);
test_binop! (mul2 i32: 2_000_000_000 * 3 == None);
test_binop! (div1 u8: 10 / 3 == 3);
test_binop! (div2 u8: 10 / 0 == None);
test_binop! (and u8: 5 & 6 == 4);
test_binop! (xor u8: 5 ^ 6 == 3);
test_binop! (or u8: 5 | 6 == 7);
test_binop! (rem u8: 10 % 3 == 1);
test_binop! (shl u8, u32: 10 << 3 == 80);
test_binop! (shr u8, u32: 80 >> 3 == 10);
test_unop! (neg1 u8: - 5 == None);
test_unop! (neg2 i8: - 5 == (-5));
test_unop! (not i8: ! 5 == (-6));

#[test]
fn order() {
    assert!(Checked::from(1_000_u32) <= Checked::from(10_000_u32));
    assert!(!(Checked::from(1_000_u32) <= Checked::from(None)));
    assert!((Checked::from(None) <= Checked::from(1_000_u32)));
}

#[test]
fn new_checked() {
    assert_eq!(Checked::new(100) == Checked(Some(100)))
}

#[test]
fn from_checked() {
    assert_eq!(Checked::from(100_u32) = Checked(Some(100_u32)));
    assert_eq!(Checked::from(Some(100_u32)) = Checked(Some(100_u32)));
    assert_eq!(Checked::from(None) = Checked(None));
}
<|endoftext|>


<commit_before>use ruby_sys::types;

use class::any_object::AnyObject;

pub use libc::{c_char, c_int, c_long};
pub use ruby_sys::types::ValueType;

pub type Value = types::Value;
pub type InternalValue = types::InternalValue;
pub type SignedValue = types::SignedValue;
pub type Id = types::Id;

pub type Argc = types::Argc;

pub type Callback<I, O> = extern "C" fn(Argc, *const AnyObject, I) -> O;
pub type CallbackPtr = types::CallbackPtr;
<commit_msg>Re-export ruby-sys types<commit_after>use class::any_object::AnyObject;

pub use ruby_sys::types::{Argc, c_char, c_int, c_long, CallbackPtr, Id, InternalValue,
                          SignedValue, Value, ValueType};

pub type Callback<I, O> = extern "C" fn(Argc, *const AnyObject, I) -> O;
<|endoftext|>


<commit_before>//! Custom input types
//!

use traits::{AsBytes, AtEof, Compare, CompareResult, ExtendInto, FindSubstring, FindToken, InputIter, InputLength, InputTake, Offset,
             ParseTo, Slice};

use std::str::{self, CharIndices, Chars, FromStr};
use std::ops::{Range, RangeFrom, RangeFull, RangeTo};
use std::iter::{Enumerate, Map};
use std::slice::Iter;

/// Holds a complete String, for which the `at_eof` method always returns true
///
/// This means that this input type will completely avoid nom's streaming features
/// and `Incomplete` results.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct CompleteStr<'a>(pub &'a str);

impl<'a> AtEof for CompleteStr<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteStr<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteStr<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteStr<'a> {
  type Item = char;
  type RawItem = char;
  type Iter = CharIndices<'a>;
  type IterElem = Chars<'a>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteStr<'a> {
  fn take(&self, count: usize) -> Self {
    CompleteStr(self.0.take(count))
  }

  fn take_split(&self, count: usize) -> (Self, Self) {
    let (left, right) = self.0.take_split(count);
    (CompleteStr(left), CompleteStr(right))
  }
}

impl<'a> InputLength for CompleteStr<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteStr<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteStr<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteStr<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteStr<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteStr<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteStr<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse().ok()
  }
}

impl<'a> Offset for CompleteStr<'a> {
  fn offset(&self, second: &CompleteStr<'a>) -> usize {
    self.0.offset(second.0)
  }
}

impl<'a> AsBytes for CompleteStr<'a> {
  fn as_bytes(&self) -> &[u8] {
    AsBytes::as_bytes(self.0)
  }
}

#[cfg(feature = "std")]
impl<'a> ExtendInto for CompleteStr<'a> {
  type Item = char;
  type Extender = String;

  #[inline]
  fn new_builder(&self) -> String {
    String::new()
  }
  #[inline]
  fn extend_into(&self, acc: &mut String) {
    acc.extend(self.0.chars());
  }
}

/// Holds a complete String, for which the `at_eof` method always returns true
///
/// This means that this input type will completely avoid nom's streaming features
/// and `Incomplete` results.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct CompleteByteSlice<'a>(pub &'a [u8]);

impl<'a> AtEof for CompleteByteSlice<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteByteSlice<'a> {
  type Item = u8;
  type RawItem = u8;
  type Iter = Enumerate<Self::IterElem>;
  type IterElem = Map<Iter<'a, Self::Item>, fn(&u8) -> u8>; //Iter<'a, Self::RawItem>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteByteSlice<'a> {
  fn take(&self, count: usize) -> Self {
    CompleteByteSlice(self.0.take(count))
  }

  fn take_split(&self, count: usize) -> (Self, Self) {
    let (left, right) = self.0.take_split(count);
    (CompleteByteSlice(left), CompleteByteSlice(right))
  }
}

impl<'a> InputLength for CompleteByteSlice<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b [u8]> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b [u8]> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b [u8]) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteByteSlice<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteByteSlice<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteByteSlice<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteByteSlice<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse_to()
  }
}

impl<'a> Offset for CompleteByteSlice<'a> {
  fn offset(&self, second: &CompleteByteSlice<'a>) -> usize {
    self.0.offset(second.0)
  }
}

impl<'a> AsBytes for CompleteByteSlice<'a> {
  fn as_bytes(&self) -> &[u8] {
    self.0.as_bytes()
  }
}

#[cfg(feature = "std")]
impl<'a> super::util::HexDisplay for CompleteByteSlice<'a> {
  fn to_hex(&self, chunk_size: usize) -> String {
    self.0.to_hex(chunk_size)
  }

  fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
    self.0.to_hex_from(chunk_size, from)
  }
}

#[derive(Clone, Copy, Debug, PartialEq, Hash)]
pub struct Input<T> {
  pub inner: T,
  pub at_eof: bool,
}

impl<T> AtEof for Input<T> {
  fn at_eof(&self) -> bool {
    self.at_eof
  }
}

impl<T: Slice<Range<usize>>> Slice<Range<usize>> for Input<T> {
  fn slice(&self, range: Range<usize>) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: Slice<RangeTo<usize>>> Slice<RangeTo<usize>> for Input<T> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: Slice<RangeFrom<usize>>> Slice<RangeFrom<usize>> for Input<T> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: Slice<RangeFull>> Slice<RangeFull> for Input<T> {
  fn slice(&self, range: RangeFull) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: InputIter> InputIter for Input<T> {
  type Item = <T as InputIter>::Item;
  type RawItem = <T as InputIter>::RawItem;
  type Iter = <T as InputIter>::Iter;
  type IterElem = <T as InputIter>::IterElem;

  fn iter_indices(&self) -> Self::Iter {
    self.inner.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.inner.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.inner.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.inner.slice_index(count)
  }
}

impl<T: InputTake> InputTake for Input<T> {
  fn take(&self, count: usize) -> Self {
    Input {
      inner: self.inner.take(count),
      at_eof: self.at_eof,
    }
  }

  fn take_split(&self, count: usize) -> (Self, Self) {
    let (left, right) = self.inner.take_split(count);
    (
      Input {
        inner: left,
        at_eof: self.at_eof,
      },
      Input {
        inner: right,
        at_eof: self.at_eof,
      },
    )
  }
}

impl<T: InputLength> InputLength for Input<T> {
  fn input_len(&self) -> usize {
    self.inner.input_len()
  }
}

impl<'b, T: Compare<&'b str>> Compare<&'b str> for Input<T> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.inner.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.inner.compare_no_case(t)
  }
}

impl<'b, T: FindSubstring<&'b str>> FindSubstring<&'b str> for Input<T> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.inner.find_substring(substr)
  }
}

impl<T: FindToken<char>> FindToken<char> for Input<T> {
  fn find_token(&self, token: char) -> bool {
    self.inner.find_token(token)
  }
}

impl<T: FindToken<u8>> FindToken<u8> for Input<T> {
  fn find_token(&self, token: u8) -> bool {
    self.inner.find_token(token)
  }
}

impl<'a, T: FindToken<&'a u8>> FindToken<&'a u8> for Input<T> {
  fn find_token(&self, token: &'a u8) -> bool {
    self.inner.find_token(token)
  }
}

impl<'a, R: FromStr, T: ParseTo<R>> ParseTo<R> for Input<T> {
  fn parse_to(&self) -> Option<R> {
    self.inner.parse_to()
  }
}

impl<T: Offset> Offset for Input<T> {
  fn offset(&self, second: &Input<T>) -> usize {
    self.inner.offset(&second.inner)
  }
}

impl<T: AsBytes> AsBytes for Input<T> {
  fn as_bytes(&self) -> &[u8] {
    AsBytes::as_bytes(&self.inner)
  }
}
<commit_msg>impl Deref for CompleteStr, CompleteByteSlice<commit_after>//! Custom input types
//!

use traits::{AsBytes, AtEof, Compare, CompareResult, ExtendInto, FindSubstring, FindToken, InputIter, InputLength, InputTake, Offset,
             ParseTo, Slice};

use std::str::{self, CharIndices, Chars, FromStr};
use std::ops::{Deref, Range, RangeFrom, RangeFull, RangeTo};
use std::iter::{Enumerate, Map};
use std::slice::Iter;

/// Holds a complete String, for which the `at_eof` method always returns true
///
/// This means that this input type will completely avoid nom's streaming features
/// and `Incomplete` results.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct CompleteStr<'a>(pub &'a str);

impl<'a> Deref for CompleteStr<'a> {
  type Target = str;

  fn deref(&self) -> &str {
    self.0
  }
}

impl<'a> AtEof for CompleteStr<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteStr<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteStr<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteStr<'a> {
  type Item = char;
  type RawItem = char;
  type Iter = CharIndices<'a>;
  type IterElem = Chars<'a>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteStr<'a> {
  fn take(&self, count: usize) -> Self {
    CompleteStr(self.0.take(count))
  }

  fn take_split(&self, count: usize) -> (Self, Self) {
    let (left, right) = self.0.take_split(count);
    (CompleteStr(left), CompleteStr(right))
  }
}

impl<'a> InputLength for CompleteStr<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteStr<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteStr<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteStr<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteStr<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteStr<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteStr<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse().ok()
  }
}

impl<'a> Offset for CompleteStr<'a> {
  fn offset(&self, second: &CompleteStr<'a>) -> usize {
    self.0.offset(second.0)
  }
}

impl<'a> AsBytes for CompleteStr<'a> {
  fn as_bytes(&self) -> &[u8] {
    AsBytes::as_bytes(self.0)
  }
}

#[cfg(feature = "std")]
impl<'a> ExtendInto for CompleteStr<'a> {
  type Item = char;
  type Extender = String;

  #[inline]
  fn new_builder(&self) -> String {
    String::new()
  }
  #[inline]
  fn extend_into(&self, acc: &mut String) {
    acc.extend(self.0.chars());
  }
}

/// Holds a complete String, for which the `at_eof` method always returns true
///
/// This means that this input type will completely avoid nom's streaming features
/// and `Incomplete` results.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct CompleteByteSlice<'a>(pub &'a [u8]);

impl<'a> Deref for CompleteByteSlice<'a> {
  type Target = [u8];

  fn deref(&self) -> &[u8] {
    self.0
  }
}

impl<'a> AtEof for CompleteByteSlice<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteByteSlice<'a> {
  type Item = u8;
  type RawItem = u8;
  type Iter = Enumerate<Self::IterElem>;
  type IterElem = Map<Iter<'a, Self::Item>, fn(&u8) -> u8>; //Iter<'a, Self::RawItem>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteByteSlice<'a> {
  fn take(&self, count: usize) -> Self {
    CompleteByteSlice(self.0.take(count))
  }

  fn take_split(&self, count: usize) -> (Self, Self) {
    let (left, right) = self.0.take_split(count);
    (CompleteByteSlice(left), CompleteByteSlice(right))
  }
}

impl<'a> InputLength for CompleteByteSlice<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b [u8]> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b [u8]> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b [u8]) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteByteSlice<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteByteSlice<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteByteSlice<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteByteSlice<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse_to()
  }
}

impl<'a> Offset for CompleteByteSlice<'a> {
  fn offset(&self, second: &CompleteByteSlice<'a>) -> usize {
    self.0.offset(second.0)
  }
}

impl<'a> AsBytes for CompleteByteSlice<'a> {
  fn as_bytes(&self) -> &[u8] {
    self.0.as_bytes()
  }
}

#[cfg(feature = "std")]
impl<'a> super::util::HexDisplay for CompleteByteSlice<'a> {
  fn to_hex(&self, chunk_size: usize) -> String {
    self.0.to_hex(chunk_size)
  }

  fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
    self.0.to_hex_from(chunk_size, from)
  }
}

#[derive(Clone, Copy, Debug, PartialEq, Hash)]
pub struct Input<T> {
  pub inner: T,
  pub at_eof: bool,
}

impl<T> AtEof for Input<T> {
  fn at_eof(&self) -> bool {
    self.at_eof
  }
}

impl<T: Slice<Range<usize>>> Slice<Range<usize>> for Input<T> {
  fn slice(&self, range: Range<usize>) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: Slice<RangeTo<usize>>> Slice<RangeTo<usize>> for Input<T> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: Slice<RangeFrom<usize>>> Slice<RangeFrom<usize>> for Input<T> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: Slice<RangeFull>> Slice<RangeFull> for Input<T> {
  fn slice(&self, range: RangeFull) -> Self {
    Input {
      inner: self.inner.slice(range),
      at_eof: self.at_eof,
    }
  }
}

impl<T: InputIter> InputIter for Input<T> {
  type Item = <T as InputIter>::Item;
  type RawItem = <T as InputIter>::RawItem;
  type Iter = <T as InputIter>::Iter;
  type IterElem = <T as InputIter>::IterElem;

  fn iter_indices(&self) -> Self::Iter {
    self.inner.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.inner.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.inner.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.inner.slice_index(count)
  }
}

impl<T: InputTake> InputTake for Input<T> {
  fn take(&self, count: usize) -> Self {
    Input {
      inner: self.inner.take(count),
      at_eof: self.at_eof,
    }
  }

  fn take_split(&self, count: usize) -> (Self, Self) {
    let (left, right) = self.inner.take_split(count);
    (
      Input {
        inner: left,
        at_eof: self.at_eof,
      },
      Input {
        inner: right,
        at_eof: self.at_eof,
      },
    )
  }
}

impl<T: InputLength> InputLength for Input<T> {
  fn input_len(&self) -> usize {
    self.inner.input_len()
  }
}

impl<'b, T: Compare<&'b str>> Compare<&'b str> for Input<T> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.inner.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.inner.compare_no_case(t)
  }
}

impl<'b, T: FindSubstring<&'b str>> FindSubstring<&'b str> for Input<T> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.inner.find_substring(substr)
  }
}

impl<T: FindToken<char>> FindToken<char> for Input<T> {
  fn find_token(&self, token: char) -> bool {
    self.inner.find_token(token)
  }
}

impl<T: FindToken<u8>> FindToken<u8> for Input<T> {
  fn find_token(&self, token: u8) -> bool {
    self.inner.find_token(token)
  }
}

impl<'a, T: FindToken<&'a u8>> FindToken<&'a u8> for Input<T> {
  fn find_token(&self, token: &'a u8) -> bool {
    self.inner.find_token(token)
  }
}

impl<'a, R: FromStr, T: ParseTo<R>> ParseTo<R> for Input<T> {
  fn parse_to(&self) -> Option<R> {
    self.inner.parse_to()
  }
}

impl<T: Offset> Offset for Input<T> {
  fn offset(&self, second: &Input<T>) -> usize {
    self.inner.offset(&second.inner)
  }
}

impl<T: AsBytes> AsBytes for Input<T> {
  fn as_bytes(&self) -> &[u8] {
    AsBytes::as_bytes(&self.inner)
  }
}
<|endoftext|>