<commit_before>use std::fmt;
use std::iter::FromIterator;

/// Interfacing with `std::io`.
pub mod io;

mod kleisli;
pub use kleisli::Kleisli;

mod pipe;
pub use pipe::*;

mod fuse;
pub use fuse::*;

enum Void {}

/// Represents a conduit, i.e. a sequence of await/yield actions.
///
/// - `I` is the type of values the conduit consumes from upstream.
/// - `O` is the type of values the conduit passes downstream.
/// - `A` is the return type of the conduit.
pub enum ConduitM<'a, I, O, A> {
    /// The case `Pure(a)` means that the conduit contains no further actions and just returns the result `a`.
    Pure(Box<A>),
    /// The case `Defer(k)` means that the conduit needs another iteration to make progress,
    /// and the remaining (suspended) program is given by the kleisli arrow `k`
    Defer(Kleisli<'a, (), I, O, A>),
    /// The case `Await(k)` means that the conduit waits for a value of type `I`,
    /// and the remaining (suspended) program is given by the kleisli arrow `k`.
    Await(Kleisli<'a, Option<I>, I, O, A>),
    /// The case `Yield(o, k)` means that the conduit yields a value of type `O`,
    /// and the remaining (suspended) program is given by the kleisli arrow `k`.
    Yield(Box<O>, Kleisli<'a, (), I, O, A>)
}

/// Provides a stream of output values,
/// without consuming any input or producing a final result.
pub type Source<'a, O> = ConduitM<'a, (), O, ()>;

impl<'a, O> ConduitM<'a, (), O, ()> {

    /// Generalize a `Source` by universally quantifying the input type.
    pub fn to_producer<I>(self) -> ConduitM<'a, I, O, ()> where O: 'static {
        match self {
            ConduitM::Pure(x) => ConduitM::Pure(x),
            ConduitM::Defer(k) => ConduitM::Defer(Kleisli::new().append(move |_| {
                k.run(()).to_producer()
            })),
            ConduitM::Await(k) => ConduitM::Defer(Kleisli::new().append(move |_| {
                k.run(Some(())).to_producer()
            })),
            ConduitM::Yield(o, k) => ConduitM::Yield(o, Kleisli::new().append(move |_| {
                k.run(()).to_producer()
            }))
        }
    }

    /// Pulls data from the source and pushes it into the sink.
    ///
    /// # Example
    ///
    /// ```rust
    /// use std::iter::FromIterator;
    /// use plumbum::{Source, Sink, produce};
    ///
    /// let src = Source::from_iter(vec![42, 43]);
    /// let sink = Sink::fold(0, |x, y| x + y);
    ///
    /// assert_eq!(src.connect(sink), 85);
    /// ```
    pub fn connect<A>(mut self, mut sink: Sink<'a, O, A>) -> A where O: 'static {
        loop {
            let (next_src, next_sink) = match sink {
                ConduitM::Pure(b_box) => {
                    return *b_box;
                },
                ConduitM::Defer(k_sink) => {
                    (self, k_sink.run(()))
                },
                ConduitM::Await(k_sink) => {
                    match self {
                        ConduitM::Pure(x) => {
                            (ConduitM::Pure(x), k_sink.run(None))
                        },
                        ConduitM::Defer(k_src) => {
                            (k_src.run(()), ConduitM::Await(k_sink))
                        },
                        ConduitM::Await(k_src) => {
                            (k_src.run(Some(())), ConduitM::Await(k_sink))
                        },
                        ConduitM::Yield(a_box, k_src) => {
                            (k_src.run(()), k_sink.run(Some(*a_box)))
                        }
                    }
                },
                ConduitM::Yield(_, _) => unreachable!()
            };
            self = next_src;
            sink = next_sink;
        }
    }

}

/// Consumes a stream of input values and produces a stream of output values,
/// without producing a final result.
pub type Conduit<'a, I, O> = ConduitM<'a, I, O, ()>;

impl<'a, I, O> ConduitM<'a, I, O, ()> {

    /// Combines two conduits together into a new conduit.
    ///
    /// # Example
    ///
    /// ```rust
    /// use std::iter::FromIterator;
    /// use plumbum::{Conduit, Source, Sink};
    ///
    /// let src = Source::from_iter(vec![42, 43]);
    /// let conduit = Conduit::transform(|x| 1 + x);
    /// let sink = Sink::fold(0, |x, y| x + y);
    ///
    /// assert_eq!(src.fuse(conduit).connect(sink), 87);
    /// ```
    pub fn fuse<P, A>(self, other: ConduitM<'a, O, P, A>) -> ConduitM<'a, I, P, A>
        where I: 'static, O: 'static, P: 'static, A: 'a {
        match other {
            ConduitM::Pure(r) => ConduitM::Pure(r),
            ConduitM::Defer(k) => ConduitM::Defer(Kleisli::new().append(move |_| {
                self.fuse(k.run(()))
            })),
            ConduitM::Yield(c, k) => ConduitM::Yield(c, Kleisli::new().append(move |_| {
                self.fuse(k.run(()))
            })),
            ConduitM::Await(k_right) => match self {
                ConduitM::Pure(_) => ConduitM::fuse(().into(), k_right.run(None)),
                ConduitM::Defer(k_left) => ConduitM::Defer(Kleisli::new().append(move |_| {
                    k_left.run(()).fuse(ConduitM::Await(k_right))
                })),
                ConduitM::Yield(b, k_left) => k_left.run(()).fuse(k_right.run(Some(*b))),
                ConduitM::Await(k_left) => ConduitM::Await(Kleisli::new().append(move |a| {
                    k_left.run(a).fuse(ConduitM::Await(k_right))
                }))
            }
        }
    }

    /// Apply a transformation to all values in a stream.
    pub fn transform<F>(f: F) -> Self where F: 'a + Fn(I) -> O {
        consume().and_then(|io| match io {
            None => ().into(),
            Some(o) => produce(f(o)).and_then(move |_| Conduit::transform(f))
        })
    }

}

impl<'a, I, O: 'a> FromIterator<O> for ConduitM<'a, I, O, ()> {
    fn from_iter<T: IntoIterator<Item=O>>(iterator: T) -> Self
        where T::Item: 'a {
        let mut conduit: Self = ().into();
        for x in iterator {
            conduit = conduit.and_then(move |_| produce(x));
        }
        conduit
    }
}

/// Consumes a stream of input values and produces a final result,
/// without producing any output.
pub type Sink<'a, I, A> = ConduitM<'a, I, Void, A>;

impl<'a, I, A> ConduitM<'a, I, Void, A> {

    /// Generalize a `Sink` by universally quantifying the output type.
    pub fn to_consumer<O>(self) -> ConduitM<'a, I, O, A> {
        unsafe { std::mem::transmute(self) }
    }

    fn sink<F>(a: A, f: F) -> Self
        where A: 'a, F: 'a + Fn(A, I) -> Result<A, A> {
        consume().and_then(|io| {
            match io {
                None => a.into(),
                Some(i) => match f(a, i) {
                    Ok(a) => Self::sink(a, f),
                    Err(a) => a.into()
                }
            }
        })
    }

    /// Fold all values from upstream into a final value.
    pub fn fold<F>(a: A, f: F) -> Self
        where A: 'a, F: 'a + Fn(A, I) -> A {
        Self::sink(a, move |a, i| Ok(f(a, i)))
    }

}

impl<'a, I, O, A> ConduitM<'a, I, O, A> {

    fn and_then_boxed<B, F>(self, js: F) -> ConduitM<'a, I, O, B>
        where F: 'a + FnOnce(Box<A>) -> ConduitM<'a, I, O, B> {
        match self {
            ConduitM::Pure(a) => js(a),
            ConduitM::Defer(is) => ConduitM::Defer(kleisli::append_boxed(is, js)),
            ConduitM::Await(is) => ConduitM::Await(kleisli::append_boxed(is, js)),
            ConduitM::Yield(o, is) => ConduitM::Yield(o, kleisli::append_boxed(is, js))
        }
    }

    /// Appends a continuation to a conduit. Which means,
    /// given a function from `A` to `ConduitM<I, O, B>`,
    /// passes the return value of the conduit to the function,
    /// and returns the resulting program.
    pub fn and_then<B, F>(self, js: F) -> ConduitM<'a, I, O, B>
        where F: 'a + FnOnce(A) -> ConduitM<'a, I, O, B> {
        match self {
            ConduitM::Pure(a) => js(*a),
            ConduitM::Defer(is) => ConduitM::Defer(is.append(js)),
            ConduitM::Await(is) => ConduitM::Await(is.append(js)),
            ConduitM::Yield(o, is) => ConduitM::Yield(o, is.append(js))
        }
    }

    /// Modifies the return value of the conduit.
    /// Seen differently, it lifts a function from
    /// `A` to `B` into a function from `ConduitM<I, O, A>`
    /// to `ConduitM<I, O, B>`.
    pub fn map<B, F>(self, f: F) -> ConduitM<'a, I, O, B>
        where F: 'a + FnOnce(A) -> B {
        self.and_then(move |a| f(a).into())
    }

}

impl<'a, I, O, A: PartialEq> PartialEq for ConduitM<'a, I, O, A> {
    fn eq(&self, other: &ConduitM<'a, I, O, A>) -> bool {
        match (self, other) {
            (&ConduitM::Pure(ref a), &ConduitM::Pure(ref b)) => a == b,
            _ => false
        }
    }
}

impl<'a, I, O, A: fmt::Debug> fmt::Debug for ConduitM<'a, I, O, A> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ConduitM::Pure(ref a) => write!(f, "Pure({:?})", a),
            &ConduitM::Defer(_) => write!(f, "Defer(..)"),
            &ConduitM::Await(_) => write!(f, "Await(..)"),
            &ConduitM::Yield(_, _) => write!(f, "Yield(..)")
        }
    }
}

impl<'a, I, O, A> From<A> for ConduitM<'a, I, O, A> {
    fn from(a: A) -> ConduitM<'a, I, O, A> {
        ConduitM::Pure(Box::new(a))
    }
}

/// Wait for a single input value from upstream.
///
/// If no data is available, returns `None`.
/// Once it returns `None`, subsequent calls will also return `None`.
pub fn consume<'a, I, O>() -> ConduitM<'a, I, O, Option<I>> {
    ConduitM::Await(Kleisli::new())
}

/// Send a value downstream to the next component to consume.
///
/// If the downstream component terminates, this call will never return control.
pub fn produce<'a, I, O>(o: O) -> ConduitM<'a, I, O, ()> {
    ConduitM::Yield(Box::new(o), Kleisli::new())
}

/// Defers a conduit action. Can be used to introduce artifical laziness.
pub fn defer<'a, I, O>() -> ConduitM<'a, I, O, ()> {
    ConduitM::Defer(Kleisli::new())
}

/// Provide for a stream of data that can be flushed.
///
/// A number of conduits need the ability to flush the stream at some point.
/// This provides a single wrapper datatype to be used in all such circumstances.
pub enum Flush<O> {
    Chunk(O),
    Flush
}

impl<O> Flush<O> {
    pub fn map<P, F: FnOnce(O) -> P>(self, f: F) -> Flush<P> {
        match self {
            Flush::Chunk(o) => Flush::Chunk(f(o)),
            Flush::Flush => Flush::Flush
        }
    }
}

impl<O> From<O> for Flush<O> {
    fn from(o: O) -> Flush<O> {
        Flush::Chunk(o)
    }
}
<commit_msg>simplify from_iter constraints<commit_after>use std::fmt;
use std::iter::FromIterator;

/// Interfacing with `std::io`.
pub mod io;

mod kleisli;
pub use kleisli::Kleisli;

mod pipe;
pub use pipe::*;

mod fuse;
pub use fuse::*;

enum Void {}

