<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"]);
//!
//!     // You must set a target to resolve the dependencies of that target
//!     depgraph.set_target("a");
//!
//!     // Iterate through each dependency.  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.satisfying_iter() {
//!         print!("{} ", node);
//!     }
//! }
//! ```
//!
//! The above will output:  `d b e c a`
//!
//! You can also mark some elements as already satisfied, and the
//! iterator will take that into account:
//!
//! ```ignore
//! depgraph.mark_as_satisfied(["e","c"]);
//! ```
//!
//! The algorithm is not deterministic, and may give a different answer each
//! time it is run.  Beware.
//!
//! Dependency cycles are detected and will cause a panic!()

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

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

extern crate log;

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

/// This is the dependency graph.  It must be mutable, as the
/// library uses internal properties in the graph to do its
/// calculations.
#[deriving(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>>,

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

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

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

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

/// This iterates through the dependencies of the DepGraph's target,
/// marking each element as satisfied as it is visited.
pub struct DepGraphSatisfyingIterator<'a> {
    depgraph: &'a mut DepGraph
}

impl DepGraph {

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

    /// Add a dependency to a DepGraph.  The 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( String::from_str(node) ) {
            Vacant(entry) => {
                let mut deps = HashSet::with_capacity(1);
                deps.insert( String::from_str(depends_on) );
                entry.set( deps );
            },
            Occupied(mut entry) => {
                (*entry.get_mut()).insert(String::from_str(depends_on));
            },
        }
    }

    /// 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( String::from_str(node) ) {
            Vacant(entry) => {
                let mut deps = HashSet::with_capacity( depends_on.len() );
                for s in depends_on.iter() {
                    deps.insert( String::from_str(*s) );
                }
                entry.set( deps );
            },
            Occupied(mut entry) => {
                for s in depends_on.iter() {
                    (*entry.get_mut()).insert( String::from_str(*s) );
                }
            },
        }
    }

    /// This sets the target node.  Iteratators on the graph always
    /// get the dependencies of the target node.
    pub fn set_target<'a>( &mut self, target: &'a str )
    {
        self.target = Some(String::from_str(target));
    }

    /// 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(String::from_str(*node));
        }
    }

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

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

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

    /// Get an iterator to iterate through the dependencies of
    /// the target node.  This iter() will loop forever if you dont
    /// mark nodes satisfied as you go.  If you want the iterator
    /// to take care of that, use satisfying_iter()
    pub fn iter<'a>(&'a mut self) -> DepGraphIterator<'a>
    {
        DepGraphIterator {
            depgraph: self
        }
    }

    /// Get an iterator to iterate through the dependencies of
    /// the target node, and also to mark those dependencies as
    /// satisfied as it goes.
    pub fn satisfying_iter<'a>(&'a mut self) -> DepGraphSatisfyingIterator<'a>
    {
        DepGraphSatisfyingIterator {
            depgraph: self
        }
    }
}

impl<'a> Iterator<String> for DepGraphIterator<'a> {
    /// Get next dependency.  This may panic!() if a cycle is detected.
    fn next(&mut self) -> Option<String>
    {
        let node = match self.depgraph.target {
            None => return None,
            Some(ref node) => node.clone()
        };
        if self.depgraph.satisfied.contains(&node) {
            return None;
        }
        self.depgraph.curpath.clear();
        Some(self.depgraph.get_next_dependency(&node))
    }
}

impl<'a> Iterator<String> for DepGraphSatisfyingIterator<'a> {
    /// Get next dependency.  This may panic!() if a cycle is detected.
    fn next(&mut self) -> Option<String>
    {
        let node = match self.depgraph.target {
            None => return None,
            Some(ref node) => node.clone()
        };
        if self.depgraph.satisfied.contains(&node) {
            return None;
        }
        self.depgraph.curpath.clear();
        let next = self.depgraph.get_next_dependency(&node);
        self.depgraph.mark_as_satisfied(&[next.as_slice()]);
        Some(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");

    depgraph.set_target("a");

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

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

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

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

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

#[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_satisfying() {
    let mut depgraph: DepGraph = DepGraph::new();

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

    depgraph.set_target("a");

    // To get past the borrow checker, we make a copy of the dependencies.
    // This is a test, and performance is not important here.
    let dependency_copy = depgraph.dependencies.clone();

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

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

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

        results.push(node);
    }
}

#[test]
fn solvent_test_circular() {

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

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

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

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

#[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.set_target("appconn");
    depgraph.mark_as_satisfied(&["owneruser","appuser"]);

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

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

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

<commit_msg>Marked solvent_test_circular as should_fail and removed proc() stuff<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"]);
//!
//!     // You must set a target to resolve the dependencies of that target
//!     depgraph.set_target("a");
//!
//!     // Iterate through each dependency.  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.satisfying_iter() {
//!         print!("{} ", node);
//!     }
//! }
//! ```
//!
//! The above will output:  `d b e c a`
//!
//! You can also mark some elements as already satisfied, and the
//! iterator will take that into account:
//!
//! ```ignore
//! depgraph.mark_as_satisfied(["e","c"]);
//! ```
//!
//! The algorithm is not deterministic, and may give a different answer each
//! time it is run.  Beware.
//!
//! Dependency cycles are detected and will cause a panic!()

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

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

extern crate log;

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

/// This is the dependency graph.  It must be mutable, as the
/// library uses internal properties in the graph to do its
/// calculations.
#[deriving(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>>,

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

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

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

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

/// This iterates through the dependencies of the DepGraph's target,
/// marking each element as satisfied as it is visited.
pub struct DepGraphSatisfyingIterator<'a> {
    depgraph: &'a mut DepGraph
}

impl DepGraph {

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

    /// Add a dependency to a DepGraph.  The 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( String::from_str(node) ) {
            Vacant(entry) => {
                let mut deps = HashSet::with_capacity(1);
                deps.insert( String::from_str(depends_on) );
                entry.set( deps );
            },
            Occupied(mut entry) => {
                (*entry.get_mut()).insert(String::from_str(depends_on));
            },
        }
    }

    /// 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( String::from_str(node) ) {
            Vacant(entry) => {
                let mut deps = HashSet::with_capacity( depends_on.len() );
                for s in depends_on.iter() {
                    deps.insert( String::from_str(*s) );
                }
                entry.set( deps );
            },
            Occupied(mut entry) => {
                for s in depends_on.iter() {
                    (*entry.get_mut()).insert( String::from_str(*s) );
                }
            },
        }
    }

    /// This sets the target node.  Iteratators on the graph always
    /// get the dependencies of the target node.
    pub fn set_target<'a>( &mut self, target: &'a str )
    {
        self.target = Some(String::from_str(target));
    }

    /// 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(String::from_str(*node));
        }
    }

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

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

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

    /// Get an iterator to iterate through the dependencies of
    /// the target node.  This iter() will loop forever if you dont
    /// mark nodes satisfied as you go.  If you want the iterator
    /// to take care of that, use satisfying_iter()
    pub fn iter<'a>(&'a mut self) -> DepGraphIterator<'a>
    {
        DepGraphIterator {
            depgraph: self
        }
    }

    /// Get an iterator to iterate through the dependencies of
    /// the target node, and also to mark those dependencies as
    /// satisfied as it goes.
    pub fn satisfying_iter<'a>(&'a mut self) -> DepGraphSatisfyingIterator<'a>
    {
        DepGraphSatisfyingIterator {
            depgraph: self
        }
    }
}

