<commit_before>// Copyright 2015 Dawid Ciężarkiewicz
// See LICENSE-MPL
//! Simple Map with default for missing values and compacting (removal of
//! elements with default value from underlying map).
//!
//! So you can just:
//!
//! ```
//! use simplemap::SimpleMap;
//!
//! let mut map = SimpleMap::new();
//!
//! assert_eq!(map[0u32], 0u32);
//! map[1] = 3;
//! assert_eq!(map[1], 3);
//! ```

#![feature(hashmap_hasher)]

#![cfg_attr(all(test, feature="bench"), feature(test))]

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

#[cfg(test)]
extern crate rand;

use std::ops::{Index, IndexMut};
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::collections::hash_state::{DefaultState, HashState};
use std::iter::Chain;
use std::hash::Hash;
use fnv::FnvHasher;
use std::fmt;

/// SimpleMap
///
/// Simple Map with default for missing values and compacting (removal of
/// elements with default value from underlying map).
#[derive(Clone)]
pub struct SimpleMap<K, V, S = DefaultState<FnvHasher>> {
    map : HashMap<K, V, S>,
    default : V,
    pending : Option<(K, V)>
}

impl<K, V> SimpleMap<K, V>
where K : Ord+Clone+Hash,
      V : Clone+Eq+Default,
{
    /// Create a `SimpleMap`.
    ///
    /// `Default::default()` will be used as a default value.
    pub fn new() -> SimpleMap<K, V, DefaultState<FnvHasher>> {
        SimpleMap {
            map : Default::default(),
            default: Default::default(),
            pending: None,
        }
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      V : Clone+Eq+Default,
      S : HashState+Default
{
    /// Create a `SimpleMap`.
    ///
    /// `Default::default()` will be used as a default value.
    pub fn with_hash_state(hash_state : S) -> SimpleMap<K, V, S> {
        SimpleMap {
            map : HashMap::with_hash_state(hash_state),
            default: Default::default(),
            pending: None,
        }
    }
}

impl<K, V> SimpleMap<K, V>
where K : Ord+Clone+Hash,
      V : Clone+Eq,
{
    /// Create a `SimpleMap` with custom default value.
    pub fn new_with_default(default : V) -> SimpleMap<K, V, DefaultState<FnvHasher>> {
        SimpleMap {
            map : Default::default(),
            default: default,
            pending: None,
        }
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      S : HashState+Default,
      V : Clone+Eq,
{
    pub fn with_default_with_hash_state(default : V, hash_state: S) -> SimpleMap<K, V, S> {
        SimpleMap {
            map : HashMap::with_hash_state(hash_state),
            default: default,
            pending: None,
        }
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      V : Clone+Eq,
      S: HashState,
{
    fn apply_pending(&mut self) {
       match self.pending {
           Some(ref pending) => {
               let &(ref idx , ref val) = pending;
               if *val == self.default {
                   self.map.remove(idx);
               } else {
                   self.map.insert(idx.clone(), val.clone());
               }
           },
           None => {}
       }
       self.pending = None;
    }

    /// Make sure to remove all elements with default value.
    pub fn compact(&mut self) {
        self.apply_pending();
    }

    /// Iterator over map elements with non-default values.
    ///
    /// Note: It might return elements with default value, unless `compact`
    /// is called before `iter()`.
    pub fn iter<'a>(&'a self) -> Chain<std::collections::hash_map::Iter<'a, K, V>, std::iter::Map<std::option::Iter<'a, (K, V)>, fn(&'a (K, V)) -> (&'a K, &'a V)>> {
        let SimpleMap {
            ref map,
            ref pending,
            ..
        } = *self;

        let f: fn(&'a (K, V)) -> (&'a K, &'a V) = ref_to_tuple_to_tuple_of_refs;

        map.iter().chain(pending.iter().map(f))
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      S: HashState,
      V : Clone+Eq,
{
    /// Iterator yielding (K, V) instead of (&K, &V)
    pub fn iter_cloned<'a>(&'a self) ->
        Chain<
            std::iter::Map<std::collections::hash_map::Iter<'a, K, V>, fn((&'a K, &'a V)) -> (K, V)>,
            std::iter::Cloned<std::option::Iter<'a, (K, V)>>
        >
    {
        let SimpleMap {
            ref map,
            ref pending,
            ..
        } = *self;

        let f: fn((&'a K, &'a V)) -> (K, V) = tuple_of_refs_to_tuple;

        map.iter().map(f).chain(pending.iter().cloned())
    }

}

fn ref_to_tuple_to_tuple_of_refs<'a, K, V>(t : &'a(K, V)) -> (&'a K, &'a V) {
    let &(ref i, ref t) = t;
    (i, t)
}

fn tuple_of_refs_to_tuple<'a, K : Clone, V : Clone>(t : (&'a K, &'a V)) -> (K, V) {
    let (i, t) = t;
    (i.clone(), t.clone())
}

use std::iter::FromIterator;
use std::iter::IntoIterator;

impl<K, V, S> FromIterator<(K, V)> for SimpleMap<K, V, S>
where K: Ord+Hash, V: Default,
      S: HashState+Default {
    fn from_iter<I>(iterator: I) -> SimpleMap<K, V, S>
        where I: IntoIterator<Item=(K, V)> {
            SimpleMap {
                default: Default::default(),
                map: FromIterator::from_iter(iterator),
                pending: None,
            }
    }
}

/// ```
/// use simplemap::SimpleMap;
///
/// let mut map = SimpleMap::new();
///
/// let val : u32 = map[0u32];
/// assert_eq!(val, 0);
/// ```
impl<K, V, S> Index<K> for SimpleMap<K, V, S>
where K : Ord+Hash,
      S : HashState+Default,
{
    type Output = V;
    fn index<'a>(&'a self, index: K) -> &'a V {
        match self.pending {
            Some(ref pending) => {
               let &(ref i, ref val) = pending;
               if *i == index {
                   return val
               }
            }
            None => {},
        }

        match self.map.get(&index) {
            Some(entry) => entry,
            None => &self.default,
        }
    }
}

/// ```
/// use simplemap::SimpleMap;
///
/// let mut map = SimpleMap::new();
///
/// map[1u32] = 3i32;
/// assert_eq!(map[1], 3);
/// ```
impl<K, V, S> IndexMut<K> for SimpleMap<K, V, S>
where
K : Ord+Clone+Hash,
V : Clone+Eq,
      S : HashState+Default,
{
    fn index_mut<'a>(&'a mut self, index: K) -> &'a mut V {
        self.apply_pending();

        match self.map.entry(index.clone()) {
            Entry::Occupied(entry) => {
                self.pending = Some((index, entry.get().clone()));
                let &mut (_, ref mut val) = self.pending.as_mut().unwrap();
                val
            },
            Entry::Vacant(_) => {
                self.pending = Some((index, self.default.clone()));
                let &mut (_, ref mut val) = self.pending.as_mut().unwrap();
                val
            }
        }
    }
}

impl<K, V, S> fmt::Debug for SimpleMap<K, V, S>
where K : Ord+Eq+Clone+Hash+fmt::Debug,
      V : Clone+Eq+fmt::Debug,
      S: HashState,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_map().entries(self.iter()).finish()
    }
}

impl<K, V> Default for SimpleMap<K, V>
where K : Ord+Clone+Hash,
      V : Clone+Eq+Default,
{
     fn default() -> Self {
         SimpleMap::with_default_with_hash_state(Default::default(), Default::default())
     }
}

#[cfg(test)]
mod tests {
    pub use super::*;
    use std::collections::HashMap;
    use std::collections::hash_state::{DefaultState};
    use fnv::FnvHasher;
    use rand::Rng;
    use rand;

    #[test]
    fn default() {
        let map = SimpleMap::new_with_default(5u32);
        assert_eq!(map[1u32], 5u32);
    }

    #[test]
    fn iter() {
        let mut map = SimpleMap::new();

        map[0u32] = 3i32; // counts
        map[1u32] = 0i32; // default, doesn't count
        map[2u32] = 2i32; // counts
        map[0u32] = 2i32; // replaces the existing one
        let _ = map[0u32]; // shouldn't change anything

        map.compact();
        assert_eq!(map.iter().count(), 2);
    }

    #[test]
    fn random() {
        let mut bmap : HashMap<_, _, DefaultState<FnvHasher>> = Default::default();
        let mut smap = SimpleMap::new();

        let mut rng = rand::thread_rng();

        for val in 0u32..10000 {
            let idx = rng.gen_range(-5i32, 5);
            let bval = *bmap.get(&idx).unwrap_or(&Default::default());
            let sval = smap[idx];
            assert_eq!(bval, sval);
            bmap.insert(idx, val);
            smap[idx] = val;
        }
    }