/// Represents a conduit, i.e. a sequence of await/yield actions.
///
/// - `I` is the type of values the conduit consumes from upstream.
/// - `O` is the type of values the conduit passes downstream.
/// - `A` is the return type of the conduit.
pub enum ConduitM<'a, I, O, A> {
    /// The case `Pure(a)` means that the conduit contains no further actions and just returns the result `a`.
    Pure(Box<A>),
    /// The case `Defer(k)` means that the conduit needs another iteration to make progress,
    /// and the remaining (suspended) program is given by the kleisli arrow `k`
    Defer(Kleisli<'a, (), I, O, A>),
    /// The case `Await(k)` means that the conduit waits for a value of type `I`,
    /// and the remaining (suspended) program is given by the kleisli arrow `k`.
    Await(Kleisli<'a, Option<I>, I, O, A>),
    /// The case `Yield(o, k)` means that the conduit yields a value of type `O`,
    /// and the remaining (suspended) program is given by the kleisli arrow `k`.
    Yield(Box<O>, Kleisli<'a, (), I, O, A>)
}

/// Provides a stream of output values,
/// without consuming any input or producing a final result.
pub type Source<'a, O> = ConduitM<'a, (), O, ()>;

impl<'a, O> ConduitM<'a, (), O, ()> {

    /// Generalize a `Source` by universally quantifying the input type.
    pub fn to_producer<I>(self) -> ConduitM<'a, I, O, ()> where O: 'static {
        match self {
            ConduitM::Pure(x) => ConduitM::Pure(x),
            ConduitM::Defer(k) => ConduitM::Defer(Kleisli::new().append(move |_| {
                k.run(()).to_producer()
            })),
            ConduitM::Await(k) => ConduitM::Defer(Kleisli::new().append(move |_| {
                k.run(Some(())).to_producer()
            })),
            ConduitM::Yield(o, k) => ConduitM::Yield(o, Kleisli::new().append(move |_| {
                k.run(()).to_producer()
            }))
        }
    }

    /// Pulls data from the source and pushes it into the sink.
    ///
    /// # Example
    ///
    /// ```rust
    /// use std::iter::FromIterator;
    /// use plumbum::{Source, Sink, produce};
    ///
    /// let src = Source::from_iter(vec![42, 43]);
    /// let sink = Sink::fold(0, |x, y| x + y);
    ///
    /// assert_eq!(src.connect(sink), 85);
    /// ```
    pub fn connect<A>(mut self, mut sink: Sink<'a, O, A>) -> A where O: 'static {
        loop {
            let (next_src, next_sink) = match sink {
                ConduitM::Pure(b_box) => {
                    return *b_box;
                },
                ConduitM::Defer(k_sink) => {
                    (self, k_sink.run(()))
                },
                ConduitM::Await(k_sink) => {
                    match self {
                        ConduitM::Pure(x) => {
                            (ConduitM::Pure(x), k_sink.run(None))
                        },
                        ConduitM::Defer(k_src) => {
                            (k_src.run(()), ConduitM::Await(k_sink))
                        },
                        ConduitM::Await(k_src) => {
                            (k_src.run(Some(())), ConduitM::Await(k_sink))
                        },
                        ConduitM::Yield(a_box, k_src) => {
                            (k_src.run(()), k_sink.run(Some(*a_box)))
                        }
                    }
                },
                ConduitM::Yield(_, _) => unreachable!()
            };
            self = next_src;
            sink = next_sink;
        }
    }

}

/// Consumes a stream of input values and produces a stream of output values,
/// without producing a final result.
pub type Conduit<'a, I, O> = ConduitM<'a, I, O, ()>;

impl<'a, I, O> ConduitM<'a, I, O, ()> {

    /// Combines two conduits together into a new conduit.
    ///
    /// # Example
    ///
    /// ```rust
    /// use std::iter::FromIterator;
    /// use plumbum::{Conduit, Source, Sink};
    ///
    /// let src = Source::from_iter(vec![42, 43]);
    /// let conduit = Conduit::transform(|x| 1 + x);
    /// let sink = Sink::fold(0, |x, y| x + y);
    ///
    /// assert_eq!(src.fuse(conduit).connect(sink), 87);
    /// ```
    pub fn fuse<P, A>(self, other: ConduitM<'a, O, P, A>) -> ConduitM<'a, I, P, A>
        where I: 'static, O: 'static, P: 'static, A: 'a {
        match other {
            ConduitM::Pure(r) => ConduitM::Pure(r),
            ConduitM::Defer(k) => ConduitM::Defer(Kleisli::new().append(move |_| {
                self.fuse(k.run(()))
            })),
            ConduitM::Yield(c, k) => ConduitM::Yield(c, Kleisli::new().append(move |_| {
                self.fuse(k.run(()))
            })),
            ConduitM::Await(k_right) => match self {
                ConduitM::Pure(_) => ConduitM::fuse(().into(), k_right.run(None)),
                ConduitM::Defer(k_left) => ConduitM::Defer(Kleisli::new().append(move |_| {
                    k_left.run(()).fuse(ConduitM::Await(k_right))
                })),
                ConduitM::Yield(b, k_left) => k_left.run(()).fuse(k_right.run(Some(*b))),
                ConduitM::Await(k_left) => ConduitM::Await(Kleisli::new().append(move |a| {
                    k_left.run(a).fuse(ConduitM::Await(k_right))
                }))
            }
        }
    }

    /// Apply a transformation to all values in a stream.
    pub fn transform<F>(f: F) -> Self where F: 'a + Fn(I) -> O {
        consume().and_then(|io| match io {
            None => ().into(),
            Some(o) => produce(f(o)).and_then(move |_| Conduit::transform(f))
        })
    }

}

impl<'a, I, O: 'a> FromIterator<O> for ConduitM<'a, I, O, ()> {
    fn from_iter<T: IntoIterator<Item=O>>(iterator: T) -> Self {
        let mut conduit: Self = ().into();
        for x in iterator {
            conduit = conduit.and_then(move |_| produce(x));
        }
        conduit
    }
}

/// Consumes a stream of input values and produces a final result,
/// without producing any output.
pub type Sink<'a, I, A> = ConduitM<'a, I, Void, A>;

impl<'a, I, A> ConduitM<'a, I, Void, A> {

    /// Generalize a `Sink` by universally quantifying the output type.
    pub fn to_consumer<O>(self) -> ConduitM<'a, I, O, A> {
        unsafe { std::mem::transmute(self) }
    }

    fn sink<F>(a: A, f: F) -> Self
        where A: 'a, F: 'a + Fn(A, I) -> Result<A, A> {
        consume().and_then(|io| {
            match io {
                None => a.into(),
                Some(i) => match f(a, i) {
                    Ok(a) => Self::sink(a, f),
                    Err(a) => a.into()
                }
            }
        })
    }

    /// Fold all values from upstream into a final value.
    pub fn fold<F>(a: A, f: F) -> Self
        where A: 'a, F: 'a + Fn(A, I) -> A {
        Self::sink(a, move |a, i| Ok(f(a, i)))
    }

}

impl<'a, I, O, A> ConduitM<'a, I, O, A> {

    fn and_then_boxed<B, F>(self, js: F) -> ConduitM<'a, I, O, B>
        where F: 'a + FnOnce(Box<A>) -> ConduitM<'a, I, O, B> {
        match self {
            ConduitM::Pure(a) => js(a),
            ConduitM::Defer(is) => ConduitM::Defer(kleisli::append_boxed(is, js)),
            ConduitM::Await(is) => ConduitM::Await(kleisli::append_boxed(is, js)),
            ConduitM::Yield(o, is) => ConduitM::Yield(o, kleisli::append_boxed(is, js))
        }
    }

    /// Appends a continuation to a conduit. Which means,
    /// given a function from `A` to `ConduitM<I, O, B>`,
    /// passes the return value of the conduit to the function,
    /// and returns the resulting program.
    pub fn and_then<B, F>(self, js: F) -> ConduitM<'a, I, O, B>
        where F: 'a + FnOnce(A) -> ConduitM<'a, I, O, B> {
        match self {
            ConduitM::Pure(a) => js(*a),
            ConduitM::Defer(is) => ConduitM::Defer(is.append(js)),
            ConduitM::Await(is) => ConduitM::Await(is.append(js)),
            ConduitM::Yield(o, is) => ConduitM::Yield(o, is.append(js))
        }
    }

    /// Modifies the return value of the conduit.
    /// Seen differently, it lifts a function from
    /// `A` to `B` into a function from `ConduitM<I, O, A>`
    /// to `ConduitM<I, O, B>`.
    pub fn map<B, F>(self, f: F) -> ConduitM<'a, I, O, B>
        where F: 'a + FnOnce(A) -> B {
        self.and_then(move |a| f(a).into())
    }

}

impl<'a, I, O, A: PartialEq> PartialEq for ConduitM<'a, I, O, A> {
    fn eq(&self, other: &ConduitM<'a, I, O, A>) -> bool {
        match (self, other) {
            (&ConduitM::Pure(ref a), &ConduitM::Pure(ref b)) => a == b,
            _ => false
        }
    }
}

impl<'a, I, O, A: fmt::Debug> fmt::Debug for ConduitM<'a, I, O, A> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ConduitM::Pure(ref a) => write!(f, "Pure({:?})", a),
            &ConduitM::Defer(_) => write!(f, "Defer(..)"),
            &ConduitM::Await(_) => write!(f, "Await(..)"),
            &ConduitM::Yield(_, _) => write!(f, "Yield(..)")
        }
    }
}

impl<'a, I, O, A> From<A> for ConduitM<'a, I, O, A> {
    fn from(a: A) -> ConduitM<'a, I, O, A> {
        ConduitM::Pure(Box::new(a))
    }
}

/// Wait for a single input value from upstream.
///
/// If no data is available, returns `None`.
/// Once it returns `None`, subsequent calls will also return `None`.
pub fn consume<'a, I, O>() -> ConduitM<'a, I, O, Option<I>> {
    ConduitM::Await(Kleisli::new())
}

/// Send a value downstream to the next component to consume.
///
/// If the downstream component terminates, this call will never return control.
pub fn produce<'a, I, O>(o: O) -> ConduitM<'a, I, O, ()> {
    ConduitM::Yield(Box::new(o), Kleisli::new())
}

/// Defers a conduit action. Can be used to introduce artifical laziness.
pub fn defer<'a, I, O>() -> ConduitM<'a, I, O, ()> {
    ConduitM::Defer(Kleisli::new())
}

/// Provide for a stream of data that can be flushed.
///
/// A number of conduits need the ability to flush the stream at some point.
/// This provides a single wrapper datatype to be used in all such circumstances.
pub enum Flush<O> {
    Chunk(O),
    Flush
}

impl<O> Flush<O> {
    pub fn map<P, F: FnOnce(O) -> P>(self, f: F) -> Flush<P> {
        match self {
            Flush::Chunk(o) => Flush::Chunk(f(o)),
            Flush::Flush => Flush::Flush
        }
    }
}

impl<O> From<O> for Flush<O> {
    fn from(o: O) -> Flush<O> {
        Flush::Chunk(o)
    }
}
<|endoftext|>


<commit_before>
use std::default::Default;
use std::hash::{Hash};
use std::collections::HashMap;
use std::iter::Map;
use std::collections::hash_map::{
    Keys,
    Occupied,
    Vacant,
};
use std::slice::{
    Items,
    MutItems,
};
use std::fmt;

/// **DiGraph** is a directed graph, with node values and edge weights.
///
/// It uses an adjacency list representation, i.e. using *O(|N| + |E|)* space.
pub struct DiGraph<N: Eq + Hash, E> {
    nodes: HashMap<N, Vec<(N, E)>>,
}

impl<N: Eq + Hash + fmt::Show, E: fmt::Show> fmt::Show for DiGraph<N, E>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.nodes.fmt(f)
    }
}

impl<N: Copy + Eq + Hash, E> DiGraph<N, E>
{
    pub fn new() -> DiGraph<N, E>
    {
        DiGraph {
            nodes: HashMap::new(),
        }
    }

    pub fn add_node(&mut self, node: N) -> N {
        self.nodes.insert(node, Vec::new());
        node
    }

    /// Return true if node was removed.
    pub fn remove_node(&mut self, node: N) -> bool {
        match self.nodes.remove(&node) {
            None => false,
            Some(..) => {
                for (_, edges) in self.nodes.iter_mut() {
                    match edges.iter().position(|&(elt, _)| elt == node) {
                        // Use swap_remove because order doesn't matter
                        Some(index) => { edges.swap_remove(index); }
                        None => {}
                    }
                }
                true
            }
        }
    }

    pub fn contains_node(&self, node: N) -> bool {
        self.nodes.contains_key(&node)
    }