impl<'a> Iterator<String> for DepGraphIterator<'a> {
    /// Get next dependency.  This may panic!() if a cycle is detected.
    fn next(&mut self) -> Option<String>
    {
        let node = match self.depgraph.target {
            None => return None,
            Some(ref node) => node.clone()
        };
        if self.depgraph.satisfied.contains(&node) {
            return None;
        }
        self.depgraph.curpath.clear();
        Some(self.depgraph.get_next_dependency(&node))
    }
}

impl<'a> Iterator<String> for DepGraphSatisfyingIterator<'a> {
    /// Get next dependency.  This may panic!() if a cycle is detected.
    fn next(&mut self) -> Option<String>
    {
        let node = match self.depgraph.target {
            None => return None,
            Some(ref node) => node.clone()
        };
        if self.depgraph.satisfied.contains(&node) {
            return None;
        }
        self.depgraph.curpath.clear();
        let next = self.depgraph.get_next_dependency(&node);
        self.depgraph.mark_as_satisfied(&[next.as_slice()]);
        Some(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");

    depgraph.set_target("a");

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

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

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

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

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

#[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_satisfying() {
    let mut depgraph: DepGraph = DepGraph::new();

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

    depgraph.set_target("a");

    // To get past the borrow checker, we make a copy of the dependencies.
    // This is a test, and performance is not important here.
    let dependency_copy = depgraph.dependencies.clone();

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

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

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

        results.push(node);
    }
}

#[test]
#[should_fail]
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");
    depgraph.set_target("a");

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

    loop {
        // Detect infinite looping bugs
        // (Since this test should fail, we cause a success here)
        if results.len() >= 30 { break; }

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

#[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.set_target("appconn");
    depgraph.mark_as_satisfied(&["owneruser","appuser"]);

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

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

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

<|endoftext|>


<commit_before>#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>initial version of Pool<commit_after>use std::error::Error;
use std::fmt::{self, Debug, Display, Formatter};
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Condvar, Mutex, Weak};
use std::time::{Duration, SystemTime};

pub struct Pool<T, F> where F: Fn() -> T {
    create: F,
    items: Mutex<Items<T>>,
    item_available: Condvar,
    weak_self: Weak<Pool<T, F>>,
}

impl<T, F> Pool<T, F> where F: Fn() -> T {
    pub fn new(create: F) -> Arc<Pool<T, F>> {
        Pool::new_internal(create, None)
    }

    fn new_internal(create: F, max_items: Option<usize>) -> Arc<Pool<T, F>> {
        let pool = Arc::new(Pool {
            create: create,
            items: Mutex::new(Items {
                available: Vec::new(),
                count: 0,
                max: max_items,
            }),
            item_available: Condvar::new(),
            weak_self: Weak::new(),
        });
        unsafe {
            let ptr = &pool.weak_self as *const Weak<Pool<T, F>> as *mut Weak<Pool<T, F>>;
            *ptr = Arc::downgrade(&pool);
        }
        pool
    }

    pub fn get(&self) -> Item<T, F> {
        self.get_internal(None).unwrap()
    }

    pub fn get_timeout(&self, duration: Duration) -> Result<Item<T, F>, TimeoutError> {
        self.get_internal(Some(duration))
    }

    fn get_internal(&self, duration: Option<Duration>) -> Result<Item<T, F>, TimeoutError> {
        let mut items = self.items.lock().unwrap();
        let item = match items.available.pop() {
            Some(item) => item,
            None => {
                if items.count < items.max.unwrap_or(std::usize::MAX) {
                    items.count += 1;
                    drop(items);
                    (self.create)()
                } else {
                    let start = SystemTime::now();
                    while items.available.is_empty() {
                        items = match duration {
                            Some(duration) => {
                                let elapsed = match start.elapsed() {
                                    Ok(elapsed) => elapsed,
                                    Err(_) => Duration::from_secs(0),
                                };
                                if elapsed > duration {
                                    return Err(TimeoutError);
                                }
                                let (items, wait_result) =
                                    self.item_available.wait_timeout(items, duration - elapsed).unwrap();
                                if wait_result.timed_out() {
                                    return Err(TimeoutError);
                                }
                                items
                            },
                            None => self.item_available.wait(items).unwrap(),
                        }
                    }
                    items.available.pop().unwrap()
                }
            }
        };
        Ok(Item {
            item: Some(item),
            pool: self.weak_self.upgrade().unwrap(),
        })
    }

    fn put(&self, item: T) {
        self.items.lock().unwrap().available.push(item);
        self.item_available.notify_one();
    }
}

impl<T, F> Debug for Pool<T, F> where T: Debug, F: Fn() -> T {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Pool")
            .field("items", &*self.items.lock().unwrap())
            .finish()
    }
}

pub struct PoolBuilder<T, F> where F: Fn() -> T {
    create: F,
    max_items: Option<usize>,
}

impl<T, F> PoolBuilder<T, F> where F: Fn() -> T {
    pub fn new(create: F) -> PoolBuilder<T, F> {
        PoolBuilder { create: create, max_items: None }
    }

    pub fn max_items(mut self, max_items: usize) -> PoolBuilder<T, F> {
        self.max_items = Some(max_items);
        self
    }

    pub fn finalize(self) -> Arc<Pool<T, F>> {
        Pool::new_internal(self.create, self.max_items)
    }
}

struct Items<T> {
    available: Vec<T>,
    count: usize,
    max: Option<usize>,
}

impl<T> Debug for Items<T> where T: Debug {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Items")
            .field("available", &self.available.len())
            .field("count", &self.count)
            .field("max", &self.max)
            .finish()
    }
}

pub struct Item<T, F> where F: Fn() -> T {
    item: Option<T>,
    pool: Arc<Pool<T, F>>,
}

impl<T, F> Debug for Item<T, F> where T: Debug, F: Fn() -> T {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Item")
            .field("item", &self.item)
            .finish()
    }
}

impl<T, F> Deref for Item<T, F> where F: Fn() -> T {
    type Target = T;

