<commit_before>extern crate flate;

mod commit;
mod meta;
mod object_id;
mod object_header;
mod object_type;
mod unit_tests;
mod serialization;
<commit_msg>Update library to have the latest modules<commit_after>extern crate flate;

mod commit;
mod meta;
mod object_id;
mod object_header;
mod object_type;
mod unit_tests;
mod serialization;
mod reader;
mod conversion;
mod error;<|endoftext|>


<commit_before>//! Solvent is a dependency resolver library written in rust.
//!
//! Solvent helps you to resolve dependency orderings by building up a dependency
//! graph and then resolving the dependences of some target node in an order such
//! that each output depends only upon the previous outputs.
//!
//! It is currently quite simple, but is still useful.
//!
//! #Example
//!
//! ```rust
//! extern crate solvent;
//!
//! use solvent::DepGraph;
//!
//! fn main() {
//!     // Create a new empty DepGraph.  Must be `mut` or else it cannot
//!     // be used by the rest of the library.
//!     let mut depgraph: DepGraph = DepGraph::new();
//!
//!     // You can register a dependency like this.  Solvent will
//!     // automatically create nodes for any term it has not seen before.
//!     // This means 'b' depends on 'd'
//!     depgraph.register_dependency("b","d");
//!
//!     // You can also register multiple dependencies at once
//!     depgraph.register_dependencies("a",&["b","c","d"]);
//!     depgraph.register_dependencies("c",&["e"]);
//!
//!     // Iterate through each dependency of "a".  The dependencies will be
//!     // returned in an order such that each output only depends on the
//!     // previous outputs (or nothing).  The target itself will be output
//!     // last.
//!     for node in depgraph.dependencies_of("a") {
//!         match node {
//!             Ok(n) => print!("{} ", n),
//!             Err(e) => panic!("Solvent error detected: {:?}", e),
//!         }
//!     }
//! }
//! ```
//!
//! The above will output:  `d b e c a` or `e c d b a` or some other valid
//! dependency order.
//!
//! The algorithm is not deterministic, and may give a different answer each
//! time it is run.  Beware.
//!
//! The iterator dependencies_of() returns an Option<Result<String,SolventError>>.
//! The for loop handles the Option part for you, but you may want to check the
//! result for SolventErrors.  Once an error is returned, all subsequent calls to
//! the iterator next() will yield None.
//!
//! You can also mark some elements as already satisfied, and the iterator
//! will take that into account:
//!
//! ```ignore
//! depgraph.mark_as_satisfied(["e","c"]);
//! ```
//!
//! Dependency cycles are detected and will return SolventError::CycleDetected.

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

// Silence warnings about unstable library features
#![feature(std_misc)]
#![feature(core)]

#[macro_use] extern crate log;

use std::collections::{HashMap,HashSet};
use std::collections::hash_map::Entry;
use std::iter::{Iterator};
use std::borrow::ToOwned;
use std::fmt;
use std::error::Error;

/// This is the dependency graph.
#[derive(Clone)]
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,HashSet<String>>,

    /// Nodes already satisfied.  dependencies_of() will prune
    /// dependency searches at these nodes, and not output nodes
    /// registered here.
    pub satisfied: HashSet<String>,
}

#[derive(Clone,Debug,PartialEq)]
pub enum SolventError {
    CycleDetected(String),
    // TODO once we implement conflicts: Conflict(String)
}

impl fmt::Display for SolventError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SolventError::CycleDetected(ref s) =>
                format!("{}: {}", self.description(), s).fmt(f),
            //_ => self.description().fmt(f)
        }
    }
}

impl Error for SolventError {
    fn description(&self) -> &str
    {
        match *self {
            SolventError::CycleDetected(_) => "Cycle Detected",
        }
    }
    fn cause(&self) -> Option<&Error> {
        match *self {
            _ => None
        }
    }
}

/// This iterates through the dependencies of the DepGraph's target
pub struct DepGraphIterator<'a> {
    depgraph: &'a DepGraph,

    // Target we are trying to satisfy
    target: String,

    // Elements already satisfied during this iterator's walk
    satisfied: HashSet<String>,

    // Current path, for cycle detection
    curpath: HashSet<String>,

    // Halted.  Used so that it can return None after an Err is returned.
    halted: bool,
}

impl DepGraph {

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

    /// Add a dependency to a DepGraph.  The node does not need
    /// to pre-exist, nor do the dependency nodes.  But if the
    /// node does pre-exist, the depends_on will be added to its
    /// existing dependency list.
    pub fn register_dependency<'a>( &mut self,
                                node: &'a str,
                                depends_on: &'a str )
    {
        match self.dependencies.entry( node.to_string() ) {
            Entry::Vacant(entry) => {
                let mut deps = HashSet::with_capacity(1);
                deps.insert( depends_on.to_string() );
                entry.insert( deps );
            },
            Entry::Occupied(mut entry) => {
                (*entry.get_mut()).insert( depends_on.to_string() );
            },
        }
    }

    /// Add multiple dependencies of one node to a DepGraph.  The
    /// node does not need to pre-exist, nor do the dependency elements.
    /// But if the node does pre-exist, the depends_on will be added
    /// to its existing dependency list.
    pub fn register_dependencies<'a>( &mut self,
                                  node: &'a str,
                                  depends_on: &'a[&'a str] )
    {
        match self.dependencies.entry( node.to_string() ) {
            Entry::Vacant(entry) => {
                let mut deps = HashSet::with_capacity( depends_on.len() );
                for s in depends_on.iter() {
                    deps.insert( s.to_string() );
                }
                entry.insert( deps );
            },
            Entry::Occupied(mut entry) => {
                for s in depends_on.iter() {
                    (*entry.get_mut()).insert( s.to_string() );
                }
            },
        }
    }

    /// This marks a node as satisfied.  Iterators will not output
    /// such nodes.
    pub fn mark_as_satisfied<'a>( &mut self,
                                   nodes: &'a[&'a str] )
    {
        for node in nodes.iter() {
            self.satisfied.insert( node.to_string() );
        }
    }

    /// Get an iterator to iterate through the dependencies of
    /// the target node.
    pub fn dependencies_of<'a>(&'a self, target: &str) -> DepGraphIterator<'a>
    {
        // TODO: iterator's satisfied could start empty, and all checks
        //       could separately check depgraph's and iterator's.  That
        //       would avoid the copy.
        DepGraphIterator {
            depgraph: self,
            target: target.to_owned(),
            satisfied: self.satisfied.clone(),
            curpath: HashSet::new(),
            halted: false,
        }
    }
}

impl<'a> DepGraphIterator<'a> {

    fn get_next_dependency(&mut self, node: &String) -> Result<String,SolventError>
    {
        if self.curpath.contains(node) {
            return Err(SolventError::CycleDetected(node.clone()));
        }
        self.curpath.insert(node.clone());

        let deplist = match self.depgraph.dependencies.get(node) {
            None => return Ok(node.clone()),
            Some(deplist) => deplist.clone() // ouch
        };

        for n in deplist.iter() {
            // Prune satisfied nodes
            if self.satisfied.contains(n) {
                continue;
            }

            return self.get_next_dependency(n);
        }
        // nodes dependencies are satisfied
        Ok(node.clone())
    }
}

impl<'a> Iterator for DepGraphIterator<'a> {
    type Item = Result<String,SolventError>;

    /// Get next dependency.  Returns None when finished.  If
    /// Some(Err(SolventError)) occurs, all subsequent calls will
    /// return None.
    fn next(&mut self) -> Option< Result<String,SolventError> >
    {
        if self.halted {
            return None;
        }

        let node = self.target.clone();
        if self.satisfied.contains(&node) {
            return None;
        }

        self.curpath.clear();
        let next = match self.get_next_dependency(&node) {
            Ok(d) => d,
            Err(e) => {
                self.halted = true;
                return Some(Err(e));
            }
        };
        self.satisfied.insert(next.clone());
        Some(Ok(next))
    }
}

#[test]
fn solvent_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");

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

    for node in depgraph.dependencies_of("a") {
        // detect infinite looping bugs
        assert!(results.len() < 30);

        let n = match node {
            Err(e) => panic!("Solvent error detected: {:?}", e),
            Ok(n) => n,
        };

        // Check that all of that nodes dependencies have already been output
        let deps: Option<&HashSet<String>> = depgraph.dependencies.get(&n);
        if deps.is_some() {
            for dep in deps.unwrap().iter() {
                assert!( results.contains(dep) );
            }
        }

        results.push(n.clone());
    }

    // Be sure we actually output enough stuff
    assert!(results.len() == 14);

    // Be sure each output is unique
    for result in results.iter() {
        let mut count: usize = 0;
        for result2 in results.iter() {
            if result == result2 { count = count + 1; }
        }
        assert!(count == 1);
    }
}

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

    depgraph.register_dependencies("a",&["b","c"]);
    depgraph.register_dependency("a","d");
    assert!(depgraph.dependencies.get("a").unwrap().contains("b"));
    assert!(depgraph.dependencies.get("a").unwrap().contains("c"));
    assert!(depgraph.dependencies.get("a").unwrap().contains("d"));
}

#[test]
fn solvent_test_circular() {

    let mut depgraph: DepGraph = DepGraph::new();
    depgraph.register_dependency("a","b");
    depgraph.register_dependency("b","c");
    depgraph.register_dependency("c","a");

    for node in depgraph.dependencies_of("a") {
        assert!(node.is_err());
        assert!(node.unwrap_err() == SolventError::CycleDetected("a".to_string()));
    }
}

#[test]
fn solvent_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.mark_as_satisfied(&["owneruser","appuser"]);

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

    for node in depgraph.dependencies_of("appconn") {
        assert!(results.len() < 30);
        match node {
            Ok(n) => results.push(n),
            Err(e) => panic!("Solvent error detected: {:?}",e),
        };
    }

    // Be sure we did not depend on these
    assert!( !results.contains( &"appuser".to_string()) );
    assert!( !results.contains( &"owneruser".to_string()) );
    assert!( !results.contains( &"superconn".to_string()) );

    // Be sure we actually output enough stuff
    assert!(results.len() == 7);

    // Be sure each output is unique
    for result in results.iter() {
        let mut count: usize = 0;
        for result2 in results.iter() {
            if result == result2 { count = count + 1; }
        }
        assert!(count == 1);
    }
}