    /// Add directed edge from `a` to `b`.
    ///
    /// Return `true` if an edge was inserted.
    pub fn add_edge(&mut self, a: N, b: N, edge: E) -> bool
    {
        // We need both lookups anyway to assert sanity, so
        // add nodes if they don't already exist
        //
        // make sure the endpoint exists in the map
        match self.nodes.entry(b) {
            Vacant(ent) => { ent.set(Vec::new()); }
            _ => {}
        }

        match self.nodes.entry(a) {
            Occupied(ent) => {
                // Add edge only if it isn't already there
                let edges = ent.into_mut();
                if edges.iter().position(|&(elt, _)| elt == b).is_none() {
                    edges.push((b, edge));
                    true
                } else {
                    false
                }
            }
            Vacant(ent) => {
                ent.set(vec![(b, edge)]);
                true
            }
        }
    }

    /// Remove edge from `a` to `b`.
    ///
    /// Return None if the edge didn't exist.
    pub fn remove_edge(&mut self, a: N, b: N) -> Option<E>
    {
        match self.nodes.entry(a) {
            Occupied(mut ent) => {
                match ent.get().iter().position(|&(elt, _)| elt == b) {
                    Some(index) => {
                        ent.get_mut().swap_remove(index).map(|(_, edge)| edge)
                    }
                    None => None,
                }
            }
            Vacant(..) => None,
        }
    }

    /// Return true if the directed edge from `a` to `b` exists
    pub fn contains_edge(&mut self, a: N, b: N) -> bool
    {
        match self.nodes.get(&a) {
            None => false,
            Some(sus) => sus.iter().any(|&(elt, _)| elt == b),
        }
    }

    pub fn nodes<'a>(&'a self) -> Nodes<'a, N, E>
    {
        Nodes{iter: self.nodes.keys()}
    }

    /// If the node **n** does not exist in the graph, return an empty iterator.
    pub fn edges<'a>(&'a self, n: N) -> Items<'a, (N, E)>
    {
        match self.nodes.get(&n) {
            Some(edges) => edges.iter(),
            None => [].iter(),
        }
    }

    /// If the node **n** does not exist in the graph, return an empty iterator.
    pub fn edges_mut<'a>(&'a mut self, n: N) -> MutItems<'a, (N, E)>
    {
        match self.nodes.get_mut(&n) {
            Some(edges) => edges.iter_mut(),
            None => [].iter_mut(),
        }
    }

    pub fn edge_mut<'a>(&'a mut self, a: N, b: N) -> Option<&'a mut E>
    {
        match self.nodes.get_mut(&a) {
            Some(succ) => {
                succ.iter_mut()
                    .find(|&&(ref n, _)| n == &b)
                    .map(|&(_, ref mut edge)| edge)
            }
            None => None,
        }
    }

}

impl<N: Copy + Eq + Hash, E: Clone> DiGraph<N, E>
{
    /// Add edge from `a` to `b`.
    pub fn add_diedge(&mut self, a: N, b: N, edge: E) -> bool
    {
        self.add_edge(a, b, edge.clone()) |
        self.add_edge(b, a, edge)
    }

    /// Return a reverse graph.
    pub fn reversed(&self) -> DiGraph<N, E>
    {
        let mut g = DiGraph::new();
        for &node in self.nodes() {
            for &(other, ref edge) in self.edges(node) {
                g.add_edge(other, node, edge.clone());
            }
        }
        g
    }
}

macro_rules! iterator_methods(
    ($elt_type:ty) => (
        #[inline]
        fn next(&mut self) -> Option<$elt_type>
        {
            self.iter.next()
        }

        #[inline]
        fn size_hint(&self) -> (uint, Option<uint>)
        {
            self.iter.size_hint()
        }
    )
)

pub struct Nodes<'a, N: 'a, E: 'a> {
    iter: Keys<'a, N, Vec<(N, E)>>
}

impl<'a, N: 'a, E: 'a> Iterator<&'a N> for Nodes<'a, N, E>
{
    iterator_methods!(&'a N)
}

<commit_msg>Add .neighbors() iter to digraph<commit_after>
use std::hash::{Hash};
use std::collections::HashMap;
use std::iter::Map;
use std::collections::hash_map::{
    Keys,
    Occupied,
    Vacant,
};
use std::slice::{
    Items,
    MutItems,
};
use std::fmt;

/// **DiGraph** is a directed graph, with node values and edge weights.
///
/// It uses an adjacency list representation, i.e. using *O(|N| + |E|)* space.
pub struct DiGraph<N: Eq + Hash, E> {
    nodes: HashMap<N, Vec<(N, E)>>,
}

impl<N: Eq + Hash + fmt::Show, E: fmt::Show> fmt::Show for DiGraph<N, E>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.nodes.fmt(f)
    }
}

impl<N: Copy + Eq + Hash, E> DiGraph<N, E>
{
    pub fn new() -> DiGraph<N, E>
    {
        DiGraph {
            nodes: HashMap::new(),
        }
    }

    pub fn add_node(&mut self, node: N) -> N {
        self.nodes.insert(node, Vec::new());
        node
    }

    /// Return true if node was removed.
    pub fn remove_node(&mut self, node: N) -> bool {
        match self.nodes.remove(&node) {
            None => false,
            Some(..) => {
                for (_, edges) in self.nodes.iter_mut() {
                    match edges.iter().position(|&(elt, _)| elt == node) {
                        // Use swap_remove because order doesn't matter
                        Some(index) => { edges.swap_remove(index); }
                        None => {}
                    }
                }
                true
            }
        }
    }

    pub fn contains_node(&self, node: N) -> bool {
        self.nodes.contains_key(&node)
    }

    /// Add directed edge from `a` to `b`.
    ///
    /// Return `true` if an edge was inserted.
    pub fn add_edge(&mut self, a: N, b: N, edge: E) -> bool
    {
        // We need both lookups anyway to assert sanity, so
        // add nodes if they don't already exist
        //
        // make sure the endpoint exists in the map
        match self.nodes.entry(b) {
            Vacant(ent) => { ent.set(Vec::new()); }
            _ => {}
        }

        match self.nodes.entry(a) {
            Occupied(ent) => {
                // Add edge only if it isn't already there
                let edges = ent.into_mut();
                if edges.iter().position(|&(elt, _)| elt == b).is_none() {
                    edges.push((b, edge));
                    true
                } else {
                    false
                }
            }
            Vacant(ent) => {
                ent.set(vec![(b, edge)]);
                true
            }
        }
    }

    /// Remove edge from `a` to `b`.
    ///
    /// Return None if the edge didn't exist.
    pub fn remove_edge(&mut self, a: N, b: N) -> Option<E>
    {
        match self.nodes.entry(a) {
            Occupied(mut ent) => {
                match ent.get().iter().position(|&(elt, _)| elt == b) {
                    Some(index) => {
                        ent.get_mut().swap_remove(index).map(|(_, edge)| edge)
                    }
                    None => None,
                }
            }
            Vacant(..) => None,
        }
    }

    /// Return true if the directed edge from `a` to `b` exists
    pub fn contains_edge(&mut self, a: N, b: N) -> bool
    {
        match self.nodes.get(&a) {
            None => false,
            Some(sus) => sus.iter().any(|&(elt, _)| elt == b),
        }
    }

    pub fn nodes<'a>(&'a self) -> Nodes<'a, N, E>
    {
        Nodes{iter: self.nodes.keys()}
    }

    pub fn neighbors(&self, n: N) -> Neighbors<N, E>
    {
        fn fst<'a, N: Copy, E>(t: &'a (N, E)) -> &'a N
        {
            &t.0
        }

        Neighbors{iter: self.edges(n).map(fst)}
    }

    /// If the node **n** does not exist in the graph, return an empty iterator.
    pub fn edges<'a>(&'a self, n: N) -> Items<'a, (N, E)>
    {
        match self.nodes.get(&n) {
            Some(edges) => edges.iter(),
            None => [].iter(),
        }
    }

    /// If the node **n** does not exist in the graph, return an empty iterator.
    pub fn edges_mut<'a>(&'a mut self, n: N) -> MutItems<'a, (N, E)>
    {
        match self.nodes.get_mut(&n) {
            Some(edges) => edges.iter_mut(),
            None => [].iter_mut(),
        }
    }

    pub fn edge_mut<'a>(&'a mut self, a: N, b: N) -> Option<&'a mut E>
    {
        match self.nodes.get_mut(&a) {
            Some(succ) => {
                succ.iter_mut()
                    .find(|&&(ref n, _)| n == &b)
                    .map(|&(_, ref mut edge)| edge)
            }
            None => None,
        }
    }

}

impl<N: Copy + Eq + Hash, E: Clone> DiGraph<N, E>
{
    /// Add edge from `a` to `b`.
    pub fn add_diedge(&mut self, a: N, b: N, edge: E) -> bool
    {
        self.add_edge(a, b, edge.clone()) |
        self.add_edge(b, a, edge)
    }

    /// Return a reverse graph.
    pub fn reversed(&self) -> DiGraph<N, E>
    {
        let mut g = DiGraph::new();
        for &node in self.nodes() {
            for &(other, ref edge) in self.edges(node) {
                g.add_edge(other, node, edge.clone());
            }
        }
        g
    }
}

macro_rules! iterator_methods(
    ($elt_type:ty) => (
        #[inline]
        fn next(&mut self) -> Option<$elt_type>
        {
            self.iter.next()
        }

        #[inline]
        fn size_hint(&self) -> (uint, Option<uint>)
        {
            self.iter.size_hint()
        }
    )
)

pub struct Nodes<'a, N: 'a, E: 'a> {
    iter: Keys<'a, N, Vec<(N, E)>>
}