    fn deref(&self) -> &T {
        self.item.as_ref().unwrap()
    }
}

impl<T, F> DerefMut for Item<T, F> where F: Fn() -> T {
    fn deref_mut(&mut self) -> &mut T {
        self.item.as_mut().unwrap()
    }
}

impl<T, F> Drop for Item<T, F> where F: Fn() -> T {
    fn drop(&mut self) {
        self.pool.put(self.item.take().unwrap());
    }
}

#[derive(Debug, Eq, PartialEq)]
pub struct TimeoutError;

impl Display for TimeoutError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.write_str("wait timed out")
    }
}

impl Error for TimeoutError {
    fn description(&self) -> &str {
        "wait timed out"
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error;
    use std::time::{Duration, SystemTime};
    use std::thread;
    use super::*;

    trait AsMillis {
        fn as_millis(&self) -> u64;
    }

    impl AsMillis for Duration {
        fn as_millis(&self) -> u64 {
            self.as_secs() * 1000 + self.subsec_nanos() as u64 / 1000000
        }
    }

    #[test]
    fn pool_builder() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let _x = pool.get();
        assert_eq!(pool.get_timeout(Duration::from_secs(0)).err(), Some(TimeoutError));
    }

    #[test]
    fn pool_get() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let x = pool.get();
        let p = pool.clone();
        let start = SystemTime::now();
        let handle = thread::spawn(move || {
            let _ = p.get();
        });
        thread::sleep(Duration::from_millis(100));
        drop(x);
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_get_mut() {
        let pool = Pool::new(|| 0);
        *pool.get() = 4;
        assert_eq!(*pool.get(), 4);
    }

    #[test]
    fn pool_get_timeout_ok() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let x = pool.get();
        let p = pool.clone();
        let start = SystemTime::now();
        let handle = thread::spawn(move || {
            let _ = p.get_timeout(Duration::from_secs(1)).unwrap();
        });
        thread::sleep(Duration::from_millis(100));
        drop(x);
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_get_timeout_err() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let _x = pool.get();
        let p = pool.clone();
        let start = SystemTime::now();
        let handle = thread::spawn(move || {
            assert_eq!(p.get_timeout(Duration::from_millis(100)).err(), Some(TimeoutError));
        });
        while start.elapsed().unwrap().as_millis() < 100 {
            pool.item_available.notify_one();
        }
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_debug() {
        let pool = PoolBuilder::new(|| 0).max_items(5).finalize();
        assert_eq!(format!("{:?}", pool),
            "Pool { items: Items { available: 0, count: 0, max: Some(5) } }");
        let x = pool.get();
        let _y = pool.get();
        let _z = pool.get();
        drop(x);
        assert_eq!(format!("{:?}", pool),
            "Pool { items: Items { available: 1, count: 3, max: Some(5) } }");
    }

    #[test]
    fn item_debug() {
        let pool = Pool::new(|| 0);
        let x = pool.get();
        assert_eq!(format!("{:?}", x), "Item { item: Some(0) }");
    }

    #[test]
    fn timeout_error() {
        assert_eq!(format!("{}", TimeoutError), "wait timed out");
        assert_eq!(TimeoutError.description(), "wait timed out");
    }
}
<|endoftext|>


<commit_before>//! This library can be used to acquire oauth2.0 authentication for services.
//! At the time of writing, only one way of doing so is implemented, the
//! [device flow](https://developers.google.com/youtube/v3/guides/authentication#devices), along
//! with a flow
//! for [refreshing tokens](https://developers.google.com/youtube/v3/guides/authentication#devices)
//!
//! For your application to use this library, you will have to obtain an application
//! id and secret by
//! [following this guide](https://developers.google.com/youtube/registering_an_application).
//!
//! # Device Flow Usage
//! As the `DeviceFlow` involves polling, the `DeviceFlowHelper` should be used
//! as means to adhere to the protocol, and remain resilient to all kinds of errors
//! that can occour on the way.
//!
//! # Service account "flow"
//! When using service account credentials, no user interaction is required. The access token
//! can be obtained automatically using the private key of the client (which you can download
//! from the API provider). See `examples/service_account/` for an example on how to use service
//! account credentials.
//!
//! # Installed Flow Usage
//! The `InstalledFlow` involves showing a URL to the user (or opening it in a browser)
//! and then either prompting the user to enter a displayed code, or make the authorizing
//! website redirect to a web server spun up by this library.
//! In order to use the interactive method, use the `InstalledInteractive` `FlowType`;
//! for the redirect method, use `InstalledRedirect`, with the port number to let the
//! server listen on.
//! You can implement your own `AuthenticatorDelegate` in order to customize the flow;
//! the `InstalledFlow` uses the `present_user_url` method.
//!
//! The returned `Token` is stored permanently to authorize future API requests in the
//! same scopes.
//!
//! ```test_harness,no_run
//! #![cfg_attr(feature = "nightly", feature(custom_derive, custom_attribute, plugin))]
//! #![cfg_attr(feature = "nightly", plugin(serde_macros))]
//! extern crate hyper;
//! extern crate yup_oauth2 as oauth2;
//! extern crate serde;
//! extern crate serde_json;
//!
//! use oauth2::{Authenticator, DefaultAuthenticatorDelegate, PollInformation, ConsoleApplicationSecret, MemoryStorage, GetToken};
//! use serde_json as json;
//! use std::default::Default;
//! # const SECRET: &'static str = "{\"installed\":{\"auth_uri\":\"https://accounts.google.com/o/oauth2/auth\",\"client_secret\":\"UqkDJd5RFwnHoiG5x5Rub8SI\",\"token_uri\":\"https://accounts.google.com/o/oauth2/token\",\"client_email\":\"\",\"redirect_uris\":[\"urn:ietf:wg:oauth:2.0:oob\",\"oob\"],\"client_x509_cert_url\":\"\",\"client_id\":\"14070749909-vgip2f1okm7bkvajhi9jugan6126io9v.apps.googleusercontent.com\",\"auth_provider_x509_cert_url\":\"https://www.googleapis.com/oauth2/v1/certs\"}}";
//!
//! # #[test] fn device() {
//! let secret = json::from_str::<ConsoleApplicationSecret>(SECRET).unwrap().installed.unwrap();
//! let res = Authenticator::new(&secret, DefaultAuthenticatorDelegate,
//!                         hyper::Client::new(),
//!                         <MemoryStorage as Default>::default(), None)
//!                         .token(&["https://www.googleapis.com/auth/youtube.upload"]);
//! match res {
//!     Ok(t) => {
//!     // now you can use t.access_token to authenticate API calls within your
//!     // given scopes. It will not be valid forever, which is when you have to
//!     // refresh it using the `RefreshFlow`
//!     },
//!     Err(err) => println!("Failed to acquire token: {}", err),
//! }
//! # }
//! ```
//!
//! # Refresh Flow Usage
//! As the `Token` you retrieved previously will only be valid for a certain time, you will have
//! to use the information from the `Token.refresh_token` field to get a new `access_token`.
//!
//! ```test_harness,no_run
//! extern crate hyper;
//! extern crate yup_oauth2 as oauth2;
//! use oauth2::{RefreshFlow, FlowType, RefreshResult};
//!
//! # #[test] fn refresh() {
//! let mut f = RefreshFlow::new(hyper::Client::new());
//! let new_token = match *f.refresh_token(FlowType::Device,
//!                                        "my_client_id", "my_secret",
//!                                        "my_refresh_token") {
//!                        RefreshResult::Success(ref t) => t,
//!                        _ => panic!("bad luck ;)")
//!                };
//! # }
//! ```
#![cfg_attr(feature = "nightly", feature(custom_derive, custom_attribute, plugin))]
#![cfg_attr(feature = "nightly", plugin(serde_macros))]

