<commit_before>// Dependency Graph Library in Rust

//! dglr is a Dependency Graph Library in Rust.
//! In short, you register elements and their dependencies, and then
//! ask for the dependencies of any element in an order that satisfies.
//!
//! Elements are simply &str strings.  You register them with
//! register_dependency() or register_dependencies().
//!
//! Dependenies are (currently) just a list of other elements that
//! the element in question depends on.  [In the future, we may add
//! boolean logic, but currently they are all AND-ed together].
//!
//! Then call get_ordered_dependencies_of() and the library does the
//! magic and returns an order which will work.  It is possible that
//! other orders also work, but the library's algorithm is
//! deterministic, so you'll always get the same particular one.

#![crate_id = "dglr#0.1"]
#![crate_type = "lib"]

// Required for log and rustdoc:
#![feature(phase)]
#[phase(plugin, link)]

extern crate log;

use std::collections::hashmap::{HashMap,HashSet};
use std::iter::{Iterator};
#[allow(unused_imports)]
use std::task;

/// This is the dependency graph.  You can create it yourself, or
/// use the convenience methods of new(), register_dependency() and
/// register_dependencies() to build one up (that must be mutable).
pub struct DepGraph {
    /// List of dependencies.  Key is the element, values are the
    /// other elements that the key element depends upon.
    pub dependencies: HashMap<String,Vec<String>>,

    // (private) target we are trying to satisfy
    target: Option<String>,

    // (private) elements already satisfied
    satisfied: HashSet<String>,

    // (private) current path, for cycle detection
    curpath: HashSet<String>,
}

pub struct DepGraphIterator<'a> {
    depgraph: &'a mut DepGraph
}
pub struct DepGraphSatisfyingIterator<'a> {
    depgraph: &'a mut DepGraph
}

impl DepGraph {

    /// Create an empty DepGraph.
    pub fn new() -> DepGraph
    {
        DepGraph {
            dependencies: HashMap::new(),
            target: None,
            curpath: HashSet::new(),
            satisfied: HashSet::new(),
        }
    }

    /// Add a dependency to a DepGraph.  The thing does not need
    /// to pre-exist, nor do the dependency elements.  But if the
    /// thing does pre-exist, the dependsOn will be added to its
    /// existing dependency list.
    pub fn register_dependency<'a>( &mut self,
                                thing: &'a str,
                                dependsOn: &'a str )
    {
        self.dependencies.insert_or_update_with(
            String::from_str(thing),
            vec![String::from_str(dependsOn)],
            |_,v| { v.push(String::from_str(dependsOn)); }
            );
    }

    /// Add multiple dependencies of one thing to a DepGraph.  The
    /// thing does not need to pre-exist, nor do the dependency elements.
    /// But if the thing does pre-exist, the dependsOn will be added
    /// to its existing dependency list.
    pub fn register_dependencies<'a>( &mut self,
                                  thing: &'a str,
                                  dependsOn: &'a[&'a str] )
    {
        let newvec: Vec<String> = dependsOn.iter().map(
            |s| String::from_str(*s)).collect();

        self.dependencies.insert_or_update_with(
            String::from_str(thing),
            newvec.clone(),
            |_,v| { v.push_all(newvec.as_slice()); }
            );
    }

    pub fn set_target<'a>( &mut self, target: &'a str )
    {
        self.target = Some(String::from_str(target));
    }

    pub fn mark_as_satisfied<'a>( &mut self,
                                   things: &'a[&'a str] )
    {
        for thing in things.iter() {
            self.satisfied.insert(String::from_str(*thing));
        }
    }

    fn get_next_dependency(&mut self, thing: &String) -> String
    {
        if self.curpath.contains(thing) {
            fail!("Circular dependency graph at {}",thing);
        }
        self.curpath.insert(thing.clone());

        let deplist = match self.dependencies.find(thing) {
            None => return thing.clone(),
            Some(deplist) => deplist.clone() // ouch
        };

        for n in deplist.iter() {
            if self.satisfied.contains(n) {
                continue;
            }
            return self.get_next_dependency(n);
        }
        // things dependencies are satisfied
        thing.clone()
    }

    pub fn iter<'a>(&'a mut self) -> DepGraphIterator<'a>
    {
        DepGraphIterator {
            depgraph: self
        }
    }

    pub fn satisfying_iter<'a>(&'a mut self) -> DepGraphSatisfyingIterator<'a>
    {
        DepGraphSatisfyingIterator {
            depgraph: self
        }
    }
}

impl<'a> Iterator<String> for DepGraphIterator<'a> {
    fn next(&mut self) -> Option<String>
    {
        let thing = match self.depgraph.target {
            None => return None,
            Some(ref thing) => thing.clone()
        };
        if self.depgraph.satisfied.contains(&thing) {
            return None;
        }
        self.depgraph.curpath.clear();
        Some(self.depgraph.get_next_dependency(&thing))
    }
}

impl<'a> Iterator<String> for DepGraphSatisfyingIterator<'a> {
    fn next(&mut self) -> Option<String>
    {
        let thing = match self.depgraph.target {
            None => return None,
            Some(ref thing) => thing.clone()
        };
        if self.depgraph.satisfied.contains(&thing) {
            return None;
        }
        self.depgraph.curpath.clear();
        let next = self.depgraph.get_next_dependency(&thing);
        self.depgraph.mark_as_satisfied([next.as_slice()]);
        Some(next)
    }
}

#[test]
fn dglr_test_branching() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e","m","g"]);
    depgraph.register_dependency("e","f");
    depgraph.register_dependency("g","h");
    depgraph.register_dependency("h","i");
    depgraph.register_dependencies("i",&["j","k"]);
    depgraph.register_dependencies("k",&["l","m"]);
    depgraph.register_dependency("m","n");

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    loop {
        // detect infinite looping bugs
        assert!(results.len() < 30);

        let thing = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied([thing.as_slice()]);
        results.push(thing);
    }

    assert!( results == vec![String::from_str("d"),
                             String::from_str("b"),
                             String::from_str("f"),
                             String::from_str("e"),
                             String::from_str("n"),
                             String::from_str("m"),
                             String::from_str("j"),
                             String::from_str("l"),
                             String::from_str("k"),
                             String::from_str("i"),
                             String::from_str("h"),
                             String::from_str("g"),
                             String::from_str("c"),
                             String::from_str("a")] );
    //info!("Deps of a = {}",results);
}

#[test]
fn dglr_test_satisfying() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e"]);

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    for thing in depgraph.satisfying_iter() {
        // detect infinite looping bugs
        assert!(results.len() < 30);
        results.push(thing);
    }

    assert!( results == vec![String::from_str("d"),
                             String::from_str("b"),
                             String::from_str("e"),
                             String::from_str("c"),
                             String::from_str("a")] );
    //info!("Deps of a = {}",results);
}

#[test]
fn dglr_test_circular() {

    let task_result = task::try(proc() {
        let mut depgraph: DepGraph = DepGraph::new();
        depgraph.register_dependency("a","b");
        depgraph.register_dependency("b","c");
        depgraph.register_dependency("c","a");
        depgraph.set_target("a");

        let mut results: Vec<String> = Vec::new();

        loop {
            // Detect infinite looping bugs by
            // breaking out successfully (successful
            // proc() means failed test!)
            if results.len() >= 30 { break; }

            let thing = match depgraph.iter().next() {
                Some(x) => x,
                None => break,
            };
            depgraph.mark_as_satisfied([thing.as_slice()]);
            results.push(thing);
        }
    });
    match task_result {
        Ok(_) => fail!("Should have failed at the circular dependency!"),
        Err(_) => () //info!("Successfully detected the circular dependency (ignore task failure)"),
    };
}

#[test]
fn dglr_test_satisfied_stoppage() {

    let mut depgraph: DepGraph = DepGraph::new();
    depgraph.register_dependencies("superconn", []);
    depgraph.register_dependencies("owneruser", ["superconn"]);
    depgraph.register_dependencies("appuser", ["superconn"]);
    depgraph.register_dependencies("database", ["owneruser"]);
    depgraph.register_dependencies("ownerconn", ["database","owneruser"]);
    depgraph.register_dependencies("adminconn", ["database"]);
    depgraph.register_dependencies("extensions", ["database","adminconn"]);
    depgraph.register_dependencies("schema_table", ["database","ownerconn"]);
    depgraph.register_dependencies("schemas", ["ownerconn","extensions","schema_table","appuser"]);
    depgraph.register_dependencies("appconn", ["database","appuser","schemas"]);

    depgraph.set_target("appconn");
    depgraph.mark_as_satisfied(["owneruser","appuser"]);

    let mut results: Vec<String> = Vec::new();

    loop {
        assert!(results.len() < 30);

        let thing = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied([thing.as_slice()]);
        results.push(thing);
    }
    assert!( !results.contains(&String::from_str("superconn")) );
}
<commit_msg>Comply with upstream: crate_id changed to crate_name, no longer accepts version<commit_after>// Dependency Graph Library in Rust

//! dglr is a Dependency Graph Library in Rust.
//! In short, you register elements and their dependencies, and then
//! ask for the dependencies of any element in an order that satisfies.
//!
//! Elements are simply &str strings.  You register them with
//! register_dependency() or register_dependencies().
//!
//! Dependenies are (currently) just a list of other elements that
//! the element in question depends on.  [In the future, we may add
//! boolean logic, but currently they are all AND-ed together].
//!
//! Then call get_ordered_dependencies_of() and the library does the
//! magic and returns an order which will work.  It is possible that
//! other orders also work, but the library's algorithm is
//! deterministic, so you'll always get the same particular one.

#![crate_name = "dglr"]
#![crate_type = "lib"]

// Required for log and rustdoc:
#![feature(phase)]
#[phase(plugin, link)]

extern crate log;

use std::collections::hashmap::{HashMap,HashSet};
use std::iter::{Iterator};
#[allow(unused_imports)]
use std::task;

/// This is the dependency graph.  You can create it yourself, or
/// use the convenience methods of new(), register_dependency() and
/// register_dependencies() to build one up (that must be mutable).
pub struct DepGraph {
    /// List of dependencies.  Key is the element, values are the
    /// other elements that the key element depends upon.
    pub dependencies: HashMap<String,Vec<String>>,

    // (private) target we are trying to satisfy
    target: Option<String>,

    // (private) elements already satisfied
    satisfied: HashSet<String>,

    // (private) current path, for cycle detection
    curpath: HashSet<String>,
}

pub struct DepGraphIterator<'a> {
    depgraph: &'a mut DepGraph
}
pub struct DepGraphSatisfyingIterator<'a> {
    depgraph: &'a mut DepGraph
}

impl DepGraph {

    /// Create an empty DepGraph.
    pub fn new() -> DepGraph
    {
        DepGraph {
            dependencies: HashMap::new(),
            target: None,
            curpath: HashSet::new(),
            satisfied: HashSet::new(),
        }
    }

    /// Add a dependency to a DepGraph.  The thing does not need
    /// to pre-exist, nor do the dependency elements.  But if the
    /// thing does pre-exist, the dependsOn will be added to its
    /// existing dependency list.
    pub fn register_dependency<'a>( &mut self,
                                thing: &'a str,
                                dependsOn: &'a str )
    {
        self.dependencies.insert_or_update_with(
            String::from_str(thing),
            vec![String::from_str(dependsOn)],
            |_,v| { v.push(String::from_str(dependsOn)); }
            );
    }