impl<'a, N: 'a, E: 'a> Iterator<&'a N> for Nodes<'a, N, E>
{
    iterator_methods!(&'a N)
}

type MapPtr<'a, From, To, Iter> = Map<&'a From, &'a To, Iter, for<'b> fn(&'b From) -> &'b To>;

pub struct Neighbors<'a, N: 'a, E: 'a> {
    iter: MapPtr<'a, (N, E), N, Items<'a, (N, E)>>,
}

impl<'a, N: 'a, E: 'a> Iterator<&'a N> for Neighbors<'a, N, E>
{
    iterator_methods!(&'a N)
}

<|endoftext|>


<commit_before>//! Manipulations and data types that represent polynomial

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

#![feature(macro_rules)]

extern crate num;

use std::{cmp, fmt};
use std::iter::{AdditiveIterator, MultiplicativeIterator};
use num::{Zero, One};

/// Polynomial expression
#[deriving(Eq, PartialEq, Clone, Show)]
pub struct Polynomial<T> { data: Vec<T> }

impl<T: Zero> Polynomial<T> {
    /// Creates new `Polynomial`.
    ///
    /// ```rust
    /// use polynomial::Polynomial;
    /// let poly = Polynomial::new(vec![1i, 2, 3]);
    /// assert_eq!("1+2*x+3*x^2", poly.pretty("x"));
    /// ```
    #[inline]
    pub fn new(mut data: Vec<T>) -> Polynomial<T> {
        while let Some(true) = data.last().map(|x| x.is_zero()) {
            let _ = data.pop();
        }
        Polynomial { data: data }
    }
}

impl<T: Zero + One + Clone> Polynomial<T> {
    /// Evaluates the polynomial value.
    ///
    /// ```rust
    /// use polynomial::Polynomial;
    /// let poly = Polynomial::new(vec![1i, 2, 3]);
    /// assert_eq!(1, poly.eval(0));
    /// assert_eq!(6, poly.eval(1));
    /// assert_eq!(17, poly.eval(2));
    /// ```
    #[inline]
    pub fn eval(&self, x: T) -> T {
        let mut sum: T = Zero::zero();
        let mut x_n: T = One::one();
        for n in self.data.iter() {
            sum = sum + n.clone() * x_n.clone();
            x_n = x_n * x.clone();
        }
        sum
    }
}

impl<T> Polynomial<T> {
    /// Gets the slice of internal data.
    #[inline]
    pub fn data(&self) -> &[T] { self.data.as_slice() }
}

impl<T: Zero + One + Eq + Neg<T> + Ord + fmt::Show + Clone> Polynomial<T> {
    /// Pretty prints the polynomial.
    pub fn pretty(&self, x: &str) -> String {
        if self.is_zero() { return "0".to_string() }

        let one = One::one();
        let mut s = Vec::new();
        for (i, n) in self.data.iter().enumerate() {
            // output n*x^i / -n*x^i
            if n.is_zero() { continue }

            let term = if i.is_zero() {
                n.to_string()
            } else if i == 1 {
                if (*n) == one { x.to_string() }
                else if (*n) == -one.clone() { format!("-{}", x) }
                else { format!("{}*{}", n.to_string(), x) }
            } else {
                if (*n) == one { format!("{}^{}", x, i) }
                else if (*n) == -one.clone() { format!("-{}^{}", x, i) }
                else { format!("{}*{}^{}", n.to_string(), x, i) }
            };

            if s.len() > 0 && (*n) > Zero::zero() { s.push("+".to_string()); }
            s.push(term);
        }

        s.concat()
    }
}

impl<'a, T: Neg<T> + Zero + Clone> Neg<Polynomial<T>> for Polynomial<T> {
    #[inline]
    fn neg(self) -> Polynomial<T> { -&self }
}

impl<'a, T: Neg<T> + Zero + Clone> Neg<Polynomial<T>> for &'a Polynomial<T> {
    #[inline]
    fn neg(self) -> Polynomial<T> {
        Polynomial::new(self.data.iter().map(|x| -x.clone()).collect())
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs, Result> $imp<Polynomial<Rhs>, Polynomial<Result>> for Polynomial<Lhs>
            where Lhs: Zero + $imp<Rhs, Result> + Clone, Rhs: Zero + Clone, Result: Zero
        {
            #[inline]
            fn $method(self, other: Polynomial<Rhs>) -> Polynomial<Result> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs, Result> $imp<Polynomial<Rhs>, Polynomial<Result>> for &'a Polynomial<Lhs>
            where Lhs: Zero + $imp<Rhs, Result> + Clone, Rhs: Zero + Clone, Result: Zero
        {
            #[inline]
            fn $method(self, other: Polynomial<Rhs>) -> Polynomial<Result> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs, Result> $imp<&'a Polynomial<Rhs>, Polynomial<Result>> for Polynomial<Lhs>
            where Lhs: Zero + $imp<Rhs, Result> + Clone, Rhs: Zero + Clone, Result: Zero
        {
            #[inline]
            fn $method(self, other: &Polynomial<Rhs>) -> Polynomial<Result> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs, Result> Add<&'b Polynomial<Rhs>, Polynomial<Result>> for &'a Polynomial<Lhs>
    where Lhs: Zero + Add<Rhs, Result> + Clone, Rhs: Zero + Clone, Result: Zero
{
    fn add(self, other: &Polynomial<Rhs>) -> Polynomial<Result> {
        let max_len = cmp::max(self.data.len(), other.data.len());
        let min_len = cmp::min(self.data.len(), other.data.len());

        let mut sum = Vec::with_capacity(max_len);
        for i in range(0, min_len) {
            sum.push(self.data[i].clone() + other.data[i].clone());
        }

        if self.data.len() <= other.data.len() {
            for i in range(min_len, max_len) {
                sum.push(num::zero::<Lhs>() + other.data[i].clone());
            }
        } else {
            for i in range(min_len, max_len) {
                sum.push(self.data[i].clone() + num::zero::<Rhs>());
            }
        }

        Polynomial::new(sum)
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs, Result> Sub<&'b Polynomial<Rhs>, Polynomial<Result>> for &'a Polynomial<Lhs>
    where Lhs: Zero + Sub<Rhs, Result> + Clone, Rhs: Zero + Clone, Result: Zero
{
    fn sub(self, other: &Polynomial<Rhs>) -> Polynomial<Result> {
        let min_len = cmp::min(self.data.len(), other.data.len());
        let max_len = cmp::max(self.data.len(), other.data.len());

        let mut sub = Vec::with_capacity(max_len);
        for i in range(0, min_len) {
            sub.push(self.data[i].clone() - other.data[i].clone());
        }
        if self.data.len() <= other.data.len() {
            for i in range(min_len, max_len) {
                sub.push(num::zero::<Lhs>() - other.data[i].clone())
            }
        } else {
            for i in range(min_len, max_len) {
                sub.push(self.data[i].clone() - num::zero::<Rhs>())
            }
        }
        Polynomial::new(sub)
    }
}

forward_all_binop!(impl Mul, mul);

impl<'a, 'b, Lhs, Rhs, Result> Mul<&'b Polynomial<Rhs>, Polynomial<Result>> for &'a Polynomial<Lhs>
    where Lhs: Zero + Mul<Rhs, Result> + Clone, Rhs: Zero + Clone, Result: Zero
{
    fn mul(self, other: &Polynomial<Rhs>) -> Polynomial<Result> {
        if self.is_zero() || other.is_zero() { return Polynomial::new(vec![]) }

        let slen = self.data.len();
        let olen = other.data.len();
        let prod = Vec::from_fn(slen + olen - 1, |i| {
            let mut p = num::zero::<Result>();
            for k in range(0, slen) {
                if i - k >= olen { continue; }
                p = p + self.data[k].clone() * other.data[i - k].clone();
            }
            p
        });
        Polynomial::new(prod)
    }
}

impl<T: Zero + Clone> Zero for Polynomial<T> {
    #[inline]
    fn zero() -> Polynomial<T> { Polynomial { data: vec![] } }
    #[inline]
    fn is_zero(&self) -> bool { self.data.is_empty() }
}

impl<T: Zero + One + Clone> One for Polynomial<T> {
    #[inline]
    fn one() -> Polynomial<T> { Polynomial { data: vec![One::one()] } }
}

impl<A: Zero + Add<A, A> + Clone, T: Iterator<Polynomial<A>>> AdditiveIterator<Polynomial<A>> for T {
    #[inline]
    fn sum(self) -> Polynomial<A> {
        let init: Polynomial<A> = Zero::zero();
        self.fold(init, |acc, x| acc + x)
    }
}

impl<A: Zero + One + Mul<A, A> + Clone, T: Iterator<Polynomial<A>>> MultiplicativeIterator<Polynomial<A>> for T {
    #[inline]
    fn product(self) -> Polynomial<A> {
        let init: Polynomial<A> = One::one();
        self.fold(init, |acc, x| acc * x)
    }
}

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

    #[test]
    fn new() {
        fn check(dst: Vec<int>, src: Vec<int>) {
            assert_eq!(dst, Polynomial::new(src).data);
        }
        check(vec![1, 2, 3], vec![1, 2, 3]);
        check(vec![1, 2, 3], vec![1, 2, 3, 0, 0]);
        check(vec![], vec![0, 0, 0]);
    }

    #[test]
    fn neg_add_sub() {
        fn check(a: &[int], b: &[int], c: &[int]) {
            fn check_eq(a: &Polynomial<int>, b: &Polynomial<int>) {
                assert_eq!(*a, *b);
                assert_eq!(-a, -b);
            }
            fn check_add(sum: &Polynomial<int>, a: &Polynomial<int>, b: &Polynomial<int>) {
                check_eq(sum, &(a + b));
                check_eq(sum, &(b + a));
            }
            fn check_sub(sum: &Polynomial<int>, a: &Polynomial<int>, b: &Polynomial<int>) {
                check_eq(a, &(sum - b));
                check_eq(b, &(sum - a));
            }

            let a = &Polynomial::new(a.to_vec());
            let b = &Polynomial::new(b.to_vec());
            let c = &Polynomial::new(c.to_vec());
            check_add(c, a, b);
            check_add(&(-c), &(-a), &(-b));
            check_sub(c, a, b);
            check_sub(&(-c), &(-a), &(-b));
        }
        check(&[], &[], &[]);
        check(&[], &[1], &[1]);
        check(&[1], &[1], &[2]);
        check(&[1, 0, 1], &[1], &[2, 0, 1]);
        check(&[1, 0, -1], &[-1, 0, 1], &[]);
    }

    #[test]
    fn mul() {
        fn check(a: &[int], b: &[int], c: &[int]) {
            let a = Polynomial::new(a.to_vec());
            let b = Polynomial::new(b.to_vec());
            let c = Polynomial::new(c.to_vec());
            assert_eq!(c, &a * &b);
            assert_eq!(c, &b * &a);
        }
        check(&[], &[], &[]);
        check(&[0, 0], &[], &[]);
        check(&[0, 0], &[1], &[]);
        check(&[1, 0], &[1], &[1]);
        check(&[1, 0, 1], &[1], &[1, 0, 1]);
        check(&[1, 1], &[1, 1], &[1, 2, 1]);
        check(&[1, 1], &[1, 0, 1], &[1, 1, 1, 1]);
        check(&[0, 0, 1], &[0, 0, 1], &[0, 0, 0, 0, 1]);
    }

    #[test]
    fn eval() {
        fn check(pol: &[int], f: |int| -> int) {
            for n in range(-10i, 10) {
                assert_eq!(f(n), Polynomial::new(pol.to_vec()).eval(n));
            }
        }
        check(&[], |_x| 0);
        check(&[1], |_x| 1);
        check(&[1, 1], |x| x + 1);
        check(&[0, 1], |x| x);
        check(&[10, -10, 10], |x| 10*x*x - 10 * x + 10);
    }

    #[test]
    fn pretty() {
        fn check(slice: &[int], s: &str) {
            assert_eq!(s.to_string(), Polynomial::new(slice.to_vec()).pretty("x"));
        }
        check(&[0], "0");
        check(&[1], "1");
        check(&[1, 1], "1+x");
        check(&[1, 1, 1], "1+x+x^2");
        check(&[2, 2, 2], "2+2*x+2*x^2");
        check(&[0, 0, 0, 1], "x^3");
        check(&[0, 0, 0, -1], "-x^3");
        check(&[-1, 0, 0, -1], "-1-x^3");
        check(&[-1, 1, 0, -1], "-1+x-x^3");
        check(&[-1, 1, -1, -1], "-1+x-x^2-x^3");
    }
}
<commit_msg>polynomial: Remove `uint` or `int` usage as general integer<commit_after>//! Manipulations and data types that represent polynomial

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

#![feature(macro_rules)]

extern crate num;

use std::{cmp, fmt};
use std::iter::{AdditiveIterator, MultiplicativeIterator};
use num::{Zero, One};

/// Polynomial expression
#[deriving(Eq, PartialEq, Clone, Show)]
pub struct Polynomial<T> { data: Vec<T> }

impl<T: Zero> Polynomial<T> {
    /// Creates new `Polynomial`.
    ///
    /// ```rust
    /// use polynomial::Polynomial;
    /// let poly = Polynomial::new(vec![1i, 2, 3]);
    /// assert_eq!("1+2*x+3*x^2", poly.pretty("x"));
    /// ```
    #[inline]
    pub fn new(mut data: Vec<T>) -> Polynomial<T> {
        while let Some(true) = data.last().map(|x| x.is_zero()) {
            let _ = data.pop();
        }
        Polynomial { data: data }
    }
}

impl<T: Zero + One + Clone> Polynomial<T> {
    /// Evaluates the polynomial value.
    ///
    /// ```rust
    /// use polynomial::Polynomial;
    /// let poly = Polynomial::new(vec![1i, 2, 3]);
    /// assert_eq!(1, poly.eval(0));
    /// assert_eq!(6, poly.eval(1));
    /// assert_eq!(17, poly.eval(2));
    /// ```
    #[inline]
    pub fn eval(&self, x: T) -> T {
        let mut sum: T = Zero::zero();
        let mut x_n: T = One::one();
        for n in self.data.iter() {
            sum = sum + n.clone() * x_n.clone();
            x_n = x_n * x.clone();
        }
        sum
    }
}

impl<T> Polynomial<T> {
    /// Gets the slice of internal data.
    #[inline]
    pub fn data(&self) -> &[T] { self.data.as_slice() }
}

impl<T: Zero + One + Eq + Neg<T> + Ord + fmt::Show + Clone> Polynomial<T> {
    /// Pretty prints the polynomial.
    pub fn pretty(&self, x: &str) -> String {
        if self.is_zero() { return "0".to_string() }

        let one = One::one();
        let mut s = Vec::new();
        for (i, n) in self.data.iter().enumerate() {
            // output n*x^i / -n*x^i
            if n.is_zero() { continue }

            let term = if i.is_zero() {
                n.to_string()
            } else if i == 1 {
                if (*n) == one { x.to_string() }
                else if (*n) == -one.clone() { format!("-{}", x) }
                else { format!("{}*{}", n.to_string(), x) }
            } else {
                if (*n) == one { format!("{}^{}", x, i) }
                else if (*n) == -one.clone() { format!("-{}^{}", x, i) }
                else { format!("{}*{}^{}", n.to_string(), x, i) }
            };

            if s.len() > 0 && (*n) > Zero::zero() { s.push("+".to_string()); }
            s.push(term);
        }

        s.concat()
    }
}

impl<'a, T: Neg<T> + Zero + Clone> Neg<Polynomial<T>> for Polynomial<T> {
    #[inline]
    fn neg(self) -> Polynomial<T> { -&self }
}

impl<'a, T: Neg<T> + Zero + Clone> Neg<Polynomial<T>> for &'a Polynomial<T> {
    #[inline]
    fn neg(self) -> Polynomial<T> {
        Polynomial::new(self.data.iter().map(|x| -x.clone()).collect())
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs, Result> $imp<Polynomial<Rhs>, Polynomial<Result>> for Polynomial<Lhs>
            where Lhs: Zero + $imp<Rhs, Result> + Clone, Rhs: Zero + Clone, Result: Zero
        {
            #[inline]
            fn $method(self, other: Polynomial<Rhs>) -> Polynomial<Result> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs, Result> $imp<Polynomial<Rhs>, Polynomial<Result>> for &'a Polynomial<Lhs>
            where Lhs: Zero + $imp<Rhs, Result> + Clone, Rhs: Zero + Clone, Result: Zero
        {
            #[inline]
            fn $method(self, other: Polynomial<Rhs>) -> Polynomial<Result> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs, Result> $imp<&'a Polynomial<Rhs>, Polynomial<Result>> for Polynomial<Lhs>
            where Lhs: Zero + $imp<Rhs, Result> + Clone, Rhs: Zero + Clone, Result: Zero
        {
            #[inline]
            fn $method(self, other: &Polynomial<Rhs>) -> Polynomial<Result> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs, Result> Add<&'b Polynomial<Rhs>, Polynomial<Result>> for &'a Polynomial<Lhs>
    where Lhs: Zero + Add<Rhs, Result> + Clone, Rhs: Zero + Clone, Result: Zero
{
    fn add(self, other: &Polynomial<Rhs>) -> Polynomial<Result> {
        let max_len = cmp::max(self.data.len(), other.data.len());
        let min_len = cmp::min(self.data.len(), other.data.len());

        let mut sum = Vec::with_capacity(max_len);
        for i in range(0, min_len) {
            sum.push(self.data[i].clone() + other.data[i].clone());
        }

        if self.data.len() <= other.data.len() {
            for i in range(min_len, max_len) {
                sum.push(num::zero::<Lhs>() + other.data[i].clone());
            }
        } else {
            for i in range(min_len, max_len) {
                sum.push(self.data[i].clone() + num::zero::<Rhs>());
            }
        }

        Polynomial::new(sum)
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs, Result> Sub<&'b Polynomial<Rhs>, Polynomial<Result>> for &'a Polynomial<Lhs>
    where Lhs: Zero + Sub<Rhs, Result> + Clone, Rhs: Zero + Clone, Result: Zero
{
    fn sub(self, other: &Polynomial<Rhs>) -> Polynomial<Result> {
        let min_len = cmp::min(self.data.len(), other.data.len());
        let max_len = cmp::max(self.data.len(), other.data.len());

        let mut sub = Vec::with_capacity(max_len);
        for i in range(0, min_len) {
            sub.push(self.data[i].clone() - other.data[i].clone());
        }
        if self.data.len() <= other.data.len() {
            for i in range(min_len, max_len) {
                sub.push(num::zero::<Lhs>() - other.data[i].clone())
            }
        } else {
            for i in range(min_len, max_len) {
                sub.push(self.data[i].clone() - num::zero::<Rhs>())
            }
        }
        Polynomial::new(sub)
    }
}

forward_all_binop!(impl Mul, mul);

impl<'a, 'b, Lhs, Rhs, Result> Mul<&'b Polynomial<Rhs>, Polynomial<Result>> for &'a Polynomial<Lhs>
    where Lhs: Zero + Mul<Rhs, Result> + Clone, Rhs: Zero + Clone, Result: Zero
{
    fn mul(self, other: &Polynomial<Rhs>) -> Polynomial<Result> {
        if self.is_zero() || other.is_zero() { return Polynomial::new(vec![]) }

        let slen = self.data.len();
        let olen = other.data.len();
        let prod = Vec::from_fn(slen + olen - 1, |i| {
            let mut p = num::zero::<Result>();
            for k in range(0, slen) {
                if i - k >= olen { continue; }
                p = p + self.data[k].clone() * other.data[i - k].clone();
            }
            p
        });
        Polynomial::new(prod)
    }
}

impl<T: Zero + Clone> Zero for Polynomial<T> {
    #[inline]
    fn zero() -> Polynomial<T> { Polynomial { data: vec![] } }
    #[inline]
    fn is_zero(&self) -> bool { self.data.is_empty() }
}

impl<T: Zero + One + Clone> One for Polynomial<T> {
    #[inline]
    fn one() -> Polynomial<T> { Polynomial { data: vec![One::one()] } }
}

impl<A: Zero + Add<A, A> + Clone, T: Iterator<Polynomial<A>>> AdditiveIterator<Polynomial<A>> for T {
    #[inline]
    fn sum(self) -> Polynomial<A> {
        let init: Polynomial<A> = Zero::zero();
        self.fold(init, |acc, x| acc + x)
    }
}

impl<A: Zero + One + Mul<A, A> + Clone, T: Iterator<Polynomial<A>>> MultiplicativeIterator<Polynomial<A>> for T {
    #[inline]
    fn product(self) -> Polynomial<A> {
        let init: Polynomial<A> = One::one();
        self.fold(init, |acc, x| acc * x)
    }
}

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

    #[test]
    fn new() {
        fn check(dst: Vec<i32>, src: Vec<i32>) {
            assert_eq!(dst, Polynomial::new(src).data);
        }
        check(vec![1, 2, 3], vec![1, 2, 3]);
        check(vec![1, 2, 3], vec![1, 2, 3, 0, 0]);
        check(vec![], vec![0, 0, 0]);
    }

    #[test]
    fn neg_add_sub() {
        fn check(a: &[i32], b: &[i32], c: &[i32]) {
            fn check_eq(a: &Polynomial<i32>, b: &Polynomial<i32>) {
                assert_eq!(*a, *b);
                assert_eq!(-a, -b);
            }
            fn check_add(sum: &Polynomial<i32>, a: &Polynomial<i32>, b: &Polynomial<i32>) {
                check_eq(sum, &(a + b));
                check_eq(sum, &(b + a));
            }
            fn check_sub(sum: &Polynomial<i32>, a: &Polynomial<i32>, b: &Polynomial<i32>) {
                check_eq(a, &(sum - b));
                check_eq(b, &(sum - a));
            }

            let a = &Polynomial::new(a.to_vec());
            let b = &Polynomial::new(b.to_vec());
            let c = &Polynomial::new(c.to_vec());
            check_add(c, a, b);
            check_add(&(-c), &(-a), &(-b));
            check_sub(c, a, b);
            check_sub(&(-c), &(-a), &(-b));
        }
        check(&[], &[], &[]);
        check(&[], &[1], &[1]);
        check(&[1], &[1], &[2]);
        check(&[1, 0, 1], &[1], &[2, 0, 1]);
        check(&[1, 0, -1], &[-1, 0, 1], &[]);
    }

    #[test]
    fn mul() {
        fn check(a: &[i32], b: &[i32], c: &[i32]) {
            let a = Polynomial::new(a.to_vec());
            let b = Polynomial::new(b.to_vec());
            let c = Polynomial::new(c.to_vec());
            assert_eq!(c, &a * &b);
            assert_eq!(c, &b * &a);
        }
        check(&[], &[], &[]);
        check(&[0, 0], &[], &[]);
        check(&[0, 0], &[1], &[]);
        check(&[1, 0], &[1], &[1]);
        check(&[1, 0, 1], &[1], &[1, 0, 1]);
        check(&[1, 1], &[1, 1], &[1, 2, 1]);
        check(&[1, 1], &[1, 0, 1], &[1, 1, 1, 1]);
        check(&[0, 0, 1], &[0, 0, 1], &[0, 0, 0, 0, 1]);
    }

    #[test]
    fn eval() {
        fn check(pol: &[i32], f: |i32| -> i32) {
            for n in range(-10, 10) {
                assert_eq!(f(n), Polynomial::new(pol.to_vec()).eval(n));
            }
        }
        check(&[], |_x| 0);
        check(&[1], |_x| 1);
        check(&[1, 1], |x| x + 1);
        check(&[0, 1], |x| x);
        check(&[10, -10, 10], |x| 10*x*x - 10 * x + 10);
    }

    #[test]
    fn pretty() {
        fn check(slice: &[i32], s: &str) {
            assert_eq!(s.to_string(), Polynomial::new(slice.to_vec()).pretty("x"));
        }
        check(&[0], "0");
        check(&[1], "1");
        check(&[1, 1], "1+x");
        check(&[1, 1, 1], "1+x+x^2");
        check(&[2, 2, 2], "2+2*x+2*x^2");
        check(&[0, 0, 0, 1], "x^3");
        check(&[0, 0, 0, -1], "-x^3");
        check(&[-1, 0, 0, -1], "-1-x^3");
        check(&[-1, 1, 0, -1], "-1+x-x^3");
        check(&[-1, 1, -1, -1], "-1+x-x^2-x^3");
    }
}
<|endoftext|>


<commit_before>//! A data type suitable for storing sensitive information such as passwords and private keys in memory, featuring constant time equality, mlock and zeroing out.
#[cfg(feature = "cbor-serialize")] extern crate cbor;
#[cfg(feature = "cbor-serialize")] extern crate rustc_serialize;
use std::fmt;
use std::borrow::{Borrow, BorrowMut};
#[cfg(feature = "cbor-serialize")] use rustc_serialize::{Decoder, Encoder, Decodable, Encodable};

/**
 * Obtain the number of bytes stored in the given byte slice
 */
fn size_of<T: Sized>(slice: &[T]) -> usize {
    slice.len() * std::mem::size_of::<T>()
}

/**
 * Create a slice reference from the given box reference
 */
fn box_as_slice<T: Sized>(reference: &Box<T>) -> &[T] {
    unsafe { std::slice::from_raw_parts(reference as &T, 1) }
}

/**
 * Create a slice reference from the given box reference
 */
fn box_as_slice_mut<T: Sized + Copy>(reference: &mut Box<T>) -> &mut [T] {
    unsafe { std::slice::from_raw_parts_mut(reference as &mut T, 1) }
}

#[cfg(feature = "libsodium-sys")]
mod mem {
    extern crate libsodium_sys as sodium;
    use ::size_of;

    pub fn zero<T: Sized + Copy>(slice: &mut [T]) {
        unsafe {
            sodium::sodium_memzero(slice.as_ptr() as *mut u8, size_of(slice));
        }
    }

    pub fn cmp<T: Sized + Copy>(us: &[T], them: &[T]) -> bool {
        if us.len() != them.len() {
            return false;
        }

        unsafe {
            sodium::sodium_memcmp(us.as_ptr() as *const u8, them.as_ptr() as *const u8, size_of(them)) == 0
        }
    }
}

#[cfg(not(feature = "libsodium-sys"))]
mod mem {
    use std;

    use ::size_of;

    #[inline(never)]
    pub fn zero<T: Sized + Copy>(slice: &mut [T]) {
        let ptr = slice.as_mut_ptr() as *mut u8;
        for i in 0 .. size_of(slice) {
            unsafe {
                std::ptr::write_volatile(ptr.offset(i as isize), 0);
            }
        }
    }

    #[inline(never)]
    pub fn cmp<T: Sized + Copy>(us: &[T], them: &[T]) -> bool {
        if us.len() != them.len() {
            return false;
        }

        let mut result: u8 = 0;

        let ptr_us   = us.as_ptr()   as *mut u8;
        let ptr_them = them.as_ptr() as *mut u8;
        for i in 0 .. size_of(us) {
            unsafe {
                result |= *(ptr_us.offset(i as isize)) ^ *(ptr_them.offset(i as isize));
            }
        }

        result == 0
    }
}

#[cfg(unix)]
mod memlock {
    extern crate libc;

    use ::size_of;

    pub fn mlock<T: Sized>(cont: &[T]) {
        unsafe {
            libc::mlock(cont.as_ptr() as *const libc::c_void, size_of(cont));
        }
    }

    pub fn munlock<T: Sized>(cont: &[T]) {
        unsafe {
            libc::munlock(cont.as_ptr() as *const libc::c_void, size_of(cont));
        }
    }
}

#[cfg(not(unix))]
mod memlock {
    pub fn mlock<T: Sized>(cont: &[T]) {
    }

    pub fn munlock<T: Sized>(cont: &[T]) {
    }
}

/// Type alias for a vector that stores just bytes
pub type SecStr = SecVec<u8>;

/// A data type suitable for storing sensitive information such as passwords and private keys in memory, that implements:
///
/// - Automatic zeroing in `Drop`
/// - Constant time comparison in `PartialEq` (does not short circuit on the first different character; but terminates instantly if strings have different length)
/// - Outputting `***SECRET***` to prevent leaking secrets into logs in `fmt::Debug` and `fmt::Display`
/// - Automatic `mlock` to protect against leaking into swap
///
/// Be careful with `SecStr::from`: if you have a borrowed string, it will be copied.
/// Use `SecStr::new` if you have a `Vec<u8>`.
#[derive(Clone, Eq)]
pub struct SecVec<T> where T: Sized + Copy {
    content: Vec<T>
}

impl<T> SecVec<T> where T: Sized + Copy {
    pub fn new(cont: Vec<T>) -> Self {
        memlock::mlock(&cont);
        SecVec { content: cont }
    }

    /// Borrow the contents of the string.
    pub fn unsecure(&self) -> &[T] {
        self.borrow()
    }

    /// Mutably borrow the contents of the string.
    pub fn unsecure_mut(&mut self) -> &mut [T] {
        self.borrow_mut()
    }

    /// Overwrite the string with zeros. This is automatically called in the destructor.
    pub fn zero_out(&mut self) {
        mem::zero(&mut self.content);
    }
}

// Creation
impl<T, U> From<U> for SecVec<T> where U: Into<Vec<T>>, T: Sized + Copy {
    fn from(s: U) -> SecVec<T> {
        SecVec::new(s.into())
    }
}

// Borrowing
impl<T> Borrow<[T]> for SecVec<T> where T: Sized + Copy {
    fn borrow(&self) -> &[T] {
        self.content.borrow()
    }
}

impl<T> BorrowMut<[T]> for SecVec<T> where T: Sized + Copy {
    fn borrow_mut(&mut self) -> &mut [T] {
        self.content.borrow_mut()
    }
}

// Overwrite memory with zeros when we're done
impl<T> Drop for SecVec<T> where T: Sized + Copy {
    fn drop(&mut self) {
        self.zero_out();
        memlock::munlock(&self.content);
    }
}

// Constant time comparison
impl<T> PartialEq for SecVec<T> where T: Sized + Copy {
    fn eq(&self, other: &SecVec<T>) -> bool {
        mem::cmp(&self.content, &other.content)
    }
}

// Make sure sensitive information is not logged accidentally
impl<T> fmt::Debug for SecVec<T> where T: Sized + Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("***SECRET***").map_err(|_| { fmt::Error })
    }
}

impl<T> fmt::Display for SecVec<T> where T: Sized + Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("***SECRET***").map_err(|_| { fmt::Error })
    }
}

#[cfg(feature = "cbor-serialize")]
impl<T> Decodable for SecVec<T> where T: Sized + Copy {
    fn decode<D: Decoder>(d: &mut D) -> Result<SecStr, D::Error> {
        let cbor::CborBytes(content) = try!(cbor::CborBytes::decode(d));
        Ok(SecVec::<T>::new(content))
    }
}

#[cfg(feature = "cbor-serialize")]
impl<T> Encodable for SecVec<T> where T: Sized + Copy {
    fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
        cbor::CborBytes(self.content.clone()).encode(e)
    }
}

#[derive(Clone, Eq)]
pub struct SecBox<T> where T: Sized + Copy {
    content: Box<T>
}

impl<T> SecBox<T> where T: Sized + Copy {
    pub fn new(cont: Box<T>) -> Self {
        memlock::mlock(box_as_slice(&cont));
        SecBox { content: cont }
    }

    /// Borrow the contents of the string.
    pub fn unsecure(&self) -> &T {
        &self.content
    }

    /// Mutably borrow the contents of the string.
    pub fn unsecure_mut(&mut self) -> &mut T {
        &mut self.content
    }

    /// Overwrite the string with zeros. This is automatically called in the destructor.
    pub fn zero_out(&mut self) {
        mem::zero(box_as_slice_mut(&mut self.content));
    }
}

// Borrowing
impl<T> Borrow<T> for SecBox<T> where T: Sized + Copy {
    fn borrow(&self) -> &T {
        &self.content
    }
}
impl<T> BorrowMut<T> for SecBox<T> where T: Sized + Copy {
    fn borrow_mut(&mut self) -> &mut T {
        &mut self.content
    }
}

// Overwrite memory with zeros when we're done
impl<T> Drop for SecBox<T> where T: Sized + Copy {
    fn drop(&mut self) {
        self.zero_out();
        memlock::munlock(box_as_slice_mut(&mut self.content));
    }
}

// Constant time comparison
impl<T> PartialEq for SecBox<T> where T: Sized + Copy {
    fn eq(&self, other: &SecBox<T>) -> bool {
        mem::cmp(box_as_slice(&self.content), box_as_slice(&other.content))
    }
}

// Make sure sensitive information is not logged accidentally
impl<T> fmt::Debug for SecBox<T> where T: Sized + Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("***SECRET***").map_err(|_| { fmt::Error })
    }
}
impl<T> fmt::Display for SecBox<T> where T: Sized + Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("***SECRET***").map_err(|_| { fmt::Error })
    }
}

#[cfg(test)]
mod tests {
    use super::{SecStr, SecVec};

    #[test]
    fn test_basic() {
        let my_sec = SecStr::from("hello");
        assert_eq!(my_sec, SecStr::from("hello".to_string()));
        assert_eq!(my_sec.unsecure(), b"hello");
    }

    #[test]
    fn test_zero_out() {
        let mut my_sec = SecStr::from("hello");
        my_sec.zero_out();
        assert_eq!(my_sec.unsecure(), b"\x00\x00\x00\x00\x00");
    }

    #[test]
    fn test_comparison() {
        assert_eq!(SecStr::from("hello"),  SecStr::from("hello"));
        assert!(  SecStr::from("hello") != SecStr::from("yolo"));
        assert!(  SecStr::from("hello") != SecStr::from("olleh"));
        assert!(  SecStr::from("hello") != SecStr::from("helloworld"));
        assert!(  SecStr::from("hello") != SecStr::from(""));
    }

    #[test]
    fn test_show() {
        assert_eq!(format!("{}", SecStr::from("hello")), "***SECRET***".to_string());
    }

    #[test]
    fn test_comparison_zero_out_mb() {
        let mbstring1 = SecVec::from(vec!['H','a','l','l','o',' ','🦄','!']);
        let mbstring2 = SecVec::from(vec!['H','a','l','l','o',' ','🦄','!']);
        let mbstring3 = SecVec::from(vec!['!','🦄',' ','o','l','l','a','H']);
        assert!(mbstring1 == mbstring2);
        assert!(mbstring1 != mbstring3);

        let mut mbstring = mbstring1.clone();
        mbstring.zero_out();
        assert_eq!(mbstring.unsecure(), &['\0','\0','\0','\0','\0','\0','\0','\0']);
    }
}
<commit_msg>Add unit test for `SecBox<[u8; 32]>`<commit_after>//! A data type suitable for storing sensitive information such as passwords and private keys in memory, featuring constant time equality, mlock and zeroing out.
#[cfg(feature = "cbor-serialize")] extern crate cbor;
#[cfg(feature = "cbor-serialize")] extern crate rustc_serialize;
use std::fmt;
use std::borrow::{Borrow, BorrowMut};
#[cfg(feature = "cbor-serialize")] use rustc_serialize::{Decoder, Encoder, Decodable, Encodable};

/**
 * Obtain the number of bytes stored in the given byte slice
 */
fn size_of<T: Sized>(slice: &[T]) -> usize {
    slice.len() * std::mem::size_of::<T>()
}

/**
 * Create a slice reference from the given box reference
 */
fn box_as_slice<T: Sized>(reference: &Box<T>) -> &[T] {
    unsafe { std::slice::from_raw_parts(reference as &T, 1) }
}

/**
 * Create a slice reference from the given box reference
 */
fn box_as_slice_mut<T: Sized + Copy>(reference: &mut Box<T>) -> &mut [T] {
    unsafe { std::slice::from_raw_parts_mut(reference as &mut T, 1) }
}

#[cfg(feature = "libsodium-sys")]
mod mem {
    extern crate libsodium_sys as sodium;
    use ::size_of;

    pub fn zero<T: Sized + Copy>(slice: &mut [T]) {
        unsafe {
            sodium::sodium_memzero(slice.as_ptr() as *mut u8, size_of(slice));
        }
    }

    pub fn cmp<T: Sized + Copy>(us: &[T], them: &[T]) -> bool {
        if us.len() != them.len() {
            return false;
        }

        unsafe {
            sodium::sodium_memcmp(us.as_ptr() as *const u8, them.as_ptr() as *const u8, size_of(them)) == 0
        }
    }
}

#[cfg(not(feature = "libsodium-sys"))]
mod mem {
    use std;

    use ::size_of;

    #[inline(never)]
    pub fn zero<T: Sized + Copy>(slice: &mut [T]) {
        let ptr = slice.as_mut_ptr() as *mut u8;
        for i in 0 .. size_of(slice) {
            unsafe {
                std::ptr::write_volatile(ptr.offset(i as isize), 0);
            }
        }
    }

    #[inline(never)]
    pub fn cmp<T: Sized + Copy>(us: &[T], them: &[T]) -> bool {
        if us.len() != them.len() {
            return false;
        }

        let mut result: u8 = 0;

        let ptr_us   = us.as_ptr()   as *mut u8;
        let ptr_them = them.as_ptr() as *mut u8;
        for i in 0 .. size_of(us) {
            unsafe {
                result |= *(ptr_us.offset(i as isize)) ^ *(ptr_them.offset(i as isize));
            }
        }

        result == 0
    }
}

#[cfg(unix)]
mod memlock {
    extern crate libc;

    use ::size_of;

    pub fn mlock<T: Sized>(cont: &[T]) {
        unsafe {
            libc::mlock(cont.as_ptr() as *const libc::c_void, size_of(cont));
        }
    }

    pub fn munlock<T: Sized>(cont: &[T]) {
        unsafe {
            libc::munlock(cont.as_ptr() as *const libc::c_void, size_of(cont));
        }
    }
}

#[cfg(not(unix))]
mod memlock {
    pub fn mlock<T: Sized>(cont: &[T]) {
    }

    pub fn munlock<T: Sized>(cont: &[T]) {
    }
}

/// Type alias for a vector that stores just bytes
pub type SecStr = SecVec<u8>;

/// A data type suitable for storing sensitive information such as passwords and private keys in memory, that implements:
///
/// - Automatic zeroing in `Drop`
/// - Constant time comparison in `PartialEq` (does not short circuit on the first different character; but terminates instantly if strings have different length)
/// - Outputting `***SECRET***` to prevent leaking secrets into logs in `fmt::Debug` and `fmt::Display`
/// - Automatic `mlock` to protect against leaking into swap
///
/// Be careful with `SecStr::from`: if you have a borrowed string, it will be copied.
/// Use `SecStr::new` if you have a `Vec<u8>`.
#[derive(Clone, Eq)]
pub struct SecVec<T> where T: Sized + Copy {
    content: Vec<T>
}

impl<T> SecVec<T> where T: Sized + Copy {
    pub fn new(cont: Vec<T>) -> Self {
        memlock::mlock(&cont);
        SecVec { content: cont }
    }

    /// Borrow the contents of the string.
    pub fn unsecure(&self) -> &[T] {
        self.borrow()
    }

    /// Mutably borrow the contents of the string.
    pub fn unsecure_mut(&mut self) -> &mut [T] {
        self.borrow_mut()
    }

    /// Overwrite the string with zeros. This is automatically called in the destructor.
    pub fn zero_out(&mut self) {
        mem::zero(&mut self.content);
    }
}

// Creation
impl<T, U> From<U> for SecVec<T> where U: Into<Vec<T>>, T: Sized + Copy {
    fn from(s: U) -> SecVec<T> {
        SecVec::new(s.into())
    }
}

// Borrowing
impl<T> Borrow<[T]> for SecVec<T> where T: Sized + Copy {
    fn borrow(&self) -> &[T] {
        self.content.borrow()
    }
}

impl<T> BorrowMut<[T]> for SecVec<T> where T: Sized + Copy {
    fn borrow_mut(&mut self) -> &mut [T] {
        self.content.borrow_mut()
    }
}

// Overwrite memory with zeros when we're done
impl<T> Drop for SecVec<T> where T: Sized + Copy {
    fn drop(&mut self) {
        self.zero_out();
        memlock::munlock(&self.content);
    }
}

// Constant time comparison
impl<T> PartialEq for SecVec<T> where T: Sized + Copy {
    fn eq(&self, other: &SecVec<T>) -> bool {
        mem::cmp(&self.content, &other.content)
    }
}

// Make sure sensitive information is not logged accidentally
impl<T> fmt::Debug for SecVec<T> where T: Sized + Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("***SECRET***").map_err(|_| { fmt::Error })
    }
}

impl<T> fmt::Display for SecVec<T> where T: Sized + Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("***SECRET***").map_err(|_| { fmt::Error })
    }
}

