<commit_before>//! A lazily populated index for looking up entities by name.

#![allow(unused)]

use clang::{self, Entity, EntityKind};
use std::collections::{hash_map, HashMap};
use std::fmt::{self, Display};
use thiserror::Error;

/// Represents errors which can occur while looking up entities in the index.
#[non_exhaustive]
#[derive(Error, Debug)]
pub(crate) enum LookupError {
    #[error("couldn't find `{0}`")]
    NotFound(Path),
    #[error("{0}")]
    SourceError(clang::SourceError),
}

/// The result of a lookup operation.
type Result<T> = std::result::Result<T, LookupError>;

/// An ID assigned to a `Path` in the index.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct NodeId(u32);

impl NodeId {
    #[inline(always)]
    fn from_usize(n: usize) -> NodeId {
        NodeId(n as u32)
    }
    #[inline(always)]
    fn as_usize(&self) -> usize {
        self.0 as usize
    }
}

/// A C++ unqualified identifier.
///
/// Examples: `std`, `vector`, or `MyClass`.
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub(crate) struct Ident {
    s: String,
}
impl From<&str> for Ident {
    /// Creates an identifier. Can panic if the identifier is invalid.
    fn from(id: &str) -> Ident {
        assert!(!id.contains("::"), "invalid identifier `{}`", id);
        Ident { s: id.to_string() }
    }
}
impl From<String> for Ident {
    fn from(id: String) -> Ident {
        From::from(id.as_str())
    }
}
impl Display for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.s)
    }
}

/// A C++ fully-qualified name.
///
/// Example: `std::vector`.
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub(crate) struct Path {
    components: Vec<Ident>,
}
impl From<&str> for Path {
    fn from(mut path: &str) -> Path {
        if path.starts_with("::") {
            path = &path[2..];
        }
        Path {
            components: path.split("::").map(Ident::from).collect(),
        }
    }
}
impl From<String> for Path {
    fn from(path: String) -> Path {
        From::from(path.as_str())
    }
}
impl Path {
    fn dummy() -> Path {
        Path { components: vec![] }
    }
    pub(crate) fn iter(&self) -> impl Iterator<Item = &Ident> {
        self.components.iter()
    }
}
impl Display for Path {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut iter = self.components.iter();
        let mut next = iter.next();
        while let Some(id) = next {
            write!(f, "{}", id)?;
            next = iter.next();
            if next.is_some() {
                write!(f, "::")?;
            }
        }
        Ok(())
    }
}

/// An index `Node` is the entity or set of entities referred to by a `Path`.
///
/// For example, `std` and `std::vector` are both nodes.
///
/// Nodes may contain children, and they may be represented by multiple
/// entities. Namespaces, for example, can have many AST entities associated
/// with them. Template specializations are another example.
#[derive(Debug, Default)]
pub(crate) struct Node<'tu> {
    //kind: EntityKind,
    entities: Vec<Entity<'tu>>,
    items: Option<HashMap<Ident, NodeId>>,
    inline_items: Vec<NodeId>,
}
impl<'tu> Node<'tu> {
    fn items_mut(&mut self) -> &mut HashMap<Ident, NodeId> {
        self.items.as_mut().unwrap()
    }
}

/// A lazily populated index for looking up `Node`s by name.
pub(crate) struct Index<'tu> {
    nodes: Vec<Node<'tu>>,
}
impl<'tu> Index<'tu> {
    /// Creates an index from the given TranslationUnit.
    pub(crate) fn new(file: &'tu clang::TranslationUnit<'_>) -> Index<'tu> {
        let entity = file.get_entity();
        let file_node = Node {
            //kind: entity.get_kind(),
            entities: vec![entity],
            items: None,
            inline_items: vec![],
        };
        Index {
            nodes: vec![file_node],
        }
    }

    #[inline(always)]
    pub(crate) fn node(&self, id: NodeId) -> &Node<'tu> {
        &self.nodes[id.0 as usize]
    }

    #[inline(always)]
    fn node_mut(&mut self, id: NodeId) -> &mut Node<'tu> {
        &mut self.nodes[id.0 as usize]
    }

    /// Returns the `Node` corresponding to the given `Path`.
    ///
    /// If the path does not exist, returns `LookupError::NotFound`.
    pub(crate) fn lookup(&mut self, path: &Path) -> Result<&Node<'tu>> {
        self.lookup_id(&path).map(move |id| self.node(id))
    }

    /// Returns the `NodeId` corresponding to the given `Path`.
    ///
    /// If the path does not exist, returns `LookupError::NotFound`.
    pub(crate) fn lookup_id(&mut self, path: &Path) -> Result<NodeId> {
        let mut cur = NodeId(0);
        for name in path.iter() {
            cur = match self.child_id_of(cur, name) {
                Ok(child) => child,
                // Fill in the path we failed to find.
                Err(LookupError::NotFound(_)) => return Err(LookupError::NotFound(path.clone())),
                Err(e) => return Err(e),
            }
        }
        Ok(cur)
    }

    /// Returns the child named `child` of the given `node`.
    pub(crate) fn child_of(&mut self, node: NodeId, child: &Ident) -> Result<&Node> {
        self.child_id_of(node, child).map(move |id| self.node(id))
    }

    /// Returns the `NodeId` of the child named `child` of the given `node`.
    pub(crate) fn child_id_of(&mut self, node: NodeId, child: &Ident) -> Result<NodeId> {
        if self.node(node).items.is_none() {
            self.expand(node);
        }
        let children = self.node(node).items.as_ref().unwrap();
        match children.get(child) {
            Some(id) => Ok(*id),
            None => Err(LookupError::NotFound(Path::dummy())),
        }
    }

    fn expand(&mut self, node: NodeId) -> Result<()> {
        self.node_mut(node).items = Some(HashMap::new());
        let num_entities = self.node(node).entities.len();
        for ent_idx in 0..num_entities {
            self.populate_children(node, self.node(node).entities[ent_idx])?;
        }
        Ok(())
    }

    fn populate_children(&mut self, node: NodeId, ent: Entity<'tu>) -> Result<()> {
        for child in ent.get_children() {
            let name = match ent.get_name() {
                Some(name) => Ident::from(name),
                None => continue,
            };
            let child_id = self.get_or_insert_child(node, name);
            self.node_mut(child_id).entities.push(child);
        }
        Ok(())
    }

    fn get_or_insert_child(&mut self, parent: NodeId, child: Ident) -> NodeId {
        let next_id = self.next_node_id();
        let child_id = *self
            .node_mut(parent)
            .items_mut()
            .entry(child)
            .or_insert(next_id);
        if child_id == next_id {
            self.nodes.push(Default::default());
        }
        child_id
    }

    #[inline(always)]
    fn next_node_id(&self) -> NodeId {
        NodeId(self.nodes.len() as u32)
    }
}

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

    #[test]
    fn paths() {
        assert_eq!(
            Path::from("::std::stuff::basic_iterator"),
            Path::from("std::stuff::basic_iterator")
        );
        assert_eq!(
            Path::from("::std::vector<bool>::basic_iterator")
                .iter()
                .cloned()
                .collect::<Vec<_>>(),
            ["std", "vector<bool>", "basic_iterator"]
                .into_iter()
                .copied()
                .map(Ident::from)
                .collect::<Vec<_>>()
        );
    }
}
<commit_msg>index: Better NotFound errors<commit_after>//! A lazily populated index for looking up entities by name.

#![allow(unused)]

use clang::{self, Entity, EntityKind};
use std::collections::{hash_map, HashMap};
use std::fmt::{self, Display};
use std::iter::{FromIterator, IntoIterator};
use thiserror::Error;

/// Represents errors which can occur while looking up entities in the index.
#[non_exhaustive]
#[derive(Error, Debug)]
pub(crate) enum LookupError {
    #[error("couldn't find `{0}`")]
    NotFound(Path),
    #[error("{0}")]
    SourceError(clang::SourceError),
}

/// The result of a lookup operation.
type Result<T> = std::result::Result<T, LookupError>;

/// An ID assigned to a `Path` in the index.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct NodeId(u32);

impl NodeId {
    #[inline(always)]
    fn from_usize(n: usize) -> NodeId {
        NodeId(n as u32)
    }
    #[inline(always)]
    fn as_usize(&self) -> usize {
        self.0 as usize
    }
}

/// A C++ unqualified identifier.
///
/// Examples: `std`, `vector`, or `MyClass`.
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub(crate) struct Ident {
    s: String,
}
impl From<&str> for Ident {
    /// Creates an identifier. Can panic if the identifier is invalid.
    fn from(id: &str) -> Ident {
        assert!(!id.contains("::"), "invalid identifier `{}`", id);
        Ident { s: id.to_string() }
    }
}
impl From<String> for Ident {
    fn from(id: String) -> Ident {
        From::from(id.as_str())
    }
}
impl Display for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.s)
    }
}

/// A C++ fully-qualified name.
///
/// Example: `std::vector`.
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub(crate) struct Path {
    components: Vec<Ident>,
}
impl From<&str> for Path {
    fn from(mut path: &str) -> Path {
        if path.starts_with("::") {
            path = &path[2..];
        }
        Path {
            components: path.split("::").map(Ident::from).collect(),
        }
    }
}
impl From<String> for Path {
    fn from(path: String) -> Path {
        From::from(path.as_str())
    }
}
impl FromIterator<Ident> for Path {
    fn from_iter<T: IntoIterator<Item = Ident>>(iter: T) -> Path {
        Path {
            components: iter.into_iter().collect(),
        }
    }
}
impl Path {
    fn dummy() -> Path {
        Path { components: vec![] }
    }
    pub(crate) fn iter(&self) -> impl Iterator<Item = &Ident> {
        self.components.iter()
    }
}
impl Display for Path {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut iter = self.components.iter();
        let mut next = iter.next();
        while let Some(id) = next {
            write!(f, "{}", id)?;
            next = iter.next();
            if next.is_some() {
                write!(f, "::")?;
            }
        }
        Ok(())
    }
}

/// An index `Node` is the entity or set of entities referred to by a `Path`.
///
/// For example, `std` and `std::vector` are both nodes.
///
/// Nodes may contain children, and they may be represented by multiple
/// entities. Namespaces, for example, can have many AST entities associated
/// with them. Template specializations are another example.
#[derive(Debug, Default)]
pub(crate) struct Node<'tu> {
    //kind: EntityKind,
    entities: Vec<Entity<'tu>>,
    items: Option<HashMap<Ident, NodeId>>,
    inline_items: Vec<NodeId>,
}
impl<'tu> Node<'tu> {
    fn items_mut(&mut self) -> &mut HashMap<Ident, NodeId> {
        self.items.as_mut().unwrap()
    }
}