#[cfg(feature = "nightly")]
include!("lib.rs.in");

#[cfg(feature = "with-serde-codegen")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
<commit_msg>docs(crate): Update crate documentation<commit_after>//! This library can be used to acquire oauth2.0 authentication for services.
//!
//! For your application to use this library, you will have to obtain an application
//! id and secret by
//! [following this guide](https://developers.google.com/youtube/registering_an_application) (for
//! Google services) respectively the documentation of the API provider you want to connect to.
//!
//! # Device Flow Usage
//! As the `DeviceFlow` involves polling, the `DeviceFlowHelper` should be used
//! as means to adhere to the protocol, and remain resilient to all kinds of errors
//! that can occour on the way.
//!
//! # Service account "flow"
//! When using service account credentials, no user interaction is required. The access token
//! can be obtained automatically using the private key of the client (which you can download
//! from the API provider). See `examples/service_account/` for an example on how to use service
//! account credentials. See
//! [developers.google.com](https://developers.google.com/identity/protocols/OAuth2ServiceAccount)
//! for a detailed description of the protocol. This crate implements OAuth for Service Accounts
//! based on the Google APIs; it may or may not work with other providers.
//!
//! # Installed Flow Usage
//! The `InstalledFlow` involves showing a URL to the user (or opening it in a browser)
//! and then either prompting the user to enter a displayed code, or make the authorizing
//! website redirect to a web server spun up by this library and running on localhost.
//!
//! In order to use the interactive method, use the `InstalledInteractive` `FlowType`;
//! for the redirect method, use `InstalledRedirect`, with the port number to let the
//! server listen on.
//!
//! You can implement your own `AuthenticatorDelegate` in order to customize the flow;
//! the `InstalledFlow` uses the `present_user_url` method.
//!
//! The returned `Token` is stored permanently in the given token storage in order to
//! authorize future API requests to the same scopes.
//!
//! ```test_harness,no_run
//! #![cfg_attr(feature = "nightly", feature(custom_derive, custom_attribute, plugin))]
//! #![cfg_attr(feature = "nightly", plugin(serde_macros))]
//! extern crate hyper;
//! extern crate yup_oauth2 as oauth2;
//! extern crate serde;
//! extern crate serde_json;
//!
//! use oauth2::{Authenticator, DefaultAuthenticatorDelegate, PollInformation, ConsoleApplicationSecret, MemoryStorage, GetToken};
//! use serde_json as json;
//! use std::default::Default;
//! # const SECRET: &'static str = "{\"installed\":{\"auth_uri\":\"https://accounts.google.com/o/oauth2/auth\",\"client_secret\":\"UqkDJd5RFwnHoiG5x5Rub8SI\",\"token_uri\":\"https://accounts.google.com/o/oauth2/token\",\"client_email\":\"\",\"redirect_uris\":[\"urn:ietf:wg:oauth:2.0:oob\",\"oob\"],\"client_x509_cert_url\":\"\",\"client_id\":\"14070749909-vgip2f1okm7bkvajhi9jugan6126io9v.apps.googleusercontent.com\",\"auth_provider_x509_cert_url\":\"https://www.googleapis.com/oauth2/v1/certs\"}}";
//!
//! # #[test] fn device() {
//! let secret = json::from_str::<ConsoleApplicationSecret>(SECRET).unwrap().installed.unwrap();
//! let res = Authenticator::new(&secret, DefaultAuthenticatorDelegate,
//!                         hyper::Client::new(),
//!                         <MemoryStorage as Default>::default(), None)
//!                         .token(&["https://www.googleapis.com/auth/youtube.upload"]);
//! match res {
//!     Ok(t) => {
//!     // now you can use t.access_token to authenticate API calls within your
//!     // given scopes. It will not be valid forever, which is when you have to
//!     // refresh it using the `RefreshFlow`
//!     },
//!     Err(err) => println!("Failed to acquire token: {}", err),
//! }
//! # }
//! ```
//!
//! # Refresh Flow Usage
//! As the `Token` you retrieved previously will only be valid for a certain time, you will have
//! to use the information from the `Token.refresh_token` field to get a new `access_token`.
//!
//! ```test_harness,no_run
//! extern crate hyper;
//! extern crate yup_oauth2 as oauth2;
//! use oauth2::{RefreshFlow, FlowType, RefreshResult};
//!
//! # #[test] fn refresh() {
//! let mut f = RefreshFlow::new(hyper::Client::new());
//! let new_token = match *f.refresh_token(FlowType::Device,
//!                                        "my_client_id", "my_secret",
//!                                        "my_refresh_token") {
//!                        RefreshResult::Success(ref t) => t,
//!                        _ => panic!("bad luck ;)")
//!                };
//! # }
//! ```
#![cfg_attr(feature = "nightly", feature(custom_derive, custom_attribute, plugin))]
#![cfg_attr(feature = "nightly", plugin(serde_macros))]

#[cfg(feature = "nightly")]
include!("lib.rs.in");

#[cfg(feature = "with-serde-codegen")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
<|endoftext|>


<commit_before>#![feature(no_std,lang_items,asm,core,alloc,collections,step_by)]
#![no_std]

#![crate_type="staticlib"]
#![crate_name="rustcode"]

#[macro_use]
extern crate core;
extern crate alloc;
extern crate collections;

use core::prelude::*;
use core::fmt::Write;
use core::atomic::Ordering;
use alloc::boxed::Box;
use collections::string::String;

extern crate rlibc;

#[macro_use]
mod notex;
#[macro_use]
mod mutex;

mod machine;
mod console;
mod vga;
mod mmu;
mod gdt;
mod acpi;
mod interrupts;
mod paging;
mod malloc;
mod smp;

use vga::Color::*;