<commit_msg>Remove features no longer required<commit_after>//! Solvent is a dependency resolver library written in rust.
//!
//! Solvent helps you to resolve dependency orderings by building up a dependency
//! graph and then resolving the dependences of some target node in an order such
//! that each output depends only upon the previous outputs.
//!
//! It is currently quite simple, but is still useful.
//!
//! #Example
//!
//! ```rust
//! extern crate solvent;
//!
//! use solvent::DepGraph;
//!
//! fn main() {
//!     // Create a new empty DepGraph.  Must be `mut` or else it cannot
//!     // be used by the rest of the library.
//!     let mut depgraph: DepGraph = DepGraph::new();
//!
//!     // You can register a dependency like this.  Solvent will
//!     // automatically create nodes for any term it has not seen before.
//!     // This means 'b' depends on 'd'
//!     depgraph.register_dependency("b","d");
//!
//!     // You can also register multiple dependencies at once
//!     depgraph.register_dependencies("a",&["b","c","d"]);
//!     depgraph.register_dependencies("c",&["e"]);
//!
//!     // Iterate through each dependency of "a".  The dependencies will be
//!     // returned in an order such that each output only depends on the
//!     // previous outputs (or nothing).  The target itself will be output
//!     // last.
//!     for node in depgraph.dependencies_of("a") {
//!         match node {
//!             Ok(n) => print!("{} ", n),
//!             Err(e) => panic!("Solvent error detected: {:?}", e),
//!         }
//!     }
//! }
//! ```
//!
//! The above will output:  `d b e c a` or `e c d b a` or some other valid
//! dependency order.
//!
//! The algorithm is not deterministic, and may give a different answer each
//! time it is run.  Beware.
//!
//! The iterator dependencies_of() returns an Option<Result<String,SolventError>>.
//! The for loop handles the Option part for you, but you may want to check the
//! result for SolventErrors.  Once an error is returned, all subsequent calls to
//! the iterator next() will yield None.
//!
//! You can also mark some elements as already satisfied, and the iterator
//! will take that into account:
//!
//! ```ignore
//! depgraph.mark_as_satisfied(["e","c"]);
//! ```
//!
//! Dependency cycles are detected and will return SolventError::CycleDetected.

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

#[macro_use] extern crate log;

use std::collections::{HashMap,HashSet};
use std::collections::hash_map::Entry;
use std::iter::{Iterator};
use std::borrow::ToOwned;
use std::fmt;
use std::error::Error;

/// This is the dependency graph.
#[derive(Clone)]
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,HashSet<String>>,

    /// Nodes already satisfied.  dependencies_of() will prune
    /// dependency searches at these nodes, and not output nodes
    /// registered here.
    pub satisfied: HashSet<String>,
}

#[derive(Clone,Debug,PartialEq)]
pub enum SolventError {
    CycleDetected(String),
    // TODO once we implement conflicts: Conflict(String)
}

impl fmt::Display for SolventError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SolventError::CycleDetected(ref s) =>
                format!("{}: {}", self.description(), s).fmt(f),
            //_ => self.description().fmt(f)
        }
    }
}

impl Error for SolventError {
    fn description(&self) -> &str
    {
        match *self {
            SolventError::CycleDetected(_) => "Cycle Detected",
        }
    }
    fn cause(&self) -> Option<&Error> {
        match *self {
            _ => None
        }
    }
}

/// This iterates through the dependencies of the DepGraph's target
pub struct DepGraphIterator<'a> {
    depgraph: &'a DepGraph,

    // Target we are trying to satisfy
    target: String,

    // Elements already satisfied during this iterator's walk
    satisfied: HashSet<String>,

    // Current path, for cycle detection
    curpath: HashSet<String>,

    // Halted.  Used so that it can return None after an Err is returned.
    halted: bool,
}

impl DepGraph {

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

    /// Add a dependency to a DepGraph.  The node does not need
    /// to pre-exist, nor do the dependency nodes.  But if the
    /// node does pre-exist, the depends_on will be added to its
    /// existing dependency list.
    pub fn register_dependency<'a>( &mut self,
                                node: &'a str,
                                depends_on: &'a str )
    {
        match self.dependencies.entry( node.to_string() ) {
            Entry::Vacant(entry) => {
                let mut deps = HashSet::with_capacity(1);
                deps.insert( depends_on.to_string() );
                entry.insert( deps );
            },
            Entry::Occupied(mut entry) => {
                (*entry.get_mut()).insert( depends_on.to_string() );
            },
        }
    }

    /// Add multiple dependencies of one node to a DepGraph.  The
    /// node does not need to pre-exist, nor do the dependency elements.
    /// But if the node does pre-exist, the depends_on will be added
    /// to its existing dependency list.
    pub fn register_dependencies<'a>( &mut self,
                                  node: &'a str,
                                  depends_on: &'a[&'a str] )
    {
        match self.dependencies.entry( node.to_string() ) {
            Entry::Vacant(entry) => {
                let mut deps = HashSet::with_capacity( depends_on.len() );
                for s in depends_on.iter() {
                    deps.insert( s.to_string() );
                }
                entry.insert( deps );
            },
            Entry::Occupied(mut entry) => {
                for s in depends_on.iter() {
                    (*entry.get_mut()).insert( s.to_string() );
                }
            },
        }
    }

    /// This marks a node as satisfied.  Iterators will not output
    /// such nodes.
    pub fn mark_as_satisfied<'a>( &mut self,
                                   nodes: &'a[&'a str] )
    {
        for node in nodes.iter() {
            self.satisfied.insert( node.to_string() );
        }
    }

    /// Get an iterator to iterate through the dependencies of
    /// the target node.
    pub fn dependencies_of<'a>(&'a self, target: &str) -> DepGraphIterator<'a>
    {
        // TODO: iterator's satisfied could start empty, and all checks
        //       could separately check depgraph's and iterator's.  That
        //       would avoid the copy.
        DepGraphIterator {
            depgraph: self,
            target: target.to_owned(),
            satisfied: self.satisfied.clone(),
            curpath: HashSet::new(),
            halted: false,
        }
    }
}

impl<'a> DepGraphIterator<'a> {

    fn get_next_dependency(&mut self, node: &String) -> Result<String,SolventError>
    {
        if self.curpath.contains(node) {
            return Err(SolventError::CycleDetected(node.clone()));
        }
        self.curpath.insert(node.clone());

        let deplist = match self.depgraph.dependencies.get(node) {
            None => return Ok(node.clone()),
            Some(deplist) => deplist.clone() // ouch
        };

        for n in deplist.iter() {
            // Prune satisfied nodes
            if self.satisfied.contains(n) {
                continue;
            }

            return self.get_next_dependency(n);
        }
        // nodes dependencies are satisfied
        Ok(node.clone())
    }
}

impl<'a> Iterator for DepGraphIterator<'a> {
    type Item = Result<String,SolventError>;

    /// Get next dependency.  Returns None when finished.  If
    /// Some(Err(SolventError)) occurs, all subsequent calls will
    /// return None.
    fn next(&mut self) -> Option< Result<String,SolventError> >
    {
        if self.halted {
            return None;
        }

        let node = self.target.clone();
        if self.satisfied.contains(&node) {
            return None;
        }

        self.curpath.clear();
        let next = match self.get_next_dependency(&node) {
            Ok(d) => d,
            Err(e) => {
                self.halted = true;
                return Some(Err(e));
            }
        };
        self.satisfied.insert(next.clone());
        Some(Ok(next))
    }
}

#[test]
fn solvent_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");

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

    for node in depgraph.dependencies_of("a") {
        // detect infinite looping bugs
        assert!(results.len() < 30);

        let n = match node {
            Err(e) => panic!("Solvent error detected: {:?}", e),
            Ok(n) => n,
        };

        // Check that all of that nodes dependencies have already been output
        let deps: Option<&HashSet<String>> = depgraph.dependencies.get(&n);
        if deps.is_some() {
            for dep in deps.unwrap().iter() {
                assert!( results.contains(dep) );
            }
        }

        results.push(n.clone());
    }

    // Be sure we actually output enough stuff
    assert!(results.len() == 14);

    // Be sure each output is unique
    for result in results.iter() {
        let mut count: usize = 0;
        for result2 in results.iter() {
            if result == result2 { count = count + 1; }
        }
        assert!(count == 1);
    }
}

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

    depgraph.register_dependencies("a",&["b","c"]);
    depgraph.register_dependency("a","d");
    assert!(depgraph.dependencies.get("a").unwrap().contains("b"));
    assert!(depgraph.dependencies.get("a").unwrap().contains("c"));
    assert!(depgraph.dependencies.get("a").unwrap().contains("d"));
}

#[test]
fn solvent_test_circular() {

    let mut depgraph: DepGraph = DepGraph::new();
    depgraph.register_dependency("a","b");
    depgraph.register_dependency("b","c");
    depgraph.register_dependency("c","a");

    for node in depgraph.dependencies_of("a") {
        assert!(node.is_err());
        assert!(node.unwrap_err() == SolventError::CycleDetected("a".to_string()));
    }
}

#[test]
fn solvent_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.mark_as_satisfied(&["owneruser","appuser"]);

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

    for node in depgraph.dependencies_of("appconn") {
        assert!(results.len() < 30);
        match node {
            Ok(n) => results.push(n),
            Err(e) => panic!("Solvent error detected: {:?}",e),
        };
    }

    // Be sure we did not depend on these
    assert!( !results.contains( &"appuser".to_string()) );
    assert!( !results.contains( &"owneruser".to_string()) );
    assert!( !results.contains( &"superconn".to_string()) );

    // Be sure we actually output enough stuff
    assert!(results.len() == 7);

    // Be sure each output is unique
    for result in results.iter() {
        let mut count: usize = 0;
        for result2 in results.iter() {
            if result == result2 { count = count + 1; }
        }
        assert!(count == 1);
    }
}

<|endoftext|>


<commit_before>#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Direction {Forward, Reverse}
use self::Direction::*;

impl Direction {
	fn reverse(self) -> Direction {
		match self {
			Forward => Reverse,
			Reverse => Forward
		}
	}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum GlyphOrient {Perpendicular, Parallel}
use self::GlyphOrient::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct DirBehavior(Direction, GlyphOrient);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum DirPreference {Horiz(DirBehavior), Vert(DirBehavior), BiOrient(DirBehavior, DirBehavior)}	// enable scripts without preference?
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Rot180 {Normal, Rotated}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct StreakTypesetting(DirBehavior, Rot180);

impl StreakTypesetting {
	fn effective_direction(&self) -> Direction {
		match self.1 {
			Rot180::Normal => self.0 . 0,
			Rot180::Rotated => self.0 . 0 .reverse()
		}
	}
}

/// ISO 15924 alphabetical code
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ScriptCode([u8; 4]);

pub static LATIN: ScriptCode = ScriptCode(['L' as u8, 'a' as u8, 't' as u8, 'n' as u8]);	// "Latn"

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MainAxis {Ltr, Rtl, Ttb, Btt}

pub struct NonNativeConf;

pub struct Run<'a>(pub &'a str, pub ScriptCode);

pub fn make_default_streak<'a>(run: &'a Run, main_axis: MainAxis) -> Streak<'a> {
	use self::MainAxis::*;
	Streak(run.0, run.1, StreakTypesetting(DirBehavior(Forward, Perpendicular), if run.1 == LATIN {
		match main_axis {
			Ltr | Ttb => Rot180::Normal,
			Rtl | Btt => Rot180::Rotated
		}
	} else {
		unimplemented!();
	}))
}

pub fn make_runs(s: &str) -> Vec<Run> {vec![Run(s, LATIN)]}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Streak<'a>(&'a str, ScriptCode, StreakTypesetting);

impl<'a> Streak<'a> {
	/// what order do the parts have if you split the streak
	pub fn direction(&self) -> Direction {self.2.effective_direction()}
}

pub fn bidi_algorithm(streaks: &mut [Streak]) {}

pub struct FontPreference<'a>(Font<'a>);

/*impl FontPreference {
	fn lookup(&self) -> Vec<Burst> {
		Vec::new()
	}
}*/