    /// Add multiple dependencies of one thing to a DepGraph.  The
    /// thing does not need to pre-exist, nor do the dependency elements.
    /// But if the thing does pre-exist, the dependsOn will be added
    /// to its existing dependency list.
    pub fn register_dependencies<'a>( &mut self,
                                  thing: &'a str,
                                  dependsOn: &'a[&'a str] )
    {
        let newvec: Vec<String> = dependsOn.iter().map(
            |s| String::from_str(*s)).collect();

        self.dependencies.insert_or_update_with(
            String::from_str(thing),
            newvec.clone(),
            |_,v| { v.push_all(newvec.as_slice()); }
            );
    }

    pub fn set_target<'a>( &mut self, target: &'a str )
    {
        self.target = Some(String::from_str(target));
    }

    pub fn mark_as_satisfied<'a>( &mut self,
                                   things: &'a[&'a str] )
    {
        for thing in things.iter() {
            self.satisfied.insert(String::from_str(*thing));
        }
    }

    fn get_next_dependency(&mut self, thing: &String) -> String
    {
        if self.curpath.contains(thing) {
            fail!("Circular dependency graph at {}",thing);
        }
        self.curpath.insert(thing.clone());

        let deplist = match self.dependencies.find(thing) {
            None => return thing.clone(),
            Some(deplist) => deplist.clone() // ouch
        };

        for n in deplist.iter() {
            if self.satisfied.contains(n) {
                continue;
            }
            return self.get_next_dependency(n);
        }
        // things dependencies are satisfied
        thing.clone()
    }

    pub fn iter<'a>(&'a mut self) -> DepGraphIterator<'a>
    {
        DepGraphIterator {
            depgraph: self
        }
    }

    pub fn satisfying_iter<'a>(&'a mut self) -> DepGraphSatisfyingIterator<'a>
    {
        DepGraphSatisfyingIterator {
            depgraph: self
        }
    }
}

impl<'a> Iterator<String> for DepGraphIterator<'a> {
    fn next(&mut self) -> Option<String>
    {
        let thing = match self.depgraph.target {
            None => return None,
            Some(ref thing) => thing.clone()
        };
        if self.depgraph.satisfied.contains(&thing) {
            return None;
        }
        self.depgraph.curpath.clear();
        Some(self.depgraph.get_next_dependency(&thing))
    }
}

impl<'a> Iterator<String> for DepGraphSatisfyingIterator<'a> {
    fn next(&mut self) -> Option<String>
    {
        let thing = match self.depgraph.target {
            None => return None,
            Some(ref thing) => thing.clone()
        };
        if self.depgraph.satisfied.contains(&thing) {
            return None;
        }
        self.depgraph.curpath.clear();
        let next = self.depgraph.get_next_dependency(&thing);
        self.depgraph.mark_as_satisfied([next.as_slice()]);
        Some(next)
    }
}

#[test]
fn dglr_test_branching() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e","m","g"]);
    depgraph.register_dependency("e","f");
    depgraph.register_dependency("g","h");
    depgraph.register_dependency("h","i");
    depgraph.register_dependencies("i",&["j","k"]);
    depgraph.register_dependencies("k",&["l","m"]);
    depgraph.register_dependency("m","n");

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    loop {
        // detect infinite looping bugs
        assert!(results.len() < 30);

        let thing = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied([thing.as_slice()]);
        results.push(thing);
    }

    assert!( results == vec![String::from_str("d"),
                             String::from_str("b"),
                             String::from_str("f"),
                             String::from_str("e"),
                             String::from_str("n"),
                             String::from_str("m"),
                             String::from_str("j"),
                             String::from_str("l"),
                             String::from_str("k"),
                             String::from_str("i"),
                             String::from_str("h"),
                             String::from_str("g"),
                             String::from_str("c"),
                             String::from_str("a")] );
    //info!("Deps of a = {}",results);
}

#[test]
fn dglr_test_satisfying() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e"]);

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    for thing in depgraph.satisfying_iter() {
        // detect infinite looping bugs
        assert!(results.len() < 30);
        results.push(thing);
    }

    assert!( results == vec![String::from_str("d"),
                             String::from_str("b"),
                             String::from_str("e"),
                             String::from_str("c"),
                             String::from_str("a")] );
    //info!("Deps of a = {}",results);
}

#[test]
fn dglr_test_circular() {

    let task_result = task::try(proc() {
        let mut depgraph: DepGraph = DepGraph::new();
        depgraph.register_dependency("a","b");
        depgraph.register_dependency("b","c");
        depgraph.register_dependency("c","a");
        depgraph.set_target("a");

        let mut results: Vec<String> = Vec::new();

        loop {
            // Detect infinite looping bugs by
            // breaking out successfully (successful
            // proc() means failed test!)
            if results.len() >= 30 { break; }

            let thing = match depgraph.iter().next() {
                Some(x) => x,
                None => break,
            };
            depgraph.mark_as_satisfied([thing.as_slice()]);
            results.push(thing);
        }
    });
    match task_result {
        Ok(_) => fail!("Should have failed at the circular dependency!"),
        Err(_) => () //info!("Successfully detected the circular dependency (ignore task failure)"),
    };
}

#[test]
fn dglr_test_satisfied_stoppage() {

    let mut depgraph: DepGraph = DepGraph::new();
    depgraph.register_dependencies("superconn", []);
    depgraph.register_dependencies("owneruser", ["superconn"]);
    depgraph.register_dependencies("appuser", ["superconn"]);
    depgraph.register_dependencies("database", ["owneruser"]);
    depgraph.register_dependencies("ownerconn", ["database","owneruser"]);
    depgraph.register_dependencies("adminconn", ["database"]);
    depgraph.register_dependencies("extensions", ["database","adminconn"]);
    depgraph.register_dependencies("schema_table", ["database","ownerconn"]);
    depgraph.register_dependencies("schemas", ["ownerconn","extensions","schema_table","appuser"]);
    depgraph.register_dependencies("appconn", ["database","appuser","schemas"]);

    depgraph.set_target("appconn");
    depgraph.mark_as_satisfied(["owneruser","appuser"]);

    let mut results: Vec<String> = Vec::new();

    loop {
        assert!(results.len() < 30);

        let thing = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied([thing.as_slice()]);
        results.push(thing);
    }
    assert!( !results.contains(&String::from_str("superconn")) );
}
<|endoftext|>


<commit_before>//! A shared ordered log.

use std::rc::Rc;
use std::cell::RefCell;
use std::time::{Instant, Duration};
use std::collections::VecDeque;

use ::{communication::Allocate, ExchangeData, PartialOrder};
use ::scheduling::Scheduler;
use worker::Worker;
use dataflow::channels::pact::Exchange;
use dataflow::operators::generic::operator::source;
use dataflow::operators::generic::operator::Operator;
use scheduling::activate::Activator;

// A Sequencer needs all operators firing with high frequency, because
// it uses the timer to gauge progress. If other workers cease
// advancing their own capabilities, although they might receive a
// record they may not actually tick forward their own source clocks,
// and no one will actually form the sequence.
//
// A CatchupActivator is an activator with an optional timestamp
// attached. This allows us to represent a special state, where after
// receiving an action from another worker, each of the other workers
// will keep scheduling its source operator, until its capability
// timestamp exceeds the greatest timestamp that the sink has
// received.
//
// This allows operators to go quiet again until a new requests shows
// up. The operators lose the ability to confirm that nothing is
// scheduled for a particular time (they could request this with a
// no-op event bearing a timestamp), but everyone still sees the same
// sequence.
struct CatchupActivator {
    pub catchup_until: Option<Duration>,
    activator: Activator,
}

impl CatchupActivator {
    pub fn activate(&self) {
        self.activator.activate();
    }
}

/// Orders elements inserted across all workers.
///
/// A Sequencer allows each worker to insert into a consistent ordered
/// sequence that is seen by all workers in the same order.
pub struct Sequencer<T> {
    activator: Rc<RefCell<Option<CatchupActivator>>>,
    send: Rc<RefCell<VecDeque<T>>>, // proposed items.
    recv: Rc<RefCell<VecDeque<T>>>, // sequenced items.
}

impl<T: Ord+ExchangeData> Sequencer<T> {

    /// Creates a new Sequencer.
    ///
    /// The `timer` instant is used to synchronize the workers, who use this
    /// elapsed time as their timestamp. Elements are ordered by this time,
    /// and cannot be made visible until all workers have reached the time.
    pub fn new<A: Allocate>(worker: &mut Worker<A>, timer: Instant) -> Self {

        let send: Rc<RefCell<VecDeque<T>>> = Rc::new(RefCell::new(VecDeque::new()));
        let recv = Rc::new(RefCell::new(VecDeque::new()));
        let send_weak = Rc::downgrade(&send);
        let recv_weak = Rc::downgrade(&recv);

        // The SequenceInput activator will be held by the sequencer,
        // by the operator itself, and by the sink operator. We can
        // only initialize the activator once we obtain the operator
        // address.
        let activator = Rc::new(RefCell::new(None));
        let activator_source = Rc::downgrade(&activator);
        let activator_sink = Rc::downgrade(&activator);

        // build a dataflow used to serialize and circulate commands
        worker.dataflow::<Duration,_,_>(move |dataflow| {

            let scope = dataflow.clone();
            let peers = dataflow.peers();

            let mut recvd = Vec::new();
            let mut vector = Vec::new();

            // a source that attempts to pull from `recv` and produce commands for everyone
            source(dataflow, "SequenceInput", move |capability, info| {

                // intialize activator, now that we have the address
                activator_source.upgrade()
                    .unwrap()
                    .replace(Some(CatchupActivator {
                        activator: scope.activator_for(&info.address[..]),
                        catchup_until: None,
                    }));

                // so we can drop, if input queue vanishes.
                let mut capability = Some(capability);

                // closure broadcasts any commands it grabs.
                move |output| {

                    if let Some(send_queue) = send_weak.upgrade() {

                        // capability *should* still be non-None.
                        let capability = capability.as_mut().expect("Capability unavailable");

                        // downgrade capability to current time.
                        capability.downgrade(&timer.elapsed());

                        // drain and broadcast `send`.
                        let mut session = output.session(&capability);
                        let mut borrow = send_queue.borrow_mut();
                        for element in borrow.drain(..) {
                            for worker_index in 0 .. peers {
                                session.give((worker_index, element.clone()));
                            }
                        }

                        let activator_cell = activator_source.upgrade().expect("can't upgrade activator ref");
                        let mut activator_borrow = activator_cell.borrow_mut();
                        let mut activator = activator_borrow.as_mut().unwrap();

                        if let Some(t) = activator.catchup_until {
                            if capability.time().less_than(&t) {
                                activator.activate();
                            } else {
                                activator.catchup_until = None;
                            }
                        }
                    } else {
                        capability = None;
                    }
                }
            })
            .sink(
                Exchange::new(|x: &(usize, T)| x.0 as u64),
                "SequenceOutput",
                move |input| {

                    // grab each command and queue it up
                    input.for_each(|time, data| {
                        data.swap(&mut vector);
                        for (_worker, element) in vector.drain(..) {
                            recvd.push((time.time().clone(), element));
                        }
                    });

                    recvd.sort();

                    if let Some(last) = recvd.last() {
                        let activator_cell = activator_sink.upgrade().expect("can't upgrade activator ref");
                        let mut activator_borrow = activator_cell.borrow_mut();
                        let mut activator = activator_borrow.as_mut().unwrap();

                        activator.catchup_until = Some(last.0);
                        activator.activate();
                    }

                    // determine how many (which) elements to read from `recvd`.
                    let count = recvd.iter().filter(|&(ref time, _)| !input.frontier().less_equal(time)).count();
                    let iter = recvd.drain(..count);

                    if let Some(recv_queue) = recv_weak.upgrade() {
                        recv_queue.borrow_mut().extend(iter.map(|(_time,elem)| elem));
                    }
                }
            );
        });

        Sequencer { activator, send, recv, }
    }