#[cfg(feature = "cbor-serialize")]
impl<T> Decodable for SecVec<T> where T: Sized + Copy {
    fn decode<D: Decoder>(d: &mut D) -> Result<SecStr, D::Error> {
        let cbor::CborBytes(content) = try!(cbor::CborBytes::decode(d));
        Ok(SecVec::<T>::new(content))
    }
}

#[cfg(feature = "cbor-serialize")]
impl<T> Encodable for SecVec<T> where T: Sized + Copy {
    fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
        cbor::CborBytes(self.content.clone()).encode(e)
    }
}

#[derive(Clone, Eq)]
pub struct SecBox<T> where T: Sized + Copy {
    content: Box<T>
}

impl<T> SecBox<T> where T: Sized + Copy {
    pub fn new(cont: Box<T>) -> Self {
        memlock::mlock(box_as_slice(&cont));
        SecBox { content: cont }
    }

    /// Borrow the contents of the string.
    pub fn unsecure(&self) -> &T {
        &self.content
    }

    /// Mutably borrow the contents of the string.
    pub fn unsecure_mut(&mut self) -> &mut T {
        &mut self.content
    }

    /// Overwrite the string with zeros. This is automatically called in the destructor.
    pub fn zero_out(&mut self) {
        mem::zero(box_as_slice_mut(&mut self.content));
    }
}