pub use interrupts::{idtDesc};
pub use interrupts::{double_fault_handler, gpf_handler,
                     page_fault_handler, kbd_interrupt_handler };
pub use malloc::{rust_allocate, rust_reallocate, rust_reallocate_inplace,
                 rust_deallocate, rust_usable_size, rust_stats_print };
pub use smp::{SMP_STACK_PTR, SMP_CR3};

#[lang="start"]
#[no_mangle]
pub fn k_main() {
    if smp::processor_count.fetch_add(1, Ordering::SeqCst) == 0 {
        paging::init();
        interrupts::init_idt();
        // YOU MAY NOW PAGE FAULT
        let smp_info = acpi::smp_info();
        interrupts::init(&(*smp_info).io_apics);
        smp::init(&(*smp_info).processors);

        let greet = "Hello from bare-bones Rust";
        let _ = console::Console.write_str("Hello");
        for i in 0..vga::ROWS {
            for j in 0..vga::COLS {
            vga::write_char_with_color(i, j, ' ', White, LightBlue);
            }
        }
        vga::paint_color(0, 0, 30, White, LightGreen);
        vga::write_string(10, 5, greet);
        vga::move_cursor(10, 5 + greet.len());
        vga::write_string_with_color(11, 10, "Test", Black, LightRed);

        let heap = Box::new('H');
        let heap2 = Box::new('!');
        vga::write_char(15,4,*heap);
        vga::write_char_with_color(15, 5, *heap2, LightGray, Pink);

        let mut string = String::from_str("Hello, ");
        string.push_str("paging");
        vga::write_string(3,5,&string);
        unsafe { *(0xB0_00_00_01 as *mut u32) = 0xcafecafe; }
        unsafe { *(0xA0_00_10_00 as *mut mmu::Descriptor) = gdt::gdt_get(1); }
        let processors = smp::processor_count.load(Ordering::SeqCst) as u8 + '0' as u8;
        vga::write_char(4, 4, processors as char);
    }
    else { // Non-main processor
        interrupts::apic::enable_lapic();
        loop {};
    }
}

#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}

#[lang = "panic_fmt"]
#[inline(always)]
fn panic_fmt() -> ! { unsafe { ::core::intrinsics::abort() } }
<commit_msg>Print pointer value<commit_after>#![feature(no_std,lang_items,asm,core,alloc,collections,step_by)]
#![no_std]

#![crate_type="staticlib"]
#![crate_name="rustcode"]

#[macro_use]
extern crate core;
extern crate alloc;
extern crate collections;

use core::prelude::*;
use core::fmt::Write;
use core::atomic::Ordering;
use alloc::boxed::Box;
use collections::string::String;

extern crate rlibc;

#[macro_use]
mod notex;
#[macro_use]
mod mutex;

mod machine;
mod console;
mod vga;
mod mmu;
mod gdt;
mod acpi;
mod interrupts;
mod paging;
mod malloc;
mod smp;

use vga::Color::*;

pub use interrupts::{idtDesc};
pub use interrupts::{double_fault_handler, gpf_handler,
                     page_fault_handler, kbd_interrupt_handler };
pub use malloc::{rust_allocate, rust_reallocate, rust_reallocate_inplace,
                 rust_deallocate, rust_usable_size, rust_stats_print };
pub use smp::{SMP_STACK_PTR, SMP_CR3};

#[lang="start"]
#[no_mangle]
pub fn k_main() {
    if smp::processor_count.fetch_add(1, Ordering::SeqCst) == 0 {
        paging::init();
        interrupts::init_idt();
        // YOU MAY NOW PAGE FAULT
        let smp_info = acpi::smp_info();
        interrupts::init(&(*smp_info).io_apics);
        smp::init(&(*smp_info).processors);

        let greet = "Hello from bare-bones Rust";
        let _ = write!(console::Console, "SMP at {:p}", smp_info);
//        let _ = console::Console.write_str("Hello");
        for i in 0..vga::ROWS {
            for j in 0..vga::COLS {
            vga::write_char_with_color(i, j, ' ', White, LightBlue);
            }
        }
        vga::paint_color(0, 0, 30, White, LightGreen);
        vga::write_string(10, 5, greet);
        vga::move_cursor(10, 5 + greet.len());
        vga::write_string_with_color(11, 10, "Test", Black, LightRed);

        let heap = Box::new('H');
        let heap2 = Box::new('!');
        vga::write_char(15,4,*heap);
        vga::write_char_with_color(15, 5, *heap2, LightGray, Pink);

        let mut string = String::from_str("Hello, ");
        string.push_str("paging");
        vga::write_string(3,5,&string);
        unsafe { *(0xB0_00_00_01 as *mut u32) = 0xcafecafe; }
        unsafe { *(0xA0_00_10_00 as *mut mmu::Descriptor) = gdt::gdt_get(1); }
        let processors = smp::processor_count.load(Ordering::SeqCst) as u8 + '0' as u8;
        vga::write_char(4, 4, processors as char);
    }
    else { // Non-main processor
        interrupts::apic::enable_lapic();
        loop {};
    }
}

#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}

#[lang = "panic_fmt"]
#[inline(always)]
fn panic_fmt() -> ! { unsafe { ::core::intrinsics::abort() } }
<|endoftext|>