    /// Adds an element to the shared log.
    pub fn push(&mut self, element: T) {
        self.send.borrow_mut().push_back(element);
        self.activator.borrow_mut().as_mut().unwrap().activate();
    }

    /// Reads the next element from the shared log.
    pub fn next(&mut self) -> Option<T> {
        self.recv.borrow_mut().pop_front()
    }
}
<commit_msg>Make sequencer take a queue of built-in commands<commit_after>//! A shared ordered log.

use std::rc::Rc;
use std::cell::RefCell;
use std::time::{Instant, Duration};
use std::collections::VecDeque;

use ::{communication::Allocate, ExchangeData, PartialOrder};
use ::scheduling::Scheduler;
use worker::Worker;
use dataflow::channels::pact::Exchange;
use dataflow::operators::generic::operator::source;
use dataflow::operators::generic::operator::Operator;
use scheduling::activate::Activator;

// A Sequencer needs all operators firing with high frequency, because
// it uses the timer to gauge progress. If other workers cease
// advancing their own capabilities, although they might receive a
// record they may not actually tick forward their own source clocks,
// and no one will actually form the sequence.
//
// A CatchupActivator is an activator with an optional timestamp
// attached. This allows us to represent a special state, where after
// receiving an action from another worker, each of the other workers
// will keep scheduling its source operator, until its capability
// timestamp exceeds the greatest timestamp that the sink has
// received.
//
// This allows operators to go quiet again until a new requests shows
// up. The operators lose the ability to confirm that nothing is
// scheduled for a particular time (they could request this with a
// no-op event bearing a timestamp), but everyone still sees the same
// sequence.
struct CatchupActivator {
    pub catchup_until: Option<Duration>,
    activator: Activator,
}

impl CatchupActivator {
    pub fn activate(&self) {
        self.activator.activate();
    }
}

/// Orders elements inserted across all workers.
///
/// A Sequencer allows each worker to insert into a consistent ordered
/// sequence that is seen by all workers in the same order.
pub struct Sequencer<T> {
    activator: Rc<RefCell<Option<CatchupActivator>>>,
    send: Rc<RefCell<VecDeque<T>>>, // proposed items.
    recv: Rc<RefCell<VecDeque<T>>>, // sequenced items.
}

impl<T: Ord+ExchangeData> Sequencer<T> {

    /// Creates a new Sequencer.
    ///
    /// The `timer` instant is used to synchronize the workers, who use this
    /// elapsed time as their timestamp. Elements are ordered by this time,
    /// and cannot be made visible until all workers have reached the time.
    pub fn new<A: Allocate>(worker: &mut Worker<A>, timer: Instant, preload: VecDeque<T>) -> Self {

        let send: Rc<RefCell<VecDeque<T>>> = Rc::new(RefCell::new(VecDeque::new()));
        let recv = Rc::new(RefCell::new(preload));
        let send_weak = Rc::downgrade(&send);
        let recv_weak = Rc::downgrade(&recv);

        // The SequenceInput activator will be held by the sequencer,
        // by the operator itself, and by the sink operator. We can
        // only initialize the activator once we obtain the operator
        // address.
        let activator = Rc::new(RefCell::new(None));
        let activator_source = Rc::downgrade(&activator);
        let activator_sink = Rc::downgrade(&activator);

        // build a dataflow used to serialize and circulate commands
        worker.dataflow::<Duration,_,_>(move |dataflow| {

            let scope = dataflow.clone();
            let peers = dataflow.peers();

            let mut recvd = Vec::new();
            let mut vector = Vec::new();

            // a source that attempts to pull from `recv` and produce commands for everyone
            source(dataflow, "SequenceInput", move |capability, info| {

                // intialize activator, now that we have the address
                activator_source.upgrade()
                    .unwrap()
                    .replace(Some(CatchupActivator {
                        activator: scope.activator_for(&info.address[..]),
                        catchup_until: None,
                    }));

                // so we can drop, if input queue vanishes.
                let mut capability = Some(capability);

                // closure broadcasts any commands it grabs.
                move |output| {

                    if let Some(send_queue) = send_weak.upgrade() {

                        // capability *should* still be non-None.
                        let capability = capability.as_mut().expect("Capability unavailable");

                        // downgrade capability to current time.
                        capability.downgrade(&timer.elapsed());

                        // drain and broadcast `send`.
                        let mut session = output.session(&capability);
                        let mut borrow = send_queue.borrow_mut();
                        for element in borrow.drain(..) {
                            for worker_index in 0 .. peers {
                                session.give((worker_index, element.clone()));
                            }
                        }

                        let activator_cell = activator_source.upgrade().expect("can't upgrade activator ref");
                        let mut activator_borrow = activator_cell.borrow_mut();
                        let mut activator = activator_borrow.as_mut().unwrap();

                        if let Some(t) = activator.catchup_until {
                            if capability.time().less_than(&t) {
                                activator.activate();
                            } else {
                                activator.catchup_until = None;
                            }
                        }
                    } else {
                        capability = None;
                    }
                }
            })
            .sink(
                Exchange::new(|x: &(usize, T)| x.0 as u64),
                "SequenceOutput",
                move |input| {

                    // grab each command and queue it up
                    input.for_each(|time, data| {
                        data.swap(&mut vector);
                        for (_worker, element) in vector.drain(..) {
                            recvd.push((time.time().clone(), element));
                        }
                    });

                    recvd.sort();

                    if let Some(last) = recvd.last() {
                        let activator_cell = activator_sink.upgrade().expect("can't upgrade activator ref");
                        let mut activator_borrow = activator_cell.borrow_mut();
                        let mut activator = activator_borrow.as_mut().unwrap();

                        activator.catchup_until = Some(last.0);
                        activator.activate();
                    }

                    // determine how many (which) elements to read from `recvd`.
                    let count = recvd.iter().filter(|&(ref time, _)| !input.frontier().less_equal(time)).count();
                    let iter = recvd.drain(..count);

                    if let Some(recv_queue) = recv_weak.upgrade() {
                        recv_queue.borrow_mut().extend(iter.map(|(_time,elem)| elem));
                    }
                }
            );
        });

        Sequencer { activator, send, recv, }
    }

    /// Adds an element to the shared log.
    pub fn push(&mut self, element: T) {
        self.send.borrow_mut().push_back(element);
        self.activator.borrow_mut().as_mut().unwrap().activate();
    }

    /// Reads the next element from the shared log.
    pub fn next(&mut self) -> Option<T> {
        self.recv.borrow_mut().pop_front()
    }
}
<|endoftext|>


<commit_before>use std::num::Float;
use std::sync::{Mutex, Arc};
use std::sync::atomic::{AtomicUint, SeqCst};

pub struct EWMA {
    pub uncounted: AtomicUint, // This tracks uncounted events
    alpha: f64,
    rate: Mutex<f64>,
    init: bool,
}

pub struct EWMASnapshot {
    value: f64
}

impl EWMASnapshot {
    pub fn rate(&self) -> f64 {
        self.value
    }
}

impl EWMA {
    pub fn rate(&self) -> f64 {
        let r = self.rate.lock();

        *r * (1e9 as f64)
    }

    pub fn snapshot(&self) -> EWMASnapshot {
        EWMASnapshot{
            value: self.rate()
        }
    }

    pub fn tick(&mut self) {
        let counter: uint = self.uncounted.load(SeqCst);

        self.uncounted.fetch_sub(counter, SeqCst); // Broken atm

        let mut rate = self.rate.lock();
        let i_rate = (counter as f64) / (5e9);

        if self.init {
            *rate += self.alpha * (i_rate - *rate);
        } else {
            self.init = true;
            *rate = i_rate;
        }

        rate.cond.signal();
    }

    pub fn update(&self, n: uint) {
        self.uncounted.fetch_add(n, SeqCst);
    }

    // construct new by alpha
    pub fn new_by_alpha(alpha: f64) -> EWMA {
        EWMA{
            uncounted: AtomicUint::new(0u),
            alpha: alpha,
            rate: Mutex::new(0f64),
            init: false
        }
    }

    // constructs a new EWMA for a n-minute moving average.
    pub fn new(rate: f64) -> EWMA {
        let i: f64 = -5.0f64 / 60.0f64 / rate;
        EWMA::new_by_alpha(1f64 - i.exp())
    }
}

#[cfg(test)]
mod test {
    use ewma::EWMA;
    use std::num::Float;

    // Tick a minute
    fn elapse_minute(e: &mut EWMA) {
        for i in range(0i, 12i) {
            e.tick();
        }
    }

    // Returns whether the rate() is within 0.0001 of expected after ticking a minute
    fn within(e: &mut EWMA, expected: f64) -> bool {
        elapse_minute(e);
        let r: f64 = e.rate();
        (r - expected).abs() < 0.0001
    }

    #[test]
    fn ewma1() {
        let mut e = EWMA::new(1f64);
        e.update(3u);
        e.tick();

        let mut r: f64;

        // initial
        r = e.rate();
        assert_eq!(r, 0.6f64);

        // 1 minute
        assert_eq!(within(&mut e, 0.22072766470286553f64), true);

        // 2 minute
        assert_eq!(within(&mut e, 0.08120116994196772f64), true);

        // 3 minute
        assert_eq!(within(&mut e, 0.029872241020718428f64), true);

        // 4 minute
        assert_eq!(within(&mut e, 0.01098938333324054f64), true);

        // 5 minute
        assert_eq!(within(&mut e, 0.004042768199451294f64), true);

        // 6 minute
        assert_eq!(within(&mut e, 0.0014872513059998212f64), true);

        // 7 minute
        assert_eq!(within(&mut e, 0.0005471291793327122f64), true);

        // 8 minute
        assert_eq!(within(&mut e, 0.00020127757674150815f64), true);

        // 9 minute
        assert_eq!(within(&mut e, 7.404588245200814e-05f64), true);

        // 10 minute
        assert_eq!(within(&mut e, 2.7239957857491083e-05f64), true);

        // 11 minute
        assert_eq!(within(&mut e, 1.0021020474147462e-05f64), true);

        // 12 minute
        assert_eq!(within(&mut e, 3.6865274119969525e-06f64), true);

        // 13 minute
        assert_eq!(within(&mut e, 1.3561976441886433e-06f64), true);

        // 14 minute
        assert_eq!(within(&mut e, 4.989172314621449e-07f64), true);

        // 15 minute
        assert_eq!(within(&mut e, 1.8354139230109722e-07f64), true);
    }

    #[test]
    fn ewma5() {
        let mut e = EWMA::new(5f64);
        e.update(3u);
        e.tick();

        let r: f64 = e.rate();
        assert_eq!(r, 0.6f64);

        // 1 minute
        assert_eq!(within(&mut e, 0.49123845184678905f64), true);

                // 2 minute
        assert_eq!(within(&mut e, 0.4021920276213837f64), true);

        // 3 minute
        assert_eq!(within(&mut e, 0.32928698165641596f64), true);

        // 4 minute
        assert_eq!(within(&mut e, 0.269597378470333f64), true);

        // 5 minute
        assert_eq!(within(&mut e, 0.2207276647028654f64), true);

        // 6 minute
        assert_eq!(within(&mut e, 0.18071652714732128f64), true);

        // 7 minute
        assert_eq!(within(&mut e, 0.14795817836496392f64), true);

        // 8 minute
        assert_eq!(within(&mut e, 0.12113791079679326f64), true);

        // 9 minute
        assert_eq!(within(&mut e, 0.09917933293295193f64), true);

        // 10 minute
        assert_eq!(within(&mut e, 0.08120116994196763f64), true);

        // 11 minute
        assert_eq!(within(&mut e, 0.06648189501740036), true);

        // 12 minute
        assert_eq!(within(&mut e, 0.05443077197364752f64), true);

        // 13 minute
        assert_eq!(within(&mut e, 0.04456414692860035f64), true);

        // 14 minute
        assert_eq!(within(&mut e, 0.03648603757513079f64), true);

        // 15 minute
        assert_eq!(within(&mut e, 0.0298722410207183831020718428f64), true);
    }