/// contains glyphs and typesetting information
pub struct FontCollection<'a>(&'a[u8]);
/// what features of the font collection do we want to use?
pub struct FontConfiguration;

/// contains character mapping
pub struct Font<'a>(&'a[u8]);

struct GlyphPoint(i16, i16);
enum ContourSegment {
	Line(GlyphPoint, GlyphPoint),
	Curve(GlyphPoint, GlyphPoint, GlyphPoint)
}

pub fn read_u32(data: &[u8]) -> Option<u32> {
	if data.len() > 3 {
		Some((data[0] as u32) << 24 | (data[1] as u32) << 16 | (data[2] as u32) << 8 | data[3] as u32)
	} else {
		None
	}
}

pub fn read_u16(data: &[u8]) -> Option<u16> {
	if data.len() > 1 {
		Some((data[0] as u16) << 8 | data[1] as u16)
	} else {
		None
	}
}

fn fourcc(tag: u32) -> String {
	let mut s = String::with_capacity(4);
	s.push((tag >> 24) as u8 as char);
	s.push((tag >> 16) as u8 as char);
	s.push((tag >> 8) as u8 as char);
	s.push(tag as u8 as char);
	s
}

macro_rules! try_opt {
	($e:expr) => (match $e {Some(x)=>x, None=>return None})
}

fn scan_table_records(data: &[u8], start: usize, label: u32, num_tables: usize) -> Option<(usize, &[u8])> {
	for pos in start..num_tables {
		if try_opt!(read_u32(&data[12+16*pos..])) == label {
			let start = read_u32(&data[12+16*pos+8..]).unwrap() as usize;
			return Some((pos, &data[start..read_u32(&data[12+16*pos+12..]).unwrap() as usize+start]));
		}
	}
	None
}

fn find_best_cmap(cmap: &[u8]) -> Option<&[u8]> {
	let mut bmp = None;
	for encoding in 0..read_u16(&cmap[2..]).unwrap() as usize {
		let enc_header = &(&cmap[4+8*encoding..])[..8];
		let (plat, enc) = (read_u16(enc_header).unwrap(), read_u16(&enc_header[2..]).unwrap());
		println!("{}:{}", plat, enc);
		match (plat, enc) {
			(0, 3) | (3, 1) => {bmp=Some(&cmap[try_opt!(read_u32(&enc_header[4..])) as usize..]);},
			(0, 4) | (3, 10) => return Some(&cmap[try_opt!(read_u32(&enc_header[4..])) as usize..]),
			_ => {}	// unknown encoding
		}
	}
	bmp
}

enum Encoding<'a> {
	Fmt4 {
		end: &'a[u8],
		start: &'a[u8],
		delta: &'a[u8],
		crazy_indexing_part: &'a[u8]
	}
}

impl<'a> Encoding<'a> {
	fn lookup(&self, c: char) -> Option<u16> {
		match *self {
			Encoding::Fmt4 {end, start, delta, crazy_indexing_part: range_offset} => {
				if c as u32 > 0xffff {return Some(0)}
				let mut range = 0..end.len()/2;
				while range.start != range.end {
					let pivot = ((range.end - range.start) & !1) + range.start*2;
					range = if read_u16(&end[pivot..]).unwrap() > c as u16 {
						pivot/2+1..range.end
					} else {
						range.start..pivot/2+1
					};
				}
				let seg_offset = range.start*2;
				let block_start = read_u16(&start[seg_offset..]).unwrap();
				if block_start < c as u16 {return Some(0)}
				let block_index = c as u16 - block_start;
				return Some((read_u16(&delta[seg_offset..]).unwrap()) + {
					let offset = read_u16(&range_offset[seg_offset..]).unwrap();
					if offset == 0 {
						block_index
					} else {	// this path is untested because the spec is really weird and I've never seen it used
						let res = read_u16(&range_offset[seg_offset+(offset as usize &!1)+block_index as usize..]).unwrap();
						if res == 0 {
							return Some(0)
						} else {
							res
						}
					}
				})
			}
		}
	}
}

fn load_enc_table(mut enc: &[u8]) -> Option<Encoding> {
	let format = try_opt!(read_u16(enc));
	println!("Format{}", format);
	match format {
		4 => {
			let len = try_opt!(read_u16(&enc[2..])) as usize;
			if len > enc.len() {return None}
			enc = &enc[..len];
			let segsX2 = try_opt!(read_u16(&enc[6..])) as usize;
			if segsX2 < 2 || segsX2 % 2 != 0 || 4*segsX2 + 16 < len {return None}
			let end = &enc[14..14+segsX2];
			if read_u16(&end[segsX2-2..]).unwrap() != 0xffff {return None}
			Some(Encoding::Fmt4 {
				end: end,
				start: &enc[16+segsX2..16+2*segsX2],
				delta: &enc[16+2*segsX2..16+3*segsX2],
				crazy_indexing_part: &enc[16+3*segsX2..]
			})
		},
		_ => None	// not implemented
	}
}

pub fn load_font<'a>(data: &'a[u8], font: &str) -> Option<Font<'a>> {
	let num_tables = try_opt!(read_u16(&data[4..])) as usize;
	let (_pos, cmap) = try_opt!(scan_table_records(data, 0, 0x636d6170, num_tables));
	let best_enc = try_opt!(find_best_cmap(cmap));
	let enc = try_opt!(load_enc_table(best_enc));
	Some(Font(best_enc))
}

struct GlyphIndex(u16);

struct Burst<'a, 'b: 'a>(Vec<GlyphIndex>, &'a Font<'b>, StreakTypesetting);

pub struct TypeSetting<'a, 'b: 'a>(Vec<Burst<'a, 'b>>);

fn typeset<'a, 'b>(streak: Streak, fonts: &FontPreference<'a>) -> TypeSetting<'b, 'a> {
	TypeSetting(Vec::new())
}<commit_msg>Extract CmapFmt4 into struct<commit_after>#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Direction {Forward, Reverse}
use self::Direction::*;

impl Direction {
	fn reverse(self) -> Direction {
		match self {
			Forward => Reverse,
			Reverse => Forward
		}
	}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum GlyphOrient {Perpendicular, Parallel}
use self::GlyphOrient::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct DirBehavior(Direction, GlyphOrient);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum DirPreference {Horiz(DirBehavior), Vert(DirBehavior), BiOrient(DirBehavior, DirBehavior)}	// enable scripts without preference?
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Rot180 {Normal, Rotated}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct StreakTypesetting(DirBehavior, Rot180);

impl StreakTypesetting {
	fn effective_direction(&self) -> Direction {
		match self.1 {
			Rot180::Normal => self.0 . 0,
			Rot180::Rotated => self.0 . 0 .reverse()
		}
	}
}

/// ISO 15924 alphabetical code
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ScriptCode([u8; 4]);

pub static LATIN: ScriptCode = ScriptCode(['L' as u8, 'a' as u8, 't' as u8, 'n' as u8]);	// "Latn"

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MainAxis {Ltr, Rtl, Ttb, Btt}

pub struct NonNativeConf;

pub struct Run<'a>(pub &'a str, pub ScriptCode);

pub fn make_default_streak<'a>(run: &'a Run, main_axis: MainAxis) -> Streak<'a> {
	use self::MainAxis::*;
	Streak(run.0, run.1, StreakTypesetting(DirBehavior(Forward, Perpendicular), if run.1 == LATIN {
		match main_axis {
			Ltr | Ttb => Rot180::Normal,
			Rtl | Btt => Rot180::Rotated
		}
	} else {
		unimplemented!();
	}))
}

pub fn make_runs(s: &str) -> Vec<Run> {vec![Run(s, LATIN)]}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Streak<'a>(&'a str, ScriptCode, StreakTypesetting);

impl<'a> Streak<'a> {
	/// what order do the parts have if you split the streak
	pub fn direction(&self) -> Direction {self.2.effective_direction()}
}

pub fn bidi_algorithm(streaks: &mut [Streak]) {}

pub struct FontPreference<'a>(Font<'a>);

/*impl FontPreference {
	fn lookup(&self) -> Vec<Burst> {
		Vec::new()
	}
}*/

/// contains glyphs and typesetting information
pub struct FontCollection<'a>(&'a[u8]);
/// what features of the font collection do we want to use?
pub struct FontConfiguration;

/// contains character mapping
pub struct Font<'a>(pub Encoding<'a>, &'a FontCollection<'a>);

struct GlyphPoint(i16, i16);
enum ContourSegment {
	Line(GlyphPoint, GlyphPoint),
	Curve(GlyphPoint, GlyphPoint, GlyphPoint)
}

pub fn read_u32(data: &[u8]) -> Option<u32> {
	if data.len() > 3 {
		Some((data[0] as u32) << 24 | (data[1] as u32) << 16 | (data[2] as u32) << 8 | data[3] as u32)
	} else {
		None
	}
}

pub fn read_u16(data: &[u8]) -> Option<u16> {
	if data.len() > 1 {
		Some((data[0] as u16) << 8 | data[1] as u16)
	} else {
		None
	}
}

fn fourcc(tag: u32) -> String {
	let mut s = String::with_capacity(4);
	s.push((tag >> 24) as u8 as char);
	s.push((tag >> 16) as u8 as char);
	s.push((tag >> 8) as u8 as char);
	s.push(tag as u8 as char);
	s
}

macro_rules! try_opt {
	($e:expr) => (match $e {Some(x)=>x, None=>return None})
}

fn scan_table_records(data: &[u8], start: usize, label: u32, num_tables: usize) -> Option<(usize, &[u8])> {
	for pos in start..num_tables {
		if try_opt!(read_u32(&data[12+16*pos..])) == label {
			let start = read_u32(&data[12+16*pos+8..]).unwrap() as usize;
			return Some((pos, &data[start..read_u32(&data[12+16*pos+12..]).unwrap() as usize+start]));
		}
	}
	None
}

fn find_best_cmap(cmap: &[u8]) -> Option<&[u8]> {
	let mut bmp = None;
	for encoding in 0..read_u16(&cmap[2..]).unwrap() as usize {
		let enc_header = &(&cmap[4+8*encoding..])[..8];
		let (plat, enc) = (read_u16(enc_header).unwrap(), read_u16(&enc_header[2..]).unwrap());
		println!("{}:{}", plat, enc);
		match (plat, enc) {
			(0, 3) | (3, 1) => {bmp=Some(&cmap[try_opt!(read_u32(&enc_header[4..])) as usize..]);},
			(0, 4) | (3, 10) => return Some(&cmap[try_opt!(read_u32(&enc_header[4..])) as usize..]),
			_ => {}	// unknown encoding
		}
	}
	bmp
}

enum Encoding<'a> {
	Fmt4(CmapFmt4<'a>)
}

trait Cmap {
	fn lookup<'a>(&self, &'a str) -> (Vec<GlyphIndex>, &'a str);
}