<commit_before>//! # The Redox OS Kernel, version 2
//!
//! The Redox OS Kernel is a hybrid kernel that supports X86 systems and
//! provides Unix-like syscalls for primarily Rust applications
//!
//! ## Syscalls
//! Syscalls in Redox are often handled by userspace `schemes`.
//! The essential syscalls in Redox are as follows:
//!
//! ## open(path: &str, flags: usize) -> Result<file_descriptor: usize>
//! Open a file, providing a path as a `&str` and flags, defined elsewhere.
//! Returns a number, known as a file descriptor, that is passed to other syscalls
//!
//! ## close(file_descriptor: usize) -> Result<()>
//! Close a file descriptor, providing the file descriptor from `open`
//! Returns an error, `EBADF`, if the file descriptor was not found.
//! This potential error is often ignored by userspace
//!
//! ## dup(file_descriptor: usize) -> Result<file_descriptor: usize>
//! Duplicate a file descriptor, providing the file descriptor from `open`
//! Returns a new file descriptor, or an error
//!
//! ## read(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>
//! Read from a file descriptor, providing the file descriptor from `open` and a mutable buffer
//! Returns the number of bytes actually read, or an error
//!
//! ## write(file_descriptor: usize, buffer: &[u8]) -> Result<count: usize>
//! Write to a file descriptor, providing the file descriptor from `open` and a const buffer
//! Returns the number of bytes actually written, or an error
//!
//! ## fstat(file_descriptor: usize, stat: &mut Stat) -> Result<()>
//! Get information from a file descriptor, providing the file descriptor from `open`
//! and a mutable Stat struct, defined elsewhere.
//! Returns an error if the operation failed
//!
//! ## fpath(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>
//! Read the path of a file descriptor, providing the file descriptor from `open`
//! and a mutable buffer. The buffer should be 4096 bytes, to ensure that the
//! entire path will fit.
//! Returns the number of bytes actually read, or an error
<commit_msg>Cleanup docs<commit_after>//! # The Redox OS Kernel, version 2
//!
//! The Redox OS Kernel is a hybrid kernel that supports X86 systems and
//! provides Unix-like syscalls for primarily Rust applications
//!
//! ## Syscalls
//! Syscalls in Redox are often handled by userspace `schemes`.
//! The essential syscalls in Redox are as follows:
//!
//! ### Open
//! `open(path: &str, flags: usize) -> Result<file_descriptor: usize>`
//!
//! Open a file, providing a path as a `&str` and flags, defined elsewhere.
//! Returns a number, known as a file descriptor, that is passed to other syscalls
//!
//! ### Close
//! `close(file_descriptor: usize) -> Result<()>`
//!
//! Close a file descriptor, providing the file descriptor from `open`
//! Returns an error, `EBADF`, if the file descriptor was not found.
//! This potential error is often ignored by userspace
//!
//! ### Duplicate
//! `dup(file_descriptor: usize) -> Result<file_descriptor: usize>`
//!
//! Duplicate a file descriptor, providing the file descriptor from `open`
//! Returns a new file descriptor, or an error
//!
//! ### Read
//! `read(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>`
//!
//! Read from a file descriptor, providing the file descriptor from `open` and a mutable buffer
//! Returns the number of bytes actually read, or an error
//!
//! ### Write
//! `write(file_descriptor: usize, buffer: &[u8]) -> Result<count: usize>`
//!
//! Write to a file descriptor, providing the file descriptor from `open` and a const buffer
//! Returns the number of bytes actually written, or an error
//!
//! ### Stat
//! `fstat(file_descriptor: usize, stat: &mut Stat) -> Result<()>`
//!
//! Get information from a file descriptor, providing the file descriptor from `open`
//! and a mutable Stat struct, defined elsewhere.
//! Returns an error if the operation failed
//!
//! ### Path
//! `fpath(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>`
//!
//! Read the path of a file descriptor, providing the file descriptor from `open`
//! and a mutable buffer. The buffer should be 4096 bytes, to ensure that the
//! entire path will fit.
//! Returns the number of bytes actually read, or an error
<|endoftext|>


<commit_before>extern crate regex;

extern crate rusoto_core;
extern crate rusoto_sts;
extern crate rusoto_dynamodb;

pub mod SessionHandler {
    use std::fs::File;
    use std::io::BufReader;
    use std::io::prelude::*;
    use std::io::{stdin, stdout};
    use std::env;
    use rusoto_core::{DefaultCredentialsProvider, ProfileProvider,
        ProvideAwsCredentials, Region, default_tls_client};
    use rusoto_sts::{Sts, StsClient, GetSessionTokenRequest, GetSessionTokenResponse, GetSessionTokenError};
    use rusoto_dynamodb::{DynamoDb, DynamoDbClient, ListTablesInput};
    use regex::Regex;
    use std::collections::HashMap;

    pub struct SessionHandler {
        AWSConfig: AWSConfig,
    }

    struct AWSConfig {
        profiles: HashMap<String, AWSProfile>,
    }

    #[derive(Debug)]
    struct AWSProfile {
        source_profile: Option<String>,
        region: Option<String>,
        output: Option<String>,
        role_arn: Option<String>,
        mfa_serial: Option<String>,
        ot_session_name: Option<String>,
        ot_expiration: Option<String>,
        ot_source_profile: Option<String>,
        ot_role_arn: Option<String>,
    }

    impl AWSConfig {
        fn get_profile(&self, name: &str) -> &AWSProfile {
            &self.profiles[name]
        }
    }

    impl SessionHandler {
        pub fn load_config(&mut self) {
            let aws_config_file = read_aws_config_file();
            let profiles = split_config_file(aws_config_file);

            // Create an instance of the AWSConfig struct
            let mut aws_config = AWSConfig {
                profiles: HashMap::new()
            };

            // Iterate over profile chunks
            for profile in profiles {
                // Create a vector of string that holds each line
                let split = profile.split("\n");
                let lines: Vec<String> = split.map(|s| s.to_string()).collect();

                // Get the profile name from the first line
                let profile_line = lines[0].to_owned();

                // Lets ignore the default for now
                if profile_line == "[default]" {
                    continue;
                }

                let split2 = profile_line.split(" ");
                let mut words: Vec<String> = split2.map(|s| s.to_string()).collect();
                let mut profile_name = String::new();
                if words.len() > 1 {
                    words[1].pop();
                    profile_name = words[1].trim_right().to_owned();
                }

                let mut aws_profile = AWSProfile{
                    source_profile: None,
                    region: None,
                    output: None,
                    role_arn: None,
                    mfa_serial: None,
                    ot_expiration: None,
                    ot_session_name: None,
                    ot_source_profile: None,
                    ot_role_arn: None,
                };

                for i in 1..lines.len() {
                    let split = lines[i].split(" = ");
                    let config: Vec<String> = split.map(|s| s.to_string()).collect();
                    let key = &config[0];
                    let value = config[1].to_owned();
                    match key.as_ref() {
                        "mfa_serial" => aws_profile.mfa_serial = Some(value),
                        "output" => aws_profile.output = Some(value),
                        "region" => aws_profile.region = Some(value),
                        "role_arn" => aws_profile.role_arn = Some(value),
                        "source_profile" => aws_profile.source_profile = Some(value),
                        "ot_session_name" => aws_profile.ot_session_name = Some(value),
                        "ot_expiration" => aws_profile.ot_expiration = Some(value),
                        "ot_source_profile" => aws_profile.ot_source_profile = Some(value),
                        "ot_role_arn" => aws_profile.ot_role_arn = Some(value),
                        _ => (),
                    }
                }

                if profile_name != "" {
                    aws_config.profiles.insert(profile_name.clone(), aws_profile);
                }
            }

            self.AWSConfig = aws_config;
        }