// Borrowing
impl<T> Borrow<T> for SecBox<T> where T: Sized + Copy {
    fn borrow(&self) -> &T {
        &self.content
    }
}
impl<T> BorrowMut<T> for SecBox<T> where T: Sized + Copy {
    fn borrow_mut(&mut self) -> &mut T {
        &mut self.content
    }
}

// Overwrite memory with zeros when we're done
impl<T> Drop for SecBox<T> where T: Sized + Copy {
    fn drop(&mut self) {
        self.zero_out();
        memlock::munlock(box_as_slice_mut(&mut self.content));
    }
}

// Constant time comparison
impl<T> PartialEq for SecBox<T> where T: Sized + Copy {
    fn eq(&self, other: &SecBox<T>) -> bool {
        mem::cmp(box_as_slice(&self.content), box_as_slice(&other.content))
    }
}

// Make sure sensitive information is not logged accidentally
impl<T> fmt::Debug for SecBox<T> where T: Sized + Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("***SECRET***").map_err(|_| { fmt::Error })
    }
}
impl<T> fmt::Display for SecBox<T> where T: Sized + Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("***SECRET***").map_err(|_| { fmt::Error })
    }
}

#[cfg(test)]
mod tests {
    use super::{SecBox, SecStr, SecVec};

    #[test]
    fn test_basic() {
        let my_sec = SecStr::from("hello");
        assert_eq!(my_sec, SecStr::from("hello".to_string()));
        assert_eq!(my_sec.unsecure(), b"hello");
    }