        #[test]
    fn ewma15() {
        let mut e = EWMA::new(15f64);
        e.update(3u);
        e.tick();

        let r: f64 = e.rate();
        assert_eq!(r, 0.6f64);

        // 1 minute
        assert_eq!(within(&mut e, 0.5613041910189706f64), true);

        // 2 minute
        assert_eq!(within(&mut e, 0.5251039914257684f64), true);

        // 3 minute
        assert_eq!(within(&mut e, 0.4912384518467888184678905f64), true);

        // 4 minute
        assert_eq!(within(&mut e, 0.459557003018789f64), true);

        // 5 minute
        assert_eq!(within(&mut e, 0.4299187863442732f64), true);

        // 6 minute
        assert_eq!(within(&mut e, 0.4021920276213831f64), true);

        // 7 minute
        assert_eq!(within(&mut e, 0.37625345116383313f64), true);

        // 8 minute
        assert_eq!(within(&mut e, 0.3519877317060185f64), true);

        // 9 minute
        assert_eq!(within(&mut e, 0.3292869816564153165641596f64), true);

        // 10 minute
        assert_eq!(within(&mut e, 0.3080502714195546f64), true);

        // 11 minute
        assert_eq!(within(&mut e, 0.2881831806538789f64), true);

        // 12 minute
        assert_eq!(within(&mut e, 0.26959737847033216f64), true);

        // 13 minute
        assert_eq!(within(&mut e, 0.2522102307052083f64), true);

        // 14 minute
        assert_eq!(within(&mut e, 0.23594443252115815f64), true);

        // 15 minute
        assert_eq!(within(&mut e, 0.2207276647028646247028654470286553f64), true);
    }
}<commit_msg>Fix unused import warning<commit_after>use std::num::Float;
use std::sync::Mutex;
use std::sync::atomic::{AtomicUint, SeqCst};

pub struct EWMA {
    pub uncounted: AtomicUint, // This tracks uncounted events
    alpha: f64,
    rate: Mutex<f64>,
    init: bool,
}

pub struct EWMASnapshot {
    value: f64
}

impl EWMASnapshot {
    pub fn rate(&self) -> f64 {
        self.value
    }
}

impl EWMA {
    pub fn rate(&self) -> f64 {
        let r = self.rate.lock();

        *r * (1e9 as f64)
    }

    pub fn snapshot(&self) -> EWMASnapshot {
        EWMASnapshot{
            value: self.rate()
        }
    }

    pub fn tick(&mut self) {
        let counter: uint = self.uncounted.load(SeqCst);

        self.uncounted.fetch_sub(counter, SeqCst); // Broken atm

        let mut rate = self.rate.lock();
        let i_rate = (counter as f64) / (5e9);

        if self.init {
            *rate += self.alpha * (i_rate - *rate);
        } else {
            self.init = true;
            *rate = i_rate;
        }

        rate.cond.signal();
    }

    pub fn update(&self, n: uint) {
        self.uncounted.fetch_add(n, SeqCst);
    }

    // construct new by alpha
    pub fn new_by_alpha(alpha: f64) -> EWMA {
        EWMA{
            uncounted: AtomicUint::new(0u),
            alpha: alpha,
            rate: Mutex::new(0f64),
            init: false
        }
    }

    // constructs a new EWMA for a n-minute moving average.
    pub fn new(rate: f64) -> EWMA {
        let i: f64 = -5.0f64 / 60.0f64 / rate;
        EWMA::new_by_alpha(1f64 - i.exp())
    }
}

#[cfg(test)]
mod test {
    use ewma::EWMA;
    use std::num::Float;

    // Tick a minute
    fn elapse_minute(e: &mut EWMA) {
        for i in range(0i, 12i) {
            e.tick();
        }
    }

    // Returns whether the rate() is within 0.0001 of expected after ticking a minute
    fn within(e: &mut EWMA, expected: f64) -> bool {
        elapse_minute(e);
        let r: f64 = e.rate();
        (r - expected).abs() < 0.0001
    }

    #[test]
    fn ewma1() {
        let mut e = EWMA::new(1f64);
        e.update(3u);
        e.tick();

        let mut r: f64;

        // initial
        r = e.rate();
        assert_eq!(r, 0.6f64);

        // 1 minute
        assert_eq!(within(&mut e, 0.22072766470286553f64), true);

        // 2 minute
        assert_eq!(within(&mut e, 0.08120116994196772f64), true);

        // 3 minute
        assert_eq!(within(&mut e, 0.029872241020718428f64), true);

        // 4 minute
        assert_eq!(within(&mut e, 0.01098938333324054f64), true);

        // 5 minute
        assert_eq!(within(&mut e, 0.004042768199451294f64), true);

        // 6 minute
        assert_eq!(within(&mut e, 0.0014872513059998212f64), true);

        // 7 minute
        assert_eq!(within(&mut e, 0.0005471291793327122f64), true);

        // 8 minute
        assert_eq!(within(&mut e, 0.00020127757674150815f64), true);

        // 9 minute
        assert_eq!(within(&mut e, 7.404588245200814e-05f64), true);

        // 10 minute
        assert_eq!(within(&mut e, 2.7239957857491083e-05f64), true);

        // 11 minute
        assert_eq!(within(&mut e, 1.0021020474147462e-05f64), true);

        // 12 minute
        assert_eq!(within(&mut e, 3.6865274119969525e-06f64), true);

        // 13 minute
        assert_eq!(within(&mut e, 1.3561976441886433e-06f64), true);

        // 14 minute
        assert_eq!(within(&mut e, 4.989172314621449e-07f64), true);

        // 15 minute
        assert_eq!(within(&mut e, 1.8354139230109722e-07f64), true);
    }

    #[test]
    fn ewma5() {
        let mut e = EWMA::new(5f64);
        e.update(3u);
        e.tick();

        let r: f64 = e.rate();
        assert_eq!(r, 0.6f64);

        // 1 minute
        assert_eq!(within(&mut e, 0.49123845184678905f64), true);

                // 2 minute
        assert_eq!(within(&mut e, 0.4021920276213837f64), true);

        // 3 minute
        assert_eq!(within(&mut e, 0.32928698165641596f64), true);

        // 4 minute
        assert_eq!(within(&mut e, 0.269597378470333f64), true);

        // 5 minute
        assert_eq!(within(&mut e, 0.2207276647028654f64), true);

        // 6 minute
        assert_eq!(within(&mut e, 0.18071652714732128f64), true);

        // 7 minute
        assert_eq!(within(&mut e, 0.14795817836496392f64), true);

        // 8 minute
        assert_eq!(within(&mut e, 0.12113791079679326f64), true);

        // 9 minute
        assert_eq!(within(&mut e, 0.09917933293295193f64), true);

        // 10 minute
        assert_eq!(within(&mut e, 0.08120116994196763f64), true);

        // 11 minute
        assert_eq!(within(&mut e, 0.06648189501740036), true);

        // 12 minute
        assert_eq!(within(&mut e, 0.05443077197364752f64), true);

        // 13 minute
        assert_eq!(within(&mut e, 0.04456414692860035f64), true);

        // 14 minute
        assert_eq!(within(&mut e, 0.03648603757513079f64), true);

        // 15 minute
        assert_eq!(within(&mut e, 0.0298722410207183831020718428f64), true);
    }

        #[test]
    fn ewma15() {
        let mut e = EWMA::new(15f64);
        e.update(3u);
        e.tick();

        let r: f64 = e.rate();
        assert_eq!(r, 0.6f64);

        // 1 minute
        assert_eq!(within(&mut e, 0.5613041910189706f64), true);

        // 2 minute
        assert_eq!(within(&mut e, 0.5251039914257684f64), true);

        // 3 minute
        assert_eq!(within(&mut e, 0.4912384518467888184678905f64), true);

        // 4 minute
        assert_eq!(within(&mut e, 0.459557003018789f64), true);

        // 5 minute
        assert_eq!(within(&mut e, 0.4299187863442732f64), true);

        // 6 minute
        assert_eq!(within(&mut e, 0.4021920276213831f64), true);

        // 7 minute
        assert_eq!(within(&mut e, 0.37625345116383313f64), true);

        // 8 minute
        assert_eq!(within(&mut e, 0.3519877317060185f64), true);

        // 9 minute
        assert_eq!(within(&mut e, 0.3292869816564153165641596f64), true);

        // 10 minute
        assert_eq!(within(&mut e, 0.3080502714195546f64), true);

        // 11 minute
        assert_eq!(within(&mut e, 0.2881831806538789f64), true);

        // 12 minute
        assert_eq!(within(&mut e, 0.26959737847033216f64), true);

        // 13 minute
        assert_eq!(within(&mut e, 0.2522102307052083f64), true);

        // 14 minute
        assert_eq!(within(&mut e, 0.23594443252115815f64), true);

        // 15 minute
        assert_eq!(within(&mut e, 0.2207276647028646247028654470286553f64), true);
    }
}
<|endoftext|>


<commit_before>#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Expr {
    Int(isize),
    Cons(Box<Expr>, Box<Expr>),
    Nil,
    EOF
}

<commit_msg>add symol and string<commit_after>#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Expr {
    Int(isize),
    Cons(Box<Expr>, Box<Expr>),
    Nil,
    Sym(String),
    Str(String),
    EOF
}

<|endoftext|>


<commit_before>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fmt::{self, Display, Formatter};
use std::{error, result};

use grpc_sys::GrpcCallStatus;
#[cfg(feature = "protobuf-codec")]
use protobuf::ProtobufError;

use call::RpcStatus;

/// Errors generated from this library.
#[derive(Debug)]
pub enum Error {
    /// Codec error.
    Codec(Box<error::Error + Send + Sync>),
    /// Failed to start an internal async call.
    CallFailure(GrpcCallStatus),
    /// Rpc request fail.
    RpcFailure(RpcStatus),
    /// Try to write to a finished rpc call.
    RpcFinished(Option<RpcStatus>),
    /// Remote is stopped.
    RemoteStopped,
    /// Failed to shutdown.
    ShutdownFailed,
    /// Failed to bind.
    BindFail(String, u16),
    /// gRPC completion queue is shutdown.
    QueueShutdown,
    /// Failed to create Google default credentials.
    GoogleAuthenticationFailed,
    /// Invalid format of metadata.
    InvalidMetadata(String),
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "{:?}", self)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Codec(_) => "gRPC Codec Error",
            Error::CallFailure(_) => "gRPC Call Error",
            Error::RpcFailure(_) => "gRPC Request Error",
            Error::RpcFinished(_) => "gRPC Finish Error",
            Error::RemoteStopped => "Remote is stopped.",
            Error::ShutdownFailed => "Failed to shutdown.",
            Error::BindFail(_, _) => "gRPC Bind Error",
            Error::QueueShutdown => "gRPC completion queue shutdown",
            Error::GoogleAuthenticationFailed => "Could not create google default credentials.",
            Error::InvalidMetadata(_) => "invalid format of metadata",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Codec(ref e) => Some(e.as_ref()),
            _ => None,
        }
    }
}