    #[test]
    fn strings() {
        let mut smap = SimpleMap::new();

        smap["one"] = 1u32;
        smap["two"] = 2u32;

        assert_eq!(smap["zero"], 0u32);
    }

#[cfg(feature="bench")]
    mod bench {
        use std::collections::BTreeMap;
        use std::collections::HashMap;
        use std::collections::hash_state::{DefaultState};
        use fnv::FnvHasher;
        use super::*;
        use test::Bencher;
        use test;
#[bench]
        fn normal_btreemap_insert(b : &mut Bencher) {
            let mut map = BTreeMap::new();

            let mut i = 0u32;
            b.iter(|| {
                map.insert(i, i);
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn normal_btreemap_get(b : &mut Bencher) {
            let mut map = BTreeMap::new();

            for i in 0u32..10000 {
                map.insert(i, i);
            }

            let mut i = 0u32;
            b.iter(|| {
                test::black_box(map.get(&i));
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn normal_hashmap_insert(b : &mut Bencher) {
            let mut map : HashMap<_, _, DefaultState<FnvHasher>> = Default::default();

            let mut i = 0u32;
            b.iter(|| {
                map.insert(i, i);
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn normal_hashmap_get(b : &mut Bencher) {
            let mut map : HashMap<_, _, DefaultState<FnvHasher>> = Default::default();

            for i in 0u32..10000 {
                map.insert(i, i);
            }

            let mut i = 0u32;
            b.iter(|| {
                test::black_box(map.get(&i));
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn compact_map_idx_assign(b : &mut Bencher) {
            let mut map = SimpleMap::new();

            let mut i = 0u32;
            b.iter(|| {
                map[i] = i;
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn compact_map_idx_get(b : &mut Bencher) {
            let mut map = SimpleMap::new();

            for i in 0u32..10000 {
                map[i] = i;
            }

            let mut i = 0u32;
            b.iter(|| {
                test::black_box(map[i]);
                i = i.wrapping_add(i);
            });
        }
    }
}
<commit_msg>Update to latest rust.<commit_after>// Copyright 2015 Dawid Ciężarkiewicz
// See LICENSE-MPL
//! Simple Map with default for missing values and compacting (removal of
//! elements with default value from underlying map).
//!
//! So you can just:
//!
//! ```
//! use simplemap::SimpleMap;
//!
//! let mut map = SimpleMap::new();
//!
//! assert_eq!(map[0u32], 0u32);
//! map[1] = 3;
//! assert_eq!(map[1], 3);
//! ```

#![cfg_attr(all(test, feature="bench"), feature(test))]

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

#[cfg(test)]
extern crate rand;

use std::ops::{Index, IndexMut};
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::iter::Chain;
use std::hash::{Hash, BuildHasherDefault, BuildHasher};
use fnv::FnvHasher;
use std::fmt;

/// SimpleMap
///
/// Simple Map with default for missing values and compacting (removal of
/// elements with default value from underlying map).
#[derive(Clone)]
pub struct SimpleMap<K, V, S> {
    map : HashMap<K, V, S>,
    default : V,
    pending : Option<(K, V)>
}

impl<K, V> SimpleMap<K, V, BuildHasherDefault<FnvHasher>>
where K : Ord+Clone+Hash,
      V : Clone+Eq+Default,
{
    /// Create a `SimpleMap`.
    ///
    /// `Default::default()` will be used as a default value.
    pub fn new() -> Self {
        let fnv = BuildHasherDefault::<FnvHasher>::default();
        SimpleMap {
            map : HashMap::with_hasher(fnv),
            default: Default::default(),
            pending: None,
        }
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      V : Clone+Eq+Default,
      S : BuildHasher+Default
{
    /// Create a `SimpleMap`.
    ///
    /// `Default::default()` will be used as a default value.
    pub fn with_hasher(hasher : S) -> SimpleMap<K, V, S> {
        SimpleMap {
            map : HashMap::with_hasher(hasher),
            default: Default::default(),
            pending: None,
        }
    }
}

impl<K, V> SimpleMap<K, V,  BuildHasherDefault<FnvHasher>>
where K : Ord+Clone+Hash,
      V : Clone+Eq,
{
    /// Create a `SimpleMap` with custom default value.
    pub fn new_with_default(default : V) -> Self {
        let fnv = BuildHasherDefault::<FnvHasher>::default();
        SimpleMap {
            map : HashMap::with_hasher(fnv),
            default: default,
            pending: None,
        }
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      V : Clone+Eq,
      S : BuildHasher+Default,
{
    pub fn with_default_with_hasher(default : V, hasher: S) -> SimpleMap<K, V, S> {
        SimpleMap {
            map : HashMap::with_hasher(hasher),
            default: default,
            pending: None,
        }
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      V : Clone+Eq,
      S: BuildHasher,
{
    fn apply_pending(&mut self) {
       match self.pending {
           Some(ref pending) => {
               let &(ref idx , ref val) = pending;
               if *val == self.default {
                   self.map.remove(idx);
               } else {
                   self.map.insert(idx.clone(), val.clone());
               }
           },
           None => {}
       }
       self.pending = None;
    }

    /// Make sure to remove all elements with default value.
    pub fn compact(&mut self) {
        self.apply_pending();
    }

    /// Iterator over map elements with non-default values.
    ///
    /// Note: It might return elements with default value, unless `compact`
    /// is called before `iter()`.
    pub fn iter<'a>(&'a self) -> Chain<std::collections::hash_map::Iter<'a, K, V>, std::iter::Map<std::option::Iter<'a, (K, V)>, fn(&'a (K, V)) -> (&'a K, &'a V)>> {
        let SimpleMap {
            ref map,
            ref pending,
            ..
        } = *self;

        let f: fn(&'a (K, V)) -> (&'a K, &'a V) = ref_to_tuple_to_tuple_of_refs;

        map.iter().chain(pending.iter().map(f))
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      V : Clone+Eq,
      S: BuildHasher,
{
    /// Iterator yielding (K, V) instead of (&K, &V)
    pub fn iter_cloned<'a>(&'a self) ->
        Chain<
            std::iter::Map<std::collections::hash_map::Iter<'a, K, V>, fn((&'a K, &'a V)) -> (K, V)>,
            std::iter::Cloned<std::option::Iter<'a, (K, V)>>
        >
    {
        let SimpleMap {
            ref map,
            ref pending,
            ..
        } = *self;

        let f: fn((&'a K, &'a V)) -> (K, V) = tuple_of_refs_to_tuple;

        map.iter().map(f).chain(pending.iter().cloned())
    }

}

fn ref_to_tuple_to_tuple_of_refs<'a, K, V>(t : &'a(K, V)) -> (&'a K, &'a V) {
    let &(ref i, ref t) = t;
    (i, t)
}

fn tuple_of_refs_to_tuple<'a, K : Clone, V : Clone>(t : (&'a K, &'a V)) -> (K, V) {
    let (i, t) = t;
    (i.clone(), t.clone())
}

use std::iter::FromIterator;
use std::iter::IntoIterator;

impl<K, V, S> FromIterator<(K, V)> for SimpleMap<K, V, S>
where K: Ord+Hash, V: Default,
      S: BuildHasher+Default {
    fn from_iter<I>(iterator: I) -> SimpleMap<K, V, S>
        where I: IntoIterator<Item=(K, V)> {
            SimpleMap {
                default: Default::default(),
                map: FromIterator::from_iter(iterator),
                pending: None,
            }
    }
}

/// ```
/// use simplemap::SimpleMap;
///
/// let mut map = SimpleMap::new();
///
/// let val : u32 = map[0u32];
/// assert_eq!(val, 0);
/// ```
impl<K, V, S> Index<K> for SimpleMap<K, V, S>
where K : Ord+Hash,
      S : BuildHasher+Default,
{
    type Output = V;
    fn index<'a>(&'a self, index: K) -> &'a V {
        match self.pending {
            Some(ref pending) => {
               let &(ref i, ref val) = pending;
               if *i == index {
                   return val
               }
            }
            None => {},
        }

        match self.map.get(&index) {
            Some(entry) => entry,
            None => &self.default,
        }
    }
}

/// ```
/// use simplemap::SimpleMap;
///
/// let mut map = SimpleMap::new();
///
/// map[1u32] = 3i32;
/// assert_eq!(map[1], 3);
/// ```
impl<K, V, S> IndexMut<K> for SimpleMap<K, V, S>
where
K : Ord+Clone+Hash,
V : Clone+Eq,
      S : BuildHasher+Default,
{
    fn index_mut<'a>(&'a mut self, index: K) -> &'a mut V {
        self.apply_pending();

        match self.map.entry(index.clone()) {
            Entry::Occupied(entry) => {
                self.pending = Some((index, entry.get().clone()));
                let &mut (_, ref mut val) = self.pending.as_mut().unwrap();
                val
            },
            Entry::Vacant(_) => {
                self.pending = Some((index, self.default.clone()));
                let &mut (_, ref mut val) = self.pending.as_mut().unwrap();
                val
            }
        }
    }
}

impl<K, V, S> fmt::Debug for SimpleMap<K, V, S>
where K : Ord+Eq+Clone+Hash+fmt::Debug,
      V : Clone+Eq+fmt::Debug,
      S: BuildHasher,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_map().entries(self.iter()).finish()
    }
}

impl<K, V, S> Default for SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      V : Clone+Eq+Default,
      S : BuildHasher+Default,
{
     fn default() -> Self {
         SimpleMap::with_default_with_hasher(Default::default(), Default::default())
     }
}

#[cfg(test)]
mod tests {
    pub use super::*;
    use std::collections::HashMap;
    use rand::Rng;
    use rand;

    #[test]
    fn default() {
        let map = SimpleMap::new_with_default(5u32);
        assert_eq!(map[1u32], 5u32);
    }

    #[test]
    fn iter() {
        let mut map = SimpleMap::new();

        map[0u32] = 3i32; // counts
        map[1u32] = 0i32; // default, doesn't count
        map[2u32] = 2i32; // counts
        map[0u32] = 2i32; // replaces the existing one
        let _ = map[0u32]; // shouldn't change anything

        map.compact();
        assert_eq!(map.iter().count(), 2);
    }

    #[test]
    fn random() {
        let mut bmap = HashMap::new();
        let mut smap = SimpleMap::new();

        let mut rng = rand::thread_rng();

        for val in 0u32..10000 {
            let idx = rng.gen_range(-5i32, 5);
            let bval = *bmap.get(&idx).unwrap_or(&Default::default());
            let sval = smap[idx];
            assert_eq!(bval, sval);
            bmap.insert(idx, val);
            smap[idx] = val;
        }
    }

    #[test]
    fn strings() {
        let mut smap = SimpleMap::new();

        smap["one"] = 1u32;
        smap["two"] = 2u32;

        assert_eq!(smap["zero"], 0u32);
    }

#[cfg(feature="bench")]
    mod bench {
        use std::collections::BTreeMap;
        use std::collections::HashMap;
        use std::collections::hash_state::{DefaultState};
        use fnv::FnvHasher;
        use super::*;
        use test::Bencher;
        use test;
#[bench]
        fn normal_btreemap_insert(b : &mut Bencher) {
            let mut map = BTreeMap::new();

            let mut i = 0u32;
            b.iter(|| {
                map.insert(i, i);
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn normal_btreemap_get(b : &mut Bencher) {
            let mut map = BTreeMap::new();

            for i in 0u32..10000 {
                map.insert(i, i);
            }

            let mut i = 0u32;
            b.iter(|| {
                test::black_box(map.get(&i));
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn normal_hashmap_insert(b : &mut Bencher) {
            let mut map : HashMap<_, _, DefaultState<FnvHasher>> = Default::default();

            let mut i = 0u32;
            b.iter(|| {
                map.insert(i, i);
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn normal_hashmap_get(b : &mut Bencher) {
            let mut map : HashMap<_, _, DefaultState<FnvHasher>> = Default::default();

            for i in 0u32..10000 {
                map.insert(i, i);
            }

            let mut i = 0u32;
            b.iter(|| {
                test::black_box(map.get(&i));
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn compact_map_idx_assign(b : &mut Bencher) {
            let mut map = SimpleMap::new();

            let mut i = 0u32;
            b.iter(|| {
                map[i] = i;
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn compact_map_idx_get(b : &mut Bencher) {
            let mut map = SimpleMap::new();

            for i in 0u32..10000 {
                map[i] = i;
            }

            let mut i = 0u32;
            b.iter(|| {
                test::black_box(map[i]);
                i = i.wrapping_add(i);
            });
        }
    }
}
<|endoftext|>


<commit_before>//! [tui](https://github.com/fdehau/tui-rs) is a library used to build rich
//! terminal users interfaces and dashboards.
//!
//! ![](https://raw.githubusercontent.com/fdehau/tui-rs/master/assets/demo.gif)
//!
//! # Get started
//!
//! ## Adding `tui` as a dependency
//!
//! ```toml
//! [dependencies]
//! tui = "0.15"
//! termion = "1.5"
//! ```
//!
//! The crate is using the `termion` backend by default but if for example you want your
//! application to work on Windows, you might want to use the `crossterm` backend instead. This can
//! be done by changing your dependencies specification to the following:
//!
//! ```toml
//! [dependencies]
//! crossterm = "0.19"
//! tui = { version = "0.15", default-features = false, features = ['crossterm'] }
//! ```
//!
//! The same logic applies for all other available backends.
//!
//! ## Creating a `Terminal`
//!
//! Every application using `tui` should start by instantiating a `Terminal`. It is a light
//! abstraction over available backends that provides basic functionalities such as clearing the
//! screen, hiding the cursor, etc.
//!
//! ```rust,no_run
//! use std::io;
//! use tui::Terminal;
//! use tui::backend::TermionBackend;
//! use termion::raw::IntoRawMode;
//!
//! fn main() -> Result<(), io::Error> {
//!     let stdout = io::stdout().into_raw_mode()?;
//!     let backend = TermionBackend::new(stdout);
//!     let mut terminal = Terminal::new(backend)?;
//!     Ok(())
//! }
//! ```
//!
//! If you had previously chosen `crossterm` as a backend, the terminal can be created in a similar
//! way:
//!
//! ```rust,ignore
//! use std::io;
//! use tui::Terminal;
//! use tui::backend::CrosstermBackend;
//!
//! fn main() -> Result<(), io::Error> {
//!     let stdout = io::stdout();
//!     let backend = CrosstermBackend::new(stdout);
//!     let mut terminal = Terminal::new(backend)?;
//!     Ok(())
//! }
//! ```
//!
//! You may also refer to the examples to find out how to create a `Terminal` for each available
//! backend.
//!
//! ## Building a User Interface (UI)
//!
//! Every component of your interface will be implementing the `Widget` trait. The library comes
//! with a predefined set of widgets that should meet most of your use cases. You are also free to
//! implement your own.
//!
//! Each widget follows a builder pattern API providing a default configuration along with methods
//! to customize them. The widget is then rendered using the [`Frame::render_widget`] which take
//! your widget instance an area to draw to.
//!
//! The following example renders a block of the size of the terminal:
//!
//! ```rust,no_run
//! use std::io;
//! use termion::raw::IntoRawMode;
//! use tui::Terminal;
//! use tui::backend::TermionBackend;
//! use tui::widgets::{Widget, Block, Borders};
//! use tui::layout::{Layout, Constraint, Direction};
//!
//! fn main() -> Result<(), io::Error> {
//!     let stdout = io::stdout().into_raw_mode()?;
//!     let backend = TermionBackend::new(stdout);
//!     let mut terminal = Terminal::new(backend)?;
//!     terminal.draw(|f| {
//!         let size = f.size();
//!         let block = Block::default()
//!             .title("Block")
//!             .borders(Borders::ALL);
//!         f.render_widget(block, size);
//!     })?;
//!     Ok(())
//! }
//! ```
//!
//! ## Layout
//!
//! The library comes with a basic yet useful layout management object called `Layout`. As you may
//! see below and in the examples, the library makes heavy use of the builder pattern to provide
//! full customization. And `Layout` is no exception:
//!
//! ```rust,no_run
//! use std::io;
//! use termion::raw::IntoRawMode;
//! use tui::Terminal;
//! use tui::backend::TermionBackend;
//! use tui::widgets::{Widget, Block, Borders};
//! use tui::layout::{Layout, Constraint, Direction};
//!
//! fn main() -> Result<(), io::Error> {
//!     let stdout = io::stdout().into_raw_mode()?;
//!     let backend = TermionBackend::new(stdout);
//!     let mut terminal = Terminal::new(backend)?;
//!     terminal.draw(|f| {
//!         let chunks = Layout::default()
//!             .direction(Direction::Vertical)
//!             .margin(1)
//!             .constraints(
//!                 [
//!                     Constraint::Percentage(10),
//!                     Constraint::Percentage(80),
//!                     Constraint::Percentage(10)
//!                 ].as_ref()
//!             )
//!             .split(f.size());
//!         let block = Block::default()
//!              .title("Block")
//!              .borders(Borders::ALL);
//!         f.render_widget(block, chunks[0]);
//!         let block = Block::default()
//!              .title("Block 2")
//!              .borders(Borders::ALL);
//!         f.render_widget(block, chunks[1]);
//!     })?;
//!     Ok(())
//! }
//! ```
//!
//! This let you describe responsive terminal UI by nesting layouts. You should note that by
//! default the computed layout tries to fill the available space completely. So if for any reason
//! you might need a blank space somewhere, try to pass an additional constraint and don't use the
//! corresponding area.

pub mod backend;
pub mod buffer;
pub mod layout;
pub mod style;
pub mod symbols;
pub mod terminal;
pub mod text;
pub mod widgets;

pub use self::terminal::{Frame, Terminal, TerminalOptions, Viewport};
<commit_msg>doc: fix minor grammatical errors (#489)<commit_after>//! [tui](https://github.com/fdehau/tui-rs) is a library used to build rich
//! terminal users interfaces and dashboards.
//!
//! ![](https://raw.githubusercontent.com/fdehau/tui-rs/master/assets/demo.gif)
//!
//! # Get started
//!
//! ## Adding `tui` as a dependency
//!
//! ```toml
//! [dependencies]
//! tui = "0.15"
//! termion = "1.5"
//! ```
//!
//! The crate is using the `termion` backend by default but if for example you want your
//! application to work on Windows, you might want to use the `crossterm` backend instead. This can
//! be done by changing your dependencies specification to the following:
//!
//! ```toml
//! [dependencies]
//! crossterm = "0.19"
//! tui = { version = "0.15", default-features = false, features = ['crossterm'] }
//! ```
//!
//! The same logic applies for all other available backends.
//!
//! ## Creating a `Terminal`
//!
//! Every application using `tui` should start by instantiating a `Terminal`. It is a light
//! abstraction over available backends that provides basic functionalities such as clearing the
//! screen, hiding the cursor, etc.
//!
//! ```rust,no_run
//! use std::io;
//! use tui::Terminal;
//! use tui::backend::TermionBackend;
//! use termion::raw::IntoRawMode;
//!
//! fn main() -> Result<(), io::Error> {
//!     let stdout = io::stdout().into_raw_mode()?;
//!     let backend = TermionBackend::new(stdout);
//!     let mut terminal = Terminal::new(backend)?;
//!     Ok(())
//! }
//! ```
//!
//! If you had previously chosen `crossterm` as a backend, the terminal can be created in a similar
//! way:
//!
//! ```rust,ignore
//! use std::io;
//! use tui::Terminal;
//! use tui::backend::CrosstermBackend;
//!
//! fn main() -> Result<(), io::Error> {
//!     let stdout = io::stdout();
//!     let backend = CrosstermBackend::new(stdout);
//!     let mut terminal = Terminal::new(backend)?;
//!     Ok(())
//! }
//! ```
//!
//! You may also refer to the examples to find out how to create a `Terminal` for each available
//! backend.
//!
//! ## Building a User Interface (UI)
//!
//! Every component of your interface will be implementing the `Widget` trait. The library comes
//! with a predefined set of widgets that should meet most of your use cases. You are also free to
//! implement your own.
//!
//! Each widget follows a builder pattern API providing a default configuration along with methods
//! to customize them. The widget is then rendered using [`Frame::render_widget`] which takes
//! your widget instance and an area to draw to.
//!
//! The following example renders a block of the size of the terminal:
//!
//! ```rust,no_run
//! use std::io;
//! use termion::raw::IntoRawMode;
//! use tui::Terminal;
//! use tui::backend::TermionBackend;
//! use tui::widgets::{Widget, Block, Borders};
//! use tui::layout::{Layout, Constraint, Direction};
//!
//! fn main() -> Result<(), io::Error> {
//!     let stdout = io::stdout().into_raw_mode()?;
//!     let backend = TermionBackend::new(stdout);
//!     let mut terminal = Terminal::new(backend)?;
//!     terminal.draw(|f| {
//!         let size = f.size();
//!         let block = Block::default()
//!             .title("Block")
//!             .borders(Borders::ALL);
//!         f.render_widget(block, size);
//!     })?;
//!     Ok(())
//! }
//! ```
//!
//! ## Layout
//!
//! The library comes with a basic yet useful layout management object called `Layout`. As you may
//! see below and in the examples, the library makes heavy use of the builder pattern to provide
//! full customization. And `Layout` is no exception:
//!
//! ```rust,no_run
//! use std::io;
//! use termion::raw::IntoRawMode;
//! use tui::Terminal;
//! use tui::backend::TermionBackend;
//! use tui::widgets::{Widget, Block, Borders};
//! use tui::layout::{Layout, Constraint, Direction};
//!
//! fn main() -> Result<(), io::Error> {
//!     let stdout = io::stdout().into_raw_mode()?;
//!     let backend = TermionBackend::new(stdout);
//!     let mut terminal = Terminal::new(backend)?;
//!     terminal.draw(|f| {
//!         let chunks = Layout::default()
//!             .direction(Direction::Vertical)
//!             .margin(1)
//!             .constraints(
//!                 [
//!                     Constraint::Percentage(10),
//!                     Constraint::Percentage(80),
//!                     Constraint::Percentage(10)
//!                 ].as_ref()
//!             )
//!             .split(f.size());
//!         let block = Block::default()
//!              .title("Block")
//!              .borders(Borders::ALL);
//!         f.render_widget(block, chunks[0]);
//!         let block = Block::default()
//!              .title("Block 2")
//!              .borders(Borders::ALL);
//!         f.render_widget(block, chunks[1]);
//!     })?;
//!     Ok(())
//! }
//! ```
//!
//! This let you describe responsive terminal UI by nesting layouts. You should note that by
//! default the computed layout tries to fill the available space completely. So if for any reason
//! you might need a blank space somewhere, try to pass an additional constraint and don't use the
//! corresponding area.

pub mod backend;
pub mod buffer;
pub mod layout;
pub mod style;
pub mod symbols;
pub mod terminal;
pub mod text;
pub mod widgets;

pub use self::terminal::{Frame, Terminal, TerminalOptions, Viewport};
<|endoftext|>


<commit_before>//#![crate_type="dylib"]
#![feature(asm, libc, question_mark)]

#![allow(dead_code)] // yells about consts otherwise
#![allow(unused_variables)]

/// Dryad --- the world's first non-functional, yet-to-be-implemented, might be impossible or more likely inefficient --- parallel, dynamic linker.
/// Many, many thanks to Mutabah, durka42, aatch, tilpner, niconii, bluss, steveklabnik, ubsan and so many others on the IRC channel for answering my stupid questions.

#[cfg(not(feature = "no_color"))]
#[macro_use] extern crate colorify;

#[macro_use] extern crate syscall;

pub extern crate goblin;

#[cfg(target_arch = "x86_64")]
pub use goblin::elf64 as elf;

#[cfg(target_arch = "x86")]
pub use goblin::elf32 as elf;

mod auxv;
mod kernel_block;
#[macro_use] mod utils;
mod image;

mod loader;
mod tls;
pub mod runtime;
pub mod linker;
pub mod gdb;

use kernel_block::KernelBlock;
use linker::Linker;
use utils::*;

extern crate libc;

extern {
    /// ELF abi requires `_start`; this must be in assembly because we need
    /// the raw stack pointer as the argument to `_dryad_init`;
    /// i.e., kernel calls symbol `_start` on dynamic linker with the kernel argument block, etc.,
    /// which in our case then calls _back_ into `dryad_init` with the pointer to the raw arguments that form the kernel block
    /// see `arch/x86/asm.s`
    fn _start();
}

#[no_mangle]
pub extern fn dryad_init (raw_args: *const u64) -> u64 {

    // the linker is currently tied to the lifetime of the kernel block... but really it's static
    let block = KernelBlock::new(raw_args);
    let linker_base = block.getauxval(auxv::AT_BASE).unwrap();
    let entry  = block.getauxval(auxv::AT_ENTRY).unwrap();

    let start_addr = _start as *const u64 as u64;
    if start_addr == entry {
        utils::set_panic();
        // because it's _tradition_
        // (https://fossies.org/dox/glibc-2.22/rtld_8c_source.html)
        // line 786:
        // > Ho ho.  We are not the program interpreter!  We are the program itself!
        println!("-=|dryad====-");
        println!("Ho ho.  We are not the program interpreter!  We are the program itself!");
        let ret = {
            if block.argc >= 2 {
                let binary = str_at(block.argv[1], 0);
                println!("binary: {:?}", binary);
                let elf = elf::Elf::from_path(::std::path::Path::new(binary)).expect(&format!("Cannot load binary {}", binary));
                println!("{:#?}", elf);
                0
            } else {
                println!("usage: dryad <path/to/bin>");
                1
            }
        };
        _exit(ret);
        return 0xd47ad // to make compiler happy
    }

    match Linker::new(linker_base, &block) {
        Ok (dryad) => {
            if let Err(msg) = dryad.link(&block) {
                println!("{}", msg);
                _exit(1);
                0xd47ad
            } else {
                entry
            }
        },
        Err (msg) => {
            // relocating self failed somehow; we try to write the error message and exit
            write(&msg);
            _exit(1);
            0xd47ad
        }
    }
}
<commit_msg>linker: update elf::Elf -> elf::Binary from upstream<commit_after>//#![crate_type="dylib"]
#![feature(asm, libc, question_mark)]

#![allow(dead_code)] // yells about consts otherwise
#![allow(unused_variables)]

/// Dryad --- the world's first non-functional, yet-to-be-implemented, might be impossible or more likely inefficient --- parallel, dynamic linker.
/// Many, many thanks to Mutabah, durka42, aatch, tilpner, niconii, bluss, steveklabnik, ubsan and so many others on the IRC channel for answering my stupid questions.

#[cfg(not(feature = "no_color"))]
#[macro_use] extern crate colorify;

#[macro_use] extern crate syscall;

pub extern crate goblin;

#[cfg(target_arch = "x86_64")]
pub use goblin::elf64 as elf;

#[cfg(target_arch = "x86")]
pub use goblin::elf32 as elf;

mod auxv;
mod kernel_block;
#[macro_use] mod utils;
mod image;

mod loader;
mod tls;
pub mod runtime;
pub mod linker;
pub mod gdb;

use kernel_block::KernelBlock;
use linker::Linker;
use utils::*;

extern crate libc;

extern {
    /// ELF abi requires `_start`; this must be in assembly because we need
    /// the raw stack pointer as the argument to `_dryad_init`;
    /// i.e., kernel calls symbol `_start` on dynamic linker with the kernel argument block, etc.,
    /// which in our case then calls _back_ into `dryad_init` with the pointer to the raw arguments that form the kernel block
    /// see `arch/x86/asm.s`
    fn _start();
}

#[no_mangle]
pub extern fn dryad_init (raw_args: *const u64) -> u64 {

    // the linker is currently tied to the lifetime of the kernel block... but really it's static
    let block = KernelBlock::new(raw_args);
    let linker_base = block.getauxval(auxv::AT_BASE).unwrap();
    let entry  = block.getauxval(auxv::AT_ENTRY).unwrap();

    let start_addr = _start as *const u64 as u64;
    if start_addr == entry {
        utils::set_panic();
        // because it's _tradition_
        // (https://fossies.org/dox/glibc-2.22/rtld_8c_source.html)
        // line 786:
        // > Ho ho.  We are not the program interpreter!  We are the program itself!
        println!("-=|dryad====-");
        println!("Ho ho.  We are not the program interpreter!  We are the program itself!");
        let ret = {
            if block.argc >= 2 {
                let binary = str_at(block.argv[1], 0);
                println!("binary: {:?}", binary);
                let elf = elf::Binary::from_path(::std::path::Path::new(binary)).expect(&format!("Cannot load binary {}", binary));
                println!("{:#?}", elf);
                0
            } else {
                println!("usage: dryad <path/to/bin>");
                1
            }
        };
        _exit(ret);
        return 0xd47ad // to make compiler happy
    }

    match Linker::new(linker_base, &block) {
        Ok (dryad) => {
            if let Err(msg) = dryad.link(&block) {
                println!("{}", msg);
                _exit(1);
                0xd47ad
            } else {
                entry
            }
        },
        Err (msg) => {
            // relocating self failed somehow; we try to write the error message and exit
            write(&msg);
            _exit(1);
            0xd47ad
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//!
//! A library for interning things that are `AsRef<str>`.
//!
//! Some strings may be interned at compile time using the `string-cache-codegen` crate, or the
//! `EmptyStaticAtomSet` may be used that has no compile-time interned strings. An `Atom` is an
//! interned string for a given set (either `EmptyStaticAtomSet` or a generated `StaticAtomSet`).
//!
//! Generated `Atom`s will have assocated macros to intern static strings at compile-time.
//!
//! # Examples
//!
//! Here are two examples, one with compile-time `Atom`s, and one without.
//!
//! ## With compile-time atoms
//!
//! In `Cargo.toml`:
//! ```toml
//! [dependencies]
//! string_cache = "0.8"
//!
//! [dev-dependencies]
//! string_cache_codegen = "0.5"
//! ```
//!
//! In `build.rs`:
//!
//! ```ignore
//! extern crate string_cache_codegen;
//!
//! use std::env;
//! use std::path::Path;
//!
//! fn main() {
//!     string_cache_codegen::AtomType::new("foo::FooAtom", "foo_atom!")
//!         .atoms(&["foo", "bar"])
//!         .write_to_file(&Path::new(&env::var("OUT_DIR").unwrap()).join("foo_atom.rs"))
//!         .unwrap()
//! }
//! ```
//!
//! In `lib.rs`:
//!
//! ```ignore
//! extern crate string_cache;
//!
//! mod foo {
//!     include!(concat!(env!("OUT_DIR"), "/foo_atom.rs"));
//! }
//!
//! fn use_the_atom(t: &str) {
//!     match *t {
//!         foo_atom!("foo") => println!("Found foo!"),
//!         foo_atom!("bar") => println!("Found bar!"),
//!         // foo_atom!("baz") => println!("Found baz!"), - would be a compile time error
//!         _ => {
//!             println!("String not interned");
//!             // We can intern strings at runtime as well
//!             foo::FooAtom::from(t)
//!         }
//!     }
//! }
//! ```
//!
//! ## No compile-time atoms
//!
//! ```
//! # extern crate string_cache;
//! use string_cache::DefaultAtom;
//!
//! # fn main() {
//! let mut interned_stuff = Vec::new();
//! let text = "here is a sentence of text that will be tokenised and
//!             interned and some repeated tokens is of text and";
//! for word in text.split_whitespace() {
//!     let seen_before = interned_stuff.iter()
//!         // We can use impl PartialEq<T> where T is anything string-like
//!         // to compare to interned strings to either other interned strings,
//!         // or actual strings  Comparing two interned strings is very fast
//!         // (normally a single cpu operation).
//!         .filter(|interned_word| interned_word == &word)
//!         .count();
//!     if seen_before > 0 {
//!         println!(r#"Seen the word "{}" {} times"#, word, seen_before);
//!     } else {
//!         println!(r#"Not seen the word "{}" before"#, word);
//!     }
//!     // We use the impl From<(Cow<'a, str>, or &'a str, or String)> for
//!     // Atom<Static> to intern a new string.
//!     interned_stuff.push(DefaultAtom::from(word));
//! }
//! # }
//! ```
//!

#![cfg_attr(test, deny(warnings))]

mod atom;
mod dynamic_set;
mod static_sets;
mod trivial_impls;

pub use atom::Atom;
pub use static_sets::{EmptyStaticAtomSet, PhfStrSet, StaticAtomSet};

/// Use this if you don’t care about static atoms.
pub type DefaultAtom = Atom<EmptyStaticAtomSet>;

// Some minor tests of internal layout here.
// See ../integration-tests for much more.

/// Guard against accidental changes to the sizes of things.
#[test]
fn assert_sizes() {
    use std::mem::size_of;
    assert_eq!(size_of::<DefaultAtom>(), 8);
    assert_eq!(size_of::<Option<DefaultAtom>>(), size_of::<DefaultAtom>(),);
}
<commit_msg>Add a Clippy exception for `derive_hash_xor_eq`<commit_after>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//!
//! A library for interning things that are `AsRef<str>`.
//!
//! Some strings may be interned at compile time using the `string-cache-codegen` crate, or the
//! `EmptyStaticAtomSet` may be used that has no compile-time interned strings. An `Atom` is an
//! interned string for a given set (either `EmptyStaticAtomSet` or a generated `StaticAtomSet`).
//!
//! Generated `Atom`s will have assocated macros to intern static strings at compile-time.
//!
//! # Examples
//!
//! Here are two examples, one with compile-time `Atom`s, and one without.
//!
//! ## With compile-time atoms
//!
//! In `Cargo.toml`:
//! ```toml
//! [dependencies]
//! string_cache = "0.8"
//!
//! [dev-dependencies]
//! string_cache_codegen = "0.5"
//! ```
//!
//! In `build.rs`:
//!
//! ```ignore
//! extern crate string_cache_codegen;
//!
//! use std::env;
//! use std::path::Path;
//!
//! fn main() {
//!     string_cache_codegen::AtomType::new("foo::FooAtom", "foo_atom!")
//!         .atoms(&["foo", "bar"])
//!         .write_to_file(&Path::new(&env::var("OUT_DIR").unwrap()).join("foo_atom.rs"))
//!         .unwrap()
//! }
//! ```
//!
//! In `lib.rs`:
//!
//! ```ignore
//! extern crate string_cache;
//!
//! mod foo {
//!     include!(concat!(env!("OUT_DIR"), "/foo_atom.rs"));
//! }
//!
//! fn use_the_atom(t: &str) {
//!     match *t {
//!         foo_atom!("foo") => println!("Found foo!"),
//!         foo_atom!("bar") => println!("Found bar!"),
//!         // foo_atom!("baz") => println!("Found baz!"), - would be a compile time error
//!         _ => {
//!             println!("String not interned");
//!             // We can intern strings at runtime as well
//!             foo::FooAtom::from(t)
//!         }
//!     }
//! }
//! ```
//!
//! ## No compile-time atoms
//!
//! ```
//! # extern crate string_cache;
//! use string_cache::DefaultAtom;
//!
//! # fn main() {
//! let mut interned_stuff = Vec::new();
//! let text = "here is a sentence of text that will be tokenised and
//!             interned and some repeated tokens is of text and";
//! for word in text.split_whitespace() {
//!     let seen_before = interned_stuff.iter()
//!         // We can use impl PartialEq<T> where T is anything string-like
//!         // to compare to interned strings to either other interned strings,
//!         // or actual strings  Comparing two interned strings is very fast
//!         // (normally a single cpu operation).
//!         .filter(|interned_word| interned_word == &word)
//!         .count();
//!     if seen_before > 0 {
//!         println!(r#"Seen the word "{}" {} times"#, word, seen_before);
//!     } else {
//!         println!(r#"Not seen the word "{}" before"#, word);
//!     }
//!     // We use the impl From<(Cow<'a, str>, or &'a str, or String)> for
//!     // Atom<Static> to intern a new string.
//!     interned_stuff.push(DefaultAtom::from(word));
//! }
//! # }
//! ```
//!

#![cfg_attr(test, deny(warnings))]

// Types, such as Atom, that impl Hash must follow the hash invariant: if two objects match
// with PartialEq, they must also have the same Hash. Clippy warns on types that derive one while
// manually impl-ing the other, because it seems easy for the two to drift apart, causing the
// invariant to be violated.
//
// But Atom is a newtype over NonZeroU64, and probably always will be, since cheap comparisons and
// copying are this library's purpose. So we know what the PartialEq comparison is going to do.
//
// The `get_hash` function, seen in `atom.rs`, consults that number, plus the global string interner
// tables. The only way for the resulting hash for two Atoms with the same inner 64-bit number to
// differ would be if the table entry changed between invocations, and that would be really bad.
#![allow(clippy::derive_hash_xor_eq)]

mod atom;
mod dynamic_set;
mod static_sets;
mod trivial_impls;

pub use atom::Atom;
pub use static_sets::{EmptyStaticAtomSet, PhfStrSet, StaticAtomSet};

/// Use this if you don’t care about static atoms.
pub type DefaultAtom = Atom<EmptyStaticAtomSet>;

// Some minor tests of internal layout here.
// See ../integration-tests for much more.

/// Guard against accidental changes to the sizes of things.
#[test]
fn assert_sizes() {
    use std::mem::size_of;
    assert_eq!(size_of::<DefaultAtom>(), 8);
    assert_eq!(size_of::<Option<DefaultAtom>>(), size_of::<DefaultAtom>(),);
}
<|endoftext|>


<commit_before>//! A [`cargo` subcommand](https://github.com/rust-lang/cargo/wiki/Third-party-cargo-subcommands) for checking and applying updates to installed executables
//!
//! # Library doc
//!
//! This library is used by `cargo-update` itself for all its function and is therefore contains all necessary functions.
//!
//! ## Data flow
//!
//! ```plaintext
//! Options::parse()
//! |> installed_main_repo_packages()
//! |> intersect_packages()
//! |> crates_token()
//! |> MainRepoPackage::pull_version()
//! ```
//!
//! # Executable manpage
//!
//! Exit values and possible errors:
//!
//! ```text
//! 1   - option parsing error
//! 2   - hash lengths differ between selected and saved
//! 3   - failed to parse hashes file
//! N+3 - N files didn't match
//! ```
//!
//! ## SYNOPSIS
//!
//! [`cargo install-update`](https://github.com/nabijaczleweli/cargo-update) [OPTIONS] [PACKAGE...]
//!
//! ## DESCRIPTION
//!
//! Cargo subcommand for checking and applying updates to installed executables.
//!
//! This was mostly built out of a frustration with periodically checking for
//! updates for my cargo-installed executables, which was long and boring.
//!
//! Only updates packages from the main repository.
//!
//! Exit values and possible errors:
//!
//!     -2 - cargo install process was terminated by a signal (Linux-only)
//!     -1 - failed to acquire crates.io auth token
//!     1  - option parsing error
//!     X  - bubbled-up cargo install exit value
//!
//! ## OPTIONS
//!
//! -a --all
//!
//! ```text
//! Update all currently installed executables.
//!
//! Exclusive with list of packages. Required if list of packages not given.
//! ```
//!
//! [PACKAGE...]
//!
//! ```text
//! List of packages to update.
//!
//! Exclusive with --all. Required if --all not given.
//! ```
//!
//! -c --cargo-dir <CARGO_DIR>
//!
//! ```text
//! Set the directory containing cargo metadata.
//!
//! Default: "$HOME/.cargo".
//! ```
//!
//! ## EXAMPLES
//!
//! `cargo install-update -a`
//!
//! ```text
//! Update all installed packages.
//!
//! Example output:
//!   Package         Installed  Latest   Needs update
//!   cargo-count     v0.2.2     v0.2.2   No
//!   cargo-graph     v0.3.0     v0.3.0   No
//!   cargo-outdated  v0.2.0     v0.2.0   No
//!   checksums       v0.5.0     v0.5.2   Yes
//!   identicon       v0.1.1     v0.1.1   No
//!   racer           v1.2.10    v1.2.10  No
//!   rustfmt         v0.6.2     v0.6.2   No
//!   treesize        v0.2.0     v0.2.1   Yes
//!
//!   Updating checksums
//!       Updating registry `https://github.com/rust-lang/crates.io-index`
//!      Downloading checksums v0.5.2
//!      [...]
//!      Compiling checksums v0.5.2
//!       Finished release [optimized] target(s) in 95.2 secs
//!      Replacing D:\Users\nabijaczleweli\.cargo\bin\checksums.exe
//!
//!   Updating treesize
//!       Updating registry `https://github.com/rust-lang/crates.io-index`
//!      Downloading treesize v0.2.1
//!      [...]
//!      Compiling treesize v0.2.1
//!       Finished release [optimized] target(s) in 76.77 secs
//!      Replacing D:\Users\nabijaczleweli\.cargo\bin\treesize.exe
//! ```
//!
//! `cargo install-update` *racer treesize cargo-cln*
//!
//! ```text
//! Only consider racer, treesize and cargo-cln for updates.
//! Since cargo-cln is not installed, it'll be ignored.
//!
//!  Example output:
//!   Package   Installed  Latest   Needs update
//!   racer     v1.2.10    v1.2.10  No
//!   treesize  v0.2.0     v0.2.1   Yes
//!
//!   Updating treesize
//!       Updating registry `https://github.com/rust-lang/crates.io-index`
//!      Downloading treesize v0.2.1
//!      [...]
//!      Compiling treesize v0.2.1
//!       Finished release [optimized] target(s) in 76.77 secs
//!      Replacing D:\Users\nabijaczleweli\.cargo\bin\treesize.exe
//! ```

#[macro_use]
extern crate lazy_static;
extern crate array_tool;
extern crate semver;
extern crate hyper;
extern crate regex;
#[macro_use]
extern crate clap;
extern crate toml;
extern crate json;

mod options;

pub mod ops;

pub use options::Options;
<commit_msg>Blergh, I really should have tried building it<commit_after>//! A [`cargo` subcommand](https://github.com/rust-lang/cargo/wiki/Third-party-cargo-subcommands) for checking and applying updates to installed executables
//!
//! # Library doc
//!
//! This library is used by `cargo-update` itself for all its function and is therefore contains all necessary functions.
//!
//! ## Data flow
//!
//! ```text
//! Options::parse()
//! |> installed_main_repo_packages()
//! |> intersect_packages()
//! |> crates_token()
//! |> MainRepoPackage::pull_version()
//! ```
//!
//! # Executable manpage
//!
//! ## SYNOPSIS
//!
//! [`cargo install-update`](https://github.com/nabijaczleweli/cargo-update) [OPTIONS] [PACKAGE...]
//!
//! ## DESCRIPTION
//!
//! Cargo subcommand for checking and applying updates to installed executables.
//!
//! This was mostly built out of a frustration with periodically checking for
//! updates for my cargo-installed executables, which was long and boring.
//!
//! Only updates packages from the main repository.
//!
//! Exit values and possible errors:
//!
//! ```text
//! -2 - cargo install process was terminated by a signal (Linux-only)
//! -1 - failed to acquire crates.io auth token
//! 1  - option parsing error
//! X  - bubbled-up cargo install exit value
//! ```
//!
//! ## OPTIONS
//!
//! -a --all
//!
//! ```text
//! Update all currently installed executables.
//!
//! Exclusive with list of packages. Required if list of packages not given.
//! ```
//!
//! [PACKAGE...]
//!
//! ```text
//! List of packages to update.
//!
//! Exclusive with --all. Required if --all not given.
//! ```
//!
//! -c --cargo-dir <CARGO_DIR>
//!
//! ```text
//! Set the directory containing cargo metadata.
//!
//! Default: "$HOME/.cargo".
//! ```
//!
//! ## EXAMPLES
//!
//! `cargo install-update -a`
//!
//! ```text
//! Update all installed packages.
//!
//! Example output:
//!   Package         Installed  Latest   Needs update
//!   cargo-count     v0.2.2     v0.2.2   No
//!   cargo-graph     v0.3.0     v0.3.0   No
//!   cargo-outdated  v0.2.0     v0.2.0   No
//!   checksums       v0.5.0     v0.5.2   Yes
//!   identicon       v0.1.1     v0.1.1   No
//!   racer           v1.2.10    v1.2.10  No
//!   rustfmt         v0.6.2     v0.6.2   No
//!   treesize        v0.2.0     v0.2.1   Yes
//!
//!   Updating checksums
//!       Updating registry `https://github.com/rust-lang/crates.io-index`
//!      Downloading checksums v0.5.2
//!      [...]
//!      Compiling checksums v0.5.2
//!       Finished release [optimized] target(s) in 95.2 secs
//!      Replacing D:\Users\nabijaczleweli\.cargo\bin\checksums.exe
//!
//!   Updating treesize
//!       Updating registry `https://github.com/rust-lang/crates.io-index`
//!      Downloading treesize v0.2.1
//!      [...]
//!      Compiling treesize v0.2.1
//!       Finished release [optimized] target(s) in 76.77 secs
//!      Replacing D:\Users\nabijaczleweli\.cargo\bin\treesize.exe
//! ```
//!
//! `cargo install-update` *racer treesize cargo-cln*
//!
//! ```text
//! Only consider racer, treesize and cargo-cln for updates.
//! Since cargo-cln is not installed, it'll be ignored.
//!
//!  Example output:
//!   Package   Installed  Latest   Needs update
//!   racer     v1.2.10    v1.2.10  No
//!   treesize  v0.2.0     v0.2.1   Yes
//!
//!   Updating treesize
//!       Updating registry `https://github.com/rust-lang/crates.io-index`
//!      Downloading treesize v0.2.1
//!      [...]
//!      Compiling treesize v0.2.1
//!       Finished release [optimized] target(s) in 76.77 secs
//!      Replacing D:\Users\nabijaczleweli\.cargo\bin\treesize.exe
//! ```

#[macro_use]
extern crate lazy_static;
extern crate array_tool;
extern crate semver;
extern crate hyper;
extern crate regex;
#[macro_use]
extern crate clap;
extern crate toml;
extern crate json;

mod options;

pub mod ops;

pub use options::Options;
<|endoftext|>


<commit_before>#![crate_type = "lib"]
#![warn(missing_docs)]

//! Synchronization primitives based on spinning

#![cfg_attr(feature = "const_fn", feature(const_fn, const_unsafe_cell_new, const_atomic_usize_new))]

#![no_std]

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

pub use mutex::*;
pub use rw_lock::*;

#[cfg(feature = "once")]
pub use once::*;

mod mutex;
mod rw_lock;

#[cfg(feature = "once")]
mod once;
<commit_msg>Fix compile error on nightly-2018-08-14<commit_after>#![crate_type = "lib"]
#![warn(missing_docs)]

//! Synchronization primitives based on spinning

#![cfg_attr(feature = "const_fn", feature(const_fn))]

#![no_std]

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

pub use mutex::*;
pub use rw_lock::*;

#[cfg(feature = "once")]
pub use once::*;

mod mutex;
mod rw_lock;

#[cfg(feature = "once")]
mod once;
<|endoftext|>


<commit_before>/*!
Simple persistent generic HashMap/Key-value store, using file locking to limit
writing between threads.

This is in a beta state at the moment.

Basic usage:

```
extern crate typedb;

use typedb::{ KV, Value };

fn main() {
    let mut test_store = KV::<String, Value>::new("./db.cab").unwrap();

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    println!("{:?}", test_store.get("key".to_string()));
    let _ = test_store.remove("key".to_string());
}
```

Usage with user defined Key and Value types:

```
#[macro_use]
extern crate typedb;
#[macro_use]
extern crate serde_derive;

use typedb::KV;

key!(MyKey:
    String(String),
    Int(i32),
);

value!(MyValue:
    String(String),
    Int(i32),
);

fn main() {
    let mut test_store = KV::<MyKey, MyValue>::new("./db.cab").unwrap();

    let _ = test_store.insert(MyKey::Int(1i32), MyValue::String("value".to_string()));
    println!("{:?}", test_store.get(MyKey::Int(1i32)));
    let _ = test_store.remove(MyKey::Int(1i32));
}
```

*/

#![deny(missing_docs)]

extern crate bincode;
#[macro_use]
extern crate log;
extern crate persy;
extern crate serde;
#[macro_use]
extern crate serde_derive;

/// Macros for simplifying custom key and value types definition
pub mod macros;

use std::collections::HashMap;
use std::hash::Hash;

use bincode::{deserialize, serialize};
use serde::ser::Serialize;
use serde::de::Deserialize;

use persy::{Config, PRes, Persy, PersyError};

/// A default value type to use with KV
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
pub enum Value {
    /// Cab default Value type for strings
    String(String),
    /// Cab default Value type for intergers
    Int(i32),
    /// Cab default Value type for floats
    Float(f32),
    /// Cab default Value type for a sub map
    Map(HashMap<String, Value>),
    /// Cab default Value type for list
    List(Vec<Value>),
}

/// Type alias for results from KV
type KVResult = PRes<bool>;

/// Type alias for PersyError
type KVError = PersyError;

/// The type that represents the key-value store
pub struct KV<K, V> {
    cab: HashMap<K, V>,
    persy: Persy,
}

impl<K, V> KV<K, V>
where
    K: Clone + Serialize + for<'kde> Deserialize<'kde> + Eq + Hash,
    V: Clone + Serialize + for<'vde> Deserialize<'vde>,
{
    /// Creates a new instance of the KV store
    pub fn new(p: &'static str) -> Result<KV<K, V>, PersyError> {
        // create the KV instance
        Persy::create(p)?;
        let persy = Persy::open(p, Config::new())?;

        let mut store = KV {
            cab: HashMap::new(),
            persy: persy,
        };

        match store.load_from_persist() {
            Ok(f) => trace!("{}", f),
            Err(e) => {
                return Err(e);
            }
        };

        Ok(store)
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: K, value: V) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: K) -> Result<Option<V>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // get the value from the cab
        match self.cab.get(&key) {
            Some(v) => Ok(Some((*v).clone())),
            None => Ok(None),
        }
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: K) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Result<Vec<K>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // create a vec from the cabs keys
        Ok(self.cab.keys().map(|k| k.clone()).collect())
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        // attempt to write to the cab
        let mut tx = self.persy.begin()?;
        // if the segment doesn't exist create
        // TODO poss move to db creation
        if !self.persy.exists_segment("tdb")? {
            self.persy.create_segment(&mut tx, "tdb")?;
        }

        // serialize the cab as a u8 vec
        let byte_vec: Vec<u8> = match serialize(&mut self.cab) {
            Ok(bv) => bv,
            Err(e) => {
                error!("serialize: {}", e);
                return Err(PersyError::Err("Couldn't encode".to_string()));
            }
        };

        self.persy.insert_record(&mut tx, "tdb", &byte_vec)?;

        let prepared = self.persy.prepare_commit(tx)?;
        self.persy.commit(prepared)?;

        Ok(true)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self) -> KVResult {
        if self.persy.exists_segment("tdb")? {
            for rec in self.persy.scan_records("tdb")? {
                let byte_vec = rec.content;
                // deserialize u8 vec back into HashMap
                match deserialize(byte_vec.as_slice()) {
                    Ok(f) => {
                        // assign read HashMap back to self
                        self.cab = f;
                    }
                    Err(e) => {
                        error!("{}", e);
                        continue;
                    }
                };
            }
        }

        Ok(true)
    }
}
<commit_msg>Don't panic when file already exists<commit_after>/*!
Simple persistent generic HashMap/Key-value store, using file locking to limit
writing between threads.

This is in a beta state at the moment.

Basic usage:

```
extern crate typedb;

use typedb::{ KV, Value };

fn main() {
    let mut test_store = KV::<String, Value>::new("./db.cab").unwrap();

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    println!("{:?}", test_store.get("key".to_string()));
    let _ = test_store.remove("key".to_string());
}
```

Usage with user defined Key and Value types:

```
#[macro_use]
extern crate typedb;
#[macro_use]
extern crate serde_derive;

use typedb::KV;

key!(MyKey:
    String(String),
    Int(i32),
);

value!(MyValue:
    String(String),
    Int(i32),
);

fn main() {
    let mut test_store = KV::<MyKey, MyValue>::new("./db.cab").unwrap();

    let _ = test_store.insert(MyKey::Int(1i32), MyValue::String("value".to_string()));
    println!("{:?}", test_store.get(MyKey::Int(1i32)));
    let _ = test_store.remove(MyKey::Int(1i32));
}
```

*/

#![deny(missing_docs)]

extern crate bincode;
#[macro_use]
extern crate log;
extern crate persy;
extern crate serde;
#[macro_use]
extern crate serde_derive;

/// Macros for simplifying custom key and value types definition
pub mod macros;

use std::collections::HashMap;
use std::hash::Hash;
use std::io::ErrorKind;

use bincode::{deserialize, serialize};
use serde::ser::Serialize;
use serde::de::Deserialize;

use persy::{Config, PRes, Persy, PersyError};

/// A default value type to use with KV
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
pub enum Value {
    /// Cab default Value type for strings
    String(String),
    /// Cab default Value type for intergers
    Int(i32),
    /// Cab default Value type for floats
    Float(f32),
    /// Cab default Value type for a sub map
    Map(HashMap<String, Value>),
    /// Cab default Value type for list
    List(Vec<Value>),
}

/// Type alias for results from KV
type KVResult = PRes<bool>;

/// Type alias for PersyError
type KVError = PersyError;

/// The type that represents the key-value store
pub struct KV<K, V> {
    cab: HashMap<K, V>,
    persy: Persy,
}

impl<K, V> KV<K, V>
where
    K: Clone + Serialize + for<'kde> Deserialize<'kde> + Eq + Hash,
    V: Clone + Serialize + for<'vde> Deserialize<'vde>,
{
    /// Creates a new instance of the KV store
    pub fn new(p: &'static str) -> Result<KV<K, V>, PersyError> {
        // create the KV instance
        match Persy::create(p) {
            Ok(o) => o,
            Err(PersyError::IO(ref e)) if e.kind() == ErrorKind::AlreadyExists => (),
            Err(e) => return Err(e),
        }
        let persy = Persy::open(p, Config::new())?;

        let mut store = KV {
            cab: HashMap::new(),
            persy: persy,
        };

        match store.load_from_persist() {
            Ok(f) => trace!("{}", f),
            Err(e) => {
                return Err(e);
            }
        };

        Ok(store)
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: K, value: V) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: K) -> Result<Option<V>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // get the value from the cab
        match self.cab.get(&key) {
            Some(v) => Ok(Some((*v).clone())),
            None => Ok(None),
        }
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: K) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Result<Vec<K>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // create a vec from the cabs keys
        Ok(self.cab.keys().map(|k| k.clone()).collect())
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        // attempt to write to the cab
        let mut tx = self.persy.begin()?;
        // if the segment doesn't exist create
        // TODO poss move to db creation
        if !self.persy.exists_segment("tdb")? {
            self.persy.create_segment(&mut tx, "tdb")?;
        }

        // serialize the cab as a u8 vec
        let byte_vec: Vec<u8> = match serialize(&mut self.cab) {
            Ok(bv) => bv,
            Err(e) => {
                error!("serialize: {}", e);
                return Err(PersyError::Err("Couldn't encode".to_string()));
            }
        };

        self.persy.insert_record(&mut tx, "tdb", &byte_vec)?;

        let prepared = self.persy.prepare_commit(tx)?;
        self.persy.commit(prepared)?;

        Ok(true)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self) -> KVResult {
        if self.persy.exists_segment("tdb")? {
            for rec in self.persy.scan_records("tdb")? {
                let byte_vec = rec.content;
                // deserialize u8 vec back into HashMap
                match deserialize(byte_vec.as_slice()) {
                    Ok(f) => {
                        // assign read HashMap back to self
                        self.cab = f;
                    }
                    Err(e) => {
                        error!("{}", e);
                        continue;
                    }
                };
            }
        }

        Ok(true)
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate secur32;
extern crate winapi;

use libc::c_ulong;
use secur32::{AcquireCredentialsHandleA, FreeCredentialsHandle, InitializeSecurityContextW,
              DeleteSecurityContext, FreeContextBuffer};
use std::error;
use std::fmt;
use std::io;
use std::mem;
use std::ops::Deref;
use std::ptr;
use std::result;
use std::slice;
use winapi::{CredHandle, SECURITY_STATUS, SCHANNEL_CRED, SCHANNEL_CRED_VERSION, UNISP_NAME,
             SECPKG_CRED_OUTBOUND, SECPKG_CRED_INBOUND, SEC_E_OK, CtxtHandle,
             ISC_REQ_CONFIDENTIALITY, ISC_REQ_INTEGRITY, ISC_REQ_REPLAY_DETECT,
             ISC_REQ_SEQUENCE_DETECT, ISC_REQ_ALLOCATE_MEMORY, ISC_REQ_STREAM, SecBuffer,
             SECBUFFER_EMPTY, SECBUFFER_TOKEN, SecBufferDesc, SECBUFFER_VERSION,
             SEC_I_CONTINUE_NEEDED};

pub type Result<T> = result::Result<T, Error>;

pub struct Error(SECURITY_STATUS);

impl fmt::Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_tuple("Error")
           .field(&format_args!("{:#x}", self.0))
           .finish()
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            n => write!(fmt, "unknown error {:#x}", n)
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        "an SChannel error"
    }
}

pub enum Direction {
    Inbound,
    Outbound,
}

pub struct SchannelCredBuilder(());

impl SchannelCredBuilder {
    pub fn new() -> SchannelCredBuilder {
        SchannelCredBuilder(())
    }

    pub fn acquire(&self, direction: Direction) -> Result<SchannelCred> {
        unsafe {
            let mut handle = mem::uninitialized();
            let mut cred_data: SCHANNEL_CRED = mem::zeroed();
            cred_data.dwVersion = SCHANNEL_CRED_VERSION;

            let direction = match direction {
                Direction::Inbound => SECPKG_CRED_INBOUND,
                Direction::Outbound => SECPKG_CRED_OUTBOUND,
            };

            let status = AcquireCredentialsHandleA(ptr::null_mut(),
                                                   UNISP_NAME.as_ptr() as *mut _,
                                                   direction,
                                                   ptr::null_mut(),
                                                   &mut cred_data as *mut _ as *mut _,
                                                   None,
                                                   ptr::null_mut(),
                                                   &mut handle,
                                                   ptr::null_mut());

            if status == SEC_E_OK {
                Ok(SchannelCred(handle))
            } else {
                Err(Error(status))
            }
        }
    }
}

pub struct SchannelCred(CredHandle);

impl Drop for SchannelCred {
    fn drop(&mut self) {
        unsafe { FreeCredentialsHandle(&mut self.0); }
    }
}

#[derive(Default)]
pub struct TlsStreamBuilder {
    domain: Option<Vec<u16>>,
}

impl TlsStreamBuilder {
    pub fn new() -> TlsStreamBuilder {
        TlsStreamBuilder::default()
    }

    pub fn domain(&mut self, domain: &str) -> &mut TlsStreamBuilder {
        self.domain = Some(domain.encode_utf16().chain(Some(0)).collect());
        self
    }

    pub fn initialize<S>(&self, cred: &SchannelCred, mut stream: S) -> io::Result<TlsStream<S>>
        where S: io::Read + io::Write
    {
        let domain = self.domain.as_ref().map(|d| &d[..]);
        let (ctxt, buf) = try!(SecurityContext::initialize_new(cred, domain)
                                   .map_err(|e| io::Error::new(io::ErrorKind::Other, e)));

        try!(stream.write_all(&buf));
        drop(buf);
        try!(stream.flush());

        panic!();
    }
}

struct SecurityContext(CtxtHandle);

impl SecurityContext {
    fn initialize_new(cred: &SchannelCred,
                      domain: Option<&[u16]>)
                      -> Result<(SecurityContext, ContextBuffer)> {
        unsafe {
            let domain = domain.map(|b| b.as_ptr() as *mut u16).unwrap_or(ptr::null_mut());

            let requests = ISC_REQ_CONFIDENTIALITY |
                ISC_REQ_INTEGRITY |
                ISC_REQ_REPLAY_DETECT |
                ISC_REQ_SEQUENCE_DETECT |
                ISC_REQ_ALLOCATE_MEMORY |
                ISC_REQ_STREAM;

            let mut ctxt = mem::uninitialized();

            let mut outbuf = SecBuffer {
                cbBuffer: 0,
                BufferType: SECBUFFER_EMPTY,
                pvBuffer: ptr::null_mut(),
            };
            let mut outbuf_desc = SecBufferDesc {
                ulVersion: SECBUFFER_VERSION,
                cBuffers: 1,
                pBuffers: &mut outbuf,
            };

            let mut attributes = 0;

            let status = InitializeSecurityContextW(&cred.0 as *const _ as *mut _,
                                                    ptr::null_mut(),
                                                    domain,
                                                    requests,
                                                    0,
                                                    0,
                                                    ptr::null_mut(),
                                                    0,
                                                    &mut ctxt,
                                                    &mut outbuf_desc,
                                                    &mut attributes,
                                                    ptr::null_mut());
            if status != SEC_I_CONTINUE_NEEDED {
                return Err(Error(status));
            }

            Ok((SecurityContext(ctxt), ContextBuffer(outbuf)))
        }
    }
}

impl Drop for SecurityContext {
    fn drop(&mut self) {
        unsafe { DeleteSecurityContext(&mut self.0); }
    }
}

struct ContextBuffer(SecBuffer);

impl Drop for ContextBuffer {
    fn drop(&mut self) {
        unsafe { FreeContextBuffer(self.0.pvBuffer); }
    }
}

impl Deref for ContextBuffer {
    type Target = [u8];

    fn deref(&self) -> &[u8] {
        unsafe { slice::from_raw_parts(self.0.pvBuffer as *const _, self.0.cbBuffer as usize) }
    }
}

pub struct TlsStream<S> {
    stream: S,
    context: SecurityContext,
}

impl<S> TlsStream<S>
    where S: io::Read + io::Write
{
    pub fn get_ref(&self) -> &S {
        &self.stream
    }

    pub fn get_mut(&mut self) -> &mut S {
        &mut self.stream
    }
}

#[cfg(test)]
mod test {
    use std::net::TcpStream;

    use super::*;

    #[test]
    fn basic() {
        let creds = SchannelCredBuilder::new().acquire(Direction::Outbound).unwrap();
        let stream = TcpStream::connect("google.com:443").unwrap();
        let stream = TlsStreamBuilder::new()
                         .domain("google.com")
                         .initialize(&creds, stream)
                         .unwrap();
    }
}<commit_msg>Restructure<commit_after>extern crate libc;
extern crate secur32;
extern crate winapi;

use libc::c_ulong;
use secur32::{AcquireCredentialsHandleA, FreeCredentialsHandle, InitializeSecurityContextW,
              DeleteSecurityContext, FreeContextBuffer};
use std::error;
use std::fmt;
use std::io::{self, Read, Write, Cursor};
use std::mem;
use std::ops::Deref;
use std::ptr;
use std::result;
use std::slice;
use winapi::{CredHandle, SECURITY_STATUS, SCHANNEL_CRED, SCHANNEL_CRED_VERSION, UNISP_NAME,
             SECPKG_CRED_OUTBOUND, SECPKG_CRED_INBOUND, SEC_E_OK, CtxtHandle,
             ISC_REQ_CONFIDENTIALITY, ISC_REQ_INTEGRITY, ISC_REQ_REPLAY_DETECT,
             ISC_REQ_SEQUENCE_DETECT, ISC_REQ_ALLOCATE_MEMORY, ISC_REQ_STREAM, SecBuffer,
             SECBUFFER_EMPTY, SECBUFFER_TOKEN, SecBufferDesc, SECBUFFER_VERSION,
             SEC_I_CONTINUE_NEEDED};

const MAX_RECORD_SIZE: usize = 16 * 1024;

const INIT_REQUESTS: c_ulong = ISC_REQ_CONFIDENTIALITY |
                ISC_REQ_INTEGRITY |
                ISC_REQ_REPLAY_DETECT |
                ISC_REQ_SEQUENCE_DETECT |
                ISC_REQ_ALLOCATE_MEMORY |
                ISC_REQ_STREAM;

pub type Result<T> = result::Result<T, Error>;

pub struct Error(SECURITY_STATUS);

impl fmt::Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_tuple("Error")
           .field(&format_args!("{:#x}", self.0))
           .finish()
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            n => write!(fmt, "unknown error {:#x}", n)
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        "an SChannel error"
    }
}

pub enum Direction {
    Inbound,
    Outbound,
}

pub struct SchannelCredBuilder(());

impl SchannelCredBuilder {
    pub fn new() -> SchannelCredBuilder {
        SchannelCredBuilder(())
    }

    pub fn acquire(&self, direction: Direction) -> Result<SchannelCred> {
        unsafe {
            let mut handle = mem::uninitialized();
            let mut cred_data: SCHANNEL_CRED = mem::zeroed();
            cred_data.dwVersion = SCHANNEL_CRED_VERSION;

            let direction = match direction {
                Direction::Inbound => SECPKG_CRED_INBOUND,
                Direction::Outbound => SECPKG_CRED_OUTBOUND,
            };

            let status = AcquireCredentialsHandleA(ptr::null_mut(),
                                                   UNISP_NAME.as_ptr() as *mut _,
                                                   direction,
                                                   ptr::null_mut(),
                                                   &mut cred_data as *mut _ as *mut _,
                                                   None,
                                                   ptr::null_mut(),
                                                   &mut handle,
                                                   ptr::null_mut());

            if status == SEC_E_OK {
                Ok(SchannelCred(handle))
            } else {
                Err(Error(status))
            }
        }
    }
}

pub struct SchannelCred(CredHandle);

impl Drop for SchannelCred {
    fn drop(&mut self) {
        unsafe { FreeCredentialsHandle(&mut self.0); }
    }
}

#[derive(Default)]
pub struct TlsStreamBuilder {
    domain: Option<Vec<u16>>,
}

impl TlsStreamBuilder {
    pub fn new() -> TlsStreamBuilder {
        TlsStreamBuilder::default()
    }

    pub fn domain(&mut self, domain: &str) -> &mut TlsStreamBuilder {
        self.domain = Some(domain.encode_utf16().chain(Some(0)).collect());
        self
    }

    pub fn initialize<S>(&self, cred: SchannelCred, mut stream: S) -> io::Result<TlsStream<S>>
        where S: Read + Write
    {
        let (ctxt, buf) = try!(SecurityContext::initialize(&cred,
                                                           self.domain.as_ref().map(|s| &s[..]))
                                   .map_err(|e| io::Error::new(io::ErrorKind::Other, e)));

        let mut stream = TlsStream {
            cred: cred,
            context: ctxt,
            domain: self.domain.clone(),
            stream: stream,
            state: State::Initializing,
            plaintext_in_buf: Cursor::new(Vec::with_capacity(MAX_RECORD_SIZE)),
            encrypted_in_buf: Vec::with_capacity(MAX_RECORD_SIZE),
            plaintext_out_buf: Cursor::new(Vec::with_capacity(MAX_RECORD_SIZE)),
            encrypted_out_buf: Cursor::new(Vec::with_capacity(MAX_RECORD_SIZE)),
        };

        stream.encrypted_out_buf.get_mut().extend_from_slice(&buf);

        Ok(stream)
    }
}

struct SecurityContext(CtxtHandle);

impl SecurityContext {
    fn initialize(cred: &SchannelCred,
                  domain: Option<&[u16]>)
                  -> Result<(SecurityContext, ContextBuffer)> {
        unsafe {
            let domain = domain.map(|b| b.as_ptr() as *mut u16).unwrap_or(ptr::null_mut());

            let mut ctxt = mem::uninitialized();

            let mut outbuf = SecBuffer {
                cbBuffer: 0,
                BufferType: SECBUFFER_EMPTY,
                pvBuffer: ptr::null_mut(),
            };
            let mut outbuf_desc = SecBufferDesc {
                ulVersion: SECBUFFER_VERSION,
                cBuffers: 1,
                pBuffers: &mut outbuf,
            };

            let mut attributes = 0;

            let status = InitializeSecurityContextW(&cred.0 as *const _ as *mut _,
                                                    ptr::null_mut(),
                                                    domain,
                                                    INIT_REQUESTS,
                                                    0,
                                                    0,
                                                    ptr::null_mut(),
                                                    0,
                                                    &mut ctxt,
                                                    &mut outbuf_desc,
                                                    &mut attributes,
                                                    ptr::null_mut());
            if status != SEC_I_CONTINUE_NEEDED {
                return Err(Error(status));
            }

            Ok((SecurityContext(ctxt), ContextBuffer(outbuf)))
        }
    }
}

impl Drop for SecurityContext {
    fn drop(&mut self) {
        unsafe { DeleteSecurityContext(&mut self.0); }
    }
}

struct ContextBuffer(SecBuffer);

impl Drop for ContextBuffer {
    fn drop(&mut self) {
        unsafe { FreeContextBuffer(self.0.pvBuffer); }
    }
}

impl Deref for ContextBuffer {
    type Target = [u8];

    fn deref(&self) -> &[u8] {
        unsafe { slice::from_raw_parts(self.0.pvBuffer as *const _, self.0.cbBuffer as usize) }
    }
}

enum State {
    Initializing,
    Streaming,
}

pub struct TlsStream<S> {
    cred: SchannelCred,
    context: SecurityContext,
    domain: Option<Vec<u16>>,
    stream: S,
    state: State,
    plaintext_in_buf: Cursor<Vec<u8>>,
    encrypted_in_buf: Vec<u8>,
    plaintext_out_buf: Cursor<Vec<u8>>,
    encrypted_out_buf: Cursor<Vec<u8>>,
}

impl<S> TlsStream<S>
    where S: Read + Write
{
    pub fn get_ref(&self) -> &S {
        &self.stream
    }

    pub fn get_mut(&mut self) -> &mut S {
        &mut self.stream
    }
}

#[cfg(test)]
mod test {
    use std::net::TcpStream;

    use super::*;

    #[test]
    fn basic() {
        let creds = SchannelCredBuilder::new().acquire(Direction::Outbound).unwrap();
        let stream = TcpStream::connect("google.com:443").unwrap();
        let stream = TlsStreamBuilder::new()
                         .domain("google.com")
                         .initialize(creds, stream)
                         .unwrap();
    }
}<|endoftext|>


<commit_before>// Compiling for the web requires some extra modules
#[macro_use] extern crate nom;
#[macro_use] extern crate serde_derive;

extern crate serde_json;
extern crate serde;

pub mod arg;
pub mod output;
pub mod parser;
pub mod step;

#[derive(Serialize, Deserialize)]
struct OutputError {
    error: String,
}

use std::mem;
use std::ffi::{CString, CStr};
use std::os::raw::{c_char, c_void};
use parser::parse_p;

// In order to work with the memory we expose (de)allocation methods
#[no_mangle]
pub extern "C" fn alloc(size: usize) -> *mut c_void {
    let mut buf = Vec::with_capacity(size);
    let ptr = buf.as_mut_ptr();
    mem::forget(buf);
    return ptr as *mut c_void;
}

#[no_mangle]
pub extern "C" fn dealloc_str(ptr: *mut c_char) {
    unsafe {
        let _ = CString::from_raw(ptr);
    }
}

#[no_mangle]
pub extern "C" fn dealloc(ptr: *mut c_void, cap: usize) {
    unsafe  {
        let _buf = Vec::from_raw_parts(ptr, 0, cap);
    }
}

/// Run input and return a typed array for use in javascript
#[no_mangle]
pub extern "C" fn parse(raw_input: *mut c_char) -> *mut c_char {
    // Parse the input
    let input = safe_string(raw_input);

    let prog = parse_p(input.as_slice());

    // Parse the macro
    if prog.is_err() {
        // Push the error
        let error = prog.unwrap_err();
        let output_error = OutputError {
            error: format!("{:?}", error),
        };
        let json = serde_json::to_string(&output_error).unwrap();

        CString::new(json).unwrap().into_raw()
    } else {
        let (_, program) = prog.unwrap();

        // Return as JSON
        let json = serde_json::to_string(&program).unwrap();
        CString::new(json).unwrap().into_raw()
    }
}

fn safe_string(input: *mut c_char) -> Vec<u8> {
    unsafe {
        CStr::from_ptr(input).to_bytes().to_owned()
    }
}
<commit_msg>alpha return parser error<commit_after>// Compiling for the web requires some extra modules
#[macro_use] extern crate nom;
#[macro_use] extern crate serde_derive;

extern crate serde_json;
extern crate serde;

pub mod arg;
pub mod output;
pub mod parser;
pub mod step;

use nom::Err::Error;
use nom::simple_errors::Context::Code;

#[derive(Debug, Serialize, Deserialize)]
struct OutputError {
    error: String,
    context: String,
}

use std::mem;
use std::ffi::{CString, CStr};
use std::os::raw::{c_char, c_void};
use parser::parse_p;

// In order to work with the memory we expose (de)allocation methods
#[no_mangle]
pub extern "C" fn alloc(size: usize) -> *mut c_void {
    let mut buf = Vec::with_capacity(size);
    let ptr = buf.as_mut_ptr();
    mem::forget(buf);
    return ptr as *mut c_void;
}

#[no_mangle]
pub extern "C" fn dealloc_str(ptr: *mut c_char) {
    unsafe {
        let _ = CString::from_raw(ptr);
    }
}

#[no_mangle]
pub extern "C" fn dealloc(ptr: *mut c_void, cap: usize) {
    unsafe  {
        let _buf = Vec::from_raw_parts(ptr, 0, cap);
    }
}

/// Run input and return a typed array for use in javascript
#[no_mangle]
pub extern "C" fn parse(raw_input: *mut c_char) -> *mut c_char {
    // covert the input
    let input = safe_string(raw_input);

    // run the parser
    let json = run(input);

    // return the result
    CString::new(json).unwrap().into_raw()
}

/// Run the internal parser and return a program or error
fn run (input: Vec<u8>) -> String {
    let prog = parse_p(input.as_slice());
    if prog.is_err() {
        // Push the error
        let error = prog.unwrap_err();

        let mut output_error = OutputError {
            error: format!("{:?}", error),
            context: "".to_string(),
        };

        if let Error(Code(list, _code)) = error {
            let context = String::from_utf8(list.to_vec()).unwrap();
            output_error.context = context;
        }

        // return error JSON
        serde_json::to_string(&output_error).unwrap()
    } else {
        let (_, program) = prog.unwrap();

        // return success JSON
        serde_json::to_string(&program).unwrap()
    }
}

fn safe_string(input: *mut c_char) -> Vec<u8> {
    unsafe {
        CStr::from_ptr(input).to_bytes().to_owned()
    }
}

#[test]
fn test_error_handling() {
    // missing ending single quotation
    let input: Vec<u8> = "#test !prompt test [ok, not 'ok]".as_bytes().to_vec();
    let result = run(input);

    let json: OutputError = serde_json::from_str(&result).unwrap();
    assert_eq!(json.context, "[ok, not 'ok]".to_string());

    // missing prompt input
    let input: Vec<u8> = "#test !prompt [test, tester, testest]".as_bytes().to_vec();
    let result = run(input);

    let json: OutputError = serde_json::from_str(&result).unwrap();
    assert_eq!(json.context, "[test, tester, testest]".to_string());
}
<|endoftext|>