    #[test]
    fn test_zero_out() {
        let mut my_sec = SecStr::from("hello");
        my_sec.zero_out();
        assert_eq!(my_sec.unsecure(), b"\x00\x00\x00\x00\x00");
    }

    #[test]
    fn test_comparison() {
        assert_eq!(SecStr::from("hello"),  SecStr::from("hello"));
        assert!(  SecStr::from("hello") != SecStr::from("yolo"));
        assert!(  SecStr::from("hello") != SecStr::from("olleh"));
        assert!(  SecStr::from("hello") != SecStr::from("helloworld"));
        assert!(  SecStr::from("hello") != SecStr::from(""));
    }

    #[test]
    fn test_show() {
        assert_eq!(format!("{}", SecStr::from("hello")), "***SECRET***".to_string());
    }

    #[test]
    fn test_comparison_zero_out_mb() {
        let mbstring1 = SecVec::from(vec!['H','a','l','l','o',' ','🦄','!']);
        let mbstring2 = SecVec::from(vec!['H','a','l','l','o',' ','🦄','!']);
        let mbstring3 = SecVec::from(vec!['!','🦄',' ','o','l','l','a','H']);
        assert!(mbstring1 == mbstring2);
        assert!(mbstring1 != mbstring3);

        let mut mbstring = mbstring1.clone();
        mbstring.zero_out();
        assert_eq!(mbstring.unsecure(), &['\0','\0','\0','\0','\0','\0','\0','\0']);
    }

    const PRIVATE_KEY_1: [u8; 32] = [
        0xb0, 0x3b, 0x34, 0xc3, 0x3a, 0x1c, 0x44, 0xf2,
        0x25, 0xb6, 0x62, 0xd2, 0xbf, 0x48, 0x59, 0xb8,
        0x13, 0x54, 0x11, 0xfa, 0x7b, 0x03, 0x86, 0xd4,
        0x5f, 0xb7, 0x5d, 0xc5, 0xb9, 0x1b, 0x44, 0x66];

    const PRIVATE_KEY_2: [u8; 32] = [
        0xc8, 0x06, 0x43, 0x9d, 0xc9, 0xd2, 0xc4, 0x76,
        0xff, 0xed, 0x8f, 0x25, 0x80, 0xc0, 0x88, 0x8d,
        0x58, 0xab, 0x40, 0x6b, 0xf7, 0xae, 0x36, 0x98,
        0x87, 0x90, 0x21, 0xb9, 0x6b, 0xb4, 0xbf, 0x59];

    #[test]
    fn test_secbox() {
        let key_1 = SecBox::new(Box::new(PRIVATE_KEY_1));
        let key_2 = SecBox::new(Box::new(PRIVATE_KEY_2));
        let key_3 = SecBox::new(Box::new(PRIVATE_KEY_1));
        assert!(key_1 == key_1);
        assert!(key_1 != key_2);
        assert!(key_2 != key_3);
        assert!(key_1 == key_3);

        let mut final_key = key_1.clone();
        final_key.zero_out();
        assert_eq!(final_key.unsecure(), &[0; 32]);
    }
}
<|endoftext|>


<commit_before>//! This crate provides native rust implementations of
//! image encoders and decoders and basic image manipulation
//! functions.
//!
//! Additional documentation can currently be found in the
//! [README.md file which is most easily viewed on github](https://github.com/image-rs/image/blob/master/README.md).

#![warn(missing_docs)]
#![warn(unused_qualifications)]
#![deny(unreachable_pub)]
#![deny(deprecated)]
#![deny(missing_copy_implementations)]
#![cfg_attr(all(test, feature = "benchmarks"), feature(test))]
// it's a bit of a pain otherwise
#![allow(clippy::many_single_char_names)]

#[cfg(all(test, feature = "benchmarks"))]
extern crate test;

#[cfg(test)]
#[macro_use]
extern crate quickcheck;

use std::io::Write;

pub use crate::color::{ColorType, ExtendedColorType};

pub use crate::color::{Luma, LumaA, Rgb, Rgba, Bgr, Bgra};

pub use crate::error::{ImageError, ImageResult};

pub use crate::image::{AnimationDecoder,
                GenericImage,
                GenericImageView,
                ImageDecoder,
                ImageDecoderExt,
                ImageEncoder,
                ImageFormat,
                ImageOutputFormat,
                Progress,
                // Iterators
                Pixels,
                SubImage};

pub use crate::buffer_::{
                 GrayAlphaImage,
                 GrayImage,
                 // Image types
                 ImageBuffer,
                 RgbImage,
                 RgbaImage};

pub use crate::flat::FlatSamples;

// Traits
pub use crate::traits::{Primitive, Pixel};

// Opening and loading images
pub use crate::io::free_functions::{guess_format, load};
pub use crate::dynimage::{load_from_memory, load_from_memory_with_format, open,
                   save_buffer, save_buffer_with_format, image_dimensions};

pub use crate::dynimage::DynamicImage;

pub use crate::animation::{Delay, Frame, Frames};

// More detailed error type
pub mod error;

/// Iterators and other auxiliary structure for the `ImageBuffer` type.
pub mod buffer {
    // Only those not exported at the top-level
    pub use crate::buffer_::{
        ConvertBuffer,
        EnumeratePixels,
        EnumeratePixelsMut,
        EnumerateRows,
        EnumerateRowsMut,
        Pixels,
        PixelsMut,
        Rows,
        RowsMut,
    };
}

// Math utils
pub mod math;

// Image processing functions
pub mod imageops;

// Io bindings
pub mod io;

// Buffer representations for ffi.
pub mod flat;

// Image codecs
#[cfg(feature = "bmp")]
pub mod bmp;
#[cfg(feature = "dds")]
pub mod dds;
#[cfg(feature = "dxt")]
pub mod dxt;
#[cfg(feature = "gif")]
pub mod gif;
#[cfg(feature = "hdr")]
pub mod hdr;
#[cfg(feature = "ico")]
pub mod ico;
#[cfg(feature = "jpeg")]
pub mod jpeg;
#[cfg(feature = "png")]
pub mod png;
#[cfg(feature = "pnm")]
pub mod pnm;
#[cfg(feature = "tga")]
pub mod tga;
#[cfg(feature = "tiff")]
pub mod tiff;
#[cfg(feature = "webp")]
pub mod webp;
#[cfg(feature = "farbfeld")]
pub mod farbfeld;

mod animation;
#[path = "buffer.rs"]
mod buffer_;
mod color;
mod dynimage;
mod image;
mod traits;
mod utils;

// Can't use the macro-call itself within the `doc` attribute. So force it to eval it as part of
// the macro invocation.
//
// The inspiration for the macro and implementation is from
// <https://github.com/GuillaumeGomez/doc-comment>
//
// MIT License
//
// Copyright (c) 2018 Guillaume Gomez
macro_rules! insert_as_doc {
    { $content:expr } => {
        #[doc = $content] extern { }
    }
}

// Provides the README.md as doc, to ensure the example works!
insert_as_doc!(include_str!("../README.md"));