#[cfg(feature = "protobuf-codec")]
impl From<ProtobufError> for Error {
    fn from(e: ProtobufError) -> Error {
        Error::Codec(Box::new(e))
    }
}

/// Type alias to use this library's [`Error`] type in a `Result`.
pub type Result<T> = result::Result<T, Error>;

#[cfg(all(test, feature = "protobuf-codec"))]
mod tests {
    use std::error::Error as StdError;

    use protobuf::error::WireError;
    use protobuf::ProtobufError;

    use super::Error;

    #[test]
    fn test_convert() {
        let error = ProtobufError::WireError(WireError::UnexpectedEof);
        let e: Error = error.into();
        assert_eq!(e.description(), "gRPC Codec Error");
        assert!(e.cause().is_some());
    }
}
<commit_msg>error: allow deprecated `Error::cause` (#268)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fmt::{self, Display, Formatter};
use std::{error, result};

use grpc_sys::GrpcCallStatus;
#[cfg(feature = "protobuf-codec")]
use protobuf::ProtobufError;

use call::RpcStatus;

/// Errors generated from this library.
#[derive(Debug)]
pub enum Error {
    /// Codec error.
    Codec(Box<error::Error + Send + Sync>),
    /// Failed to start an internal async call.
    CallFailure(GrpcCallStatus),
    /// Rpc request fail.
    RpcFailure(RpcStatus),
    /// Try to write to a finished rpc call.
    RpcFinished(Option<RpcStatus>),
    /// Remote is stopped.
    RemoteStopped,
    /// Failed to shutdown.
    ShutdownFailed,
    /// Failed to bind.
    BindFail(String, u16),
    /// gRPC completion queue is shutdown.
    QueueShutdown,
    /// Failed to create Google default credentials.
    GoogleAuthenticationFailed,
    /// Invalid format of metadata.
    InvalidMetadata(String),
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "{:?}", self)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Codec(_) => "gRPC Codec Error",
            Error::CallFailure(_) => "gRPC Call Error",
            Error::RpcFailure(_) => "gRPC Request Error",
            Error::RpcFinished(_) => "gRPC Finish Error",
            Error::RemoteStopped => "Remote is stopped.",
            Error::ShutdownFailed => "Failed to shutdown.",
            Error::BindFail(_, _) => "gRPC Bind Error",
            Error::QueueShutdown => "gRPC completion queue shutdown",
            Error::GoogleAuthenticationFailed => "Could not create google default credentials.",
            Error::InvalidMetadata(_) => "invalid format of metadata",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Codec(ref e) => Some(e.as_ref()),
            _ => None,
        }
    }

    // TODO: impl `Error::source`, but it may break backward compatibility,
    // Eg. TiKV still uses nightly-2018-07-18, which does not compile.
}

#[cfg(feature = "protobuf-codec")]
impl From<ProtobufError> for Error {
    fn from(e: ProtobufError) -> Error {
        Error::Codec(Box::new(e))
    }
}

/// Type alias to use this library's [`Error`] type in a `Result`.
pub type Result<T> = result::Result<T, Error>;

#[cfg(all(test, feature = "protobuf-codec"))]
mod tests {
    use std::error::Error as StdError;

    use protobuf::error::WireError;
    use protobuf::ProtobufError;

    use super::Error;

    #[allow(deprecated)]
    #[test]
    fn test_convert() {
        let error = ProtobufError::WireError(WireError::UnexpectedEof);
        let e: Error = error.into();
        assert_eq!(e.description(), "gRPC Codec Error");
        assert!(e.cause().is_some());
    }
}
<|endoftext|>


<commit_before>use crate::alloc::{String, ToString};
use core::fmt::{self, Display};

/// Error when a `Serializer` or `Deserializer` trait object fails.
#[derive(Debug)]
pub struct Error {
    msg: String,
}

/// Result type alias where the error is `erased_serde::Error`.
pub type Result<T> = core::result::Result<T, Error>;

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.msg.fmt(formatter)
    }
}

#[cfg(feature = "std")]
impl std::error::Error for Error {}

#[cfg(not(feature = "std"))]
impl serde::ser::StdError for Error {}

impl serde::ser::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error {
            msg: msg.to_string(),
        }
    }
}

impl serde::de::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error {
            msg: msg.to_string(),
        }
    }
}
<commit_msg>Do std error implementation without conditional compilation<commit_after>use crate::alloc::{String, ToString};
use core::fmt::{self, Display};

/// Error when a `Serializer` or `Deserializer` trait object fails.
#[derive(Debug)]
pub struct Error {
    msg: String,
}

/// Result type alias where the error is `erased_serde::Error`.
pub type Result<T> = core::result::Result<T, Error>;

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.msg.fmt(formatter)
    }
}

impl serde::ser::StdError for Error {}

impl serde::ser::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error {
            msg: msg.to_string(),
        }
    }
}

impl serde::de::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error {
            msg: msg.to_string(),
        }
    }
}
<|endoftext|>


<commit_before>
use ffi;

pub type FtResult<T> = Result<T, Error>;

#[deriving(Clone, PartialEq, Eq, Show)]
#[repr(i32)]
pub enum Error {
    Ok                          = ffi::FT_Err_Ok,
    CannotOpenResource          = ffi::FT_Err_Cannot_Open_Resource,
    UnknownFileFormat           = ffi::FT_Err_Unknown_File_Format,
    InvalidFileFormat           = ffi::FT_Err_Invalid_File_Format,
    InvalidVersion              = ffi::FT_Err_Invalid_Version,
    LowerModuleVersion          = ffi::FT_Err_Lower_Module_Version,
    InvalidArgument             = ffi::FT_Err_Invalid_Argument,
    UnimplementedFeature        = ffi::FT_Err_Unimplemented_Feature,
    InvalidTable                = ffi::FT_Err_Invalid_Table,
    InvalidOffset               = ffi::FT_Err_Invalid_Offset,
    ArrayTooLarge               = ffi::FT_Err_Array_Too_Large,
    MissingModule               = ffi::FT_Err_Missing_Module,
    MissingProperty             = ffi::FT_Err_Missing_Property,
    InvalidGlyphIndex           = ffi::FT_Err_Invalid_Glyph_Index,
    InvalidCharacterCode        = ffi::FT_Err_Invalid_Character_Code,
    InvalidGlyphFormat          = ffi::FT_Err_Invalid_Glyph_Format,
    CannotRenderGlyph           = ffi::FT_Err_Cannot_Render_Glyph,
    InvalidOutline              = ffi::FT_Err_Invalid_Outline,
    InvalidComposite            = ffi::FT_Err_Invalid_Composite,
    TooManyHints                = ffi::FT_Err_Too_Many_Hints,
    InvalidPixelSize            = ffi::FT_Err_Invalid_Pixel_Size,
    InvalidHandle               = ffi::FT_Err_Invalid_Handle,
    InvalidLibraryHandle        = ffi::FT_Err_Invalid_Library_Handle,
    InvalidDriverHandle         = ffi::FT_Err_Invalid_Driver_Handle,
    InvalidFaceHandle           = ffi::FT_Err_Invalid_Face_Handle,
    InvalidSizeHandle           = ffi::FT_Err_Invalid_Size_Handle,
    InvalidSlotHandle           = ffi::FT_Err_Invalid_Slot_Handle,
    InvalidCharMapHandle        = ffi::FT_Err_Invalid_CharMap_Handle,
    InvalidCacheHandle          = ffi::FT_Err_Invalid_Cache_Handle,
    InvalidStreamHandle         = ffi::FT_Err_Invalid_Stream_Handle,
    TooManyDrivers              = ffi::FT_Err_Too_Many_Drivers,
    TooManyExtensions           = ffi::FT_Err_Too_Many_Extensions,
    OutOfMemory                 = ffi::FT_Err_Out_Of_Memory,
    UnlistedObject              = ffi::FT_Err_Unlisted_Object,
    CannotOpenStream            = ffi::FT_Err_Cannot_Open_Stream,
    InvalidStreamSeek           = ffi::FT_Err_Invalid_Stream_Seek,
    InvalidStreamSkip           = ffi::FT_Err_Invalid_Stream_Skip,
    InvalidStreamRead           = ffi::FT_Err_Invalid_Stream_Read,
    InvalidStreamOperation      = ffi::FT_Err_Invalid_Stream_Operation,
    InvalidFrameOperation       = ffi::FT_Err_Invalid_Frame_Operation,
    NestedFrameAccess           = ffi::FT_Err_Nested_Frame_Access,
    InvalidFrameRead            = ffi::FT_Err_Invalid_Frame_Read,
    RasterUninitialized         = ffi::FT_Err_Raster_Uninitialized,
    RasterCorrupted             = ffi::FT_Err_Raster_Corrupted,
    RasterOverflow              = ffi::FT_Err_Raster_Overflow,
    RasterNegativeHeight        = ffi::FT_Err_Raster_Negative_Height,
    TooManyCaches               = ffi::FT_Err_Too_Many_Caches,
    InvalidOpcode               = ffi::FT_Err_Invalid_Opcode,
    TooFewArguments             = ffi::FT_Err_Too_Few_Arguments,
    StackOverflow               = ffi::FT_Err_Stack_Overflow,
    CodeOverflow                = ffi::FT_Err_Code_Overflow,
    BadArgument                 = ffi::FT_Err_Bad_Argument,
    DivideByZero                = ffi::FT_Err_Divide_By_Zero,
    InvalidReference            = ffi::FT_Err_Invalid_Reference,
    DebugOpCode                 = ffi::FT_Err_Debug_OpCode,
    ENDFInExecStream            = ffi::FT_Err_ENDF_In_Exec_Stream,
    NestedDEFS                  = ffi::FT_Err_Nested_DEFS,
    InvalidCodeRange            = ffi::FT_Err_Invalid_CodeRange,
    ExecutionTooLong            = ffi::FT_Err_Execution_Too_Long,
    TooManyFunctionDefs         = ffi::FT_Err_Too_Many_Function_Defs,
    TooManyInstructionDefs      = ffi::FT_Err_Too_Many_Instruction_Defs,
    TableMissing                = ffi::FT_Err_Table_Missing,
    HorizHeaderMissing          = ffi::FT_Err_Horiz_Header_Missing,
    LocationsMissing            = ffi::FT_Err_Locations_Missing,
    NameTableMissing            = ffi::FT_Err_Name_Table_Missing,
    CMapTableMissing            = ffi::FT_Err_CMap_Table_Missing,
    HmtxTableMissing            = ffi::FT_Err_Hmtx_Table_Missing,
    PostTableMissing            = ffi::FT_Err_Post_Table_Missing,
    InvalidHorizMetrics         = ffi::FT_Err_Invalid_Horiz_Metrics,
    InvalidCharMapFormat        = ffi::FT_Err_Invalid_CharMap_Format,
    InvalidPPem                 = ffi::FT_Err_Invalid_PPem,
    InvalidVertMetrics          = ffi::FT_Err_Invalid_Vert_Metrics,
    CouldNotFindContext         = ffi::FT_Err_Could_Not_Find_Context,
    InvalidPostTableFormat      = ffi::FT_Err_Invalid_Post_Table_Format,
    InvalidPostTable            = ffi::FT_Err_Invalid_Post_Table,
    SyntaxError                 = ffi::FT_Err_Syntax_Error,
    StackUnderflow              = ffi::FT_Err_Stack_Underflow,
    Ignore                      = ffi::FT_Err_Ignore,
    NoUnicodeGlyphName          = ffi::FT_Err_No_Unicode_Glyph_Name,
    MissingStartfontField       = ffi::FT_Err_Missing_Startfont_Field,
    MissingFontField            = ffi::FT_Err_Missing_Font_Field,
    MissingSizeField            = ffi::FT_Err_Missing_Size_Field,
    MissingFontboundingboxField = ffi::FT_Err_Missing_Fontboundingbox_Field,
    MissingCharsField           = ffi::FT_Err_Missing_Chars_Field,
    MissingStartcharField       = ffi::FT_Err_Missing_Startchar_Field,
    MissingEncodingField        = ffi::FT_Err_Missing_Encoding_Field,
    MissingBbxField             = ffi::FT_Err_Missing_Bbx_Field,
    BbxTooBig                   = ffi::FT_Err_Bbx_Too_Big,
    CorruptedFontHeader         = ffi::FT_Err_Corrupted_Font_Header,
    CorruptedFontGlyphs         = ffi::FT_Err_Corrupted_Font_Glyphs,
    Max                         = ffi::FT_Err_Max,
    UnknownError,
}