        pub fn create(&self, profile_name: &str) {
            println!("Creating session for profile \"{}\"...", profile_name);
            //let aws_profile = &self.AWSConfig.profiles[profile_name];
            let aws_profile = &self.AWSConfig.get_profile(profile_name);

            let mut provider = ProfileProvider::new().unwrap();
            provider.set_profile(profile_name);
            // let region = &aws_profile.region;
            // match region {
            //     &Some(ref region) => region,
            //     &None => panic!("You must specify a region for profile {}", profile_name)
            // };
            // println!("Region: {:?}", region.as_ref().unwrap());
            let client = StsClient::new(default_tls_client().unwrap(), provider, Region::EuWest1);

            let mfa_serial = &aws_profile.mfa_serial;
            if mfa_serial.is_some() {
                print!("Enter AWS MFA code for profile [{}]: ", profile_name);
                stdout().flush();
                let mut token_code = String::new();
                stdin().read_line(&mut token_code)
                    .ok()
                    .expect("Couldn't read line");
                token_code.pop(); // Remove newline

                let request = GetSessionTokenRequest {
                    duration_seconds: None,
                    serial_number: Some(mfa_serial.as_ref().unwrap().to_owned()),
                    token_code: Some(token_code),
                };
                let response = client.get_session_token(&request);
                match response {
                    Result::Ok(response) => println!("{:?}", response.credentials.unwrap()),
                    Result::Err(err) => panic!("Failed to get session token for profile {}: {:?}", profile_name, err),
                };
            }
        }

        pub fn show(&self, profile_name: &str) {
            println!("Showing config for profile {}...", profile_name);
            println!("{:?}", self.AWSConfig.profiles[profile_name]);
        }
    }

    pub fn create(profile_name: &str) {
        println!("Creating session for profile \"{}\"...", profile_name);

    }

    pub fn new() -> SessionHandler {
            SessionHandler {
                AWSConfig: AWSConfig {
                    profiles: HashMap::new()
                }
            }
    }

    pub fn refresh() {
        println!("Refreshing sessions...");
    }

    pub fn clean() {
        println!("Cleaning sessions...");
    }

    fn read_aws_config_file() -> String {
        let path = match env::home_dir() {
            Some(path) => path,
            None => panic!("Could not retrieve user's home directory."),
        };
        let config_file_path = format!("{}/.aws/config", path.display());

        let f = File::open(config_file_path).expect("Could not find AWS config file.");
        let mut buf_reader = BufReader::new(f);
        let mut contents = String::new();
        buf_reader.read_to_string(&mut contents).expect("Found config file but could not read it.");

        contents
    }

    fn split_config_file(aws_config: String) -> Vec<String> {
        let split = aws_config.split("\n\n");
        let mut profiles: Vec<String> = split.map(|s| s.to_string()).collect();;

        profiles.pop(); // Remove last element as it is always empty
        profiles
    }
}
<commit_msg>Add function to save credentials<commit_after>extern crate regex;

extern crate rusoto_core;
extern crate rusoto_sts;
extern crate rusoto_dynamodb;

pub mod SessionHandler {
    use std::fs::{File, OpenOptions};
    use std::io::{BufReader, Error};
    use std::io;
    use std::io::prelude::*;
    use std::io::{stdin, stdout};
    use std::env;
    use rusoto_core::{DefaultCredentialsProvider, ProfileProvider,
        ProvideAwsCredentials, Region, default_tls_client};
    use rusoto_sts::{Sts, StsClient, GetSessionTokenRequest, GetSessionTokenResponse, GetSessionTokenError, Credentials};
    use rusoto_dynamodb::{DynamoDb, DynamoDbClient, ListTablesInput};
    use regex::Regex;
    use std::collections::HashMap;

    pub struct SessionHandler {
        AWSConfig: AWSConfig,
    }

    struct AWSConfig {
        profiles: HashMap<String, AWSProfile>,
    }

    #[derive(Debug)]
    struct AWSProfile {
        source_profile: Option<String>,
        region: Option<String>,
        output: Option<String>,
        role_arn: Option<String>,
        mfa_serial: Option<String>,
        ot_session_name: Option<String>,
        ot_expiration: Option<String>,
        ot_source_profile: Option<String>,
        ot_role_arn: Option<String>,
    }

    impl AWSConfig {
        fn get_profile(&self, name: &str) -> &AWSProfile {
            &self.profiles[name]
        }
    }

    impl SessionHandler {
        pub fn load_config(&mut self) {
            let aws_config_file = read_aws_config_file();
            let profiles = split_config_file(aws_config_file);

            // Create an instance of the AWSConfig struct
            let mut aws_config = AWSConfig {
                profiles: HashMap::new()
            };

            // Iterate over profile chunks
            for profile in profiles {
                // Create a vector of string that holds each line
                let split = profile.split("\n");
                let lines: Vec<String> = split.map(|s| s.to_string()).collect();

                // Get the profile name from the first line
                let profile_line = lines[0].to_owned();

                // Lets ignore the default for now
                if profile_line == "[default]" {
                    continue;
                }

                let split2 = profile_line.split(" ");
                let mut words: Vec<String> = split2.map(|s| s.to_string()).collect();
                let mut profile_name = String::new();
                if words.len() > 1 {
                    words[1].pop();
                    profile_name = words[1].trim_right().to_owned();
                }

                let mut aws_profile = AWSProfile{
                    source_profile: None,
                    region: None,
                    output: None,
                    role_arn: None,
                    mfa_serial: None,
                    ot_expiration: None,
                    ot_session_name: None,
                    ot_source_profile: None,
                    ot_role_arn: None,
                };

                for i in 1..lines.len() {
                    let split = lines[i].split(" = ");
                    let config: Vec<String> = split.map(|s| s.to_string()).collect();
                    let key = &config[0];
                    let value = config[1].to_owned();
                    match key.as_ref() {
                        "mfa_serial" => aws_profile.mfa_serial = Some(value),
                        "output" => aws_profile.output = Some(value),
                        "region" => aws_profile.region = Some(value),
                        "role_arn" => aws_profile.role_arn = Some(value),
                        "source_profile" => aws_profile.source_profile = Some(value),
                        "ot_session_name" => aws_profile.ot_session_name = Some(value),
                        "ot_expiration" => aws_profile.ot_expiration = Some(value),
                        "ot_source_profile" => aws_profile.ot_source_profile = Some(value),
                        "ot_role_arn" => aws_profile.ot_role_arn = Some(value),
                        _ => (),
                    }
                }

                if profile_name != "" {
                    aws_config.profiles.insert(profile_name.clone(), aws_profile);
                }
            }

            self.AWSConfig = aws_config;
        }