/// A lazily populated index for looking up `Node`s by name.
pub(crate) struct Index<'tu> {
    nodes: Vec<Node<'tu>>,
}
impl<'tu> Index<'tu> {
    /// Creates an index from the given TranslationUnit.
    pub(crate) fn new(file: &'tu clang::TranslationUnit<'_>) -> Index<'tu> {
        let entity = file.get_entity();
        let file_node = Node {
            //kind: entity.get_kind(),
            entities: vec![entity],
            items: None,
            inline_items: vec![],
        };
        Index {
            nodes: vec![file_node],
        }
    }

    #[inline(always)]
    pub(crate) fn node(&self, id: NodeId) -> &Node<'tu> {
        &self.nodes[id.0 as usize]
    }

    #[inline(always)]
    fn node_mut(&mut self, id: NodeId) -> &mut Node<'tu> {
        &mut self.nodes[id.0 as usize]
    }

    /// Returns the `Node` corresponding to the given `Path`.
    ///
    /// If the path does not exist, returns `LookupError::NotFound`.
    pub(crate) fn lookup(&mut self, path: &Path) -> Result<&Node<'tu>> {
        self.lookup_id(&path).map(move |id| self.node(id))
    }

    /// Returns the `NodeId` corresponding to the given `Path`.
    ///
    /// If the path does not exist, returns `LookupError::NotFound`.
    pub(crate) fn lookup_id(&mut self, path: &Path) -> Result<NodeId> {
        let mut cur = NodeId(0);
        for (idx, name) in path.iter().enumerate() {
            cur = match self.child_id_of(cur, name)? {
                Some(child) => child,
                None => {
                    let err_path = path.iter().take(idx + 1).cloned().collect::<Path>();
                    return Err(LookupError::NotFound(err_path));
                }
            };
        }
        Ok(cur)
    }

    /// Returns the child named `child` of the given `node`.
    pub(crate) fn child_of(&mut self, node: NodeId, child: &Ident) -> Result<Option<&Node>> {
        self.child_id_of(node, child)
            .map(|opt| opt.map(move |id| self.node(id)))
    }

    /// Returns the `NodeId` of the child named `child` of the given `node`.
    pub(crate) fn child_id_of(&mut self, node: NodeId, child: &Ident) -> Result<Option<NodeId>> {
        if self.node(node).items.is_none() {
            self.expand(node);
        }
        let children = self.node(node).items.as_ref().unwrap();
        Ok(children.get(child).copied())
    }

    fn expand(&mut self, node: NodeId) -> Result<()> {
        self.node_mut(node).items = Some(HashMap::new());
        let num_entities = self.node(node).entities.len();
        for ent_idx in 0..num_entities {
            self.populate_children(node, self.node(node).entities[ent_idx])?;
        }
        Ok(())
    }

    fn populate_children(&mut self, node: NodeId, ent: Entity<'tu>) -> Result<()> {
        for child in ent.get_children() {
            let name = match ent.get_name() {
                Some(name) => Ident::from(name),
                None => continue,
            };
            let child_id = self.get_or_insert_child(node, name);
            self.node_mut(child_id).entities.push(child);
        }
        Ok(())
    }

    fn get_or_insert_child(&mut self, parent: NodeId, child: Ident) -> NodeId {
        let next_id = self.next_node_id();
        let child_id = *self
            .node_mut(parent)
            .items_mut()
            .entry(child)
            .or_insert(next_id);
        if child_id == next_id {
            self.nodes.push(Default::default());
        }
        child_id
    }

    #[inline(always)]
    fn next_node_id(&self) -> NodeId {
        NodeId(self.nodes.len() as u32)
    }
}

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

    #[test]
    fn paths() {
        assert_eq!(
            Path::from("::std::stuff::basic_iterator"),
            Path::from("std::stuff::basic_iterator")
        );
        assert_eq!(
            Path::from("::std::vector<bool>::basic_iterator")
                .iter()
                .cloned()
                .collect::<Vec<_>>(),
            ["std", "vector<bool>", "basic_iterator"]
                .into_iter()
                .copied()
                .map(Ident::from)
                .collect::<Vec<_>>()
        );
    }
}
<|endoftext|>


<commit_before>extern crate lipsum;

use std::env;

fn main() {
    // First command line argument or "" if not supplied.
    let arg = env::args().skip(1).next().unwrap_or_default();
    // Number of words to generate.
    let n = arg.parse().unwrap_or(25);
    // Print n words of lorem ipsum text.
    println!("{}", lipsum::lipsum(n));
}
<commit_msg>clippy: use nth(1) instead of skip(1).next()<commit_after>extern crate lipsum;

use std::env;

fn main() {
    // First command line argument or "" if not supplied.
    let arg = env::args().nth(1).unwrap_or_default();
    // Number of words to generate.
    let n = arg.parse().unwrap_or(25);
    // Print n words of lorem ipsum text.
    println!("{}", lipsum::lipsum(n));
}
<|endoftext|>


<commit_before>use cairo::{self, ImageSurface};
use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};
use nalgebra::{Matrix3, Matrix4x5, Matrix5, Vector5};

use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::number_list::{NumberList, NumberListError, NumberListLength};
use crate::parsers::{self, Parse, ParseValue};
use crate::property_bag::PropertyBag;
use crate::surface_utils::{
    iterators::Pixels, shared_surface::SharedImageSurface, ImageSurfaceDataExt, Pixel,
};
use crate::util::clamp;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// Color matrix operation types.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
enum OperationType {
    Matrix,
    Saturate,
    HueRotate,
    LuminanceToAlpha,
}

/// The `feColorMatrix` filter primitive.
pub struct FeColorMatrix {
    base: PrimitiveWithInput,
    matrix: Matrix5<f64>,
}

impl Default for FeColorMatrix {
    /// Constructs a new `ColorMatrix` with empty properties.
    #[inline]
    fn default() -> FeColorMatrix {
        FeColorMatrix {
            base: PrimitiveWithInput::new::<Self>(),
            matrix: Matrix5::identity(),
        }
    }
}

impl NodeTrait for FeColorMatrix {
    impl_node_as_filter_effect!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        // First, determine the operation type.
        let mut operation_type = OperationType::Matrix;
        for (attr, value) in pbag
            .iter()
            .filter(|(attr, _)| attr.expanded() == expanded_name!(svg "type"))
        {
            operation_type = attr.parse(value)?;
        }