impl<'a> Encoding<'a> {
	pub fn lookup(&self, c: char) -> Option<GlyphIndex> {
		match *self {
			Encoding::Fmt4 (CmapFmt4 {end, start, delta, crazy_indexing_part: range_offset}) => {
				if c as u32 > 0xffff {return Some(GlyphIndex(0))}
				let mut range = 0..end.len()/2;
				while range.start != range.end {
					let pivot = ((range.end - range.start) & !1) + range.start*2;
					range = if read_u16(&end[pivot..]).unwrap() > c as u16 {
						pivot/2+1..range.end
					} else {
						range.start..pivot/2+1
					};
				}
				let seg_offset = range.start*2;
				let block_start = read_u16(&start[seg_offset..]).unwrap();
				if block_start < c as u16 {return Some(GlyphIndex(0))}
				let block_index = c as u16 - block_start;
				return Some(GlyphIndex((read_u16(&delta[seg_offset..]).unwrap()).wrapping_add({
					let offset = read_u16(&range_offset[seg_offset..]).unwrap();
					if offset == 0 {
						block_index
					} else {	// this path is untested because the spec is really weird and I've never seen it used
						let res = read_u16(&range_offset[seg_offset+(offset as usize &!1)+block_index as usize..]).unwrap();
						if res == 0 {
							return Some(GlyphIndex(0))
						} else {
							res
						}
					}
				})))
			}
		}
	}
}

struct CmapFmt4<'a> {
	end: &'a[u8],
	start: &'a[u8],
	delta: &'a[u8],
	crazy_indexing_part: &'a[u8]
}

fn load_enc_table(mut enc: &[u8]) -> Option<Encoding> {
	let format = try_opt!(read_u16(enc));
	println!("Format{}", format);
	match format {
		4 => {
			let len = try_opt!(read_u16(&enc[2..])) as usize;
			if len > enc.len() {return None}
			enc = &enc[..len];
			let segsX2 = try_opt!(read_u16(&enc[6..])) as usize;
			if segsX2 < 2 || segsX2 % 2 != 0 || 4*segsX2 + 16 < len {return None}
			let end = &enc[14..14+segsX2];
			if read_u16(&end[segsX2-2..]).unwrap() != 0xffff {return None}
			Some(Encoding::Fmt4(CmapFmt4{
				end: end,
				start: &enc[16+segsX2..16+2*segsX2],
				delta: &enc[16+2*segsX2..16+3*segsX2],
				crazy_indexing_part: &enc[16+3*segsX2..]
			}))
		},
		_ => None	// not implemented
	}
}

pub fn load_font_collection(data: &[u8]) -> Option<FontCollection> {
	Some(FontCollection(data))
}

pub fn load_font<'a>(collection: &'a FontCollection<'a>, font: &str) -> Option<Font<'a>> {
	let data = collection.0;
	let num_tables = try_opt!(read_u16(&data[4..])) as usize;
	let (_pos, cmap) = try_opt!(scan_table_records(data, 0, 0x636d6170, num_tables));
	let best_enc = try_opt!(find_best_cmap(cmap));
	let enc = try_opt!(load_enc_table(best_enc));
	Some(Font(enc, collection))
}

#[derive(Debug)]
pub struct GlyphIndex(u16);

struct Burst<'a, 'b: 'a>(Vec<GlyphIndex>, &'a Font<'b>, StreakTypesetting);

pub struct TypeSetting<'a, 'b: 'a>(Vec<Burst<'a, 'b>>);

fn typeset<'a, 'b>(streak: Streak, fonts: &FontPreference<'a>) -> TypeSetting<'b, 'a> {
	TypeSetting(Vec::new())
}<|endoftext|>


<commit_before>#![crate_type= "lib"]

#![feature(collections, core, libc)]

//! A simply library for parsing command line arguments when writing
//! command line and console applications.
//!
//!
//! You can use `clap` to lay out a list of possible valid command line arguments and let `clap` parse the string given by the user at runtime.
//! When using `clap` you define a set of parameters and rules for your arguments and at runtime `clap` will determine their validity.
//! Also, `clap` provides the traditional version and help switches 'for free' by parsing the list of possible valid arguments lazily at runtime.
//! i.e. only when it's been determined that the user wants or needs to see the help and version information.
//!
//! After defining a list of possible valid arguments you get a list of matches that the user supplied at runtime. You can then use this list to
//! determine the functioning of your program.
//!
//! Example:
//!
//! ```no_run
//! use clap::{Arg, App};
//!
//! // ...
//!
//! let matches = App::new("MyApp")
//!						.version("1.0")
//!						.author("Kevin K. <kbknapp@gmail.com>")
//!						.about("Does awesome things")
//!						.arg(Arg::new("config")
//!									.short("c")
//!									.long("config")
//!									.help("Sets a custom config file")
//!									.takes_value(true))
//!						.arg(Arg::new("output")
//!									.help("Sets an optional output file")
//!									.index(1))
//!						.arg(Arg::new("debug")
//!									.short("d")
//! 								.multiple(true)
//!									.help("Turn debugging information on"))
//!						.get_matches();
//!
//!	if let Some(o) = matches.value_of("output") {
//!		println!("Value for output: {}", o);
//!	}
//!
//!	if let Some(c) = matches.value_of("config") {
//!		println!("Value for config: {}", c);
//!	}
//!
//! match matches.occurrences_of("debug") {
//! 	0 => println!("Debug mode is off"),
//!		1 => println!("Debug mode is kind of on"),
//!		2 => println!("Debug mode is on"),
//!		3 | _ => println!("Don't be crazy"),
//! }
//!
//! // more porgram logic goes here...
//! ```
//!
//! If you were to compile the above program and run it with the flag `--help` or `-h` the following output woud be presented
//!
//! ```sh
//! $ myprog --help
//! MyApp 1.0
//! Kevin K. <kbknapp@gmail.com>
//! Does awesome things
//!
//! USAGE:
//! 	MyApp [FLAGS] [OPTIONS] [POSITIONAL]
//!
//! FLAGS:
//! 	-d   			Turn debugging information on
//! 	-h,--help		Prints this message
//! 	-v,--version	Prints version information
//!
//! OPTIONS:
//! 	-c,--config <config>		Sets a custom config file
//!
//! POSITIONAL ARGUMENTS:
//! 	output			Sets an optional output file
//! ```

pub use argmatches::ArgMatches;
pub use arg::Arg;
pub use app::App;

mod app;
mod argmatches;
mod arg;
mod args;

#[cfg(test)]
mod tests {
	use super::*;
<<<<<<< HEAD
=======

	#[test]
	#[should_fail]
	fn unique_arg_names(){
		App::new("some").args(vec![
			Arg::new("arg").short("a"),
			Arg::new("arg").short("b")
		]);
	}
	#[test]
	#[should_fail]
	fn unique_arg_shorts(){
		App::new("some").args(vec![
			Arg::new("arg1").short("a"),
			Arg::new("arg2").short("a")
		]);
	}
	#[test]
	#[should_fail]
	fn unique_arg_longs(){
		App::new("some").args(vec![
			Arg::new("arg1").long("long"),
			Arg::new("arg2").long("long")
		]);
	}
	#[test]
	fn create_app(){
		App::new("some").about("about").author("author").version("1.0");
	}
	#[test]
	fn create_arg_flag(){
		Arg::new("some").short("a").long("long").help("help with some arg").multiple(true);
	}
	#[test]
	fn create_arg_pos(){
		Arg::new("some").index(1).help("help with some arg").required(true);
	}
	#[test]
	fn create_arg_opt(){
		Arg::new("some").short("s").long("some").takes_value(true).help("help with some arg").required(true);
>>>>>>> tests
	}
}
<commit_msg>adding tests<commit_after>#![crate_type= "lib"]

#![feature(collections, core, libc)]

//! A simply library for parsing command line arguments when writing
//! command line and console applications.
//!
//!
//! You can use `clap` to lay out a list of possible valid command line arguments and let `clap` parse the string given by the user at runtime.
//! When using `clap` you define a set of parameters and rules for your arguments and at runtime `clap` will determine their validity.
//! Also, `clap` provides the traditional version and help switches 'for free' by parsing the list of possible valid arguments lazily at runtime.
//! i.e. only when it's been determined that the user wants or needs to see the help and version information.
//!
//! After defining a list of possible valid arguments you get a list of matches that the user supplied at runtime. You can then use this list to
//! determine the functioning of your program.
//!
//! Example:
//!
//! ```no_run
//! use clap::{Arg, App};
//!
//! // ...
//!
//! let matches = App::new("MyApp")
//!						.version("1.0")
//!						.author("Kevin K. <kbknapp@gmail.com>")
//!						.about("Does awesome things")
//!						.arg(Arg::new("config")
//!									.short("c")
//!									.long("config")
//!									.help("Sets a custom config file")
//!									.takes_value(true))
//!						.arg(Arg::new("output")
//!									.help("Sets an optional output file")
//!									.index(1))
//!						.arg(Arg::new("debug")
//!									.short("d")
//! 								.multiple(true)
//!									.help("Turn debugging information on"))
//!						.get_matches();
//!
//!	if let Some(o) = matches.value_of("output") {
//!		println!("Value for output: {}", o);
//!	}
//!
//!	if let Some(c) = matches.value_of("config") {
//!		println!("Value for config: {}", c);
//!	}
//!
//! match matches.occurrences_of("debug") {
//! 	0 => println!("Debug mode is off"),
//!		1 => println!("Debug mode is kind of on"),
//!		2 => println!("Debug mode is on"),
//!		3 | _ => println!("Don't be crazy"),
//! }
//!
//! // more porgram logic goes here...
//! ```
//!
//! If you were to compile the above program and run it with the flag `--help` or `-h` the following output woud be presented
//!
//! ```sh
//! $ myprog --help
//! MyApp 1.0
//! Kevin K. <kbknapp@gmail.com>
//! Does awesome things
//!
//! USAGE:
//! 	MyApp [FLAGS] [OPTIONS] [POSITIONAL]
//!
//! FLAGS:
//! 	-d   			Turn debugging information on
//! 	-h,--help		Prints this message
//! 	-v,--version	Prints version information
//!
//! OPTIONS:
//! 	-c,--config <config>		Sets a custom config file
//!
//! POSITIONAL ARGUMENTS:
//! 	output			Sets an optional output file
//! ```

pub use argmatches::ArgMatches;
pub use arg::Arg;
pub use app::App;

mod app;
mod argmatches;
mod arg;
mod args;

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

	#[test]
	#[should_fail]
	fn unique_arg_names(){
		App::new("some").args(vec![
			Arg::new("arg").short("a"),
			Arg::new("arg").short("b")
		]);
	}
	#[test]
	#[should_fail]
	fn unique_arg_shorts(){
		App::new("some").args(vec![
			Arg::new("arg1").short("a"),
			Arg::new("arg2").short("a")
		]);
	}
	#[test]
	#[should_fail]
	fn unique_arg_longs(){
		App::new("some").args(vec![
			Arg::new("arg1").long("long"),
			Arg::new("arg2").long("long")
		]);
	}
	#[test]
	fn create_app(){
		App::new("some").about("about").author("author").version("1.0");
	}
	#[test]
	fn create_arg_flag(){
		Arg::new("some").short("a").long("long").help("help with some arg").multiple(true);
	}
	#[test]
	fn create_arg_pos(){
		Arg::new("some").index(1).help("help with some arg").required(true);
	}
	#[test]
	fn create_arg_opt(){
		Arg::new("some").short("s").long("some").takes_value(true).help("help with some arg").required(true);
	}
}
<|endoftext|>