        pub fn create(&self, profile_name: &str) {
            println!("Creating session for profile \"{}\"...", profile_name);
            //let aws_profile = &self.AWSConfig.profiles[profile_name];
            let aws_profile = &self.AWSConfig.get_profile(profile_name);

            let mut provider = ProfileProvider::new().unwrap();
            provider.set_profile(profile_name);
            // let region = &aws_profile.region;
            // match region {
            //     &Some(ref region) => region,
            //     &None => panic!("You must specify a region for profile {}", profile_name)
            // };
            // println!("Region: {:?}", region.as_ref().unwrap());
            let client = StsClient::new(default_tls_client().unwrap(), provider, Region::EuWest1);

            let mfa_serial = &aws_profile.mfa_serial;
            if mfa_serial.is_some() {
                print!("Enter AWS MFA code for profile [{}]: ", profile_name);
                stdout().flush();
                let mut token_code = String::new();
                stdin().read_line(&mut token_code)
                    .ok()
                    .expect("Couldn't read line");
                token_code.pop(); // Remove newline

                let request = GetSessionTokenRequest {
                    duration_seconds: None,
                    serial_number: Some(mfa_serial.as_ref().unwrap().to_owned()),
                    token_code: Some(token_code),
                };
                let response = client.get_session_token(&request);
                match response {
                    Ok(response) => {
                        let credentials = response.credentials.unwrap();
                        println!("{:?}", credentials);
                        match save_credentials(credentials) {
                            Ok(_) => println!("Saved to credentials file."),
                            Err(err) => println!("Error saving credentials to file: {:?}", err)
                        };
                    },
                    Err(err) => panic!("Failed to get session token for profile {}: {:?}", profile_name, err),
                };
            }
        }

        pub fn show(&self, profile_name: &str) {
            println!("Showing config for profile {}...", profile_name);
            println!("{:?}", self.AWSConfig.profiles[profile_name]);
        }
    }

    pub fn create(profile_name: &str) {
        println!("Creating session for profile \"{}\"...", profile_name);

    }

    pub fn new() -> SessionHandler {
            SessionHandler {
                AWSConfig: AWSConfig {
                    profiles: HashMap::new()
                }
            }
    }

    pub fn refresh() {
        println!("Refreshing sessions...");
    }

    pub fn clean() {
        println!("Cleaning sessions...");
    }

    fn read_aws_config_file() -> String {
        let path = match env::home_dir() {
            Some(path) => path,
            None => panic!("Could not retrieve user's home directory."),
        };
        let config_file_path = format!("{}/.aws/config", path.display());

        let f = File::open(config_file_path).expect("Could not find AWS config file.");
        let mut buf_reader = BufReader::new(f);
        let mut contents = String::new();
        buf_reader.read_to_string(&mut contents).expect("Found config file but could not read it.");

        contents
    }

    fn split_config_file(aws_config: String) -> Vec<String> {
        let split = aws_config.split("\n\n");
        let mut profiles: Vec<String> = split.map(|s| s.to_string()).collect();;

        profiles.pop(); // Remove last element as it is always empty
        profiles
    }

    fn save_credentials(credentials: Credentials) -> Result<(), io::Error> {
        let mut aws_credentials_path = env::home_dir().unwrap().display().to_string();
        aws_credentials_path.push_str("/.aws/credentials");
        let mut file = OpenOptions::new()
                       .write(true)
                       .append(true)
                       .open(aws_credentials_path)
                       .unwrap();

        try!(file.write_all("Hi from Bluenine!\n".as_bytes()));
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! This crate contains utilities to work with Fractal Global Credits. It contains the wallet
//! address representation and the currency amount type. Each of them is explained in its own
//! documentation and can be easily used by third parties.
//!
//! Using it is as simple as including this in the crate:
//!
//! ```
//! extern crate fractal_utils;
//! ```
#![forbid(missing_docs, warnings)]
#![deny(deprecated, improper_ctypes, non_shorthand_field_patterns, overflowing_literals,
    plugin_as_library, private_no_mangle_fns, private_no_mangle_statics, stable_features,
    unconditional_recursion, unknown_lints, unused, unused_allocation, unused_attributes,
    unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused, unused_extern_crates, unused_import_braces,
    unused_qualifications, unused_results, variant_size_differences)]

extern crate rustc_serialize;
extern crate rust_base58;

pub mod amount;
pub mod wallet_address;
pub mod location;
pub mod relations;

pub use amount::Amount;
pub use wallet_address::{WALLET_ADDRESS_LEN, WalletAddress};
pub use location::Address;
pub use relations::{Relationship, get_relationship_id, get_relationship};
/// The symbol of Fractal Global Credits
///
/// This symbol, `Ͼ` should be used whenever an amount of currency has to be represented. It is a
/// dotted lumate sigma symbol, the Unicode *U+03FE* character. It can easily be used when
/// formatting currencies:
///
/// ```
/// use fractal_utils::{CURRENCY_SYMBOL, Amount};
/// # assert_eq!(CURRENCY_SYMBOL, 'Ͼ');
/// # assert_eq!(CURRENCY_SYMBOL, '\u{03FE}');
/// let amount = Amount::from_repr(30_000); // 30.000
/// assert_eq!(format!("{} {}", CURRENCY_SYMBOL, amount), "Ͼ 30");
/// ```
pub const CURRENCY_SYMBOL: char = 'Ͼ';
<commit_msg>Added space between imports and comments<commit_after>//! This crate contains utilities to work with Fractal Global Credits. It contains the wallet
//! address representation and the currency amount type. Each of them is explained in its own
//! documentation and can be easily used by third parties.
//!
//! Using it is as simple as including this in the crate:
//!
//! ```
//! extern crate fractal_utils;
//! ```
#![forbid(missing_docs, warnings)]
#![deny(deprecated, improper_ctypes, non_shorthand_field_patterns, overflowing_literals,
    plugin_as_library, private_no_mangle_fns, private_no_mangle_statics, stable_features,
    unconditional_recursion, unknown_lints, unused, unused_allocation, unused_attributes,
    unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused, unused_extern_crates, unused_import_braces,
    unused_qualifications, unused_results, variant_size_differences)]

extern crate rustc_serialize;
extern crate rust_base58;

pub mod amount;
pub mod wallet_address;
pub mod location;
pub mod relations;

pub use amount::Amount;
pub use wallet_address::{WALLET_ADDRESS_LEN, WalletAddress};
pub use location::Address;
pub use relations::{Relationship, get_relationship_id, get_relationship};

/// The symbol of Fractal Global Credits
///
/// This symbol, `Ͼ` should be used whenever an amount of currency has to be represented. It is a
/// dotted lumate sigma symbol, the Unicode *U+03FE* character. It can easily be used when
/// formatting currencies:
///
/// ```
/// use fractal_utils::{CURRENCY_SYMBOL, Amount};
/// # assert_eq!(CURRENCY_SYMBOL, 'Ͼ');
/// # assert_eq!(CURRENCY_SYMBOL, '\u{03FE}');
/// let amount = Amount::from_repr(30_000); // 30.000
/// assert_eq!(format!("{} {}", CURRENCY_SYMBOL, amount), "Ͼ 30");
/// ```
pub const CURRENCY_SYMBOL: char = 'Ͼ';
<|endoftext|>