        // Now read the matrix correspondingly.
        // LuminanceToAlpha doesn't accept any matrix.
        if operation_type == OperationType::LuminanceToAlpha {
            self.matrix = {
                #[cfg_attr(rustfmt, rustfmt_skip)]
                Matrix5::new(
                    0.0,    0.0,    0.0,    0.0, 0.0,
                    0.0,    0.0,    0.0,    0.0, 0.0,
                    0.0,    0.0,    0.0,    0.0, 0.0,
                    0.2125, 0.7154, 0.0721, 0.0, 0.0,
                    0.0,    0.0,    0.0,    0.0, 1.0,
                )
            };
        } else {
            for (attr, value) in pbag
                .iter()
                .filter(|(attr, _)| attr.expanded() == expanded_name!(svg "values"))
            {
                let new_matrix = match operation_type {
                    OperationType::LuminanceToAlpha => unreachable!(),
                    OperationType::Matrix => {
                        let NumberList(v) =
                            NumberList::parse_str(value, NumberListLength::Exact(20))
                                .map_err(|err| {
                                    let err_str = match err {
                                        NumberListError::IncorrectNumberOfElements => {
                                            "incorrect number of elements: expected 20"
                                        }
                                        NumberListError::Parse(ref err) => &err,
                                    };

                                    ValueErrorKind::parse_error(err_str)
                                })
                                .attribute(attr)?;
                        let matrix = Matrix4x5::from_row_slice(&v);
                        let mut matrix = matrix.fixed_resize(0.0);
                        matrix[(4, 4)] = 1.0;
                        matrix
                    }
                    OperationType::Saturate => {
                        let s = parsers::number(value).attribute(attr.clone())?;
                        if s < 0.0 || s > 1.0 {
                            return Err(ValueErrorKind::value_error("expected value from 0 to 1"))
                                .attribute(attr);
                        }

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        Matrix5::new(
                            0.213 + 0.787 * s, 0.715 - 0.715 * s, 0.072 - 0.072 * s, 0.0, 0.0,
                            0.213 - 0.213 * s, 0.715 + 0.285 * s, 0.072 - 0.072 * s, 0.0, 0.0,
                            0.213 - 0.213 * s, 0.715 - 0.715 * s, 0.072 + 0.928 * s, 0.0, 0.0,
                            0.0,               0.0,               0.0,               1.0, 0.0,
                            0.0,               0.0,               0.0,               0.0, 1.0,
                        )
                    }
                    OperationType::HueRotate => {
                        let degrees = parsers::number(value).attribute(attr.clone())?;
                        let (sin, cos) = degrees.to_radians().sin_cos();

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        let a = Matrix3::new(
                            0.213, 0.715, 0.072,
                            0.213, 0.715, 0.072,
                            0.213, 0.715, 0.072,
                        );

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        let b = Matrix3::new(
                             0.787, -0.715, -0.072,
                            -0.213,  0.285, -0.072,
                            -0.213, -0.715,  0.928,
                        );

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        let c = Matrix3::new(
                            -0.213, -0.715,  0.928,
                             0.143,  0.140, -0.283,
                            -0.787,  0.715,  0.072,
                        );

                        let top_left = a + b * cos + c * sin;

                        let mut matrix = top_left.fixed_resize(0.0);
                        matrix[(3, 3)] = 1.0;
                        matrix[(4, 4)] = 1.0;
                        matrix
                    }
                };

                self.matrix = new_matrix;
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeColorMatrix {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .into_irect(draw_ctx);

        let mut output_surface = ImageSurface::create(
            cairo::Format::ARgb32,
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        let output_stride = output_surface.get_stride() as usize;
        {
            let mut output_data = output_surface.get_data().unwrap();

            for (x, y, pixel) in Pixels::new(input.surface(), bounds) {
                let alpha = f64::from(pixel.a) / 255f64;

                let pixel_vec = if alpha == 0.0 {
                    Vector5::new(0.0, 0.0, 0.0, 0.0, 1.0)
                } else {
                    Vector5::new(
                        f64::from(pixel.r) / 255f64 / alpha,
                        f64::from(pixel.g) / 255f64 / alpha,
                        f64::from(pixel.b) / 255f64 / alpha,
                        alpha,
                        1.0,
                    )
                };
                let mut new_pixel_vec = Vector5::zeros();
                self.matrix.mul_to(&pixel_vec, &mut new_pixel_vec);

                let new_alpha = clamp(new_pixel_vec[3], 0.0, 1.0);

                let premultiply = |x: f64| ((clamp(x, 0.0, 1.0) * new_alpha * 255f64) + 0.5) as u8;

                let output_pixel = Pixel {
                    r: premultiply(new_pixel_vec[0]),
                    g: premultiply(new_pixel_vec[1]),
                    b: premultiply(new_pixel_vec[2]),
                    a: ((new_alpha * 255f64) + 0.5) as u8,
                };

                output_data.set_pixel(output_stride, output_pixel, x, y);
            }
        }

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: SharedImageSurface::new(output_surface, input.surface().surface_type())?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}

impl Parse for OperationType {
    fn parse(parser: &mut Parser<'_, '_>) -> Result<Self, ValueErrorKind> {
        parse_identifiers!(
            parser,
            "matrix" => OperationType::Matrix,
            "saturate" => OperationType::Saturate,
            "hueRotate" => OperationType::HueRotate,
            "luminanceToAlpha" => OperationType::LuminanceToAlpha,
        ).map_err(|_: ParseError| ValueErrorKind::parse_error("parse error"))
    }
}
<commit_msg>color_matrix.rs: impl Default for OperationType<commit_after>use cairo::{self, ImageSurface};
use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};
use nalgebra::{Matrix3, Matrix4x5, Matrix5, Vector5};

use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::number_list::{NumberList, NumberListError, NumberListLength};
use crate::parsers::{self, Parse, ParseValue};
use crate::property_bag::PropertyBag;
use crate::surface_utils::{
    iterators::Pixels, shared_surface::SharedImageSurface, ImageSurfaceDataExt, Pixel,
};
use crate::util::clamp;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// Color matrix operation types.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
enum OperationType {
    Matrix,
    Saturate,
    HueRotate,
    LuminanceToAlpha,
}

impl Default for OperationType {
    fn default() -> Self {
        OperationType::Matrix
    }
}

/// The `feColorMatrix` filter primitive.
pub struct FeColorMatrix {
    base: PrimitiveWithInput,
    matrix: Matrix5<f64>,
}

impl Default for FeColorMatrix {
    /// Constructs a new `ColorMatrix` with empty properties.
    #[inline]
    fn default() -> FeColorMatrix {
        FeColorMatrix {
            base: PrimitiveWithInput::new::<Self>(),
            matrix: Matrix5::identity(),
        }
    }
}

impl NodeTrait for FeColorMatrix {
    impl_node_as_filter_effect!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        // First, determine the operation type.
        let mut operation_type = Default::default();
        for (attr, value) in pbag
            .iter()
            .filter(|(attr, _)| attr.expanded() == expanded_name!(svg "type"))
        {
            operation_type = attr.parse(value)?;
        }

        // Now read the matrix correspondingly.
        // LuminanceToAlpha doesn't accept any matrix.
        if operation_type == OperationType::LuminanceToAlpha {
            self.matrix = {
                #[cfg_attr(rustfmt, rustfmt_skip)]
                Matrix5::new(
                    0.0,    0.0,    0.0,    0.0, 0.0,
                    0.0,    0.0,    0.0,    0.0, 0.0,
                    0.0,    0.0,    0.0,    0.0, 0.0,
                    0.2125, 0.7154, 0.0721, 0.0, 0.0,
                    0.0,    0.0,    0.0,    0.0, 1.0,
                )
            };
        } else {
            for (attr, value) in pbag
                .iter()
                .filter(|(attr, _)| attr.expanded() == expanded_name!(svg "values"))
            {
                let new_matrix = match operation_type {
                    OperationType::LuminanceToAlpha => unreachable!(),
                    OperationType::Matrix => {
                        let NumberList(v) =
                            NumberList::parse_str(value, NumberListLength::Exact(20))
                                .map_err(|err| {
                                    let err_str = match err {
                                        NumberListError::IncorrectNumberOfElements => {
                                            "incorrect number of elements: expected 20"
                                        }
                                        NumberListError::Parse(ref err) => &err,
                                    };

                                    ValueErrorKind::parse_error(err_str)
                                })
                                .attribute(attr)?;
                        let matrix = Matrix4x5::from_row_slice(&v);
                        let mut matrix = matrix.fixed_resize(0.0);
                        matrix[(4, 4)] = 1.0;
                        matrix
                    }
                    OperationType::Saturate => {
                        let s = parsers::number(value).attribute(attr.clone())?;
                        if s < 0.0 || s > 1.0 {
                            return Err(ValueErrorKind::value_error("expected value from 0 to 1"))
                                .attribute(attr);
                        }

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        Matrix5::new(
                            0.213 + 0.787 * s, 0.715 - 0.715 * s, 0.072 - 0.072 * s, 0.0, 0.0,
                            0.213 - 0.213 * s, 0.715 + 0.285 * s, 0.072 - 0.072 * s, 0.0, 0.0,
                            0.213 - 0.213 * s, 0.715 - 0.715 * s, 0.072 + 0.928 * s, 0.0, 0.0,
                            0.0,               0.0,               0.0,               1.0, 0.0,
                            0.0,               0.0,               0.0,               0.0, 1.0,
                        )
                    }
                    OperationType::HueRotate => {
                        let degrees = parsers::number(value).attribute(attr.clone())?;
                        let (sin, cos) = degrees.to_radians().sin_cos();

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        let a = Matrix3::new(
                            0.213, 0.715, 0.072,
                            0.213, 0.715, 0.072,
                            0.213, 0.715, 0.072,
                        );

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        let b = Matrix3::new(
                             0.787, -0.715, -0.072,
                            -0.213,  0.285, -0.072,
                            -0.213, -0.715,  0.928,
                        );

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        let c = Matrix3::new(
                            -0.213, -0.715,  0.928,
                             0.143,  0.140, -0.283,
                            -0.787,  0.715,  0.072,
                        );

                        let top_left = a + b * cos + c * sin;

                        let mut matrix = top_left.fixed_resize(0.0);
                        matrix[(3, 3)] = 1.0;
                        matrix[(4, 4)] = 1.0;
                        matrix
                    }
                };

                self.matrix = new_matrix;
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeColorMatrix {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .into_irect(draw_ctx);

        let mut output_surface = ImageSurface::create(
            cairo::Format::ARgb32,
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        let output_stride = output_surface.get_stride() as usize;
        {
            let mut output_data = output_surface.get_data().unwrap();

            for (x, y, pixel) in Pixels::new(input.surface(), bounds) {
                let alpha = f64::from(pixel.a) / 255f64;

                let pixel_vec = if alpha == 0.0 {
                    Vector5::new(0.0, 0.0, 0.0, 0.0, 1.0)
                } else {
                    Vector5::new(
                        f64::from(pixel.r) / 255f64 / alpha,
                        f64::from(pixel.g) / 255f64 / alpha,
                        f64::from(pixel.b) / 255f64 / alpha,
                        alpha,
                        1.0,
                    )
                };
                let mut new_pixel_vec = Vector5::zeros();
                self.matrix.mul_to(&pixel_vec, &mut new_pixel_vec);

                let new_alpha = clamp(new_pixel_vec[3], 0.0, 1.0);

                let premultiply = |x: f64| ((clamp(x, 0.0, 1.0) * new_alpha * 255f64) + 0.5) as u8;

                let output_pixel = Pixel {
                    r: premultiply(new_pixel_vec[0]),
                    g: premultiply(new_pixel_vec[1]),
                    b: premultiply(new_pixel_vec[2]),
                    a: ((new_alpha * 255f64) + 0.5) as u8,
                };

                output_data.set_pixel(output_stride, output_pixel, x, y);
            }
        }

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: SharedImageSurface::new(output_surface, input.surface().surface_type())?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}

impl Parse for OperationType {
    fn parse(parser: &mut Parser<'_, '_>) -> Result<Self, ValueErrorKind> {
        parse_identifiers!(
            parser,
            "matrix" => OperationType::Matrix,
            "saturate" => OperationType::Saturate,
            "hueRotate" => OperationType::HueRotate,
            "luminanceToAlpha" => OperationType::LuminanceToAlpha,
        ).map_err(|_: ParseError| ValueErrorKind::parse_error("parse error"))
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use arrayvec::ArrayString;
use async_trait::async_trait;
use devp2p::*;
use ethereum_types::*;
use hex_literal::hex;
use k256::ecdsa::SigningKey;
use rand::rngs::OsRng;
use rlp_derive::{RlpDecodable, RlpEncodable};
use std::{
    convert::{identity, TryInto},
    sync::Arc,
};
use task_group::TaskGroup;
use tracing::*;
use tracing_subscriber::EnvFilter;
use trust_dns_resolver::{config::*, TokioAsyncResolver};

const DNS_BOOTNODE: &str = "all.mainnet.ethdisco.net";

#[derive(Debug, RlpEncodable, RlpDecodable)]
struct StatusMessage {
    protocol_version: usize,
    network_id: usize,
    total_difficulty: U256,
    best_hash: H256,
    genesis_hash: H256,
}

#[derive(Debug)]
struct CapabilityServerImpl;

#[async_trait]
impl CapabilityServer for CapabilityServerImpl {
    async fn on_peer_connect(&self, _: PeerId) -> PeerConnectOutcome {
        let status_message = StatusMessage {
            protocol_version: 63,
            network_id: 1,
            total_difficulty: 17608636743620256866935_u128.into(),
            best_hash: H256::from(hex!(
                "28042e7e4d35a3482bf5f0d862501868b04c1734f483ceae3bf1393561951829"
            )),
            genesis_hash: H256::from(hex!(
                "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
            )),
        };

        PeerConnectOutcome::Retain {
            hello: Some(Message {
                id: 0,
                data: rlp::encode(&status_message).into(),
            }),
        }
    }
    #[instrument(skip(peer, message), level = "debug", name = "ingress", fields(peer=&*peer.id.to_string(), id=message.id))]
    async fn on_ingress_message(
        &self,
        peer: IngressPeer,
        message: Message,
    ) -> Result<(Option<Message>, Option<ReputationReport>), HandleError> {
        let Message { id, data } = message;

        info!(
            "Received message with id {}, data {}",
            id,
            hex::encode(&data)
        );

        if id == 0 {
            match rlp::decode::<StatusMessage>(&data) {
                Ok(v) => {
                    info!("Decoded status message: {:?}", v);
                }
                Err(e) => {
                    info!("Failed to decode status message: {}! Kicking peer.", e);
                    return Ok((None, Some(ReputationReport::Kick)));
                }
            }
        }

        let out_id = match id {
            3 => Some(4),
            5 => Some(6),
            _ => None,
        };

        Ok((
            out_id.map(|id| Message {
                id,
                data: rlp::encode_list::<String, String>(&[]).into(),
            }),
            None,
        ))
    }
}

#[tokio::main]
async fn main() {
    tracing_subscriber::fmt()
        .with_env_filter(EnvFilter::from_default_env())
        .init();

    let secret_key = SigningKey::random(&mut OsRng);

    let dns_resolver = dnsdisc::Resolver::new(Arc::new(
        TokioAsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default())
            .await
            .unwrap(),
    ));

    let discovery = DnsDiscovery::new(Arc::new(dns_resolver), DNS_BOOTNODE.to_string(), None);

    let task_group = Arc::new(TaskGroup::default());

    let client = RLPxNodeBuilder::new()
        .with_task_group(task_group.clone())
        .with_listen_options(ListenOptions {
            discovery: Some(DiscoveryOptions {
                discovery: Arc::new(tokio::sync::Mutex::new(discovery)),
                tasks: 1_usize.try_into().unwrap(),
            }),
            max_peers: 50,
            addr: "0.0.0.0:30303".parse().unwrap(),
        })
        .build(secret_key)
        .await
        .unwrap();

    let _handle = client.register(
        CapabilityInfo {
            name: CapabilityName(ArrayString::from("eth").unwrap()),
            version: 63,
            length: 17,
        },
        Arc::new(CapabilityServerImpl),
    );

    loop {
        tokio::time::delay_for(std::time::Duration::from_secs(5)).await;
        info!(
            "Peers: {}. Tasks: {}.",
            client.connected_peers(identity, None, None).len(),
            task_group.len()
        );
    }
}
<commit_msg>sentry: shared task group with metrics<commit_after>#![allow(dead_code)]

use arrayvec::ArrayString;
use async_trait::async_trait;
use devp2p::*;
use ethereum_types::*;
use hex_literal::hex;
use k256::ecdsa::SigningKey;
use rand::rngs::OsRng;
use rlp_derive::{RlpDecodable, RlpEncodable};
use std::{
    convert::{identity, TryInto},
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
};
use task_group::TaskGroup;
use tracing::*;
use tracing_subscriber::EnvFilter;
use trust_dns_resolver::{config::*, TokioAsyncResolver};
use uuid::Uuid;

const DNS_BOOTNODE: &str = "all.mainnet.ethdisco.net";

#[derive(Debug, Default)]
struct TaskMetrics {
    count: AtomicUsize,
}

impl task_group::Metrics for TaskMetrics {
    fn task_started(&self, id: Uuid, name: String) {
        let c = self.count.fetch_add(1, Ordering::Relaxed);
        trace!("Current tasks: {}. Started task {}/{}", c + 1, name, id)
    }

    fn task_stopped(&self, id: Uuid, name: String) {
        let c = self.count.fetch_sub(1, Ordering::Relaxed);
        trace!("Current tasks: {}. Stopped task {}/{}", c - 1, name, id)
    }
}

#[derive(Debug, RlpEncodable, RlpDecodable)]
struct StatusMessage {
    protocol_version: usize,
    network_id: usize,
    total_difficulty: U256,
    best_hash: H256,
    genesis_hash: H256,
}

#[derive(Debug)]
struct CapabilityServerImpl;

#[async_trait]
impl CapabilityServer for CapabilityServerImpl {
    async fn on_peer_connect(&self, _: PeerId) -> PeerConnectOutcome {
        let status_message = StatusMessage {
            protocol_version: 63,
            network_id: 1,
            total_difficulty: 17608636743620256866935_u128.into(),
            best_hash: H256::from(hex!(
                "28042e7e4d35a3482bf5f0d862501868b04c1734f483ceae3bf1393561951829"
            )),
            genesis_hash: H256::from(hex!(
                "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
            )),
        };

        PeerConnectOutcome::Retain {
            hello: Some(Message {
                id: 0,
                data: rlp::encode(&status_message).into(),
            }),
        }
    }
    #[instrument(skip(peer, message), level = "debug", name = "ingress", fields(peer=&*peer.id.to_string(), id=message.id))]
    async fn on_ingress_message(
        &self,
        peer: IngressPeer,
        message: Message,
    ) -> Result<(Option<Message>, Option<ReputationReport>), HandleError> {
        let Message { id, data } = message;

        info!(
            "Received message with id {}, data {}",
            id,
            hex::encode(&data)
        );

        if id == 0 {
            match rlp::decode::<StatusMessage>(&data) {
                Ok(v) => {
                    info!("Decoded status message: {:?}", v);
                }
                Err(e) => {
                    info!("Failed to decode status message: {}! Kicking peer.", e);
                    return Ok((None, Some(ReputationReport::Kick)));
                }
            }
        }

        let out_id = match id {
            3 => Some(4),
            5 => Some(6),
            _ => None,
        };

        Ok((
            out_id.map(|id| Message {
                id,
                data: rlp::encode_list::<String, String>(&[]).into(),
            }),
            None,
        ))
    }
}

#[tokio::main]
async fn main() {
    tracing_subscriber::fmt()
        .with_env_filter(EnvFilter::from_default_env())
        .init();

    let secret_key = SigningKey::random(&mut OsRng);

    let task_metrics = Arc::new(TaskMetrics::default());
    let task_group = Arc::new(TaskGroup::new_with_metrics(task_metrics.clone()));

    let mut dns_resolver = dnsdisc::Resolver::new(Arc::new(
        TokioAsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default())
            .await
            .unwrap(),
    ));
    dns_resolver.with_task_group(task_group.clone());

    let discovery = DnsDiscovery::new(Arc::new(dns_resolver), DNS_BOOTNODE.to_string(), None);

    let client = RLPxNodeBuilder::new()
        .with_task_group(task_group.clone())
        .with_listen_options(ListenOptions {
            discovery: Some(DiscoveryOptions {
                discovery: Arc::new(tokio::sync::Mutex::new(discovery)),
                tasks: 1_usize.try_into().unwrap(),
            }),
            max_peers: 50,
            addr: "0.0.0.0:30303".parse().unwrap(),
        })
        .build(secret_key)
        .await
        .unwrap();

    let _handle = client.register(
        CapabilityInfo {
            name: CapabilityName(ArrayString::from("eth").unwrap()),
            version: 63,
            length: 17,
        },
        Arc::new(CapabilityServerImpl),
    );

    loop {
        tokio::time::delay_for(std::time::Duration::from_secs(5)).await;
        info!(
            "Peers: {}.",
            client.connected_peers(identity, None, None).len()
        );
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate http;
extern crate router;

use std::io::net::ip::Ipv4Addr;
use iron::{ServerT, Iron, Alloy, Request, Response};
use http::method::Get;
use router::{Router, Params};

fn main() {
    let mut server: ServerT = Iron::new();
    let mut router = Router::new();

    fn handler(_req: &mut Request, res: &mut Response, alloy: &mut Alloy) {
        let query = alloy.find::<Params>().unwrap().get("query").unwrap();
        let _ = res.write(query.as_bytes());
    }

    // Setup our route.
    router.route(
        Get,
        "/:query".to_string(),
        vec!["query".to_string()],
        handler);

    server.link(router);
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}

<commit_msg>(doc) Updated example for chain.link changes.<commit_after>extern crate iron;
extern crate http;
extern crate router;

use std::io::net::ip::Ipv4Addr;
use iron::{ServerT, Iron, Alloy, Request, Response, Chain};
use http::method::Get;
use router::{Router, Params};

fn main() {
    let mut server: ServerT = Iron::new();
    let mut router = Router::new();

    fn handler(_req: &mut Request, res: &mut Response, alloy: &mut Alloy) {
        let query = alloy.find::<Params>().unwrap().get("query").unwrap();
        let _ = res.write(query.as_bytes());
    }

    // Setup our route.
    router.route(
        Get,
        "/:query".to_string(),
        vec!["query".to_string()],
        handler);

    server.chain.link(router);
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}

<|endoftext|>


<commit_before>// Learning.

use term::Term;
use stroke::Stroke;
use words::{LearnWord, Words};

use std::io::Write;
use termion::color;

pub struct Learn {
    words: Words,
    term: Term,

    // How many of the words are we getting right.  TODO: Store this in the datafile instead of
    // regenerating it each time.
    ratio: f64,
}

impl Learn {
    pub fn new(words: Words, term: Term) -> Learn {
        Learn {
            words: words,
            term: term,
            ratio: 1.0,
        }
    }

    // Consume the learner, returning the wordset contained in it.
    pub fn into_words(self) -> Words {
        self.words
    }

    pub fn run(&mut self) {
        loop {
            // TODO: Check for things that have expired we need to learn.

            let mut word = match self.words.get_learned() {
                None => {
                    match self.words.get_unlearned() {
                        None => {
                            println!("No more words to learn\r");
                            return;
                        },
                        Some(word) => word,
                    }
                }
                Some(word) => word,
            };

            let status = self.single(&mut word);

            // Return the word.
            self.words.push_word(word);

            match status {
                Status::Stopped => break,
                Status::Continue(true) => {
                    self.ratio = self.ratio * 0.97 + 0.03;
                }
                Status::Continue(false) => {
                    self.ratio = self.ratio * 0.97;
                }
            }
            if status == Status::Stopped {
                break;
            }
        }
    }

    // Learn a single word, updating its timing information based on how well it was learned.
    fn single(&mut self, word: &mut LearnWord) -> Status {
        let counts = self.words.get_counts();

        writeln!(self.term, "\r\nActive: {}, Later: {}, Unlearned: {}, Interval {}, Ratio {:.1}\r",
                 counts.active, counts.later, counts.unlearned,
                 humanize_time(word.interval),
                 self.ratio * 100.0).unwrap();
        for b in &counts.buckets {
            writeln!(self.term, "  {:-4}: {:4} {}\r", b.name, b.count,
                     stars(65, b.count, counts.active + counts.later)).unwrap();
        }
        writeln!(self.term, "\r").unwrap();
        self.term.flush().unwrap();

        let mut state = Single::new(&mut self.term, word);
        state.run()
    }
}

// Format an interval (in seconds) in terms of nicer units.
fn humanize_time(interval: f64) -> String {
    let mut val = interval;
    for unit in UNITS {
        if val < unit.div {
            return format!("{:.1} {}", val, unit.name);
        }
        val /= unit.div;
    }
    // Out of bounds, return the unmodified time.
    format!("{:.1} seconds", interval)
}

struct UnitEntry {
    name: &'static str,
    div: f64,
}

static UNITS: &'static [UnitEntry] = &[
    UnitEntry{ name: "seconds", div: 60.0 },
    UnitEntry{ name: "minutes", div: 60.0 },
    UnitEntry{ name: "hours", div: 24.0 },
    UnitEntry{ name: "days", div: 365.0 },
    UnitEntry{ name: "months", div: 12.0 },
    UnitEntry{ name: "years", div: 1.0e6 },
];

// Print a line of stars resembling a histogram bar.  `len` is the number of stars to use, a is the
// number in question, and total is the expected total.
fn stars(len: usize, value: usize, total: usize) -> String {
    let mut buf = String::new();
    buf.push('|');
    let thresh = value as f64 / total as f64 * len as f64;
    for i in 0 .. len {
        if (i as f64) < thresh {
            buf.push('*');
        } else {
            buf.push(' ');
        };
    }
    buf.push('|');
    buf
}

struct Single<'t, 'w> {
    term: &'t mut Term,
    word: &'w mut LearnWord,
    user: Vec<Stroke>,
    errors: u32,
}

impl<'t, 'w> Single<'t, 'w> {
    fn new<'tt, 'ww>(term: &'tt mut Term, word: &'ww mut LearnWord) -> Single<'tt, 'ww> {
        Single {
            term: term,
            word: word,
            user: vec![],
            errors: 0,
        }
    }

    fn prompt(&mut self) {
        write!(self.term, "\r\x1b[J{:20}: {}{}",
               self.word.english,
               if self.word.strokes == self.user {
                   if self.errors == 0 { '✓' } else { '✗' }
               } else { ' ' },
               slashed(&self.user, &self.word.strokes)).unwrap();
        if self.errors > 0 {
            write!(self.term, "  ({})", slashed(&self.word.strokes, &self.word.strokes)).unwrap();
        }
        self.term.flush().unwrap();
    }

    fn run(&mut self) -> Status {
        let result;
        loop {
            self.prompt();
            if self.word.strokes == self.user {
                result = Status::Continue(self.errors == 0);
                break;
            }

            let stroke = match self.term.read_stroke().unwrap() {
                None => { result = Status::Stopped; break; }
                Some(st) => st,
            };
            if stroke.is_star() {
                self.user.pop();
            } else {
                self.user.push(stroke);
                let pos = self.user.len();
                if pos > self.word.strokes.len() ||
                    self.user[pos-1] != self.word.strokes[pos-1]
                {
                    self.errors += 1;
                }
            }
        }

        match result {
            Status::Continue(right) => {
                if right {
                    self.word.correct();
                } else {
                    self.word.incorrect();
                }

                writeln!(self.term, "\r\nNew interval {}\r", humanize_time(self.word.interval)).unwrap();
            }
            Status::Stopped => {
                writeln!(self.term, "\r").unwrap();
            }
        }
        self.term.flush().unwrap();
        result
    }
}

// Generate a slash separated version of the given stroke list.
fn slashed(strokes: &[Stroke], expected: &[Stroke]) -> String {
    let mut buf = vec![];
    let mut first = true;

    for (i, st) in strokes.iter().enumerate() {
        if !first {
            buf.push(b'/');
        }
        first = false;

        let correct = expected.get(i) == Some(st);
        if !correct {
            write!(&mut buf, "{}{}",
                   color::Bg(color::LightRed),
                   color::Fg(color::Black)).unwrap();
        }
        write!(&mut buf, "{}", st).unwrap();
        if !correct {
            write!(&mut buf, "{}{}",
                   color::Bg(color::Reset),
                   color::Fg(color::Reset)).unwrap();
        }
    }
    String::from_utf8(buf).unwrap()
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Status {
    // Continue learning, and returns if the word is correct.
    Continue(bool),
    Stopped,
}
<commit_msg>Revert "Start tracking the correct ratio"<commit_after>// Learning.

use term::Term;
use stroke::Stroke;
use words::{LearnWord, Words};

use std::io::Write;
use termion::color;

pub struct Learn {
    words: Words,
    term: Term,
}

impl Learn {
    pub fn new(words: Words, term: Term) -> Learn {
        Learn {
            words: words,
            term: term,
        }
    }

    // Consume the learner, returning the wordset contained in it.
    pub fn into_words(self) -> Words {
        self.words
    }

    pub fn run(&mut self) {
        loop {
            // TODO: Check for things that have expired we need to learn.

            let mut word = match self.words.get_learned() {
                None => {
                    match self.words.get_unlearned() {
                        None => {
                            println!("No more words to learn\r");
                            return;
                        },
                        Some(word) => word,
                    }
                }
                Some(word) => word,
            };

            let status = self.single(&mut word);

            // Return the word.
            self.words.push_word(word);

            if status == Status::Stopped {
                break;
            }
        }
    }

    // Learn a single word, updating its timing information based on how well it was learned.
    fn single(&mut self, word: &mut LearnWord) -> Status {
        let counts = self.words.get_counts();

        writeln!(self.term, "\r\nActive: {}, Later: {}, Unlearned: {}, Interval {}\r",
                 counts.active, counts.later, counts.unlearned,
                 humanize_time(word.interval)).unwrap();
        for b in &counts.buckets {
            writeln!(self.term, "  {:-4}: {:4} {}\r", b.name, b.count,
                     stars(65, b.count, counts.active + counts.later)).unwrap();
        }
        writeln!(self.term, "\r").unwrap();
        self.term.flush().unwrap();

        let mut state = Single::new(&mut self.term, word);
        state.run()
    }
}

// Format an interval (in seconds) in terms of nicer units.
fn humanize_time(interval: f64) -> String {
    let mut val = interval;
    for unit in UNITS {
        if val < unit.div {
            return format!("{:.1} {}", val, unit.name);
        }
        val /= unit.div;
    }
    // Out of bounds, return the unmodified time.
    format!("{:.1} seconds", interval)
}

struct UnitEntry {
    name: &'static str,
    div: f64,
}

static UNITS: &'static [UnitEntry] = &[
    UnitEntry{ name: "seconds", div: 60.0 },
    UnitEntry{ name: "minutes", div: 60.0 },
    UnitEntry{ name: "hours", div: 24.0 },
    UnitEntry{ name: "days", div: 365.0 },
    UnitEntry{ name: "months", div: 12.0 },
    UnitEntry{ name: "years", div: 1.0e6 },
];

// Print a line of stars resembling a histogram bar.  `len` is the number of stars to use, a is the
// number in question, and total is the expected total.
fn stars(len: usize, value: usize, total: usize) -> String {
    let mut buf = String::new();
    buf.push('|');
    let thresh = value as f64 / total as f64 * len as f64;
    for i in 0 .. len {
        if (i as f64) < thresh {
            buf.push('*');
        } else {
            buf.push(' ');
        };
    }
    buf.push('|');
    buf
}

struct Single<'t, 'w> {
    term: &'t mut Term,
    word: &'w mut LearnWord,
    user: Vec<Stroke>,
    errors: u32,
}

impl<'t, 'w> Single<'t, 'w> {
    fn new<'tt, 'ww>(term: &'tt mut Term, word: &'ww mut LearnWord) -> Single<'tt, 'ww> {
        Single {
            term: term,
            word: word,
            user: vec![],
            errors: 0,
        }
    }

    fn prompt(&mut self) {
        write!(self.term, "\r\x1b[J{:20}: {}{}",
               self.word.english,
               if self.word.strokes == self.user {
                   if self.errors == 0 { '✓' } else { '✗' }
               } else { ' ' },
               slashed(&self.user, &self.word.strokes)).unwrap();
        if self.errors > 0 {
            write!(self.term, "  ({})", slashed(&self.word.strokes, &self.word.strokes)).unwrap();
        }
        self.term.flush().unwrap();
    }

    fn run(&mut self) -> Status {
        let mut result = Status::Continue;
        loop {
            self.prompt();
            if self.word.strokes == self.user {
                break;
            }

            let stroke = match self.term.read_stroke().unwrap() {
                None => { result = Status::Stopped; break; }
                Some(st) => st,
            };
            if stroke.is_star() {
                self.user.pop();
            } else {
                self.user.push(stroke);
                let pos = self.user.len();
                if pos > self.word.strokes.len() ||
                    self.user[pos-1] != self.word.strokes[pos-1]
                {
                    self.errors += 1;
                }
            }
        }

        if result == Status::Continue {
            if self.errors > 0 {
                self.word.incorrect();
            } else {
                self.word.correct();
            }

            writeln!(self.term, "\r\nNew interval {}\r", humanize_time(self.word.interval)).unwrap();
        } else {
            writeln!(self.term, "\r").unwrap();
        }
        self.term.flush().unwrap();
        result
    }
}

// Generate a slash separated version of the given stroke list.
fn slashed(strokes: &[Stroke], expected: &[Stroke]) -> String {
    let mut buf = vec![];
    let mut first = true;

    for (i, st) in strokes.iter().enumerate() {
        if !first {
            buf.push(b'/');
        }
        first = false;

        let correct = expected.get(i) == Some(st);
        if !correct {
            write!(&mut buf, "{}{}",
                   color::Bg(color::LightRed),
                   color::Fg(color::Black)).unwrap();
        }
        write!(&mut buf, "{}", st).unwrap();
        if !correct {
            write!(&mut buf, "{}{}",
                   color::Bg(color::Reset),
                   color::Fg(color::Reset)).unwrap();
        }
    }
    String::from_utf8(buf).unwrap()
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Status {
    Continue,
    Stopped,
}
<|endoftext|>


<commit_before>
use std::collections::BinaryHeap;
use std::sync::{Condvar, Mutex};
use std::thread;
use std::sync::{Arc};
use std::sync::mpsc::{Sender, Receiver, channel};
use std::cmp::{Ordering, min, max};

use time::{SteadyTime, Duration};

struct TimerEvent {
    when: SteadyTime,
    completion_sink: Sender<()>,
    period: Option<u32>,
}
impl Ord for TimerEvent {
    fn cmp(&self, other: &TimerEvent) -> Ordering {
        other.when.cmp(&self.when)
    }
}
impl PartialEq for TimerEvent {
    fn eq(&self, other: &TimerEvent) -> bool {
        let self_ptr: *const TimerEvent = self;
        let other_ptr: *const TimerEvent = other;

        self_ptr == other_ptr
    }
}
impl Eq for TimerEvent {}
impl PartialOrd for TimerEvent {
    fn partial_cmp(&self, other: &TimerEvent) -> Option<Ordering> {
        other.when.partial_cmp(&self.when)
    }
}

struct TimerRequest {
    duration: u32,
    periodic: bool,
    completion_sink: Sender<()>,
}

struct TimerInterface {
    trigger: Arc<Condvar>,
    adder: Sender<TimerRequest>,
}

struct TimerWorker {
    trigger: Arc<Condvar>,
    request_source: Receiver<TimerRequest>,
    schedule: BinaryHeap<TimerEvent>,
}

impl TimerWorker {
    fn new(trigger: Arc<Condvar>, request_source: Receiver<TimerRequest>) -> TimerWorker {
        TimerWorker{
            trigger: trigger,
            request_source: request_source,
            schedule: BinaryHeap::new(),
        }
    }

    fn drain_request_queue(&mut self) {
        while let Ok(request) = self.request_source.try_recv() {
            println!("Scheduling a new timeout for {} ms from now", request.duration);
            self.schedule.push(TimerEvent{
                when: SteadyTime::now() + Duration::milliseconds(request.duration as i64),
                period: if request.periodic { Some(request.duration) } else { None },
                completion_sink: request.completion_sink
            });
        }
    }

    fn has_event_now(&self) -> bool {
        if let Some(evt) = self.schedule.peek() {
            evt.when < SteadyTime::now()
        } else {
            false
        }
    }

    fn fire_event(&mut self) {
        println!("Firing an event!");
        if let Some(evt) = self.schedule.pop() {
            match evt.completion_sink.send( () ) {
                Ok( () ) => {
                    println!("Send succeeded!");
                    if let Some(period) = evt.period.clone() {
                        self.schedule.push(TimerEvent{
                            when: SteadyTime::now() + Duration::milliseconds(period as i64),
                            period: evt.period,
                            completion_sink: evt.completion_sink,
                        });
                    }
                }
                Err(_) => {
                    // The receiver is no longer waiting for us
                }
            }
        }
    }

    fn ms_until_next_event(&self) -> u32 {
        if let Some(evt) = self.schedule.peek() {
            max(0, min((evt.when - SteadyTime::now()).num_milliseconds(), 100000))  as u32
        } else {
            100000
        }
    }

    fn run(&mut self) {
        let m = Mutex::new(false);
        let mut g = m.lock().unwrap(); // The mutex isn't poisoned, since we just made it

        loop {
            self.drain_request_queue();

            // Fire off as many events as we are supposed to.
            loop {
                if self.has_event_now() {
                    self.fire_event();
                } else {
                    break;
                }
            }

            let wait_millis = self.ms_until_next_event();

            println!("Timer is waiting for {}!", wait_millis);
            // unwrap() is safe because the mutex will not be poisoned,
            // since we have not shared it with another thread.
            g = self.trigger.wait_timeout_ms(g, wait_millis).unwrap().0;
            println!("Timer is done waiting");
        }
    }
}

lazy_static! {
    static ref TIMER_INTERFACE  : Mutex<TimerInterface> = {
        let (sender, receiver) = channel();
        let trigger = Arc::new(Condvar::new());
        let trigger2 = trigger.clone();
        thread::spawn(move|| {
            TimerWorker::new(trigger2, receiver).run();
        });

        let interface = TimerInterface {
            trigger: trigger,
            adder: sender
        };

        Mutex::new(interface)
    };
}

fn add_request(duration_ms: u32, periodic: bool) -> Receiver<()> {
    let (sender, receiver) = channel();

    let interface = TIMER_INTERFACE.lock().ok().expect("Failed to acquire the global timer worker");
    interface.adder.send(TimerRequest{
        duration:duration_ms,
        completion_sink:sender,
        periodic: periodic
    }).ok().expect("Failed to send a request to the global timer worker");

    interface.trigger.notify_one();

    receiver
}

pub fn oneshot_ms(ms: u32) -> Receiver<()> {
    add_request(ms, false)
}

pub fn periodic_ms(ms: u32) -> Receiver<()> {
    add_request(ms, true)
}
<commit_msg>Prevent drift in periodic timers<commit_after>
use std::collections::BinaryHeap;
use std::sync::{Condvar, Mutex};
use std::thread;
use std::sync::{Arc};
use std::sync::mpsc::{Sender, Receiver, channel};
use std::cmp::{Ordering, min, max};

use time::{SteadyTime, Duration};

struct TimerEvent {
    when: SteadyTime,
    completion_sink: Sender<()>,
    period: Option<u32>,
}
impl Ord for TimerEvent {
    fn cmp(&self, other: &TimerEvent) -> Ordering {
        other.when.cmp(&self.when)
    }
}
impl PartialEq for TimerEvent {
    fn eq(&self, other: &TimerEvent) -> bool {
        let self_ptr: *const TimerEvent = self;
        let other_ptr: *const TimerEvent = other;

        self_ptr == other_ptr
    }
}
impl Eq for TimerEvent {}
impl PartialOrd for TimerEvent {
    fn partial_cmp(&self, other: &TimerEvent) -> Option<Ordering> {
        other.when.partial_cmp(&self.when)
    }
}

struct TimerRequest {
    duration: u32,
    periodic: bool,
    completion_sink: Sender<()>,
}

struct TimerInterface {
    trigger: Arc<Condvar>,
    adder: Sender<TimerRequest>,
}

struct TimerWorker {
    trigger: Arc<Condvar>,
    request_source: Receiver<TimerRequest>,
    schedule: BinaryHeap<TimerEvent>,
}

impl TimerWorker {
    fn new(trigger: Arc<Condvar>, request_source: Receiver<TimerRequest>) -> TimerWorker {
        TimerWorker{
            trigger: trigger,
            request_source: request_source,
            schedule: BinaryHeap::new(),
        }
    }

    fn drain_request_queue(&mut self) {
        while let Ok(request) = self.request_source.try_recv() {
            println!("Scheduling a new timeout for {} ms from now", request.duration);
            self.schedule.push(TimerEvent{
                when: SteadyTime::now() + Duration::milliseconds(request.duration as i64),
                period: if request.periodic { Some(request.duration) } else { None },
                completion_sink: request.completion_sink
            });
        }
    }

    fn has_event_now(&self) -> bool {
        if let Some(evt) = self.schedule.peek() {
            evt.when < SteadyTime::now()
        } else {
            false
        }
    }

    fn fire_event(&mut self) {
        println!("Firing an event!");
        if let Some(evt) = self.schedule.pop() {
            match evt.completion_sink.send( () ) {
                Ok( () ) => {
                    println!("Send succeeded!");
                    if let Some(period) = evt.period.clone() {
                        self.schedule.push(TimerEvent{
                            when: evt.when + Duration::milliseconds(period as i64),
                            period: evt.period,
                            completion_sink: evt.completion_sink,
                        });
                    }
                }
                Err(_) => {
                    // The receiver is no longer waiting for us
                }
            }
        }
    }

    fn ms_until_next_event(&self) -> u32 {
        if let Some(evt) = self.schedule.peek() {
            max(0, min((evt.when - SteadyTime::now()).num_milliseconds(), 100000))  as u32
        } else {
            100000
        }
    }

    fn run(&mut self) {
        let m = Mutex::new(false);
        let mut g = m.lock().unwrap(); // The mutex isn't poisoned, since we just made it

        loop {
            self.drain_request_queue();

            // Fire off as many events as we are supposed to.
            loop {
                if self.has_event_now() {
                    self.fire_event();
                } else {
                    break;
                }
            }

            let wait_millis = self.ms_until_next_event();

            println!("Timer is waiting for {}!", wait_millis);
            // unwrap() is safe because the mutex will not be poisoned,
            // since we have not shared it with another thread.
            g = self.trigger.wait_timeout_ms(g, wait_millis).unwrap().0;
            println!("Timer is done waiting");
        }
    }
}

lazy_static! {
    static ref TIMER_INTERFACE  : Mutex<TimerInterface> = {
        let (sender, receiver) = channel();
        let trigger = Arc::new(Condvar::new());
        let trigger2 = trigger.clone();
        thread::spawn(move|| {
            TimerWorker::new(trigger2, receiver).run();
        });

        let interface = TimerInterface {
            trigger: trigger,
            adder: sender
        };

        Mutex::new(interface)
    };
}

fn add_request(duration_ms: u32, periodic: bool) -> Receiver<()> {
    let (sender, receiver) = channel();

    let interface = TIMER_INTERFACE.lock().ok().expect("Failed to acquire the global timer worker");
    interface.adder.send(TimerRequest{
        duration:duration_ms,
        completion_sink:sender,
        periodic: periodic
    }).ok().expect("Failed to send a request to the global timer worker");

    interface.trigger.notify_one();

    receiver
}

pub fn oneshot_ms(ms: u32) -> Receiver<()> {
    add_request(ms, false)
}

pub fn periodic_ms(ms: u32) -> Receiver<()> {
    add_request(ms, true)
}
<|endoftext|>


<commit_before>//! Data consumers
//!
//! The goal of data producers is to parse data depending on the previous result.
//! It can be used to selectively seek in a file.
//!
//! ## Example
//!
//! This consumer will take 4 samples from the input, print them, then stop
//!
//! ```rust
//!  use nom::{IResult,Needed,MemProducer,Consumer,ConsumerState};
//!  use std::str;
//!
//!  struct TestPrintConsumer {
//!    counter: usize
//!  }
//!
//!  impl TestPrintConsumer {
//!    fn new() -> TestPrintConsumer {
//!      TestPrintConsumer { counter: 0 }
//!    }
//!  }
//!
//!  fn take4(i:&[u8]) -> IResult<&[u8], &[u8]>{
//!    if i.len() < 4 {
//!      IResult::Incomplete(Needed::Size(4))
//!    } else {
//!      IResult::Done(&i[4..],&i[0..4])
//!    }
//!  }
//!
//!  // Return ConsumerState::Await if it needs more data, or ConsumerDone when it ends
//!  impl Consumer for TestPrintConsumer {
//!    fn consume(&mut self, input: &[u8]) -> ConsumerState {
//!      match take4(input) {
//!        IResult::Error(a)      => ConsumerState::ConsumerError(0),
//!        IResult::Incomplete(a) => ConsumerState::Await(0, 4),
//!        IResult::Done(i, o)    => {
//!          println!("{} -> {}", self.counter, str::from_utf8(o).unwrap());
//!          self.counter = self.counter + 1;
//!          if self.counter <= 4 {
//!            ConsumerState::Await(4, 4)
//!          } else {
//!            ConsumerState::ConsumerDone
//!          }
//!        }
//!      }
//!    }
//!
//!    fn failed(&mut self, error_code: u32) {
//!      println!("failed with error code {}", error_code);
//!    }
//!
//!    fn end(&mut self) {
//!      println!("finished");
//!    }
//!  }
//!
//!  // It can consume data directly from a producer
//!  let mut p = MemProducer::new(b"abcdefghijklmnopqrstuvwx", 4);
//!  let mut c = TestPrintConsumer::new();
//!  c.run(&mut p);
//! ```

use self::ConsumerState::*;
use producer::Producer;
use producer::ProducerState::*;
use std::io::SeekFrom;

/// Holds the current state of the consumer
///
/// * Await(consumed, needed input data size) if more data is needed
///
/// * Seek(consumed, new position, needed input data size) if the consumer must move back or forth
///
/// * Incomplete if there is not enough data but not enough information for Await or Seek
///
/// * ConsumerDone if the consumer does not need anymore data to be parsed
///
/// * ConsumerError(error code) when something went wrong
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum ConsumerState {
  Await(
    usize,    // consumed
    usize     // needed buffer size
  ),
  Seek(
    usize,    // consumed
    SeekFrom, // new position
    usize     // needed buffer size
  ),
  Incomplete,
  ConsumerDone,
  ConsumerError(u32)
}

/// Implement the consume method, taking a byte array as input and returning a consumer state
///
/// The run function takes care of continuing or not
pub trait Consumer {
  fn consume(&mut self, input: &[u8]) -> ConsumerState;
  fn failed(&mut self, error_code: u32);
  fn end(&mut self);

  fn run(&mut self, producer: &mut Producer) {
    let mut acc: Vec<u8>       = Vec::new();
    let mut position           = 0;
    let mut should_seek        = false;
    let mut consumed:usize     = 0;
    let mut needed:usize       = 0;
    let mut seek_from:SeekFrom = SeekFrom::Current(0);
    let mut eof = false;
    let mut end = false;
    let mut err: Option<u32> = None;

    loop {
      //self.getDataFromProducer(producer, seek_from, needed, acc);
      if !should_seek && acc.len() - consumed >= needed {
        //println!("buffer is large enough, skipping");
        let mut tmp = Vec::new();
        //println!("before:\n{}", acc.to_hex(16));
        //println!("after:\n{}", (&acc[consumed..acc.len()]).to_hex(16));
        tmp.extend(acc[consumed..acc.len()].iter().cloned());
        acc.clear();
        acc = tmp;
      } else {
        if should_seek {
          let _ = producer.seek(seek_from);
          //println!("seeking: {:?}", pos);
          should_seek = false;
          eof = false;
          acc.clear();
        } else {
          let mut tmp = Vec::new();
          tmp.extend(acc[consumed..acc.len()].iter().cloned());
          acc.clear();
          acc = tmp;
        }

        loop {
          let state   = producer.produce();
          match state {
            Data(v) => {
              //println!("got data: {} bytes", v.len());
              acc.extend(v.iter().cloned());
              position = position + v.len();
            },
            Eof(v) => {
              if v.is_empty() {
                //println!("eof empty");
                //eof = true;
                self.end();
                return
              } else {
                //println!("eof with {} bytes", v.len());
                eof = true;
                acc.extend(v.iter().cloned());
                position = position + v.len();
                break;
              }
            }
            ProducerError(_) => {break;}
            Continue => { continue; }
          }
          //println!("acc size: {}", acc.len());
          if acc.len() >= needed { break; }
        }
      }

      //println!("full:\n{}", acc.to_hex(8));
      //println!("truncated:\n{}", (&acc[0..needed]).to_hex(16));
      match self.consume(&acc[0..needed]) {
        ConsumerError(e) => {
          //println!("consumer error, stopping: {}", e);
          err = Some(e);
        },
        ConsumerDone => {
          //println!("data, done");
          end = true;
        },
        Seek(consumed_bytes, sf, needed_bytes) => {
          //println!("Seek: consumed {} bytes, got {:?} and asked {} bytes", consumed_bytes, sf, needed_bytes);
          seek_from = match sf {
            SeekFrom::Current(i) => SeekFrom::Current(i - (acc.len() - needed) as i64),
            a => a
          };
          should_seek = true;
          consumed = consumed_bytes;
          needed   = needed_bytes;
        },
        Await(consumed_bytes, needed_bytes) => {
          //println!("consumed: {} bytes | needed: {} bytes", consumed_bytes, needed_bytes);
          consumed = consumed_bytes;
          needed   = needed_bytes;
        },
        Incomplete => {
          //println!("incomplete");
        }
      }
      if let Some(e) = err {
        self.failed(e);
        break;
      }
      if eof && !should_seek {
        self.end();
        break;
      }
      if end {
        self.end();
        break;
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use super::ConsumerState::*;
  use producer::MemProducer;
  use internal::{Needed,IResult};
  use std::str;
  use std::io::SeekFrom;

#[macro_export]
macro_rules! take(
  ($name:ident $count:expr) => (
    fn $name(i:&[u8]) -> IResult<&[u8], &[u8]>{
      if i.len() < $count {
        IResult::Incomplete(Needed::Size($count))
      } else {
        IResult::Done(&i[$count..],&i[0..$count])
      }
    }
  )
);

  struct TestPrintConsumer {
    counter: usize,
    ended:   bool
  }

  impl TestPrintConsumer {
    fn new() -> TestPrintConsumer {
      TestPrintConsumer { counter: 0, ended: false }
    }
  }

  take!(take4 4);

  impl Consumer for TestPrintConsumer {
    fn consume(&mut self, input: &[u8]) -> ConsumerState {
      match take4(input) {
        IResult::Error(_)      => ConsumerError(0),
        IResult::Incomplete(_) => Await(0, 4),
        IResult::Done(_, o)    => {
          println!("{} -> {}", self.counter, str::from_utf8(o).unwrap());
          self.counter = self.counter + 1;
          if self.counter <= 4 {
            Await(4, 4)
          } else {
            ConsumerDone
          }
        }
      }
    }

    fn end(&mut self) {
      assert_eq!(self.counter, 5);
      self.ended = true;
    }

    fn failed(&mut self, error_code: u32) {
      println!("failed with error code: {}", error_code);
    }
  }

  #[test]
  fn pull() {
    let mut p = MemProducer::new(&b"abcdefghijklmnopqrstuvwx"[..], 4);
    let mut c = TestPrintConsumer::new();
    c.run(&mut p);

    assert!(c.ended);
  }

  #[derive(Debug,PartialEq,Eq,Clone,Copy)]
  enum TestSeekState {
      Start,
      ToEnd,
      ToStart,
      Further
  }

  #[derive(Debug)]
  struct TestSeekConsumer {
      state: TestSeekState,
      result: [u8;3],
      ended: bool
  }

  impl TestSeekConsumer {

      fn new() -> TestSeekConsumer {
          TestSeekConsumer { state: TestSeekState::Start,
                            result: [0x00, 0x00, 0x00],
                             ended: false
           }
      }
      fn result(&self) -> [u8;3] {
          self.result
      }

      fn ended(&self) -> bool {
          self.ended
      }
  }

  impl Consumer for TestSeekConsumer {

    fn consume(&mut self, input: &[u8]) -> ConsumerState {
        let s = self.state;
        match s {
            TestSeekState::Start => {
                self.state = TestSeekState::ToEnd;
                ConsumerState::Seek(0,SeekFrom::End(-1), 1)
            },
            TestSeekState::ToEnd => {
                self.state = TestSeekState::ToStart;
                self.result[0] = input[0];
                ConsumerState::Seek(1,SeekFrom::Start(0), 1)
            },
            TestSeekState::ToStart => {
                self.state = TestSeekState::Further;
                self.result[1] = input[0];
                ConsumerState::Await(1,1)
            }
            TestSeekState::Further => {
                self.result[2] = input[0];
                ConsumerState::ConsumerDone
            }

        }
    }

    fn end(&mut self) {
      assert_eq!(self.state, TestSeekState::Further);
      self.ended = true;
    }

    fn failed(&mut self, error_code: u32) {
      println!("failed with error code: {}", error_code);
    }
  }

  #[test]
  fn seeking() {
    let mut p = MemProducer::new(&b"abc"[..], 1);
    let mut c = TestSeekConsumer::new();
    c.run(&mut p);
    let res = c.result();
    assert_eq!(Ok("cab"),str::from_utf8(&res));
    assert!(c.ended());
  }
}
<commit_msg>always pass the largest possible input to consume<commit_after>//! Data consumers
//!
//! The goal of data producers is to parse data depending on the previous result.
//! It can be used to selectively seek in a file.
//!
//! ## Example
//!
//! This consumer will take 4 samples from the input, print them, then stop
//!
//! ```rust
//!  use nom::{IResult,Needed,MemProducer,Consumer,ConsumerState};
//!  use std::str;
//!
//!  struct TestPrintConsumer {
//!    counter: usize
//!  }
//!
//!  impl TestPrintConsumer {
//!    fn new() -> TestPrintConsumer {
//!      TestPrintConsumer { counter: 0 }
//!    }
//!  }
//!
//!  fn take4(i:&[u8]) -> IResult<&[u8], &[u8]>{
//!    if i.len() < 4 {
//!      IResult::Incomplete(Needed::Size(4))
//!    } else {
//!      IResult::Done(&i[4..],&i[0..4])
//!    }
//!  }
//!
//!  // Return ConsumerState::Await if it needs more data, or ConsumerDone when it ends
//!  impl Consumer for TestPrintConsumer {
//!    fn consume(&mut self, input: &[u8]) -> ConsumerState {
//!      match take4(input) {
//!        IResult::Error(a)      => ConsumerState::ConsumerError(0),
//!        IResult::Incomplete(a) => ConsumerState::Await(0, 4),
//!        IResult::Done(i, o)    => {
//!          println!("{} -> {}", self.counter, str::from_utf8(o).unwrap());
//!          self.counter = self.counter + 1;
//!          if self.counter <= 4 {
//!            ConsumerState::Await(4, 4)
//!          } else {
//!            ConsumerState::ConsumerDone
//!          }
//!        }
//!      }
//!    }
//!
//!    fn failed(&mut self, error_code: u32) {
//!      println!("failed with error code {}", error_code);
//!    }
//!
//!    fn end(&mut self) {
//!      println!("finished");
//!    }
//!  }
//!
//!  // It can consume data directly from a producer
//!  let mut p = MemProducer::new(b"abcdefghijklmnopqrstuvwx", 4);
//!  let mut c = TestPrintConsumer::new();
//!  c.run(&mut p);
//! ```

use self::ConsumerState::*;
use producer::Producer;
use producer::ProducerState::*;
use std::io::SeekFrom;

/// Holds the current state of the consumer
///
/// * Await(consumed, needed input data size) if more data is needed
///
/// * Seek(consumed, new position, needed input data size) if the consumer must move back or forth
///
/// * Incomplete if there is not enough data but not enough information for Await or Seek
///
/// * ConsumerDone if the consumer does not need anymore data to be parsed
///
/// * ConsumerError(error code) when something went wrong
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum ConsumerState {
  Await(
    usize,    // consumed
    usize     // needed buffer size
  ),
  Seek(
    usize,    // consumed
    SeekFrom, // new position
    usize     // needed buffer size
  ),
  Incomplete,
  ConsumerDone,
  ConsumerError(u32)
}

/// Implement the consume method, taking a byte array as input and returning a consumer state
///
/// The run function takes care of continuing or not
pub trait Consumer {
  fn consume(&mut self, input: &[u8]) -> ConsumerState;
  fn failed(&mut self, error_code: u32);
  fn end(&mut self);

  fn run(&mut self, producer: &mut Producer) {
    let mut acc: Vec<u8>       = Vec::new();
    let mut position           = 0;
    let mut should_seek        = false;
    let mut consumed:usize     = 0;
    let mut needed:usize       = 0;
    let mut seek_from:SeekFrom = SeekFrom::Current(0);
    let mut eof = false;
    let mut end = false;
    let mut err: Option<u32> = None;

    loop {
      //self.getDataFromProducer(producer, seek_from, needed, acc);
      if !should_seek && acc.len() - consumed >= needed {
        //println!("buffer is large enough, skipping");
        let mut tmp = Vec::new();
        //println!("before:\n{}", acc.to_hex(16));
        //println!("after:\n{}", (&acc[consumed..acc.len()]).to_hex(16));
        tmp.extend(acc[consumed..acc.len()].iter().cloned());
        acc.clear();
        acc = tmp;
      } else {
        if should_seek {
          let _ = producer.seek(seek_from);
          //println!("seeking: {:?}", pos);
          should_seek = false;
          eof = false;
          acc.clear();
        } else {
          let mut tmp = Vec::new();
          tmp.extend(acc[consumed..acc.len()].iter().cloned());
          acc.clear();
          acc = tmp;
        }

        loop {
          let state   = producer.produce();
          match state {
            Data(v) => {
              //println!("got data: {} bytes", v.len());
              acc.extend(v.iter().cloned());
              position = position + v.len();
            },
            Eof(v) => {
              if v.is_empty() {
                //println!("eof empty");
                //eof = true;
                self.end();
                return
              } else {
                //println!("eof with {} bytes", v.len());
                eof = true;
                acc.extend(v.iter().cloned());
                position = position + v.len();
                break;
              }
            }
            ProducerError(_) => {break;}
            Continue => { continue; }
          }
          //println!("acc size: {}", acc.len());
          if acc.len() >= needed { break; }
        }
      }

      //println!("full:\n{}", acc.to_hex(8));
      //println!("truncated:\n{}", (&acc[0..needed]).to_hex(16));
      match self.consume(&acc[0..]) {
        ConsumerError(e) => {
          //println!("consumer error, stopping: {}", e);
          err = Some(e);
        },
        ConsumerDone => {
          //println!("data, done");
          end = true;
        },
        Seek(consumed_bytes, sf, needed_bytes) => {
          //println!("Seek: consumed {} bytes, got {:?} and asked {} bytes", consumed_bytes, sf, needed_bytes);
          seek_from = match sf {
            SeekFrom::Current(i) => SeekFrom::Current(i - (acc.len() - needed) as i64),
            a => a
          };
          should_seek = true;
          consumed = consumed_bytes;
          needed   = needed_bytes;
        },
        Await(consumed_bytes, needed_bytes) => {
          //println!("consumed: {} bytes | needed: {} bytes", consumed_bytes, needed_bytes);
          consumed = consumed_bytes;
          needed   = needed_bytes;
        },
        Incomplete => {
          //println!("incomplete");
        }
      }
      if let Some(e) = err {
        self.failed(e);
        break;
      }
      if eof && !should_seek {
        self.end();
        break;
      }
      if end {
        self.end();
        break;
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use super::ConsumerState::*;
  use producer::MemProducer;
  use internal::{Needed,IResult};
  use std::str;
  use std::io::SeekFrom;

#[macro_export]
macro_rules! take(
  ($name:ident $count:expr) => (
    fn $name(i:&[u8]) -> IResult<&[u8], &[u8]>{
      if i.len() < $count {
        IResult::Incomplete(Needed::Size($count))
      } else {
        IResult::Done(&i[$count..],&i[0..$count])
      }
    }
  )
);

  struct TestPrintConsumer {
    counter: usize,
    ended:   bool
  }

  impl TestPrintConsumer {
    fn new() -> TestPrintConsumer {
      TestPrintConsumer { counter: 0, ended: false }
    }
  }

  take!(take4 4);

  impl Consumer for TestPrintConsumer {
    fn consume(&mut self, input: &[u8]) -> ConsumerState {
      match take4(input) {
        IResult::Error(_)      => ConsumerError(0),
        IResult::Incomplete(_) => Await(0, 4),
        IResult::Done(_, o)    => {
          println!("{} -> {}", self.counter, str::from_utf8(o).unwrap());
          self.counter = self.counter + 1;
          if self.counter <= 4 {
            Await(4, 4)
          } else {
            ConsumerDone
          }
        }
      }
    }

    fn end(&mut self) {
      assert_eq!(self.counter, 5);
      self.ended = true;
    }

    fn failed(&mut self, error_code: u32) {
      println!("failed with error code: {}", error_code);
    }
  }

  #[test]
  fn pull() {
    let mut p = MemProducer::new(&b"abcdefghijklmnopqrstuvwx"[..], 4);
    let mut c = TestPrintConsumer::new();
    c.run(&mut p);

    assert!(c.ended);
  }

  #[derive(Debug,PartialEq,Eq,Clone,Copy)]
  enum TestSeekState {
      Start,
      ToEnd,
      ToStart,
      Further
  }

  #[derive(Debug)]
  struct TestSeekConsumer {
      state: TestSeekState,
      result: [u8;3],
      ended: bool
  }

  impl TestSeekConsumer {

      fn new() -> TestSeekConsumer {
          TestSeekConsumer { state: TestSeekState::Start,
                            result: [0x00, 0x00, 0x00],
                             ended: false
           }
      }
      fn result(&self) -> [u8;3] {
          self.result
      }

      fn ended(&self) -> bool {
          self.ended
      }
  }

  impl Consumer for TestSeekConsumer {

    fn consume(&mut self, input: &[u8]) -> ConsumerState {
        let s = self.state;
        match s {
            TestSeekState::Start => {
                self.state = TestSeekState::ToEnd;
                ConsumerState::Seek(0,SeekFrom::End(-1), 1)
            },
            TestSeekState::ToEnd => {
                self.state = TestSeekState::ToStart;
                self.result[0] = input[0];
                ConsumerState::Seek(1,SeekFrom::Start(0), 1)
            },
            TestSeekState::ToStart => {
                self.state = TestSeekState::Further;
                self.result[1] = input[0];
                ConsumerState::Await(1,1)
            }
            TestSeekState::Further => {
                self.result[2] = input[0];
                ConsumerState::ConsumerDone
            }

        }
    }

    fn end(&mut self) {
      assert_eq!(self.state, TestSeekState::Further);
      self.ended = true;
    }

    fn failed(&mut self, error_code: u32) {
      println!("failed with error code: {}", error_code);
    }
  }

  #[test]
  fn seeking() {
    let mut p = MemProducer::new(&b"abc"[..], 1);
    let mut c = TestSeekConsumer::new();
    c.run(&mut p);
    let res = c.result();
    assert_eq!(Ok("cab"),str::from_utf8(&res));
    assert!(c.ended());
  }
}
<|endoftext|>


<commit_before>use super::{Actor, ActorCell, ActorRef, Dispatcher};
use super::actor_factory::create_actor;
use futures::prelude::*;
use std::collections::HashMap;
use std::boxed::FnBox;
use std::sync::{Arc, Mutex};
use std::time::Instant;
use uuid::Uuid;

#[derive(Clone)]
pub struct ActorSystem {
    inner: Arc<Mutex<ActorSystemInner>>,
}

struct ActorSystemInner {
    start: Instant,
    counter: u64,
    dispatcher: Dispatcher,
    root_actor: Option<ActorRef>,
}

impl ActorSystem {
    pub fn new() -> Self {
        let mut dispatcher = Dispatcher::new();
        dispatcher.start();
        let inner = ActorSystemInner {
            start: Instant::now(),
            counter: 0,
            dispatcher: dispatcher,
            root_actor: None,
        };
        let system = Self { inner: Arc::new(Mutex::new(inner)) };
        system.inner.lock().unwrap().root_actor =
            Some(create_actor(&system, Uuid::new_v4(), GuardianActor {}));
        system
    }

    pub fn on_startup<F>(&mut self, f: F)
        where F: FnBox() -> Box<Future<Item = (), Error = ()>> + Send + 'static
    {
        println!("Send");
        let root_ref = self.root_actor();
        root_ref.send(GuardianMessage::Execute(Box::new(f)), &root_ref)
    }

    fn root_actor(&self) -> ActorRef {
        self.inner
            .lock()
            .unwrap()
            .root_actor
            .as_ref()
            .unwrap()
            .clone()
    }

    pub fn start(&self) {
        start_deadlock_detector();
        ::std::thread::sleep_ms(1000000);
    }

    pub fn dispatch(&mut self, actor: ActorCell) {
        self.inner
            .lock()
            .expect("Failed to dispatch")
            .dispatch(actor);
    }
}

impl ActorSystemInner {
    fn dispatch(&mut self, actor: ActorCell) {
        self.counter += 1;
        if self.counter % 10000 == 0 {
            println!("Counter: {}", self.counter);
        }
        if self.counter > 1000000 {
            let dt = (Instant::now() - self.start).as_secs();
            if dt > 0 {
                let rate = self.counter / dt;
                println!("Dispatch {} ({}/s)", self.counter, rate);
                ::std::process::exit(0);
            }
        }
        self.dispatcher.dispatch(actor)
    }
}

struct GuardianActor {}

enum GuardianMessage {
    Execute(Box<FnBox() -> Box<Future<Item = (), Error = ()>> + Send>),
}

impl Actor for GuardianActor {
    type Message = GuardianMessage;

    fn handle_message(&mut self, message: Self::Message) -> Box<Future<Item = (), Error = ()>> {
        match message {
            GuardianMessage::Execute(f) => f(),
        }
    }
}

fn start_deadlock_detector() {
    {
        // only for #[cfg]
        use std::thread;
        use std::time::Duration;
        use parking_lot::deadlock;

        // Create a background thread which checks for deadlocks every 10s
        thread::spawn(move || loop {
                          println!("Checking");
                          thread::sleep(Duration::from_secs(10));
                          let deadlocks = deadlock::check_deadlock();
                          if deadlocks.is_empty() {
                              continue;
                          }

                          println!("{} deadlocks detected", deadlocks.len());
                          for (i, threads) in deadlocks.iter().enumerate() {
                              println!("Deadlock #{}", i);
                              for t in threads {
                                  println!("Thread Id {:#?}", t.thread_id());
                                  println!("{:#?}", t.backtrace());
                              }
                          }
                      });
    }
}
<commit_msg>Parking lot mutex<commit_after>use super::{Actor, ActorCell, ActorRef, Dispatcher};
use super::actor_factory::create_actor;
use futures::prelude::*;
use parking_lot::Mutex;
use std::collections::HashMap;
use std::boxed::FnBox;
use std::sync::Arc;
use std::time::Instant;
use uuid::Uuid;

#[derive(Clone)]
pub struct ActorSystem {
    inner: Arc<Mutex<ActorSystemInner>>,
}

struct ActorSystemInner {
    start: Instant,
    counter: u64,
    dispatcher: Dispatcher,
    root_actor: Option<ActorRef>,
}

impl ActorSystem {
    pub fn new() -> Self {
        let mut dispatcher = Dispatcher::new();
        dispatcher.start();
        let inner = ActorSystemInner {
            start: Instant::now(),
            counter: 0,
            dispatcher: dispatcher,
            root_actor: None,
        };
        let system = Self { inner: Arc::new(Mutex::new(inner)) };
        system.inner.lock().root_actor =
            Some(create_actor(&system, Uuid::new_v4(), GuardianActor {}));
        system
    }

    pub fn on_startup<F>(&mut self, f: F)
        where F: FnBox() -> Box<Future<Item = (), Error = ()>> + Send + 'static
    {
        println!("Send");
        let root_ref = self.root_actor();
        root_ref.send(GuardianMessage::Execute(Box::new(f)), &root_ref)
    }

    fn root_actor(&self) -> ActorRef {
        self.inner.lock().root_actor.as_ref().unwrap().clone()
    }

    pub fn start(&self) {
        start_deadlock_detector();
        ::std::thread::sleep_ms(1000000);
    }

    pub fn dispatch(&mut self, actor: ActorCell) {
        self.inner.lock().dispatch(actor);
    }
}

impl ActorSystemInner {
    fn dispatch(&mut self, actor: ActorCell) {
        self.counter += 1;
        if self.counter % 10000 == 0 {
            println!("Counter: {}", self.counter);
        }
        if self.counter > 1000000 {
            let dt = (Instant::now() - self.start).as_secs();
            if dt > 0 {
                let rate = self.counter / dt;
                println!("Dispatch {} ({}/s)", self.counter, rate);
                ::std::process::exit(0);
            }
        }
        self.dispatcher.dispatch(actor)
    }
}

struct GuardianActor {}

enum GuardianMessage {
    Execute(Box<FnBox() -> Box<Future<Item = (), Error = ()>> + Send>),
}

impl Actor for GuardianActor {
    type Message = GuardianMessage;

    fn handle_message(&mut self, message: Self::Message) -> Box<Future<Item = (), Error = ()>> {
        match message {
            GuardianMessage::Execute(f) => f(),
        }
    }
}

fn start_deadlock_detector() {
    {
        // only for #[cfg]
        use std::thread;
        use std::time::Duration;
        use parking_lot::deadlock;

        // Create a background thread which checks for deadlocks every 10s
        thread::spawn(move || loop {
                          println!("Checking");
                          thread::sleep(Duration::from_secs(10));
                          let deadlocks = deadlock::check_deadlock();
                          if deadlocks.is_empty() {
                              continue;
                          }

                          println!("{} deadlocks detected", deadlocks.len());
                          for (i, threads) in deadlocks.iter().enumerate() {
                              println!("Deadlock #{}", i);
                              for t in threads {
                                  println!("Thread Id {:#?}", t.thread_id());
                                  println!("{:#?}", t.backtrace());
                              }
                          }
                      });
    }
}
<|endoftext|>