<commit_before>//! Async WebSocket usage.
//!
//! This library is an implementation of WebSocket handshakes and streams. It
//! is based on the crate which implements all required WebSocket protocol
//! logic. So this crate basically just brings tokio support / tokio integration
//! to it.
//!
//! Each WebSocket stream implements the required `Stream` and `Sink` traits,
//! so the socket is just a stream of messages coming in and going out.

#![deny(
    missing_docs,
    unused_must_use,
    unused_mut,
    unused_imports,
    unused_import_braces)]

extern crate futures;
extern crate tokio_io;
extern crate tungstenite;

#[cfg(feature="connect")]
mod connect;

#[cfg(feature="stream")]
pub mod stream;

use std::io::ErrorKind;

use futures::{Poll, Future, Async, AsyncSink, Stream, Sink, StartSend};
use tokio_io::{AsyncRead, AsyncWrite};

use tungstenite::handshake::client::{ClientHandshake, Response, Request};
use tungstenite::handshake::server::{ServerHandshake, Callback, NoCallback};
use tungstenite::handshake::{HandshakeRole, HandshakeError};
use tungstenite::protocol::{WebSocket, Message};
use tungstenite::error::Error as WsError;
use tungstenite::server;

#[cfg(feature="connect")]
pub use connect::{connect_async, client_async_tls};

/// Creates a WebSocket handshake from a request and a stream.
/// For convenience, the user may call this with a url string, a URL,
/// or a `Request`. Calling with `Request` allows the user to add
/// a WebSocket protocol or other custom headers.
///
/// Internally, this custom creates a handshake representation and returns
/// a future representing the resolution of the WebSocket handshake. The
/// returned future will resolve to either `WebSocketStream<S>` or `Error`
/// depending on whether the handshake is successful.
///
/// This is typically used for clients who have already established, for
/// example, a TCP connection to the remote server.
pub fn client_async<'a, R, S>(request: R, stream: S) -> ConnectAsync<S>
where
    R: Into<Request<'a>>,
    S: AsyncRead + AsyncWrite
{
    ConnectAsync {
        inner: MidHandshake {
            inner: Some(ClientHandshake::start(stream, request.into()).handshake())
        }
    }
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function will internally call `server::accept` to create a
/// handshake representation and returns a future representing the
/// resolution of the WebSocket handshake. The returned future will resolve
/// to either `WebSocketStream<S>` or `Error` depending if it's successful
/// or not.
///
/// This is typically used after a socket has been accepted from a
/// `TcpListener`. That socket is then passed to this function to perform
/// the server half of the accepting a client's websocket connection.
pub fn accept_async<S>(stream: S) -> AcceptAsync<S, NoCallback>
where
    S: AsyncRead + AsyncWrite,
{
    accept_hdr_async(stream, NoCallback)
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function does the same as `accept_async()` but accepts an extra callback
/// for header processing. The callback receives headers of the incoming
/// requests and is able to add extra headers to the reply.
pub fn accept_hdr_async<S, C>(stream: S, callback: C) -> AcceptAsync<S, C>
where
    S: AsyncRead + AsyncWrite,
    C: Callback,
{
    AcceptAsync {
        inner: MidHandshake {
            inner: Some(server::accept_hdr(stream, callback))
        }
    }
}

/// A wrapper around an underlying raw stream which implements the WebSocket
/// protocol.
///
/// A `WebSocketStream<S>` represents a handshake that has been completed
/// successfully and both the server and the client are ready for receiving
/// and sending data. Message from a `WebSocketStream<S>` are accessible
/// through the respective `Stream` and `Sink`. Check more information about
/// them in `futures-rs` crate documentation or have a look on the examples
/// and unit tests for this crate.
pub struct WebSocketStream<S> {
    inner: WebSocket<S>,
}

impl<T> Stream for WebSocketStream<T> where T: AsyncRead + AsyncWrite {
    type Item = Message;
    type Error = WsError;

    fn poll(&mut self) -> Poll<Option<Message>, WsError> {
        self.inner.read_message().map(|m| Some(m)).to_async()
    }
}

impl<T> Sink for WebSocketStream<T> where T: AsyncRead + AsyncWrite {
    type SinkItem = Message;
    type SinkError = WsError;

    fn start_send(&mut self, item: Message) -> StartSend<Message, WsError> {
        try!(self.inner.write_message(item).to_async());
        Ok(AsyncSink::Ready)
    }

    fn poll_complete(&mut self) -> Poll<(), WsError> {
        self.inner.write_pending().to_async()
    }

    fn close(&mut self) -> Poll<(), WsError> {
        self.inner.close(None).to_async()
    }
}

/// Future returned from client_async() which will resolve
/// once the connection handshake has finished.
pub struct ConnectAsync<S: AsyncRead + AsyncWrite> {
    inner: MidHandshake<ClientHandshake<S>>,
}

impl<S: AsyncRead + AsyncWrite> Future for ConnectAsync<S> {
    type Item = (WebSocketStream<S>, Response);
    type Error = WsError;

    fn poll(&mut self) -> Poll<Self::Item, WsError> {
        match self.inner.poll()? {
            Async::NotReady => Ok(Async::NotReady),
            Async::Ready((ws, resp)) => Ok(Async::Ready((WebSocketStream { inner: ws }, resp))),
        }
    }
}

/// Future returned from accept_async() which will resolve
/// once the connection handshake has finished.
pub struct AcceptAsync<S: AsyncRead + AsyncWrite, C: Callback> {
    inner: MidHandshake<ServerHandshake<S, C>>,
}

impl<S: AsyncRead + AsyncWrite, C: Callback> Future for AcceptAsync<S, C> {
    type Item = WebSocketStream<S>;
    type Error = WsError;

    fn poll(&mut self) -> Poll<Self::Item, WsError> {
        match self.inner.poll()? {
            Async::NotReady => Ok(Async::NotReady),
            Async::Ready(ws) => Ok(Async::Ready(WebSocketStream { inner: ws })),
        }
    }
}

struct MidHandshake<H: HandshakeRole> {
    inner: Option<Result<<H as HandshakeRole>::FinalResult, HandshakeError<H>>>,
}

impl<H: HandshakeRole> Future for MidHandshake<H> {
    type Item = <H as HandshakeRole>::FinalResult;
    type Error = WsError;

    fn poll(&mut self) -> Poll<Self::Item, WsError> {
        match self.inner.take().expect("cannot poll MidHandshake twice") {
            Ok(result) => Ok(Async::Ready(result)),
            Err(HandshakeError::Failure(e)) => Err(e),
            Err(HandshakeError::Interrupted(s)) => {
                match s.handshake() {
                    Ok(result) => Ok(Async::Ready(result)),
                    Err(HandshakeError::Failure(e)) => Err(e),
                    Err(HandshakeError::Interrupted(s)) => {
                        self.inner = Some(Err(HandshakeError::Interrupted(s)));
                        Ok(Async::NotReady)
                    }
                }
            }
        }
    }
}

trait ToAsync {
    type T;
    type E;
    fn to_async(self) -> Result<Async<Self::T>, Self::E>;
}

impl<T> ToAsync for Result<T, WsError> {
    type T = T;
    type E = WsError;
    fn to_async(self) -> Result<Async<Self::T>, Self::E> {
        match self {
            Ok(x) => Ok(Async::Ready(x)),
            Err(error) => match error {
                WsError::Io(ref err) if err.kind() == ErrorKind::WouldBlock => Ok(Async::NotReady),
                err => Err(err),
            },
        }
    }
}

<commit_msg>trivial: make tungstenite crate public<commit_after>//! Async WebSocket usage.
//!
//! This library is an implementation of WebSocket handshakes and streams. It
//! is based on the crate which implements all required WebSocket protocol
//! logic. So this crate basically just brings tokio support / tokio integration
//! to it.
//!
//! Each WebSocket stream implements the required `Stream` and `Sink` traits,
//! so the socket is just a stream of messages coming in and going out.

#![deny(
    missing_docs,
    unused_must_use,
    unused_mut,
    unused_imports,
    unused_import_braces)]

extern crate futures;
extern crate tokio_io;

pub extern crate tungstenite;

#[cfg(feature="connect")]
mod connect;

#[cfg(feature="stream")]
pub mod stream;

use std::io::ErrorKind;

use futures::{Poll, Future, Async, AsyncSink, Stream, Sink, StartSend};
use tokio_io::{AsyncRead, AsyncWrite};

use tungstenite::handshake::client::{ClientHandshake, Response, Request};
use tungstenite::handshake::server::{ServerHandshake, Callback, NoCallback};
use tungstenite::handshake::{HandshakeRole, HandshakeError};
use tungstenite::protocol::{WebSocket, Message};
use tungstenite::error::Error as WsError;
use tungstenite::server;

#[cfg(feature="connect")]
pub use connect::{connect_async, client_async_tls};