// Copies data from `src` to `dst`
//
// Panics if the length of `dst` is less than the length of `src`.
#[inline]
fn copy_memory(src: &[u8], mut dst: &mut [u8]) {
    let len_src = src.len();
    assert!(dst.len() >= len_src);
    dst.write_all(src).unwrap();
}
<commit_msg>Add library top-level documentation<commit_after>//! This crate provides native rust implementations of
//! image encoders and decoders and basic image manipulation
//! functions.
//!
//! Additional documentation can currently also be found in the
//! [README.md file which is most easily viewed on github](https://github.com/image-rs/image/blob/master/README.md).
//!
//! [Jump forward to crate content](#reexports)
//!
//! # Overview
//!
//! There are two core problems for this library provides solutions: a unified interface for images
//! encodings and simple generic buffers for their content. It's possible to use either feature
//! without the other. The focus is on small and stable set of common operations that can be
//! supplemented by other specialized crates. The library also prefers safe solutions with few
//! dependencies.
//!
//! | Format | Decoding | Encoding |
//! | ------ | -------- | -------- |
//! | PNG    | All supported color types | Same as decoding |
//! | JPEG   | Baseline and progressive | Baseline JPEG |
//! | GIF    | Yes | Yes |
//! | BMP    | Yes | RGB(8), RGBA(8), Gray(8), GrayA(8) |
//! | ICO    | Yes | Yes |
//! | TIFF   | Baseline(no fax support) + LZW + PackBits | RGB(8), RGBA(8), Gray(8) |
//! | WebP   | Lossy(Luma channel only) | No |
//! | PNM    | PBM, PGM, PPM, standard PAM | Yes |
//! | DDS    | DXT1, DXT3, DXT5 | No |
//! | TGA    | Yes | No |
//! | farbfeld | Yes | Yes |
//!
//! ## Using images decoders
//!
//! There exists a huge variety of image formats that are concerned with efficiently encoding image
//! pixel data and auxiliary meta data for many different purposes. The `image` library provides
//! decoders for many common formats, depending on the active features. The best way to use them
//! depends on your use case.
//!
//! * [`open`] is a very simple way to load images from the file system, automatically deducing the
//!   format but offering little customization.
//! * [`load_from_memory`], [`load_from_memory_with_format`] present a similar interface for images
//!   whose encoded data is already present in memory.
//! * [`io::Reader`] is a builder providing a superset of the functions. It offers both
//!   customization and auto-deduction but is slightly more involved. The main benefit is that the
//!   interface is easier to evolve.
//! * [`ImageDecoder`] is a trait for querying meta data and reading image pixels into a generic
//!   byte buffer. It also contains a `Read` adaptor for stream reading the pixels.
//! * [`DynamicImage::from_decoder`] can be used for creating a buffer from a single specific or
//!   any custom decoder implementing the [`ImageDecoder`] trait.
//!
//! [`open`]: #fn.open.html
//! [`load_from_memory`]: #fn.load_from_memory.html
//! [`load_from_memory_with_format`]: #fn.load_from_memory_with_format.html
//! [`io::Reader`]: io/struct.Reader.html
//! [`DynamicImage::from_decoder`]: enum.DynamicImage.html#method.from_decoder
//! [`ImageDecoder`]: trait.ImageDecoder.html
//!
//! ## Using image encoders
//!
//! Encoding pixel data is supported for the majority of formats but not quite as broadly.
//!
//! * [`DynamicImage::save`] is converse of `open` and stores a `DynamicImage`.
//! * [`DynamicImage::write_to`] can be used to encode an image into any writer, for example into a
//!   vector of bytes in memory.
//! * [`save_buffer`], [`save_buffer_with_format`] are a low-level interface for saving an image
//!   in the file system where the library initializes the chosen encoder.
//! * [`ImageEncoder`] is a trait for encoding a byte buffer of image data and the inverse of the
//!   `ImageDecoder` interface.
//!
//! [`save_buffer`]: #fn.save_buffer.html
//! [`save_buffer_with_format`]: #fn.save_buffer_with_format.html
//! [`DynamicImage::save`]: enum.DynamicImage.html#method.save
//! [`DynamicImage::write_to`]: enum.DynamicImage.html#method.write_to
//! [`ImageEncoder`]: trait.ImageEncoder.html
//!
//! ## Image buffers
//!
//! The library adds containers for channel data which together form some representation of a 2D
//! matrix of pixels. These are all statically typed to avoid misinterpretation of byte data (and
//! since Rust has no standard safe encapsulation for reinterpreting byte slices as another type).
//! The main traits [`GenericImageView`] and [`GenericImage`] model a view on a 2D-matrix of
//! addressable pixels and a buffer of independently accessible pixels respectively.
//!
//! The two main types for owning pixel data are [`ImageBuffer`] and [`DynamicImage`]. Note that
//! the latter is an enum over well-supported pixel types that also offers conversion
//! functionality.
//!
//! Additionally, the [`flat`] module contains items for interoperability with generic channel
//! matrices and foreign interface. While still strict typed these dynamically validate length and
//! other layout assumptions required to provide the trait interface. While quite generic You
//! should be prepared for a bit of boilerplate when using these types.
//!
//! [`GenericImageView`]: trait.GenericImageView.html
//! [`GenericImage`]: trait.GenericImage.html
//! [`ImageBuffer`]: struct.ImageBuffer.html
//! [`DynamicImage`]: enum.DynamicImage.html
//! [`flat`]: flat/index.html

#![warn(missing_docs)]
#![warn(unused_qualifications)]
#![deny(unreachable_pub)]
#![deny(deprecated)]
#![deny(missing_copy_implementations)]
#![cfg_attr(all(test, feature = "benchmarks"), feature(test))]
// it's a bit of a pain otherwise
#![allow(clippy::many_single_char_names)]

#[cfg(all(test, feature = "benchmarks"))]
extern crate test;

#[cfg(test)]
#[macro_use]
extern crate quickcheck;

use std::io::Write;

pub use crate::color::{ColorType, ExtendedColorType};

pub use crate::color::{Luma, LumaA, Rgb, Rgba, Bgr, Bgra};

pub use crate::error::{ImageError, ImageResult};

pub use crate::image::{AnimationDecoder,
                GenericImage,
                GenericImageView,
                ImageDecoder,
                ImageDecoderExt,
                ImageEncoder,
                ImageFormat,
                ImageOutputFormat,
                Progress,
                // Iterators
                Pixels,
                SubImage};

pub use crate::buffer_::{
                 GrayAlphaImage,
                 GrayImage,
                 // Image types
                 ImageBuffer,
                 RgbImage,
                 RgbaImage};

pub use crate::flat::FlatSamples;

// Traits
pub use crate::traits::{Primitive, Pixel};

// Opening and loading images
pub use crate::io::free_functions::{guess_format, load};
pub use crate::dynimage::{load_from_memory, load_from_memory_with_format, open,
                   save_buffer, save_buffer_with_format, image_dimensions};

pub use crate::dynimage::DynamicImage;

pub use crate::animation::{Delay, Frame, Frames};

// More detailed error type
pub mod error;

/// Iterators and other auxiliary structure for the `ImageBuffer` type.
pub mod buffer {
    // Only those not exported at the top-level
    pub use crate::buffer_::{
        ConvertBuffer,
        EnumeratePixels,
        EnumeratePixelsMut,
        EnumerateRows,
        EnumerateRowsMut,
        Pixels,
        PixelsMut,
        Rows,
        RowsMut,
    };
}

// Math utils
pub mod math;

// Image processing functions
pub mod imageops;

// Io bindings
pub mod io;

// Buffer representations for ffi.
pub mod flat;

// Image codecs
#[cfg(feature = "bmp")]
pub mod bmp;
#[cfg(feature = "dds")]
pub mod dds;
#[cfg(feature = "dxt")]
pub mod dxt;
#[cfg(feature = "gif")]
pub mod gif;
#[cfg(feature = "hdr")]
pub mod hdr;
#[cfg(feature = "ico")]
pub mod ico;
#[cfg(feature = "jpeg")]
pub mod jpeg;
#[cfg(feature = "png")]
pub mod png;
#[cfg(feature = "pnm")]
pub mod pnm;
#[cfg(feature = "tga")]
pub mod tga;
#[cfg(feature = "tiff")]
pub mod tiff;
#[cfg(feature = "webp")]
pub mod webp;
#[cfg(feature = "farbfeld")]
pub mod farbfeld;

mod animation;
#[path = "buffer.rs"]
mod buffer_;
mod color;
mod dynimage;
mod image;
mod traits;
mod utils;

// Can't use the macro-call itself within the `doc` attribute. So force it to eval it as part of
// the macro invocation.
//
// The inspiration for the macro and implementation is from
// <https://github.com/GuillaumeGomez/doc-comment>
//
// MIT License
//
// Copyright (c) 2018 Guillaume Gomez
macro_rules! insert_as_doc {
    { $content:expr } => {
        #[doc = $content] extern { }
    }
}

// Provides the README.md as doc, to ensure the example works!
insert_as_doc!(include_str!("../README.md"));

// Copies data from `src` to `dst`
//
// Panics if the length of `dst` is less than the length of `src`.
#[inline]
fn copy_memory(src: &[u8], mut dst: &mut [u8]) {
    let len_src = src.len();
    assert!(dst.len() >= len_src);
    dst.write_all(src).unwrap();
}
<|endoftext|>


<commit_before>//! Perlin is a free and open source information retrieval library.
//!
//! Version 0.1.0
//!
//! # Features
//! * boolean retrieval on arbitrary types
//! * minimal dependencies
//! * lazy and zero-allocation query evaluation
//!
//! # Basic Usage
//!
//! Add Perlin to Cargo.toml
//!
//! ```toml
//! [dependencies]
//! perlin = "0.1"
//! ```
//!
//! and import it in your crate root:
//!
//! ```rust
//! extern crate perlin;
//! ```
//!
//!
//! ## Build index and run queries
//! ```rust
//! use perlin::index::Index;
//! use perlin::storage::RamStorage;
//! use perlin::index::boolean_index::{QueryBuilder, IndexBuilder};
//!
//! //Use `IndexBuilder` to construct a new Index and add documents to it.
//! //Perlin does not dictate what "documents" are.
//! //Rather it expects iterators over iterators over terms.
//! //In our case a "document" consists of a series of `usize` values:
//! let index = IndexBuilder::<_, RamStorage<_>>::new().create(vec![(0..10),
//! (0..15), (10..34)].into_iter()).unwrap();
//!
//! //Now use the `QueryBuilder` to construct a query
//! //Simple query for the number 4
//! let simple_query = QueryBuilder::atom(4).build();
//!
//! //When executing queries the index does not evaluate return all results at once.
//! //Rather it runs lazily and returns an iterator over the resulting document ids.
//! for id in index.execute_query(&simple_query) {
//!    println!("{}", id); //Will print 0 and 1
//! }
//!
//! ```
//!
//! Have a look in the [examples folder](https://github.com/JDemler/perlin/tree/master/examples) for more
//! elaborate examples!
//!
//!
#![doc(html_root_url = "https://doc.perlin-ir.org/")]

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

#[macro_use]
mod utils;
mod chunked_storage;
pub mod language;
pub mod index;
pub mod storage;

#[cfg(test)]
mod test_utils;
<commit_msg>reinstatiate deny warnings and no_lib<commit_after>//! Perlin is a free and open source information retrieval library.
//!
//! Version 0.1.0
//!
//! # Features
//! * boolean retrieval on arbitrary types
//! * minimal dependencies
//! * lazy and zero-allocation query evaluation
//!
//! # Basic Usage
//!
//! Add Perlin to Cargo.toml
//!
//! ```toml
//! [dependencies]
//! perlin = "0.1"
//! ```
//!
//! and import it in your crate root:
//!
//! ```rust
//! extern crate perlin;
//! ```
//!
//!
//! ## Build index and run queries
//! ```rust
//! use perlin::index::Index;
//! use perlin::storage::RamStorage;
//! use perlin::index::boolean_index::{QueryBuilder, IndexBuilder};
//!
//! //Use `IndexBuilder` to construct a new Index and add documents to it.
//! //Perlin does not dictate what "documents" are.
//! //Rather it expects iterators over iterators over terms.
//! //In our case a "document" consists of a series of `usize` values:
//! let index = IndexBuilder::<_, RamStorage<_>>::new().create(vec![(0..10),
//! (0..15), (10..34)].into_iter()).unwrap();
//!
//! //Now use the `QueryBuilder` to construct a query
//! //Simple query for the number 4
//! let simple_query = QueryBuilder::atom(4).build();
//!
//! //When executing queries the index does not evaluate return all results at once.
//! //Rather it runs lazily and returns an iterator over the resulting document ids.
//! for id in index.execute_query(&simple_query) {
//!    println!("{}", id); //Will print 0 and 1
//! }
//!
//! ```
//!
//! Have a look in the [examples folder](https://github.com/JDemler/perlin/tree/master/examples) for more
//! elaborate examples!
//!
//!
#![doc(html_root_url = "https://doc.perlin-ir.org/")]
#![deny(missing_docs, warnings)]

#[macro_use]
mod utils;
mod chunked_storage;
pub mod language;
pub mod index;
pub mod storage;

#[cfg(test)]
mod test_utils;
<|endoftext|>