impl FromPrimitive for Error {
    fn from_i64(n: i64) -> Option<Error> {
        FromPrimitive::from_i32(n as i32)
    }

    fn from_u64(n: u64) -> Option<Error> {
        FromPrimitive::from_i32(n as i32)
    }

    #[allow(non_upper_case_globals)]
    fn from_i32(n: i32) -> Option<Error> {
        match n {
            ffi::FT_Err_Ok                            => Some(Ok),
            ffi::FT_Err_Cannot_Open_Resource          => Some(ffi::CannotOpenResource),
            ffi::FT_Err_Unknown_File_Format           => Some(ffi::UnknownFileFormat),
            ffi::FT_Err_Invalid_File_Format           => Some(ffi::InvalidFileFormat),
            ffi::FT_Err_Invalid_Version               => Some(ffi::InvalidVersion),
            ffi::FT_Err_Lower_Module_Version          => Some(ffi::LowerModuleVersion),
            ffi::FT_Err_Invalid_Argument              => Some(ffi::InvalidArgument),
            ffi::FT_Err_Unimplemented_Feature         => Some(ffi::UnimplementedFeature),
            ffi::FT_Err_Invalid_Table                 => Some(ffi::InvalidTable),
            ffi::FT_Err_Invalid_Offset                => Some(ffi::InvalidOffset),
            ffi::FT_Err_Array_Too_Large               => Some(ffi::ArrayTooLarge),
            ffi::FT_Err_Missing_Module                => Some(ffi::MissingModule),
            ffi::FT_Err_Missing_Property              => Some(ffi::MissingProperty),
            ffi::FT_Err_Invalid_Glyph_Index           => Some(ffi::InvalidGlyphIndex),
            ffi::FT_Err_Invalid_Character_Code        => Some(ffi::InvalidCharacterCode),
            ffi::FT_Err_Invalid_Glyph_Format          => Some(ffi::InvalidGlyphFormat),
            ffi::FT_Err_Cannot_Render_Glyph           => Some(ffi::CannotRenderGlyph),
            ffi::FT_Err_Invalid_Outline               => Some(ffi::InvalidOutline),
            ffi::FT_Err_Invalid_Composite             => Some(ffi::InvalidComposite),
            ffi::FT_Err_Too_Many_Hints                => Some(ffi::TooManyHints),
            ffi::FT_Err_Invalid_Pixel_Size            => Some(ffi::InvalidPixelSize),
            ffi::FT_Err_Invalid_Handle                => Some(ffi::InvalidHandle),
            ffi::FT_Err_Invalid_Library_Handle        => Some(ffi::InvalidLibraryHandle),
            ffi::FT_Err_Invalid_Driver_Handle         => Some(ffi::InvalidDriverHandle),
            ffi::FT_Err_Invalid_Face_Handle           => Some(ffi::InvalidFaceHandle),
            ffi::FT_Err_Invalid_Size_Handle           => Some(ffi::InvalidSizeHandle),
            ffi::FT_Err_Invalid_Slot_Handle           => Some(ffi::InvalidSlotHandle),
            ffi::FT_Err_Invalid_CharMap_Handle        => Some(ffi::InvalidCharMapHandle),
            ffi::FT_Err_Invalid_Cache_Handle          => Some(ffi::InvalidCacheHandle),
            ffi::FT_Err_Invalid_Stream_Handle         => Some(ffi::InvalidStreamHandle),
            ffi::FT_Err_Too_Many_Drivers              => Some(ffi::TooManyDrivers),
            ffi::FT_Err_Too_Many_Extensions           => Some(ffi::TooManyExtensions),
            ffi::FT_Err_Out_Of_Memory                 => Some(ffi::OutOfMemory),
            ffi::FT_Err_Unlisted_Object               => Some(ffi::UnlistedObject),
            ffi::FT_Err_Cannot_Open_Stream            => Some(ffi::CannotOpenStream),
            ffi::FT_Err_Invalid_Stream_Seek           => Some(ffi::InvalidStreamSeek),
            ffi::FT_Err_Invalid_Stream_Skip           => Some(ffi::InvalidStreamSkip),
            ffi::FT_Err_Invalid_Stream_Read           => Some(ffi::InvalidStreamRead),
            ffi::FT_Err_Invalid_Stream_Operation      => Some(ffi::InvalidStreamOperation),
            ffi::FT_Err_Invalid_Frame_Operation       => Some(ffi::InvalidFrameOperation),
            ffi::FT_Err_Nested_Frame_Access           => Some(ffi::NestedFrameAccess),
            ffi::FT_Err_Invalid_Frame_Read            => Some(ffi::InvalidFrameRead),
            ffi::FT_Err_Raster_Uninitialized          => Some(ffi::RasterUninitialized),
            ffi::FT_Err_Raster_Corrupted              => Some(ffi::RasterCorrupted),
            ffi::FT_Err_Raster_Overflow               => Some(ffi::RasterOverflow),
            ffi::FT_Err_Raster_Negative_Height        => Some(ffi::RasterNegativeHeight),
            ffi::FT_Err_Too_Many_Caches               => Some(ffi::TooManyCaches),
            ffi::FT_Err_Invalid_Opcode                => Some(ffi::InvalidOpcode),
            ffi::FT_Err_Too_Few_Arguments             => Some(ffi::TooFewArguments),
            ffi::FT_Err_Stack_Overflow                => Some(ffi::StackOverflow),
            ffi::FT_Err_Code_Overflow                 => Some(ffi::CodeOverflow),
            ffi::FT_Err_Bad_Argument                  => Some(ffi::BadArgument),
            ffi::FT_Err_Divide_By_Zero                => Some(ffi::DivideByZero),
            ffi::FT_Err_Invalid_Reference             => Some(ffi::InvalidReference),
            ffi::FT_Err_Debug_OpCode                  => Some(ffi::DebugOpCode),
            ffi::FT_Err_ENDF_In_Exec_Stream           => Some(ffi::ENDFInExecStream),
            ffi::FT_Err_Nested_DEFS                   => Some(ffi::NestedDEFS),
            ffi::FT_Err_Invalid_CodeRange             => Some(ffi::InvalidCodeRange),
            ffi::FT_Err_Execution_Too_Long            => Some(ffi::ExecutionTooLong),
            ffi::FT_Err_Too_Many_Function_Defs        => Some(ffi::TooManyFunctionDefs),
            ffi::FT_Err_Too_Many_Instruction_Defs     => Some(ffi::TooManyInstructionDefs),
            ffi::FT_Err_Table_Missing                 => Some(ffi::TableMissing),
            ffi::FT_Err_Horiz_Header_Missing          => Some(ffi::HorizHeaderMissing),
            ffi::FT_Err_Locations_Missing             => Some(ffi::LocationsMissing),
            ffi::FT_Err_Name_Table_Missing            => Some(ffi::NameTableMissing),
            ffi::FT_Err_CMap_Table_Missing            => Some(ffi::CMapTableMissing),
            ffi::FT_Err_Hmtx_Table_Missing            => Some(ffi::HmtxTableMissing),
            ffi::FT_Err_Post_Table_Missing            => Some(ffi::PostTableMissing),
            ffi::FT_Err_Invalid_Horiz_Metrics         => Some(ffi::InvalidHorizMetrics),
            ffi::FT_Err_Invalid_CharMap_Format        => Some(ffi::InvalidCharMapFormat),
            ffi::FT_Err_Invalid_PPem                  => Some(ffi::InvalidPPem),
            ffi::FT_Err_Invalid_Vert_Metrics          => Some(ffi::InvalidVertMetrics),
            ffi::FT_Err_Could_Not_Find_Context        => Some(ffi::CouldNotFindContext),
            ffi::FT_Err_Invalid_Post_Table_Format     => Some(ffi::InvalidPostTableFormat),
            ffi::FT_Err_Invalid_Post_Table            => Some(ffi::InvalidPostTable),
            ffi::FT_Err_Syntax_Error                  => Some(ffi::SyntaxError),
            ffi::FT_Err_Stack_Underflow               => Some(ffi::StackUnderflow),
            ffi::FT_Err_Ignore                        => Some(ffi::Ignore),
            ffi::FT_Err_No_Unicode_Glyph_Name         => Some(ffi::NoUnicodeGlyphName),
            ffi::FT_Err_Missing_Startfont_Field       => Some(ffi::MissingStartfontField),
            ffi::FT_Err_Missing_Font_Field            => Some(ffi::MissingFontField),
            ffi::FT_Err_Missing_Size_Field            => Some(ffi::MissingSizeField),
            ffi::FT_Err_Missing_Fontboundingbox_Field => Some(ffi::MissingFontboundingboxField),
            ffi::FT_Err_Missing_Chars_Field           => Some(ffi::MissingCharsField),
            ffi::FT_Err_Missing_Startchar_Field       => Some(ffi::MissingStartcharField),
            ffi::FT_Err_Missing_Encoding_Field        => Some(ffi::MissingEncodingField),
            ffi::FT_Err_Missing_Bbx_Field             => Some(ffi::MissingBbxField),
            ffi::FT_Err_Bbx_Too_Big                   => Some(ffi::BbxTooBig),
            ffi::FT_Err_Corrupted_Font_Header         => Some(ffi::CorruptedFontHeader),
            ffi::FT_Err_Corrupted_Font_Glyphs         => Some(ffi::CorruptedFontGlyphs),
            ffi::FT_Err_Max                           => Some(ffi::Max),
            _ => Some(ffi::UnknownError),
        }
    }
}

<commit_msg>Should be using the correct namespace now.<commit_after>
use ffi;

pub type FtResult<T> = Result<T, Error>;