/// Creates a WebSocket handshake from a request and a stream.
/// For convenience, the user may call this with a url string, a URL,
/// or a `Request`. Calling with `Request` allows the user to add
/// a WebSocket protocol or other custom headers.
///
/// Internally, this custom creates a handshake representation and returns
/// a future representing the resolution of the WebSocket handshake. The
/// returned future will resolve to either `WebSocketStream<S>` or `Error`
/// depending on whether the handshake is successful.
///
/// This is typically used for clients who have already established, for
/// example, a TCP connection to the remote server.
pub fn client_async<'a, R, S>(request: R, stream: S) -> ConnectAsync<S>
where
    R: Into<Request<'a>>,
    S: AsyncRead + AsyncWrite
{
    ConnectAsync {
        inner: MidHandshake {
            inner: Some(ClientHandshake::start(stream, request.into()).handshake())
        }
    }
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function will internally call `server::accept` to create a
/// handshake representation and returns a future representing the
/// resolution of the WebSocket handshake. The returned future will resolve
/// to either `WebSocketStream<S>` or `Error` depending if it's successful
/// or not.
///
/// This is typically used after a socket has been accepted from a
/// `TcpListener`. That socket is then passed to this function to perform
/// the server half of the accepting a client's websocket connection.
pub fn accept_async<S>(stream: S) -> AcceptAsync<S, NoCallback>
where
    S: AsyncRead + AsyncWrite,
{
    accept_hdr_async(stream, NoCallback)
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function does the same as `accept_async()` but accepts an extra callback
/// for header processing. The callback receives headers of the incoming
/// requests and is able to add extra headers to the reply.
pub fn accept_hdr_async<S, C>(stream: S, callback: C) -> AcceptAsync<S, C>
where
    S: AsyncRead + AsyncWrite,
    C: Callback,
{
    AcceptAsync {
        inner: MidHandshake {
            inner: Some(server::accept_hdr(stream, callback))
        }
    }
}

/// A wrapper around an underlying raw stream which implements the WebSocket
/// protocol.
///
/// A `WebSocketStream<S>` represents a handshake that has been completed
/// successfully and both the server and the client are ready for receiving
/// and sending data. Message from a `WebSocketStream<S>` are accessible
/// through the respective `Stream` and `Sink`. Check more information about
/// them in `futures-rs` crate documentation or have a look on the examples
/// and unit tests for this crate.
pub struct WebSocketStream<S> {
    inner: WebSocket<S>,
}

impl<T> Stream for WebSocketStream<T> where T: AsyncRead + AsyncWrite {
    type Item = Message;
    type Error = WsError;

    fn poll(&mut self) -> Poll<Option<Message>, WsError> {
        self.inner.read_message().map(|m| Some(m)).to_async()
    }
}

impl<T> Sink for WebSocketStream<T> where T: AsyncRead + AsyncWrite {
    type SinkItem = Message;
    type SinkError = WsError;

    fn start_send(&mut self, item: Message) -> StartSend<Message, WsError> {
        try!(self.inner.write_message(item).to_async());
        Ok(AsyncSink::Ready)
    }

    fn poll_complete(&mut self) -> Poll<(), WsError> {
        self.inner.write_pending().to_async()
    }

    fn close(&mut self) -> Poll<(), WsError> {
        self.inner.close(None).to_async()
    }
}

/// Future returned from client_async() which will resolve
/// once the connection handshake has finished.
pub struct ConnectAsync<S: AsyncRead + AsyncWrite> {
    inner: MidHandshake<ClientHandshake<S>>,
}

impl<S: AsyncRead + AsyncWrite> Future for ConnectAsync<S> {
    type Item = (WebSocketStream<S>, Response);
    type Error = WsError;

    fn poll(&mut self) -> Poll<Self::Item, WsError> {
        match self.inner.poll()? {
            Async::NotReady => Ok(Async::NotReady),
            Async::Ready((ws, resp)) => Ok(Async::Ready((WebSocketStream { inner: ws }, resp))),
        }
    }
}

/// Future returned from accept_async() which will resolve
/// once the connection handshake has finished.
pub struct AcceptAsync<S: AsyncRead + AsyncWrite, C: Callback> {
    inner: MidHandshake<ServerHandshake<S, C>>,
}

impl<S: AsyncRead + AsyncWrite, C: Callback> Future for AcceptAsync<S, C> {
    type Item = WebSocketStream<S>;
    type Error = WsError;

    fn poll(&mut self) -> Poll<Self::Item, WsError> {
        match self.inner.poll()? {
            Async::NotReady => Ok(Async::NotReady),
            Async::Ready(ws) => Ok(Async::Ready(WebSocketStream { inner: ws })),
        }
    }
}

struct MidHandshake<H: HandshakeRole> {
    inner: Option<Result<<H as HandshakeRole>::FinalResult, HandshakeError<H>>>,
}

impl<H: HandshakeRole> Future for MidHandshake<H> {
    type Item = <H as HandshakeRole>::FinalResult;
    type Error = WsError;

    fn poll(&mut self) -> Poll<Self::Item, WsError> {
        match self.inner.take().expect("cannot poll MidHandshake twice") {
            Ok(result) => Ok(Async::Ready(result)),
            Err(HandshakeError::Failure(e)) => Err(e),
            Err(HandshakeError::Interrupted(s)) => {
                match s.handshake() {
                    Ok(result) => Ok(Async::Ready(result)),
                    Err(HandshakeError::Failure(e)) => Err(e),
                    Err(HandshakeError::Interrupted(s)) => {
                        self.inner = Some(Err(HandshakeError::Interrupted(s)));
                        Ok(Async::NotReady)
                    }
                }
            }
        }
    }
}

trait ToAsync {
    type T;
    type E;
    fn to_async(self) -> Result<Async<Self::T>, Self::E>;
}

impl<T> ToAsync for Result<T, WsError> {
    type T = T;
    type E = WsError;
    fn to_async(self) -> Result<Async<Self::T>, Self::E> {
        match self {
            Ok(x) => Ok(Async::Ready(x)),
            Err(error) => match error {
                WsError::Io(ref err) if err.kind() == ErrorKind::WouldBlock => Ok(Async::NotReady),
                err => Err(err),
            },
        }
    }
}

<|endoftext|>


<commit_before>extern crate hyper;
extern crate route_recognizer;

use hyper::header::Headers;
use hyper::method::Method;
use hyper::server::Handler as HyperHandler;
use hyper::server::{Request, Response};
use hyper::status::StatusCode;
use hyper::uri::RequestUri;

use route_recognizer::Router;

pub use route_recognizer::{Match, Params};

#[macro_export]
macro_rules! create_router {
    ( $( $path:expr => $( $method:ident ),+ => $handler:expr ),+, ) => {{
        let mut router = $crate::HyperRouter::new();

        $(
            let mut entry = $crate::RouteEntry::with_handler($handler);
            $(
                entry.add_method($crate::MethodRoutes::$method);
            )+

            router.add_path_entry($path, entry);
        )+

        router
    }};
}

fn method_to_bit(method: &Method) -> u8 {
    use hyper::method::Method::*;
    let exp = match *method {
        Options => 0,
        Get | Head => 1,
        Post => 2,
        Put => 3,
        Delete => 4,
        Connect => 5,
        Patch => 6,
        Trace | Extension(_) => 7,
    };

    1u8 << exp
}

fn method_route_to_bit(method: MethodRoutes) -> u8 {
    use MethodRoutes::*;
    let exp = match method {
        Options => 0,
        Get => 1,
        Post => 2,
        Put => 3,
        Delete => 4,
        Connect => 5,
        Patch => 6,
        Other => 7,
    };

    1u8 << exp
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum MethodRoutes {
    Options,
    Get,
    Post,
    Put,
    Delete,
    Connect,
    Patch,
    Other,
}

#[derive(Debug)]
pub struct RouteEntry<H> {
    accepted_methods: u8,
    handler: H,
}

impl<H> RouteEntry<H> {
    pub fn with_handler(handler: H) -> RouteEntry<H> {
        RouteEntry {
            accepted_methods: 0,
            handler: handler,
        }
    }

    pub fn add_method(&mut self, method: MethodRoutes) {
        self.accepted_methods |= method_route_to_bit(method);
    }

    pub fn add_methods(&mut self, methods: &[MethodRoutes]) {
        for method in methods {
            self.accepted_methods |= method_route_to_bit(*method);
        }
    }

    pub fn add_all_methods(&mut self) {
        self.accepted_methods = !0u8;
    }

    pub fn accepts_method(&self, method: &Method) -> bool {
        (self.accepted_methods & method_to_bit(method)) > 0
    }

    pub fn handler(&self) -> &H {
        &self.handler
    }
}

pub trait RouteHandler: Sync + Send {
    fn handle<'a, 'k>(&'a self, params: Params, req: Request<'a, 'k>, res: Response<'a>);

    fn check_continue(&self, _: Params, _: (&Method, &RequestUri, &Headers)) -> StatusCode {
        StatusCode::Continue
    }
}

impl RouteHandler for Box<RouteHandler> {
    fn handle<'a, 'k>(&'a self, params: Params, req: Request<'a, 'k>, res: Response<'a>) {
        self.as_ref().handle(params, req, res)
    }

    fn check_continue(&self, params: Params, t: (&Method, &RequestUri, &Headers)) -> StatusCode {
        self.as_ref().check_continue(params, t)
    }
}

impl RouteHandler for HyperHandler {
    fn handle<'a, 'k>(&'a self, _: Params, req: Request<'a, 'k>, res: Response<'a>) {
        self.handle(req, res)
    }

    fn check_continue(&self, _: Params, tuple: (&Method, &RequestUri, &Headers)) -> StatusCode {
        self.check_continue(tuple)
    }
}

impl<F> RouteHandler for F
    where F: Fn(Params, Request, Response),
          F: Sync + Send
{
    fn handle<'a, 'k>(&'a self, params: Params, req: Request<'a, 'k>, res: Response<'a>) {
        self(params, req, res)
    }
}

pub struct HyperRouter<H> {
    path_router: Router<RouteEntry<H>>,
    url_router: Router<RouteEntry<H>>,
    authority_router: Router<RouteEntry<H>>,
    server_wide: Option<RouteEntry<H>>,
}

impl<H> HyperRouter<H> {
    pub fn new() -> HyperRouter<H> {
        HyperRouter {
            path_router: Router::new(),
            url_router: Router::new(),
            authority_router: Router::new(),
            server_wide: None,
        }
    }

    pub fn add_path_entry(&mut self, route: &str, entry: RouteEntry<H>) {
        self.path_router.add(route, entry);
    }

    pub fn add_url_entry(&mut self, route: &str, entry: RouteEntry<H>) {
        self.path_router.add(route, entry);
    }

    pub fn add_authority_entry(&mut self, route: &str, entry: RouteEntry<H>) {
        self.path_router.add(route, entry);
    }

    pub fn add_server_wide_entry(&mut self, entry: RouteEntry<H>) {
        self.server_wide = Some(entry);
    }

    pub fn get_match(&self, method: &Method, uri: &RequestUri) -> Option<Match<&RouteEntry<H>>> {
        use hyper::uri::RequestUri::*;

        let m = match *uri {
            AbsolutePath(ref path) => self.path_router.recognize(&path).ok(),
            AbsoluteUri(ref url) => self.url_router.recognize(url.as_str()).ok(),
            Authority(ref authority) => self.authority_router.recognize(&authority).ok(),
            Star => {
                self.server_wide.as_ref().map(|handler| {
                    Match {
                        handler: handler,
                        params: Params::new(),
                    }
                })
            }
        };

        if let Some(mat) = m {
            if mat.handler.accepts_method(method) {
                Some(mat)
            } else {
                None
            }
        } else {
            None
        }
    }
}

impl<H> HyperHandler for HyperRouter<H>
    where H: RouteHandler
{
    fn handle<'a, 'k>(&'a self, req: Request<'a, 'k>, mut res: Response<'a>) {
        if let Some(matches) = self.get_match(&req.method, &req.uri) {
            let Match { handler, params } = matches;
            handler.handler.handle(params, req, res);
        } else {
            *res.status_mut() = StatusCode::NotFound;
        }
    }

    fn check_continue(&self, tuple: (&Method, &RequestUri, &Headers)) -> StatusCode {
        if let Some(matches) = self.get_match(tuple.0, tuple.1) {
            let Match { handler, params } = matches;
            handler.handler.check_continue(params, tuple)
        } else {
            StatusCode::Continue
        }
    }
}

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

    use hyper::method::Method;
    use hyper::uri::RequestUri;

    #[test]
    fn simple_test() {
        let mut entry = RouteEntry::with_handler(0u8);
        entry.add_method(MethodRoutes::Get);
        let mut router = HyperRouter::new();
        router.add_path_entry("/test/", entry);

        let res = router.get_match(&Method::Get,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert_eq!(res.unwrap().handler.handler, 0u8);

        let res = router.get_match(&Method::Get,
                                   &RequestUri::AbsolutePath(String::from("/test2/")));
        assert!(res.is_none());

        let res = router.get_match(&Method::Post,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert!(res.is_none());
    }

    #[test]
    fn multi_method_test() {
        let mut entry = RouteEntry::with_handler(0u8);
        entry.add_method(MethodRoutes::Get);
        entry.add_method(MethodRoutes::Put);
        let mut router = HyperRouter::new();
        router.add_path_entry("/test/", entry);

        let res = router.get_match(&Method::Get,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert_eq!(res.unwrap().handler.handler, 0u8);

        let res = router.get_match(&Method::Put,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert_eq!(res.unwrap().handler.handler, 0u8);

        let res = router.get_match(&Method::Post,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert!(res.is_none());
    }

    #[test]
    fn create_router_test() {
        let router = create_router! {
            "/test/" => Get, Put => 0u8,
            "/test2/:id" => Delete => 1u8,
        };

        let res = router.get_match(&Method::Get,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert_eq!(res.unwrap().handler.handler, 0u8);

        let res = router.get_match(&Method::Put,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert_eq!(res.unwrap().handler.handler, 0u8);

        let res = router.get_match(&Method::Delete,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert!(res.is_none());

        let res = router.get_match(&Method::Delete,
                                   &RequestUri::AbsolutePath(String::from("/test2/test")));
        assert_eq!(res.as_ref().unwrap().handler.handler, 1u8);
        assert_eq!(res.unwrap().params["id"], "test");
    }
}
<commit_msg>Don't match against query string<commit_after>extern crate hyper;
extern crate route_recognizer;

use hyper::header::Headers;
use hyper::method::Method;
use hyper::server::Handler as HyperHandler;
use hyper::server::{Request, Response};
use hyper::status::StatusCode;
use hyper::uri::RequestUri;

use route_recognizer::Router;

pub use route_recognizer::{Match, Params};

#[macro_export]
macro_rules! create_router {
    ( $( $path:expr => $( $method:ident ),+ => $handler:expr ),+, ) => {{
        let mut router = $crate::HyperRouter::new();

        $(
            let mut entry = $crate::RouteEntry::with_handler($handler);
            $(
                entry.add_method($crate::MethodRoutes::$method);
            )+

            router.add_path_entry($path, entry);
        )+

        router
    }};
}

fn method_to_bit(method: &Method) -> u8 {
    use hyper::method::Method::*;
    let exp = match *method {
        Options => 0,
        Get | Head => 1,
        Post => 2,
        Put => 3,
        Delete => 4,
        Connect => 5,
        Patch => 6,
        Trace | Extension(_) => 7,
    };

    1u8 << exp
}

fn method_route_to_bit(method: MethodRoutes) -> u8 {
    use MethodRoutes::*;
    let exp = match method {
        Options => 0,
        Get => 1,
        Post => 2,
        Put => 3,
        Delete => 4,
        Connect => 5,
        Patch => 6,
        Other => 7,
    };

    1u8 << exp
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum MethodRoutes {
    Options,
    Get,
    Post,
    Put,
    Delete,
    Connect,
    Patch,
    Other,
}

#[derive(Debug)]
pub struct RouteEntry<H> {
    accepted_methods: u8,
    handler: H,
}

impl<H> RouteEntry<H> {
    pub fn with_handler(handler: H) -> RouteEntry<H> {
        RouteEntry {
            accepted_methods: 0,
            handler: handler,
        }
    }

    pub fn add_method(&mut self, method: MethodRoutes) {
        self.accepted_methods |= method_route_to_bit(method);
    }

    pub fn add_methods(&mut self, methods: &[MethodRoutes]) {
        for method in methods {
            self.accepted_methods |= method_route_to_bit(*method);
        }
    }

    pub fn add_all_methods(&mut self) {
        self.accepted_methods = !0u8;
    }

    pub fn accepts_method(&self, method: &Method) -> bool {
        (self.accepted_methods & method_to_bit(method)) > 0
    }

    pub fn handler(&self) -> &H {
        &self.handler
    }
}

pub trait RouteHandler: Sync + Send {
    fn handle<'a, 'k>(&'a self, params: Params, req: Request<'a, 'k>, res: Response<'a>);

    fn check_continue(&self, _: Params, _: (&Method, &RequestUri, &Headers)) -> StatusCode {
        StatusCode::Continue
    }
}

impl RouteHandler for Box<RouteHandler> {
    fn handle<'a, 'k>(&'a self, params: Params, req: Request<'a, 'k>, res: Response<'a>) {
        self.as_ref().handle(params, req, res)
    }

    fn check_continue(&self, params: Params, t: (&Method, &RequestUri, &Headers)) -> StatusCode {
        self.as_ref().check_continue(params, t)
    }
}

impl RouteHandler for HyperHandler {
    fn handle<'a, 'k>(&'a self, _: Params, req: Request<'a, 'k>, res: Response<'a>) {
        self.handle(req, res)
    }

    fn check_continue(&self, _: Params, tuple: (&Method, &RequestUri, &Headers)) -> StatusCode {
        self.check_continue(tuple)
    }
}

impl<F> RouteHandler for F
    where F: Fn(Params, Request, Response),
          F: Sync + Send
{
    fn handle<'a, 'k>(&'a self, params: Params, req: Request<'a, 'k>, res: Response<'a>) {
        self(params, req, res)
    }
}

pub struct HyperRouter<H> {
    path_router: Router<RouteEntry<H>>,
    url_router: Router<RouteEntry<H>>,
    authority_router: Router<RouteEntry<H>>,
    server_wide: Option<RouteEntry<H>>,
}

impl<H> HyperRouter<H> {
    pub fn new() -> HyperRouter<H> {
        HyperRouter {
            path_router: Router::new(),
            url_router: Router::new(),
            authority_router: Router::new(),
            server_wide: None,
        }
    }

    pub fn add_path_entry(&mut self, route: &str, entry: RouteEntry<H>) {
        self.path_router.add(route, entry);
    }

    pub fn add_url_entry(&mut self, route: &str, entry: RouteEntry<H>) {
        self.path_router.add(route, entry);
    }

    pub fn add_authority_entry(&mut self, route: &str, entry: RouteEntry<H>) {
        self.path_router.add(route, entry);
    }

    pub fn add_server_wide_entry(&mut self, entry: RouteEntry<H>) {
        self.server_wide = Some(entry);
    }

    pub fn get_match(&self, method: &Method, uri: &RequestUri) -> Option<Match<&RouteEntry<H>>> {
        use hyper::uri::RequestUri::*;

        let m = match *uri {
            AbsolutePath(ref path) => {
                self.path_router
                    .recognize(&path.splitn(2, |c| c == '?' || c == '#').collect::<Vec<&str>>()[0])
                    .ok()
            }
            AbsoluteUri(ref url) => self.url_router.recognize(url.as_str()).ok(),
            Authority(ref authority) => self.authority_router.recognize(&authority).ok(),
            Star => {
                self.server_wide.as_ref().map(|handler| {
                    Match {
                        handler: handler,
                        params: Params::new(),
                    }
                })
            }
        };

        if let Some(mat) = m {
            if mat.handler.accepts_method(method) {
                Some(mat)
            } else {
                None
            }
        } else {
            None
        }
    }
}

impl<H> HyperHandler for HyperRouter<H>
    where H: RouteHandler
{
    fn handle<'a, 'k>(&'a self, req: Request<'a, 'k>, mut res: Response<'a>) {
        if let Some(matches) = self.get_match(&req.method, &req.uri) {
            let Match { handler, params } = matches;
            handler.handler.handle(params, req, res);
        } else {
            *res.status_mut() = StatusCode::NotFound;
        }
    }

    fn check_continue(&self, tuple: (&Method, &RequestUri, &Headers)) -> StatusCode {
        if let Some(matches) = self.get_match(tuple.0, tuple.1) {
            let Match { handler, params } = matches;
            handler.handler.check_continue(params, tuple)
        } else {
            StatusCode::Continue
        }
    }
}

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

    use hyper::method::Method;
    use hyper::uri::RequestUri;

    #[test]
    fn simple_test() {
        let mut entry = RouteEntry::with_handler(0u8);
        entry.add_method(MethodRoutes::Get);
        let mut router = HyperRouter::new();
        router.add_path_entry("/test/", entry);

        let res = router.get_match(&Method::Get,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert_eq!(res.unwrap().handler.handler, 0u8);

        let res = router.get_match(&Method::Get,
                                   &RequestUri::AbsolutePath(String::from("/test2/")));
        assert!(res.is_none());

        let res = router.get_match(&Method::Post,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert!(res.is_none());
    }

    #[test]
    fn multi_method_test() {
        let mut entry = RouteEntry::with_handler(0u8);
        entry.add_method(MethodRoutes::Get);
        entry.add_method(MethodRoutes::Put);
        let mut router = HyperRouter::new();
        router.add_path_entry("/test/", entry);

        let res = router.get_match(&Method::Get,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert_eq!(res.unwrap().handler.handler, 0u8);

        let res = router.get_match(&Method::Put,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert_eq!(res.unwrap().handler.handler, 0u8);

        let res = router.get_match(&Method::Post,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert!(res.is_none());
    }

    #[test]
    fn query_string_test() {
        let mut entry = RouteEntry::with_handler(0u8);
        entry.add_method(MethodRoutes::Get);
        entry.add_method(MethodRoutes::Put);
        let mut router = HyperRouter::new();
        router.add_path_entry("/test/", entry);

        let res = router.get_match(&Method::Get,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert_eq!(res.unwrap().handler.handler, 0u8);

        let res = router.get_match(&Method::Put,
                                   &RequestUri::AbsolutePath(String::from("/test/?test=foo")));
        assert_eq!(res.unwrap().handler.handler, 0u8);

        let res = router.get_match(&Method::Put,
                                   &RequestUri::AbsolutePath(String::from("/test/#test")));
        assert_eq!(res.unwrap().handler.handler, 0u8);
    }

    #[test]
    fn create_router_test() {
        let router = create_router! {
            "/test/" => Get, Put => 0u8,
            "/test2/:id" => Delete => 1u8,
        };

        let res = router.get_match(&Method::Get,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert_eq!(res.unwrap().handler.handler, 0u8);

        let res = router.get_match(&Method::Put,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert_eq!(res.unwrap().handler.handler, 0u8);

        let res = router.get_match(&Method::Delete,
                                   &RequestUri::AbsolutePath(String::from("/test/")));
        assert!(res.is_none());

        let res = router.get_match(&Method::Delete,
                                   &RequestUri::AbsolutePath(String::from("/test2/test")));
        assert_eq!(res.as_ref().unwrap().handler.handler, 1u8);
        assert_eq!(res.unwrap().params["id"], "test");
    }
}
<|endoftext|>


<commit_before>//! A dead-simple test helper for rust.
//!
//! Example
//! --------
//!
//! ```rust
//! use bear::fixture;
//!
//! // Get a content of 'tests/fixtures/hello.txt'
//! let content = fixture("hello.txt");
//!
//! // Do whatever you want with it
//! ```

#![doc(html_logo_url    = "https://simnalamburt.github.io/bear/cute.png",
       html_favicon_url = "https://simnalamburt.github.io/bear/cute.png",
       html_root_url    = "https://simnalamburt.github.io/bear")]

use std::path::Path;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;

/// Open a file from the 'tests/fixtures' directory, and return its content as a `String`
///
/// Example
/// --------
///
/// ```rust
/// use bear::fixture;
///
/// // Get a content of 'tests/fixtures/hello.txt'
/// let content = fixture("hello.txt");
///
/// /* Do whatever you want with it */
/// ```
pub fn fixture(filename: &str) -> String {
    let path = Path::new("tests").join("fixtures").join(filename);
    let file = File::open(&path).unwrap();
    let mut reader = BufReader::new(file);

    let mut ret = String::new();

    reader.read_to_string(&mut ret).unwrap();

    ret
}
<commit_msg>Format codes with `cargo fmt`<commit_after>//! A dead-simple test helper for rust.
//!
//! Example
//! --------
//!
//! ```rust
//! use bear::fixture;
//!
//! // Get a content of 'tests/fixtures/hello.txt'
//! let content = fixture("hello.txt");
//!
//! // Do whatever you want with it
//! ```

#![doc(
    html_logo_url = "https://simnalamburt.github.io/bear/cute.png",
    html_favicon_url = "https://simnalamburt.github.io/bear/cute.png",
    html_root_url = "https://simnalamburt.github.io/bear"
)]

use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::Path;

/// Open a file from the 'tests/fixtures' directory, and return its content as a `String`
///
/// Example
/// --------
///
/// ```rust
/// use bear::fixture;
///
/// // Get a content of 'tests/fixtures/hello.txt'
/// let content = fixture("hello.txt");
///
/// /* Do whatever you want with it */
/// ```
pub fn fixture(filename: &str) -> String {
    let path = Path::new("tests").join("fixtures").join(filename);
    let file = File::open(&path).unwrap();
    let mut reader = BufReader::new(file);

    let mut ret = String::new();

    reader.read_to_string(&mut ret).unwrap();

    ret
}
<|endoftext|>


<commit_before>
//! Hubcaps wraps hyper with an interface for interacting with the Github API

extern crate hyper;
extern crate rustc_serialize;
extern crate url;

pub mod keys;
pub mod gists;
pub mod deployments;
pub mod errors;
pub mod issues;
pub mod labels;
pub mod rep;
pub mod releases;
pub mod repositories;
pub mod statuses;
pub mod pullrequests;

pub use rep::*;
pub use errors::Error;
use gists::{Gists, UserGists};
use hyper::Client;
use hyper::method::Method;
use hyper::header::{Authorization, UserAgent};
use hyper::status::StatusCode;
use repositories::{Repository, Repositories, UserRepositories};
use std::default::Default;
use std::fmt;
use std::io::Read;

/// alias for Result that infers hubcaps::Error as Err
pub type Result<T> = std::result::Result<T, Error>;

/// enum representation of github pull and issue state
pub enum State {
  Open,
  Closed,
  All
}

impl fmt::Display for State {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", match *self {
            State::Open   => "open",
            State::Closed => "closed",
            State::All    => "all"
        })
    }
}

impl Default for State {
    fn default() -> State {
        State::Open
    }
}

/// enum representation of Github list sorting options
pub enum SortDirection {
    Asc,
    Desc
}

impl fmt::Display for SortDirection {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", match *self {
            SortDirection::Asc => "asc",
            SortDirection::Desc => "desc"
        })
    }
}

impl Default for SortDirection {
    fn default() -> SortDirection {
        SortDirection::Asc
    }
}

/// Entry point interface for interacting with Github API
pub struct Github<'a> {
    host: &'static str,
    agent: &'static str,
    client: &'a Client,
    token: Option<&'static str>
}

impl<'a> Github<'a> {
    /// Create a new Github instance
    pub fn new(
        agent: &'static str, client: &'a Client, token: Option<&'static str>) -> Github<'a> {
        Github::host("https://api.github.com", agent, client, token)
    }

    /// Create a new Github instance hosted at a custom location
    pub fn host(
        host: &'static str, agent: &'static str,
        client: &'a Client, token: Option<&'static str>) -> Github<'a> {
        Github {
            host: host,
            agent: agent,
            client: client,
            token: token
        }
    }

    /// Return a reference to a Github reposistory
    pub fn repo(&self, owner: &'static str, repo: &'static str) -> Repository {
        Repository::new(self, owner, repo)
    }

    /// Return a reference to the collection of repositories owned by an
    /// associated with an owner
    pub fn user_repos(&self, owner: &'static str) -> UserRepositories {
        UserRepositories::new(self, owner)
    }

    /// Return a reference to  the collection of repositores owned by the user
    /// associated with the current authentication credentials
    pub fn repos(&self) -> Repositories {
        Repositories::new(self)
    }

    /// Return a reference to an interface that provides access to a user's gists
    pub fn user_gists(&self, owner: &'static str) -> UserGists {
        UserGists::new(self, owner)
    }

    /// Return a reference to an interface that provides access to the
    /// gists belonging to the owner of the token used to configure this client
    pub fn gists(&self) -> Gists {
        Gists::new(self)
    }

    fn request(
        &self, method: Method, uri: &str, body: Option<&'a [u8]>) -> Result<String> {
        let url = format!("{}{}", self.host, uri);
        let builder = self.client.request(method, &url).header(
            UserAgent(self.agent.to_owned())
        );
        let authenticated = match self.token {
            Some(token) =>
                builder.header(
                    Authorization(format!("token {}", token))
               ),
            _ =>
                builder
        };
        let mut res = try!(
            match body {
                Some(ref bod) => authenticated.body(*bod).send(),
                _ => authenticated.send()
            }
        );
        let mut body = String::new();
        try!(res.read_to_string(&mut body));
        match res.status {
            StatusCode::BadRequest
            | StatusCode::UnprocessableEntity
            | StatusCode::Unauthorized
            | StatusCode::NotFound
            | StatusCode::Forbidden => Err(
                Error::Fault { code: res.status, body: body }
            ),
            _ => Ok(body)
        }
    }

    fn get(&self, uri: &str) -> Result<String> {
        self.request(
            Method::Get,
            uri,
            None
        )
    }

    fn delete(&self, uri: &str) -> Result<()> {
        self.request(
            Method::Delete,
            uri,
            None
        ).map(|_| ())
    }

    fn post(&self, uri: &str, message: &[u8]) -> Result<String> {
        self.request(
            Method::Post,
            uri,
            Some(message)
        )
    }

    fn patch(&self, uri: &str, message: &[u8]) -> Result<String> {
        self.request(
            Method::Patch,
            uri,
            Some(message)
        )
    }

    fn put(&self, uri: &str, message: &[u8]) -> Result<String> {
        self.request(
            Method::Put,
            uri,
            Some(message)
        )
    }
}
<commit_msg>code style<commit_after>
//! Hubcaps wraps hyper with an interface for interacting with the Github API

extern crate hyper;
extern crate rustc_serialize;
extern crate url;

pub mod keys;
pub mod gists;
pub mod deployments;
pub mod errors;
pub mod issues;
pub mod labels;
pub mod rep;
pub mod releases;
pub mod repositories;
pub mod statuses;
pub mod pullrequests;

pub use rep::*;
pub use errors::Error;
use gists::{Gists, UserGists};
use hyper::Client;
use hyper::method::Method;
use hyper::header::{Authorization, UserAgent};
use hyper::status::StatusCode;
use repositories::{Repository, Repositories, UserRepositories};
use std::default::Default;
use std::fmt;
use std::io::Read;

/// alias for Result that infers hubcaps::Error as Err
pub type Result<T> = std::result::Result<T, Error>;

/// enum representation of github pull and issue state
pub enum State {
  Open,
  Closed,
  All
}

impl fmt::Display for State {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", match *self {
            State::Open   => "open",
            State::Closed => "closed",
            State::All    => "all"
        })
    }
}

impl Default for State {
    fn default() -> State {
        State::Open
    }
}

/// enum representation of Github list sorting options
pub enum SortDirection {
    Asc,
    Desc
}

impl fmt::Display for SortDirection {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", match *self {
            SortDirection::Asc => "asc",
            SortDirection::Desc => "desc"
        })
    }
}

impl Default for SortDirection {
    fn default() -> SortDirection {
        SortDirection::Asc
    }
}

/// Entry point interface for interacting with Github API
pub struct Github<'a> {
    host: &'static str,
    agent: &'static str,
    client: &'a Client,
    token: Option<&'static str>
}