#[deriving(Clone, PartialEq, Eq, Show)]
#[repr(i32)]
pub enum Error {
    Ok                          = ffi::FT_Err_Ok,
    CannotOpenResource          = ffi::FT_Err_Cannot_Open_Resource,
    UnknownFileFormat           = ffi::FT_Err_Unknown_File_Format,
    InvalidFileFormat           = ffi::FT_Err_Invalid_File_Format,
    InvalidVersion              = ffi::FT_Err_Invalid_Version,
    LowerModuleVersion          = ffi::FT_Err_Lower_Module_Version,
    InvalidArgument             = ffi::FT_Err_Invalid_Argument,
    UnimplementedFeature        = ffi::FT_Err_Unimplemented_Feature,
    InvalidTable                = ffi::FT_Err_Invalid_Table,
    InvalidOffset               = ffi::FT_Err_Invalid_Offset,
    ArrayTooLarge               = ffi::FT_Err_Array_Too_Large,
    MissingModule               = ffi::FT_Err_Missing_Module,
    MissingProperty             = ffi::FT_Err_Missing_Property,
    InvalidGlyphIndex           = ffi::FT_Err_Invalid_Glyph_Index,
    InvalidCharacterCode        = ffi::FT_Err_Invalid_Character_Code,
    InvalidGlyphFormat          = ffi::FT_Err_Invalid_Glyph_Format,
    CannotRenderGlyph           = ffi::FT_Err_Cannot_Render_Glyph,
    InvalidOutline              = ffi::FT_Err_Invalid_Outline,
    InvalidComposite            = ffi::FT_Err_Invalid_Composite,
    TooManyHints                = ffi::FT_Err_Too_Many_Hints,
    InvalidPixelSize            = ffi::FT_Err_Invalid_Pixel_Size,
    InvalidHandle               = ffi::FT_Err_Invalid_Handle,
    InvalidLibraryHandle        = ffi::FT_Err_Invalid_Library_Handle,
    InvalidDriverHandle         = ffi::FT_Err_Invalid_Driver_Handle,
    InvalidFaceHandle           = ffi::FT_Err_Invalid_Face_Handle,
    InvalidSizeHandle           = ffi::FT_Err_Invalid_Size_Handle,
    InvalidSlotHandle           = ffi::FT_Err_Invalid_Slot_Handle,
    InvalidCharMapHandle        = ffi::FT_Err_Invalid_CharMap_Handle,
    InvalidCacheHandle          = ffi::FT_Err_Invalid_Cache_Handle,
    InvalidStreamHandle         = ffi::FT_Err_Invalid_Stream_Handle,
    TooManyDrivers              = ffi::FT_Err_Too_Many_Drivers,
    TooManyExtensions           = ffi::FT_Err_Too_Many_Extensions,
    OutOfMemory                 = ffi::FT_Err_Out_Of_Memory,
    UnlistedObject              = ffi::FT_Err_Unlisted_Object,
    CannotOpenStream            = ffi::FT_Err_Cannot_Open_Stream,
    InvalidStreamSeek           = ffi::FT_Err_Invalid_Stream_Seek,
    InvalidStreamSkip           = ffi::FT_Err_Invalid_Stream_Skip,
    InvalidStreamRead           = ffi::FT_Err_Invalid_Stream_Read,
    InvalidStreamOperation      = ffi::FT_Err_Invalid_Stream_Operation,
    InvalidFrameOperation       = ffi::FT_Err_Invalid_Frame_Operation,
    NestedFrameAccess           = ffi::FT_Err_Nested_Frame_Access,
    InvalidFrameRead            = ffi::FT_Err_Invalid_Frame_Read,
    RasterUninitialized         = ffi::FT_Err_Raster_Uninitialized,
    RasterCorrupted             = ffi::FT_Err_Raster_Corrupted,
    RasterOverflow              = ffi::FT_Err_Raster_Overflow,
    RasterNegativeHeight        = ffi::FT_Err_Raster_Negative_Height,
    TooManyCaches               = ffi::FT_Err_Too_Many_Caches,
    InvalidOpcode               = ffi::FT_Err_Invalid_Opcode,
    TooFewArguments             = ffi::FT_Err_Too_Few_Arguments,
    StackOverflow               = ffi::FT_Err_Stack_Overflow,
    CodeOverflow                = ffi::FT_Err_Code_Overflow,
    BadArgument                 = ffi::FT_Err_Bad_Argument,
    DivideByZero                = ffi::FT_Err_Divide_By_Zero,
    InvalidReference            = ffi::FT_Err_Invalid_Reference,
    DebugOpCode                 = ffi::FT_Err_Debug_OpCode,
    ENDFInExecStream            = ffi::FT_Err_ENDF_In_Exec_Stream,
    NestedDEFS                  = ffi::FT_Err_Nested_DEFS,
    InvalidCodeRange            = ffi::FT_Err_Invalid_CodeRange,
    ExecutionTooLong            = ffi::FT_Err_Execution_Too_Long,
    TooManyFunctionDefs         = ffi::FT_Err_Too_Many_Function_Defs,
    TooManyInstructionDefs      = ffi::FT_Err_Too_Many_Instruction_Defs,
    TableMissing                = ffi::FT_Err_Table_Missing,
    HorizHeaderMissing          = ffi::FT_Err_Horiz_Header_Missing,
    LocationsMissing            = ffi::FT_Err_Locations_Missing,
    NameTableMissing            = ffi::FT_Err_Name_Table_Missing,
    CMapTableMissing            = ffi::FT_Err_CMap_Table_Missing,
    HmtxTableMissing            = ffi::FT_Err_Hmtx_Table_Missing,
    PostTableMissing            = ffi::FT_Err_Post_Table_Missing,
    InvalidHorizMetrics         = ffi::FT_Err_Invalid_Horiz_Metrics,
    InvalidCharMapFormat        = ffi::FT_Err_Invalid_CharMap_Format,
    InvalidPPem                 = ffi::FT_Err_Invalid_PPem,
    InvalidVertMetrics          = ffi::FT_Err_Invalid_Vert_Metrics,
    CouldNotFindContext         = ffi::FT_Err_Could_Not_Find_Context,
    InvalidPostTableFormat      = ffi::FT_Err_Invalid_Post_Table_Format,
    InvalidPostTable            = ffi::FT_Err_Invalid_Post_Table,
    SyntaxError                 = ffi::FT_Err_Syntax_Error,
    StackUnderflow              = ffi::FT_Err_Stack_Underflow,
    Ignore                      = ffi::FT_Err_Ignore,
    NoUnicodeGlyphName          = ffi::FT_Err_No_Unicode_Glyph_Name,
    MissingStartfontField       = ffi::FT_Err_Missing_Startfont_Field,
    MissingFontField            = ffi::FT_Err_Missing_Font_Field,
    MissingSizeField            = ffi::FT_Err_Missing_Size_Field,
    MissingFontboundingboxField = ffi::FT_Err_Missing_Fontboundingbox_Field,
    MissingCharsField           = ffi::FT_Err_Missing_Chars_Field,
    MissingStartcharField       = ffi::FT_Err_Missing_Startchar_Field,
    MissingEncodingField        = ffi::FT_Err_Missing_Encoding_Field,
    MissingBbxField             = ffi::FT_Err_Missing_Bbx_Field,
    BbxTooBig                   = ffi::FT_Err_Bbx_Too_Big,
    CorruptedFontHeader         = ffi::FT_Err_Corrupted_Font_Header,
    CorruptedFontGlyphs         = ffi::FT_Err_Corrupted_Font_Glyphs,
    Max                         = ffi::FT_Err_Max,
    UnknownError,
}

impl FromPrimitive for Error {
    fn from_i64(n: i64) -> Option<Error> {
        FromPrimitive::from_i32(n as i32)
    }

    fn from_u64(n: u64) -> Option<Error> {
        FromPrimitive::from_i32(n as i32)
    }

    #[allow(non_upper_case_globals)]
    fn from_i32(n: i32) -> Option<Error> {
        match n {
            ffi::FT_Err_Ok                            => Some(Error::Ok),
            ffi::FT_Err_Cannot_Open_Resource          => Some(Error::CannotOpenResource),
            ffi::FT_Err_Unknown_File_Format           => Some(Error::UnknownFileFormat),
            ffi::FT_Err_Invalid_File_Format           => Some(Error::InvalidFileFormat),
            ffi::FT_Err_Invalid_Version               => Some(Error::InvalidVersion),
            ffi::FT_Err_Lower_Module_Version          => Some(Error::LowerModuleVersion),
            ffi::FT_Err_Invalid_Argument              => Some(Error::InvalidArgument),
            ffi::FT_Err_Unimplemented_Feature         => Some(Error::UnimplementedFeature),
            ffi::FT_Err_Invalid_Table                 => Some(Error::InvalidTable),
            ffi::FT_Err_Invalid_Offset                => Some(Error::InvalidOffset),
            ffi::FT_Err_Array_Too_Large               => Some(Error::ArrayTooLarge),
            ffi::FT_Err_Missing_Module                => Some(Error::MissingModule),
            ffi::FT_Err_Missing_Property              => Some(Error::MissingProperty),
            ffi::FT_Err_Invalid_Glyph_Index           => Some(Error::InvalidGlyphIndex),
            ffi::FT_Err_Invalid_Character_Code        => Some(Error::InvalidCharacterCode),
            ffi::FT_Err_Invalid_Glyph_Format          => Some(Error::InvalidGlyphFormat),
            ffi::FT_Err_Cannot_Render_Glyph           => Some(Error::CannotRenderGlyph),
            ffi::FT_Err_Invalid_Outline               => Some(Error::InvalidOutline),
            ffi::FT_Err_Invalid_Composite             => Some(Error::InvalidComposite),
            ffi::FT_Err_Too_Many_Hints                => Some(Error::TooManyHints),
            ffi::FT_Err_Invalid_Pixel_Size            => Some(Error::InvalidPixelSize),
            ffi::FT_Err_Invalid_Handle                => Some(Error::InvalidHandle),
            ffi::FT_Err_Invalid_Library_Handle        => Some(Error::InvalidLibraryHandle),
            ffi::FT_Err_Invalid_Driver_Handle         => Some(Error::InvalidDriverHandle),
            ffi::FT_Err_Invalid_Face_Handle           => Some(Error::InvalidFaceHandle),
            ffi::FT_Err_Invalid_Size_Handle           => Some(Error::InvalidSizeHandle),
            ffi::FT_Err_Invalid_Slot_Handle           => Some(Error::InvalidSlotHandle),
            ffi::FT_Err_Invalid_CharMap_Handle        => Some(Error::InvalidCharMapHandle),
            ffi::FT_Err_Invalid_Cache_Handle          => Some(Error::InvalidCacheHandle),
            ffi::FT_Err_Invalid_Stream_Handle         => Some(Error::InvalidStreamHandle),
            ffi::FT_Err_Too_Many_Drivers              => Some(Error::TooManyDrivers),
            ffi::FT_Err_Too_Many_Extensions           => Some(Error::TooManyExtensions),
            ffi::FT_Err_Out_Of_Memory                 => Some(Error::OutOfMemory),
            ffi::FT_Err_Unlisted_Object               => Some(Error::UnlistedObject),
            ffi::FT_Err_Cannot_Open_Stream            => Some(Error::CannotOpenStream),
            ffi::FT_Err_Invalid_Stream_Seek           => Some(Error::InvalidStreamSeek),
            ffi::FT_Err_Invalid_Stream_Skip           => Some(Error::InvalidStreamSkip),
            ffi::FT_Err_Invalid_Stream_Read           => Some(Error::InvalidStreamRead),
            ffi::FT_Err_Invalid_Stream_Operation      => Some(Error::InvalidStreamOperation),
            ffi::FT_Err_Invalid_Frame_Operation       => Some(Error::InvalidFrameOperation),
            ffi::FT_Err_Nested_Frame_Access           => Some(Error::NestedFrameAccess),
            ffi::FT_Err_Invalid_Frame_Read            => Some(Error::InvalidFrameRead),
            ffi::FT_Err_Raster_Uninitialized          => Some(Error::RasterUninitialized),
            ffi::FT_Err_Raster_Corrupted              => Some(Error::RasterCorrupted),
            ffi::FT_Err_Raster_Overflow               => Some(Error::RasterOverflow),
            ffi::FT_Err_Raster_Negative_Height        => Some(Error::RasterNegativeHeight),
            ffi::FT_Err_Too_Many_Caches               => Some(Error::TooManyCaches),
            ffi::FT_Err_Invalid_Opcode                => Some(Error::InvalidOpcode),
            ffi::FT_Err_Too_Few_Arguments             => Some(Error::TooFewArguments),
            ffi::FT_Err_Stack_Overflow                => Some(Error::StackOverflow),
            ffi::FT_Err_Code_Overflow                 => Some(Error::CodeOverflow),
            ffi::FT_Err_Bad_Argument                  => Some(Error::BadArgument),
            ffi::FT_Err_Divide_By_Zero                => Some(Error::DivideByZero),
            ffi::FT_Err_Invalid_Reference             => Some(Error::InvalidReference),
            ffi::FT_Err_Debug_OpCode                  => Some(Error::DebugOpCode),
            ffi::FT_Err_ENDF_In_Exec_Stream           => Some(Error::ENDFInExecStream),
            ffi::FT_Err_Nested_DEFS                   => Some(Error::NestedDEFS),
            ffi::FT_Err_Invalid_CodeRange             => Some(Error::InvalidCodeRange),
            ffi::FT_Err_Execution_Too_Long            => Some(Error::ExecutionTooLong),
            ffi::FT_Err_Too_Many_Function_Defs        => Some(Error::TooManyFunctionDefs),
            ffi::FT_Err_Too_Many_Instruction_Defs     => Some(Error::TooManyInstructionDefs),
            ffi::FT_Err_Table_Missing                 => Some(Error::TableMissing),
            ffi::FT_Err_Horiz_Header_Missing          => Some(Error::HorizHeaderMissing),
            ffi::FT_Err_Locations_Missing             => Some(Error::LocationsMissing),
            ffi::FT_Err_Name_Table_Missing            => Some(Error::NameTableMissing),
            ffi::FT_Err_CMap_Table_Missing            => Some(Error::CMapTableMissing),
            ffi::FT_Err_Hmtx_Table_Missing            => Some(Error::HmtxTableMissing),
            ffi::FT_Err_Post_Table_Missing            => Some(Error::PostTableMissing),
            ffi::FT_Err_Invalid_Horiz_Metrics         => Some(Error::InvalidHorizMetrics),
            ffi::FT_Err_Invalid_CharMap_Format        => Some(Error::InvalidCharMapFormat),
            ffi::FT_Err_Invalid_PPem                  => Some(Error::InvalidPPem),
            ffi::FT_Err_Invalid_Vert_Metrics          => Some(Error::InvalidVertMetrics),
            ffi::FT_Err_Could_Not_Find_Context        => Some(Error::CouldNotFindContext),
            ffi::FT_Err_Invalid_Post_Table_Format     => Some(Error::InvalidPostTableFormat),
            ffi::FT_Err_Invalid_Post_Table            => Some(Error::InvalidPostTable),
            ffi::FT_Err_Syntax_Error                  => Some(Error::SyntaxError),
            ffi::FT_Err_Stack_Underflow               => Some(Error::StackUnderflow),
            ffi::FT_Err_Ignore                        => Some(Error::Ignore),
            ffi::FT_Err_No_Unicode_Glyph_Name         => Some(Error::NoUnicodeGlyphName),
            ffi::FT_Err_Missing_Startfont_Field       => Some(Error::MissingStartfontField),
            ffi::FT_Err_Missing_Font_Field            => Some(Error::MissingFontField),
            ffi::FT_Err_Missing_Size_Field            => Some(Error::MissingSizeField),
            ffi::FT_Err_Missing_Fontboundingbox_Field => Some(Error::MissingFontboundingboxField),
            ffi::FT_Err_Missing_Chars_Field           => Some(Error::MissingCharsField),
            ffi::FT_Err_Missing_Startchar_Field       => Some(Error::MissingStartcharField),
            ffi::FT_Err_Missing_Encoding_Field        => Some(Error::MissingEncodingField),
            ffi::FT_Err_Missing_Bbx_Field             => Some(Error::MissingBbxField),
            ffi::FT_Err_Bbx_Too_Big                   => Some(Error::BbxTooBig),
            ffi::FT_Err_Corrupted_Font_Header         => Some(Error::CorruptedFontHeader),
            ffi::FT_Err_Corrupted_Font_Glyphs         => Some(Error::CorruptedFontGlyphs),
            ffi::FT_Err_Max                           => Some(Error::Max),
            _ => Some(Error::UnknownError),
        }
    }
}

<|endoftext|>


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

// implement custom errors
//
// Classes of errors:
// - Dbus (IO, validation)
// - crypto
// - parsing dbus output (dbus returns unrecognizable output). Sometimes it's
//     for if the index exists in the results vector, sometimes it's for whether
//     the value being parsed at that index is the right type. Along these lines
//     I'm currently using unwrap() for converting types, should these also return
//     Result?
//
//     Almost all custom errors are of this type. It's mostly an internal error,
//     unexpected behavior indicates something very wrong, so should it panic? Or
//     is it still better to bubble up?
// - locked (currently custom dbus error)
// - prompt dismissed (not an error?) (currently custom dbus error)

use std::error;
use std::fmt;
use zbus;

/// Result type often returned from methods that have SsError.
/// Fns in this library return ::Result<T> when using this alias.
// (This pattern is something I saw in hyper)
pub type Result<T> = ::std::result::Result<T, SsError>;

#[derive(Debug)]
pub enum SsError {
    Crypto(String),
    Zbus(zbus::Error),
    ZbusMsg(zbus::MessageError),
    ZbusFdo(zbus::fdo::Error),
    Zvariant(zvariant::Error),
    Locked,
    NoResult,
    Parse,
    Prompt,
}

impl fmt::Display for SsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt:: Result {
        match *self {
            // crypto error does not implement Display
            SsError::Crypto(_) => write!(f, "Crypto error: Invalid Length or Padding"),
            SsError::Zbus(ref err) => write!(f, "zbus error: {}", err),
            SsError::ZbusMsg(ref err) => write!(f, "zbus message error: {}", err),
            SsError::ZbusFdo(ref err) => write!(f, "zbus fdo error: {}", err),
            SsError::Zvariant(ref err) => write!(f, "zbus fdo error: {}", err),
            SsError::Locked => write!(f, "SS Error: object locked"),
            SsError::NoResult => write!(f, "SS error: result not returned from SS API"),
            SsError::Parse => write!(f, "SS error: could not parse Dbus output"),
            SsError::Prompt => write!(f, "SS error: prompt dismissed"),
        }
    }
}

impl error::Error for SsError {
    fn description(&self) -> &str {
        match *self {
            SsError::Crypto(_) => "crypto: Invalid Length or Padding",
            SsError::Zbus(ref err) => err.description(),
            SsError::ZbusMsg(ref err) => err.description(),
            SsError::ZbusFdo(ref err) => err.description(),
            SsError::Zvariant(ref err) => err.description(),
            SsError::Locked => "Object locked",
            SsError::NoResult => "Result not returned from SS API",
            SsError::Parse => "Error parsing Dbus output",
            SsError::Prompt => "Prompt Dismissed",
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        match *self {
            SsError::Zbus(ref err) => Some(err),
            SsError::ZbusMsg(ref err) => Some(err),
            SsError::ZbusFdo(ref err) => Some(err),
            SsError::Zvariant(ref err) => Some(err),
            _ => None,
        }
    }
}

impl From<block_modes::BlockModeError> for SsError {
    fn from(_err: block_modes::BlockModeError) -> SsError {
        SsError::Crypto("Block mode error".into())
    }
}

impl From<block_modes::InvalidKeyIvLength> for SsError {
    fn from(_err: block_modes::InvalidKeyIvLength) -> SsError {
        SsError::Crypto("Invalid Key Iv Lengt".into())
    }
}

impl From<zbus::Error> for SsError {
    fn from(err: zbus::Error) -> SsError {
        SsError::Zbus(err)
    }
}

impl From<zbus::fdo::Error> for SsError {
    fn from(err: zbus::fdo::Error) -> SsError {
        SsError::ZbusFdo(err)
    }
}

impl From<zvariant::Error> for SsError {
    fn from(err: zvariant::Error) -> SsError {
        SsError::Zvariant(err)
    }
}

impl From<zbus::MessageError> for SsError {
    fn from(err: zbus::MessageError) -> SsError {
        SsError::ZbusMsg(err)
    }
}
<commit_msg>update Error implementation<commit_after>//Copyright 2016 secret-service-rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

// implement custom errors
//
// Classes of errors:
// - Dbus (IO, validation)
// - crypto
// - parsing dbus output (dbus returns unrecognizable output). Sometimes it's
//     for if the index exists in the results vector, sometimes it's for whether
//     the value being parsed at that index is the right type. Along these lines
//     I'm currently using unwrap() for converting types, should these also return
//     Result?
//
//     Almost all custom errors are of this type. It's mostly an internal error,
//     unexpected behavior indicates something very wrong, so should it panic? Or
//     is it still better to bubble up?
// - locked (currently custom dbus error)
// - prompt dismissed (not an error?) (currently custom dbus error)

use std::error;
use std::fmt;
use zbus;

/// Result type often returned from methods that have SsError.
/// Fns in this library return ::Result<T> when using this alias.
// (This pattern is something I saw in hyper)
pub type Result<T> = ::std::result::Result<T, SsError>;

#[derive(Debug)]
pub enum SsError {
    Crypto(String),
    Zbus(zbus::Error),
    ZbusMsg(zbus::MessageError),
    ZbusFdo(zbus::fdo::Error),
    Zvariant(zvariant::Error),
    Locked,
    NoResult,
    Parse,
    Prompt,
}

impl fmt::Display for SsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt:: Result {
        match *self {
            // crypto error does not implement Display
            SsError::Crypto(_) => write!(f, "Crypto error: Invalid Length or Padding"),
            SsError::Zbus(ref err) => write!(f, "zbus error: {}", err),
            SsError::ZbusMsg(ref err) => write!(f, "zbus message error: {}", err),
            SsError::ZbusFdo(ref err) => write!(f, "zbus fdo error: {}", err),
            SsError::Zvariant(ref err) => write!(f, "zbus fdo error: {}", err),
            SsError::Locked => write!(f, "SS Error: object locked"),
            SsError::NoResult => write!(f, "SS error: result not returned from SS API"),
            SsError::Parse => write!(f, "SS error: could not parse Dbus output"),
            SsError::Prompt => write!(f, "SS error: prompt dismissed"),
        }
    }
}

impl error::Error for SsError {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match *self {
            SsError::Zbus(ref err) => Some(err),
            SsError::ZbusMsg(ref err) => Some(err),
            SsError::ZbusFdo(ref err) => Some(err),
            SsError::Zvariant(ref err) => Some(err),
            _ => None,
        }
    }
}

impl From<block_modes::BlockModeError> for SsError {
    fn from(_err: block_modes::BlockModeError) -> SsError {
        SsError::Crypto("Block mode error".into())
    }
}

impl From<block_modes::InvalidKeyIvLength> for SsError {
    fn from(_err: block_modes::InvalidKeyIvLength) -> SsError {
        SsError::Crypto("Invalid Key Iv Lengt".into())
    }
}

impl From<zbus::Error> for SsError {
    fn from(err: zbus::Error) -> SsError {
        SsError::Zbus(err)
    }
}

impl From<zbus::fdo::Error> for SsError {
    fn from(err: zbus::fdo::Error) -> SsError {
        SsError::ZbusFdo(err)
    }
}

impl From<zvariant::Error> for SsError {
    fn from(err: zvariant::Error) -> SsError {
        SsError::Zvariant(err)
    }
}

impl From<zbus::MessageError> for SsError {
    fn from(err: zbus::MessageError) -> SsError {
        SsError::ZbusMsg(err)
    }
}
<|endoftext|>