impl<'a> Github<'a> {
    /// Create a new Github instance
    pub fn new(
        agent: &'static str, client: &'a Client, token: Option<&'static str>) -> Github<'a> {
        Github::host("https://api.github.com", agent, client, token)
    }

    /// Create a new Github instance hosted at a custom location
    pub fn host(
        host: &'static str,
        agent: &'static str,
        client: &'a Client,
        token: Option<&'static str>
     ) -> Github<'a> {
        Github {
            host: host,
            agent: agent,
            client: client,
            token: token
        }
    }

    /// Return a reference to a Github reposistory
    pub fn repo(&self, owner: &'static str, repo: &'static str) -> Repository {
        Repository::new(self, owner, repo)
    }

    /// Return a reference to the collection of repositories owned by an
    /// associated with an owner
    pub fn user_repos(&self, owner: &'static str) -> UserRepositories {
        UserRepositories::new(self, owner)
    }

    /// Return a reference to  the collection of repositores owned by the user
    /// associated with the current authentication credentials
    pub fn repos(&self) -> Repositories {
        Repositories::new(self)
    }

    /// Return a reference to an interface that provides access to a user's gists
    pub fn user_gists(&self, owner: &'static str) -> UserGists {
        UserGists::new(self, owner)
    }

    /// Return a reference to an interface that provides access to the
    /// gists belonging to the owner of the token used to configure this client
    pub fn gists(&self) -> Gists {
        Gists::new(self)
    }

    fn request(
        &self, method: Method, uri: &str, body: Option<&'a [u8]>) -> Result<String> {
        let url = format!("{}{}", self.host, uri);
        let builder = self.client.request(method, &url).header(
            UserAgent(self.agent.to_owned())
        );
        let authenticated = match self.token {
            Some(token) =>
                builder.header(
                    Authorization(format!("token {}", token))
               ),
            _ =>
                builder
        };
        let mut res = try!(
            match body {
                Some(ref bod) => authenticated.body(*bod).send(),
                _ => authenticated.send()
            }
        );
        let mut body = String::new();
        try!(res.read_to_string(&mut body));
        match res.status {
            StatusCode::BadRequest
            | StatusCode::UnprocessableEntity
            | StatusCode::Unauthorized
            | StatusCode::NotFound
            | StatusCode::Forbidden => Err(
                Error::Fault { code: res.status, body: body }
            ),
            _ => Ok(body)
        }
    }

    fn get(&self, uri: &str) -> Result<String> {
        self.request(
            Method::Get,
            uri,
            None
        )
    }

    fn delete(&self, uri: &str) -> Result<()> {
        self.request(
            Method::Delete,
            uri,
            None
        ).map(|_| ())
    }

    fn post(&self, uri: &str, message: &[u8]) -> Result<String> {
        self.request(
            Method::Post,
            uri,
            Some(message)
        )
    }

    fn patch(&self, uri: &str, message: &[u8]) -> Result<String> {
        self.request(
            Method::Patch,
            uri,
            Some(message)
        )
    }

    fn put(&self, uri: &str, message: &[u8]) -> Result<String> {
        self.request(
            Method::Put,
            uri,
            Some(message)
        )
    }
}
<|endoftext|>