<commit_before>//! # aHash
//!
//! This hashing algorithm is intended to be a high performance, (hardware specific), keyed hash function.
//! This can be seen as a DOS resistant alternative to `FxHash`, or a fast equivalent to `SipHash`.
//! It provides a high speed hash algorithm, but where the result is not predictable without knowing a Key.
//! This allows it to be used in a `HashMap` without allowing for the possibility that an malicious user can
//! induce a collision.
//!
//! # How aHash works
//!
//! aHash uses the hardware AES instruction on x86 processors to provide a keyed hash function.
//! It uses two rounds of AES per hash. So it should not be considered cryptographically secure.
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
//#![feature(core_intrinsics)]
extern crate const_random;

#[macro_use]
mod convert;

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
mod aes_hash;
mod fallback_hash;
#[cfg(test)]
mod hash_quality_test;

#[cfg(feature = "std")]
mod hash_map;
#[cfg(feature = "std")]
mod hash_set;

#[cfg(feature = "compile-time-rng")]
use const_random::const_random;

use core::hash::BuildHasher;
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::Ordering;

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
pub use crate::aes_hash::AHasher;

#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
pub use crate::fallback_hash::AHasher;

#[cfg(feature = "std")]
pub use crate::hash_map::AHashMap;
#[cfg(feature = "std")]
pub use crate::hash_set::AHashSet;

///This constant come from Kunth's prng
const MULTIPLE: u64 = 6364136223846793005;

// Const random provides randomized starting key with no runtime cost.
#[cfg(feature = "compile-time-rng")]
static SEED: AtomicUsize = AtomicUsize::new(const_random!(u64));

#[cfg(not(feature = "compile-time-rng"))]
static SEED: AtomicUsize = AtomicUsize::new(MULTIPLE as usize);

/// Provides a default [Hasher] compile time generated constants for keys.
/// This is typically used in conjunction with [`BuildHasherDefault`] to create
/// [AHasher]s in order to hash the keys of the map.
///
/// # Example
/// ```
/// use std::hash::BuildHasherDefault;
/// use ahash::{AHasher, ABuildHasher};
/// use std::collections::HashMap;
///
/// let mut map: HashMap<i32, i32, ABuildHasher> = HashMap::default();
/// map.insert(12, 34);
/// ```
///
/// [BuildHasherDefault]: std::hash::BuildHasherDefault
/// [Hasher]: std::hash::Hasher
/// [HashMap]: std::collections::HashMap
#[cfg(feature = "compile-time-rng")]
impl Default for AHasher {
    /// Constructs a new [AHasher] with compile time generated constants for keys.
    /// This means the keys will be the same from one instance to another,
    /// but different from build to the next. So if it is possible for a potential
    /// attacker to have access to the compiled binary it would be better
    /// to specify keys generated at runtime.
    ///
    /// This is defined only if the `compile-time-rng` feature is enabled.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::AHasher;
    /// use std::hash::Hasher;
    ///
    /// let mut hasher_1 = AHasher::default();
    /// let mut hasher_2 = AHasher::default();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    /// ```
    #[inline]
    fn default() -> AHasher {
        AHasher::new_with_keys(const_random!(u64), const_random!(u64))
    }
}

/// Provides a [Hasher] factory. This is typically used (e.g. by [`HashMap`]) to create
/// [AHasher]s in order to hash the keys of the map. See `build_hasher` below.
///
/// [build_hasher]: ahash::
/// [Hasher]: std::hash::Hasher
/// [BuildHasher]: std::hash::BuildHasher
/// [HashMap]: std::collections::HashMap
#[derive(Clone)]
pub struct ABuildHasher {
    k0: u64,
    k1: u64,
}

impl ABuildHasher {
    #[inline]
    pub fn new() -> ABuildHasher {
        //Using a self pointer. When running with ASLR this is a random value.
        let previous = SEED.load(Ordering::Relaxed) as u64;
        let stack_mem_loc = &previous as *const _ as u64;
        //This is similar to the update function in the fallback.
        //only one multiply is needed because memory locations are not under an attackers control.
        let current_seed = previous.wrapping_mul(MULTIPLE).wrapping_add(stack_mem_loc).rotate_left(31);
        SEED.store(current_seed as usize, Ordering::Relaxed);
        return ABuildHasher {
            k0: &SEED as *const _ as u64,
            k1: current_seed
        };
    }
}

impl Default for ABuildHasher {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl BuildHasher for ABuildHasher {
    type Hasher = AHasher;

    /// Constructs a new [AHasher] with keys based on compile time generated constants** and the location
    /// of the this object in memory. This means that two different [BuildHasher]s will will generate
    /// [AHasher]s that will return different hashcodes, but [Hasher]s created from the same [BuildHasher]
    /// will generate the same hashes for the same input data.
    ///
    /// ** - only if the `compile-time-rng` feature is enabled.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::{AHasher, ABuildHasher};
    /// use std::hash::{Hasher, BuildHasher};
    ///
    /// let build_hasher = ABuildHasher::new();
    /// let mut hasher_1 = build_hasher.build_hasher();
    /// let mut hasher_2 = build_hasher.build_hasher();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    ///
    /// let other_build_hasher = ABuildHasher::new();
    /// let mut different_hasher = other_build_hasher.build_hasher();
    /// different_hasher.write_u32(1234);
    /// assert_ne!(different_hasher.finish(), hasher_1.finish());
    /// ```
    /// [Hasher]: std::hash::Hasher
    /// [BuildHasher]: std::hash::BuildHasher
    /// [HashMap]: std::collections::HashMap
    #[inline]
    fn build_hasher(&self) -> AHasher {
        let (k0, k1) = scramble_keys(self.k0, self.k1);
        return AHasher::new_with_keys(k0, k1);
    }
}

pub(crate) fn scramble_keys(k0: u64, k1: u64) -> (u64, u64) {
    //Scramble seeds (based on xoroshiro128+)
    //This is intentionally not similar the hash algorithm
    let result1 = k0.wrapping_add(k1);
    let k1 = k1 ^ k0;
    let k0 = k0.rotate_left(24) ^ k1 ^ (k1.wrapping_shl(16));
    let result2 = k0.wrapping_add(k1.rotate_left(37));
    return (result2, result1);
}

#[cfg(test)]
mod test {
    use crate::convert::Convert;
    use crate::*;
    use core::hash::BuildHasherDefault;
    use std::collections::HashMap;

    #[test]
    fn test_default_builder() {
        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }
    #[test]
    fn test_builder() {
        let mut map = HashMap::<u32, u64, ABuildHasher>::default();
        map.insert(1, 3);
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }

    #[test]
    fn test_ahasher_construction() {
        let _ = AHasher::new_with_keys(1245, 5678);
    }
}
<commit_msg>Configure lints<commit_after>//! # aHash
//!
//! This hashing algorithm is intended to be a high performance, (hardware specific), keyed hash function.
//! This can be seen as a DOS resistant alternative to `FxHash`, or a fast equivalent to `SipHash`.
//! It provides a high speed hash algorithm, but where the result is not predictable without knowing a Key.
//! This allows it to be used in a `HashMap` without allowing for the possibility that an malicious user can
//! induce a collision.
//!
//! # How aHash works
//!
//! aHash uses the hardware AES instruction on x86 processors to provide a keyed hash function.
//! It uses two rounds of AES per hash. So it should not be considered cryptographically secure.
#![deny(clippy::correctness, clippy::complexity, clippy::perf)]
#![allow(clippy::pedantic, clippy::cast_lossless, clippy::unreadable_literal)]

#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
extern crate const_random;

#[macro_use]
mod convert;

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
mod aes_hash;
mod fallback_hash;
#[cfg(test)]
mod hash_quality_test;

#[cfg(feature = "std")]
mod hash_map;
#[cfg(feature = "std")]
mod hash_set;

#[cfg(feature = "compile-time-rng")]
use const_random::const_random;

use core::hash::BuildHasher;
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::Ordering;

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
pub use crate::aes_hash::AHasher;

#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
pub use crate::fallback_hash::AHasher;

#[cfg(feature = "std")]
pub use crate::hash_map::AHashMap;
#[cfg(feature = "std")]
pub use crate::hash_set::AHashSet;

///This constant come from Kunth's prng
const MULTIPLE: u64 = 6364136223846793005;

// Const random provides randomized starting key with no runtime cost.
#[cfg(feature = "compile-time-rng")]
static SEED: AtomicUsize = AtomicUsize::new(const_random!(u64));

#[cfg(not(feature = "compile-time-rng"))]
static SEED: AtomicUsize = AtomicUsize::new(MULTIPLE as usize);

/// Provides a default [Hasher] compile time generated constants for keys.
/// This is typically used in conjunction with [`BuildHasherDefault`] to create
/// [AHasher]s in order to hash the keys of the map.
///
/// # Example
/// ```
/// use std::hash::BuildHasherDefault;
/// use ahash::{AHasher, ABuildHasher};
/// use std::collections::HashMap;
///
/// let mut map: HashMap<i32, i32, ABuildHasher> = HashMap::default();
/// map.insert(12, 34);
/// ```
///
/// [BuildHasherDefault]: std::hash::BuildHasherDefault
/// [Hasher]: std::hash::Hasher
/// [HashMap]: std::collections::HashMap
#[cfg(feature = "compile-time-rng")]
impl Default for AHasher {
    /// Constructs a new [AHasher] with compile time generated constants for keys.
    /// This means the keys will be the same from one instance to another,
    /// but different from build to the next. So if it is possible for a potential
    /// attacker to have access to the compiled binary it would be better
    /// to specify keys generated at runtime.
    ///
    /// This is defined only if the `compile-time-rng` feature is enabled.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::AHasher;
    /// use std::hash::Hasher;
    ///
    /// let mut hasher_1 = AHasher::default();
    /// let mut hasher_2 = AHasher::default();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    /// ```
    #[inline]
    fn default() -> AHasher {
        AHasher::new_with_keys(const_random!(u64), const_random!(u64))
    }
}

/// Provides a [Hasher] factory. This is typically used (e.g. by [`HashMap`]) to create
/// [AHasher]s in order to hash the keys of the map. See `build_hasher` below.
///
/// [build_hasher]: ahash::
/// [Hasher]: std::hash::Hasher
/// [BuildHasher]: std::hash::BuildHasher
/// [HashMap]: std::collections::HashMap
#[derive(Clone)]
pub struct ABuildHasher {
    k0: u64,
    k1: u64,
}

impl ABuildHasher {
    #[inline]
    pub fn new() -> ABuildHasher {
        //Using a self pointer. When running with ASLR this is a random value.
        let previous = SEED.load(Ordering::Relaxed) as u64;
        let stack_mem_loc = &previous as *const _ as u64;
        //This is similar to the update function in the fallback.
        //only one multiply is needed because memory locations are not under an attackers control.
        let current_seed = previous.wrapping_mul(MULTIPLE).wrapping_add(stack_mem_loc).rotate_left(31);
        SEED.store(current_seed as usize, Ordering::Relaxed);
        return ABuildHasher {
            k0: &SEED as *const _ as u64,
            k1: current_seed
        };
    }
}

impl Default for ABuildHasher {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl BuildHasher for ABuildHasher {
    type Hasher = AHasher;

    /// Constructs a new [AHasher] with keys based on compile time generated constants** and the location
    /// of the this object in memory. This means that two different [BuildHasher]s will will generate
    /// [AHasher]s that will return different hashcodes, but [Hasher]s created from the same [BuildHasher]
    /// will generate the same hashes for the same input data.
    ///
    /// ** - only if the `compile-time-rng` feature is enabled.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::{AHasher, ABuildHasher};
    /// use std::hash::{Hasher, BuildHasher};
    ///
    /// let build_hasher = ABuildHasher::new();
    /// let mut hasher_1 = build_hasher.build_hasher();
    /// let mut hasher_2 = build_hasher.build_hasher();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    ///
    /// let other_build_hasher = ABuildHasher::new();
    /// let mut different_hasher = other_build_hasher.build_hasher();
    /// different_hasher.write_u32(1234);
    /// assert_ne!(different_hasher.finish(), hasher_1.finish());
    /// ```
    /// [Hasher]: std::hash::Hasher
    /// [BuildHasher]: std::hash::BuildHasher
    /// [HashMap]: std::collections::HashMap
    #[inline]
    fn build_hasher(&self) -> AHasher {
        let (k0, k1) = scramble_keys(self.k0, self.k1);
        return AHasher::new_with_keys(k0, k1);
    }
}

pub(crate) fn scramble_keys(k0: u64, k1: u64) -> (u64, u64) {
    //Scramble seeds (based on xoroshiro128+)
    //This is intentionally not similar the hash algorithm
    let result1 = k0.wrapping_add(k1);
    let k1 = k1 ^ k0;
    let k0 = k0.rotate_left(24) ^ k1 ^ (k1.wrapping_shl(16));
    let result2 = k0.wrapping_add(k1.rotate_left(37));
    return (result2, result1);
}

#[cfg(test)]
mod test {
    use crate::convert::Convert;
    use crate::*;
    use core::hash::BuildHasherDefault;
    use std::collections::HashMap;

    #[test]
    fn test_default_builder() {
        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }
    #[test]
    fn test_builder() {
        let mut map = HashMap::<u32, u64, ABuildHasher>::default();
        map.insert(1, 3);
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }

    #[test]
    fn test_ahasher_construction() {
        let _ = AHasher::new_with_keys(1245, 5678);
    }
}
<|endoftext|>


<commit_before>//! A formatted and aligned table printer written in rust
use std::io::{stdout, Write, Error, ErrorKind};
use std::fmt;
use std::str;
use std::string::ToString;

/// A Struct representing a printable table
#[derive(Clone, Debug)]
pub struct Table {
	num_cols: usize,
	titles: Vec<String>,
	rows: Vec<Vec<String>>,
	col_sep: char,
	line_sep: char,
	sep_cross: char
}

impl Table {
	/// Create a new table with the number of columns equals to the length of `titles`
	pub fn new(titles: Vec<String>) -> Table {
		let n = titles.len();
		return Table {
			num_cols: n,
			titles: titles,
			rows: Vec::new(),
			col_sep: '|',
			line_sep: '-',
			sep_cross: '+'
		};
	}

	/// Change separators
	///
	/// `col` is the column separator
	/// `line` is the line separator
	/// `cross` is a special separator used when line and collumn separators meet
	/// Default separators used are '|', '-' and '+'
	pub fn separators(&mut self, col: char, line: char, cross: char) {
		self.col_sep = col;
		self.line_sep = line;
		self.sep_cross = cross;
	}

	/// Get the number of column
	pub fn get_column_num(&self) -> usize {
		return self.num_cols;
	}

	/// Get the number of rows
	pub fn len(&self) -> usize {
		return self.rows.len();
	}

	/// Get a mutable reference to a row
	pub fn get_mut_row(&mut self, row: usize) -> &mut Vec<String> {
		return &mut self.rows[row];
	}

	/// Get an immutable reference to a row
	pub fn get_row(&self, row: usize) -> &Vec<String> {
		return &self.rows[row];
	}

	/// Append a row in the table, transferring ownership of this row to the table
	/// and returning a mutable reference to the row
	pub fn add_row(&mut self, row: Vec<String>) -> Result<&mut Vec<String>, &str> {
		if row.len() != self.num_cols {
			return Err("Row does not have the proper number of column");
		}
		self.rows.push(row);
		let l = self.rows.len()-1;
		return Ok(self.get_mut_row(l));
	}

	/// Append an empty row in the table. Return a mutable reference to this new row.
	pub fn add_empty_row(&mut self) -> Result<&mut Vec<String>, &str> {
		let n = self.num_cols;
		return Ok(try!(self.add_row(vec!["".to_string(); n])));
	}

	/// Modify a single element in the table
	pub fn set_element<T: ToString>(&mut self, element: T, column: usize, row: usize) -> Result<(), &str> {
		if column >= self.num_cols {
			return Err("Column index is higher than expected");
		}
		let rowline: &mut Vec<String>;
		if row > self.rows.len() {
			rowline = try!(self.add_empty_row());
		}
		else {
			rowline = self.get_mut_row(row);
		}
		rowline[column] = element.to_string();
		return Ok(());
	}

	/// Remove a row
	pub fn remove_row(&mut self, row: usize) {
		self.rows.remove(row);
	}

	fn get_col_width(&self, col_idx: usize) -> Result<usize, &str> {
		if col_idx >= self.num_cols {
			return Err("Column index is too high");
		}
		let mut width = self.titles[col_idx].len();
		for r in &self.rows {
			let l = r[col_idx].len();
			if l > width {
				width = l;
			}
		}
		return Ok(width);
	}

	fn print_line_separator<T: Write>(&self, out: &mut T, col_width: &[usize]) -> Result<(), Error> {
		try!(write!(out, "{}", self.sep_cross));
		for i in 0..self.num_cols {
			for _ in 0..(col_width[i] + 2) {
				try!(write!(out, "{}", self.line_sep));
			}
			try!(write!(out, "{}", self.sep_cross));
		}
		return writeln!(out, "");
	}

	fn print_line<T: Write>(&self, out: &mut T, line: &[String], col_width: &[usize]) -> Result<(), Error> {
		try!(write!(out, "{}", self.col_sep));
		for i in 0..self.num_cols {
			try!(write!(out, " {} ", line[i]));
			for _ in 0..(col_width[i] - line[i].len()) {
				try!(write!(out, " "));
			}
			try!(write!(out, "{}", self.col_sep));
		}
		return writeln!(out, "");
	}

	/// Print the table to `out`
	pub fn print<T: Write>(&self, out: &mut T) -> Result<(), Error> {
		let mut col_width = vec![0usize; self.num_cols];
		for i in 0..self.num_cols {
			col_width[i] = self.get_col_width(i).unwrap();
		}
		try!(self.print_line_separator(out, &col_width));
		try!(self.print_line(out, &self.titles, &col_width));
		try!(self.print_line_separator(out, &col_width));
		for r in &self.rows {
			try!(self.print_line(out, r, &col_width));
			try!(self.print_line_separator(out, &col_width));
		}
		return out.flush();
	}

	/// Print the table to standard output
	/// # Panic
	/// Panic if writing to standard output fails
	pub fn printstd(&self) {
		self.print(&mut stdout())
			.ok()
			.expect("Cannot print table to standard output");
	}
}

impl fmt::Display for Table {
	fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		let mut writer =  StringWriter::new();
		if let Err(_) = self.print(&mut writer) {
			return Err(fmt::Error)
		}
		return fmt.write_str(writer.as_string());
	}
}

/// Internal utility for writing data into a string
struct StringWriter {
	string: String
}

impl StringWriter {
	/// Create a new `StringWriter`
	fn new() -> StringWriter {
		return StringWriter{string: String::new()};
	}

	/// Return a reference to the internally written `String`
	fn as_string(&self) -> &String {
		return &self.string;
	}
}

impl Write for StringWriter {
	fn write(&mut self, data: &[u8]) -> Result<usize, Error> {
		let string = match str::from_utf8(data) {
			Ok(s) => s,
			Err(e) => return Err(Error::new(ErrorKind::Other, format!("Cannot decode utf8 string : {}", e)))
		};
		self.string.push_str(string);
		return Ok(data.len());
	}

	fn flush(&mut self) -> Result<(), Error> {
		return Ok(());
	}
}

/// Create a table with column's titles from arguments.
///
/// The table can also be initialized with some values.
/// All the arguments used for titles and elements must implement the `std::string::ToString` trait
/// # Syntax
/// table!([Title1, Title2, ...], [Element1_ row1, Element2_ row1, ...], [Element1_row2, ...], ...);
/// # Panic
/// May panic if some rows could not be inserted
/// # Example
/// ```
/// # #[macro_use] extern crate tabprint;
/// # fn main() {
/// // Create an empty table with titles :
/// let tab = table!(["Title1", "Title2", "Title3"]);
/// // Create a table initialized with some rows :
/// let tab = table!(["Title1", "Title2", "Title3"],
/// 				 ["Element1", "Element2", "Element3"],
/// 				 [1, 2, 3]
/// 				 );
/// # drop(tab);
/// # }
/// ```
#[macro_export]
macro_rules! table {
	([$($title: expr), *]) => ($crate::Table::new(vec![$($title.to_string()), *]));
	(
		[$($title: expr), *], $([$($key:expr), *]), *
	) => (
		{
			let mut tab = table!([$($title), *]);
			$(
				let row = vec![$($key.to_string()), *];
				if let Err(e) = tab.add_row(row) {
					panic!("Cannot create table from : {}", e);
				}
			)*
			tab
		}
	)
}

/// Create a table with `table!` macro, print it to standard output, then return this table for future usage.
///
/// The syntax is the same that the one for the `table!` macro
/// # Panic
/// May panic if some rows could not be inserted
#[macro_export]
macro_rules! ptable {
	([$($title: expr), *]) => (
		{
			let tab = table!([$($title), *]);
			tab.printstd();
			tab
		}
	);
	(
		[$($title: expr), *], $([$($key:expr), *]), *
	) => (
		{
			let tab = table!([$($title), *], $([$($key), *]), *);
			tab.printstd();
			tab
		}
	)
}<commit_msg>Reduced the use of write! macro<commit_after>//! A formatted and aligned table printer written in rust
use std::io::{stdout, Write, Error, ErrorKind};
use std::fmt;
use std::str;
use std::string::ToString;

/// A Struct representing a printable table
#[derive(Clone, Debug)]
pub struct Table {
	num_cols: usize,
	titles: Vec<String>,
	rows: Vec<Vec<String>>,
	col_sep: char,
	line_sep: char,
	sep_cross: char
}

impl Table {
	/// Create a new table with the number of columns equals to the length of `titles`
	pub fn new(titles: Vec<String>) -> Table {
		let n = titles.len();
		return Table {
			num_cols: n,
			titles: titles,
			rows: Vec::new(),
			col_sep: '|',
			line_sep: '-',
			sep_cross: '+'
		};
	}

	/// Change separators
	///
	/// `col` is the column separator
	/// `line` is the line separator
	/// `cross` is a special separator used when line and collumn separators meet
	/// Default separators used are '|', '-' and '+'
	pub fn separators(&mut self, col: char, line: char, cross: char) {
		self.col_sep = col;
		self.line_sep = line;
		self.sep_cross = cross;
	}

	/// Get the number of column
	pub fn get_column_num(&self) -> usize {
		return self.num_cols;
	}

	/// Get the number of rows
	pub fn len(&self) -> usize {
		return self.rows.len();
	}

	/// Get a mutable reference to a row
	pub fn get_mut_row(&mut self, row: usize) -> &mut Vec<String> {
		return &mut self.rows[row];
	}

	/// Get an immutable reference to a row
	pub fn get_row(&self, row: usize) -> &Vec<String> {
		return &self.rows[row];
	}

	/// Append a row in the table, transferring ownership of this row to the table
	/// and returning a mutable reference to the row
	pub fn add_row(&mut self, row: Vec<String>) -> Result<&mut Vec<String>, &str> {
		if row.len() != self.num_cols {
			return Err("Row does not have the proper number of column");
		}
		self.rows.push(row);
		let l = self.rows.len()-1;
		return Ok(self.get_mut_row(l));
	}

	/// Append an empty row in the table. Return a mutable reference to this new row.
	pub fn add_empty_row(&mut self) -> Result<&mut Vec<String>, &str> {
		let n = self.num_cols;
		return Ok(try!(self.add_row(vec!["".to_string(); n])));
	}

	/// Modify a single element in the table
	pub fn set_element<T: ToString>(&mut self, element: T, column: usize, row: usize) -> Result<(), &str> {
		if column >= self.num_cols {
			return Err("Column index is higher than expected");
		}
		if row > self.rows.len() {
			return Err("Row index is higher than contained number of rows");
		}
		let rowline = self.get_mut_row(row);
		rowline[column] = element.to_string();
		return Ok(());
	}

	/// Remove a row
	pub fn remove_row(&mut self, row: usize) {
		self.rows.remove(row);
	}

	fn get_col_width(&self, col_idx: usize) -> Result<usize, &str> {
		if col_idx >= self.num_cols {
			return Err("Column index is too high");
		}
		let mut width = self.titles[col_idx].len();
		for r in &self.rows {
			let l = r[col_idx].len();
			if l > width {
				width = l;
			}
		}
		return Ok(width);
	}

	fn print_line_separator<T: Write>(&self, out: &mut T, col_width: &[usize]) -> Result<(), Error> {
		try!(out.write_all(self.sep_cross.to_string().as_bytes()));
		for i in 0..self.num_cols {
			for _ in 0..(col_width[i] + 2) {
				try!(out.write_all(self.line_sep.to_string().as_bytes()));
			}
			try!(out.write_all(self.sep_cross.to_string().as_bytes()));
		}
		return out.write_all(b"\n");
	}

	fn print_line<T: Write>(&self, out: &mut T, line: &[String], col_width: &[usize]) -> Result<(), Error> {
		try!(out.write_all(self.col_sep.to_string().as_bytes()));
		for i in 0..self.num_cols {
			try!(out.write_all(b" "));
			try!(out.write_all(line[i].as_bytes()));
			try!(out.write_all(b" "));
			for _ in 0..(col_width[i] - line[i].len()) {
				try!(out.write_all(b" "));
			}
			try!(out.write_all(self.col_sep.to_string().as_bytes()));
		}
		return out.write_all(b"\n");
	}

	/// Print the table to `out`
	pub fn print<T: Write>(&self, out: &mut T) -> Result<(), Error> {
		let mut col_width = vec![0usize; self.num_cols];
		for i in 0..self.num_cols {
			col_width[i] = self.get_col_width(i).unwrap();
		}
		try!(self.print_line_separator(out, &col_width));
		try!(self.print_line(out, &self.titles, &col_width));
		try!(self.print_line_separator(out, &col_width));
		for r in &self.rows {
			try!(self.print_line(out, r, &col_width));
			try!(self.print_line_separator(out, &col_width));
		}
		return out.flush();
	}

	/// Print the table to standard output
	/// # Panic
	/// Panic if writing to standard output fails
	pub fn printstd(&self) {
		self.print(&mut stdout())
			.ok()
			.expect("Cannot print table to standard output");
	}
}

impl fmt::Display for Table {
	fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
		let mut writer =  StringWriter::new();
		if let Err(_) = self.print(&mut writer) {
			return Err(fmt::Error)
		}
		return fmt.write_str(writer.as_string());
	}
}

/// Internal utility for writing data into a string
struct StringWriter {
	string: String
}

impl StringWriter {
	/// Create a new `StringWriter`
	fn new() -> StringWriter {
		return StringWriter{string: String::new()};
	}

	/// Return a reference to the internally written `String`
	fn as_string(&self) -> &String {
		return &self.string;
	}
}

impl Write for StringWriter {
	fn write(&mut self, data: &[u8]) -> Result<usize, Error> {
		let string = match str::from_utf8(data) {
			Ok(s) => s,
			Err(e) => return Err(Error::new(ErrorKind::Other, format!("Cannot decode utf8 string : {}", e)))
		};
		self.string.push_str(string);
		return Ok(data.len());
	}

	fn flush(&mut self) -> Result<(), Error> {
		return Ok(());
	}
}

/// Create a table with column's titles from arguments.
///
/// The table can also be initialized with some values.
/// All the arguments used for titles and elements must implement the `std::string::ToString` trait
/// # Syntax
/// table!([Title1, Title2, ...], [Element1_ row1, Element2_ row1, ...], [Element1_row2, ...], ...);
/// # Panic
/// May panic if some rows could not be inserted
/// # Example
/// ```
/// # #[macro_use] extern crate tabprint;
/// # fn main() {
/// // Create an empty table with titles :
/// let tab = table!(["Title1", "Title2", "Title3"]);
/// // Create a table initialized with some rows :
/// let tab = table!(["Title1", "Title2", "Title3"],
/// 				 ["Element1", "Element2", "Element3"],
/// 				 [1, 2, 3]
/// 				 );
/// # drop(tab);
/// # }
/// ```
#[macro_export]
macro_rules! table {
	([$($title: expr), *]) => ($crate::Table::new(vec![$($title.to_string()), *]));
	(
		[$($title: expr), *], $([$($key:expr), *]), *
	) => (
		{
			let mut tab = table!([$($title), *]);
			$(
				let row = vec![$($key.to_string()), *];
				if let Err(e) = tab.add_row(row) {
					panic!("Cannot create table from : {}", e);
				}
			)*
			tab
		}
	)
}

/// Create a table with `table!` macro, print it to standard output, then return this table for future usage.
///
/// The syntax is the same that the one for the `table!` macro
/// # Panic
/// May panic if some rows could not be inserted
#[macro_export]
macro_rules! ptable {
	([$($title: expr), *]) => (
		{
			let tab = table!([$($title), *]);
			tab.printstd();
			tab
		}
	);
	(
		[$($title: expr), *], $([$($key:expr), *]), *
	) => (
		{
			let tab = table!([$($title), *], $([$($key), *]), *);
			tab.printstd();
			tab
		}
	)
}<|endoftext|>


<commit_before>#![feature(macro_rules)]
#![feature(phase)]
#![macro_escape]

#![unstable]

#[phase(plugin)] extern crate compile_msg;
extern crate libc;

pub mod ffi;

static mut native_window: Option<ffi::NativeWindowType> = None;

#[cfg(not(target_os = "android"))]
compile_note!("You are not compiling for Android")

#[macro_export]
macro_rules! android_start(
    ($main: ident) => (
        pub mod __android_start {
            extern crate android_glue;
            extern crate libc;
            extern crate native;

            /// This is the entry point of the Android application
            #[no_mangle]
            #[allow(non_snake_case)]
            pub extern "C" fn ANativeActivity_onCreate(activity: *mut android_glue::ffi::ANativeActivity,
                _saved_state: *mut libc::c_void, _saved_state_size: libc::size_t)
            {
                use self::native::NativeTaskBuilder;
                use std::mem;
                use std::task::TaskBuilder;

                let mut activity = unsafe { &mut *activity };
                let mut callbacks = unsafe { &mut *activity.callbacks };

                callbacks.onDestroy = android_glue::native_ondestroy;
                callbacks.onStart = android_glue::native_onstart;
                callbacks.onResume = android_glue::native_onresume;
                callbacks.onSaveInstanceState = android_glue::native_onsaveinstancestate;
                callbacks.onPause = android_glue::native_onpause;
                callbacks.onStop = android_glue::native_onstop;
                callbacks.onConfigurationChanged = android_glue::native_onconfigurationchanged;
                callbacks.onLowMemory = android_glue::native_onlowmemory;
                callbacks.onWindowFocusChanged = android_glue::native_onwindowfocuschanged;
                callbacks.onNativeWindowCreated = android_glue::native_onnativewindowcreated;
                callbacks.onNativeWindowDestroyed = android_glue::native_onnativewindowdestroyed;

                TaskBuilder::new().native().spawn(proc() {
                    super::$main()
                });
            }
        }
    )
)

/**
 * Returns a handle to the native window.
 */
pub fn get_native_window() -> ffi::NativeWindowType {
    unsafe { native_window.unwrap() }
}

/**
 *
 */
pub fn write_log(message: &str) {
    message.with_c_str(|message| {
        b"RustAndroidGlue".with_c_str(|tag| {
            unsafe { ffi::__android_log_write(3, tag, message) };
        });
    });
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onnativewindowcreated(_: *mut ffi::ANativeActivity, window: *const ffi::ANativeWindow) {
    unsafe { native_window = Some(window); }
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onnativewindowdestroyed(_: *mut ffi::ANativeActivity, _: *const ffi::ANativeWindow) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_ondestroy(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onstart(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onresume(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onsaveinstancestate(_: *mut ffi::ANativeActivity, _: *mut libc::size_t) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onpause(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onstop(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onconfigurationchanged(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onlowmemory(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onwindowfocuschanged(_: *mut ffi::ANativeActivity, _: libc::c_int) {
}
<commit_msg>Add debug log message in ANativeActivity_onCreate<commit_after>#![feature(macro_rules)]
#![feature(phase)]
#![macro_escape]

#![unstable]

#[phase(plugin)] extern crate compile_msg;
extern crate libc;

pub mod ffi;

static mut native_window: Option<ffi::NativeWindowType> = None;

#[cfg(not(target_os = "android"))]
compile_note!("You are not compiling for Android")

#[macro_export]
macro_rules! android_start(
    ($main: ident) => (
        pub mod __android_start {
            extern crate android_glue;
            extern crate libc;
            extern crate native;

            /// This is the entry point of the Android application
            #[no_mangle]
            #[allow(non_snake_case)]
            pub extern "C" fn ANativeActivity_onCreate(activity: *mut android_glue::ffi::ANativeActivity,
                _saved_state: *mut libc::c_void, _saved_state_size: libc::size_t)
            {
                use self::native::NativeTaskBuilder;
                use std::mem;
                use std::task::TaskBuilder;

                android_glue::write_log("ANativeActivity_onCreate has been called");

                let mut activity = unsafe { &mut *activity };
                let mut callbacks = unsafe { &mut *activity.callbacks };

                callbacks.onDestroy = android_glue::native_ondestroy;
                callbacks.onStart = android_glue::native_onstart;
                callbacks.onResume = android_glue::native_onresume;
                callbacks.onSaveInstanceState = android_glue::native_onsaveinstancestate;
                callbacks.onPause = android_glue::native_onpause;
                callbacks.onStop = android_glue::native_onstop;
                callbacks.onConfigurationChanged = android_glue::native_onconfigurationchanged;
                callbacks.onLowMemory = android_glue::native_onlowmemory;
                callbacks.onWindowFocusChanged = android_glue::native_onwindowfocuschanged;
                callbacks.onNativeWindowCreated = android_glue::native_onnativewindowcreated;
                callbacks.onNativeWindowDestroyed = android_glue::native_onnativewindowdestroyed;

                TaskBuilder::new().native().spawn(proc() {
                    super::$main()
                });
            }
        }
    )
)

/**
 * Returns a handle to the native window.
 */
pub fn get_native_window() -> ffi::NativeWindowType {
    unsafe { native_window.unwrap() }
}

/**
 *
 */
pub fn write_log(message: &str) {
    message.with_c_str(|message| {
        b"RustAndroidGlue".with_c_str(|tag| {
            unsafe { ffi::__android_log_write(3, tag, message) };
        });
    });
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onnativewindowcreated(_: *mut ffi::ANativeActivity, window: *const ffi::ANativeWindow) {
    unsafe { native_window = Some(window); }
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onnativewindowdestroyed(_: *mut ffi::ANativeActivity, _: *const ffi::ANativeWindow) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_ondestroy(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onstart(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onresume(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onsaveinstancestate(_: *mut ffi::ANativeActivity, _: *mut libc::size_t) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onpause(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onstop(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onconfigurationchanged(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onlowmemory(_: *mut ffi::ANativeActivity) {
}

#[doc(hidden)]
#[allow(visible_private_types)]
pub extern fn native_onwindowfocuschanged(_: *mut ffi::ANativeActivity, _: libc::c_int) {
}
<|endoftext|>


<commit_before>//! Shiplift is a multi-transport for utility for maneuvering [docker](https://www.docker.com/) containers
//!
//! # examples
//!
//! ```
//! extern crate shiplift;
//!
//! let mut docker = shiplift::Docker::new();
//! let mut images = docker.images().list().unwrap();
//! println!("docker images in stock");
//! for i in images {
//!   println!("{:?}", i.RepoTags);
//! }
//! ```

extern crate hyper;
extern crate openssl;
extern crate rustc_serialize;
extern crate unix_socket;
extern crate url;

pub mod builder;
pub mod rep;
pub mod transport;

use builder::ContainerBuilder;
use hyper::{ Client, Url };
use hyper::method::Method;
use openssl::x509::X509FileType;
use rustc_serialize::json;
use rep::Image as ImageRep;
use rep::Container as ContainerRep;
use rep::{
  Change, ContainerDetails, History, ImageDetails, Info, SearchResult, Top, Version
};
use std::env::{ self, VarError };
use std::path::Path;
use std::io::{ Read, Result };
use transport::{ Body, Transport };
use unix_socket::UnixStream;
use url::{ Host, RelativeSchemeData, SchemeData };

/// Entrypoint interface for communicating with docker daemon
pub struct Docker {
  transport: Box<Transport>
}

/// Interface for accessing and manipulating a named docker image
pub struct Image<'a, 'b> {
  docker: &'a mut Docker,
  name: &'b str
}

impl<'a, 'b> Image<'a, 'b> {
  pub fn new(docker: &'a mut Docker, name: &'b str) -> Image<'a, 'b> {
    Image { docker: docker, name: name }
  }

  pub fn inspect(self) -> Result<ImageDetails> {
    let raw = try!(self.docker.get(&format!("/images/{}/json", self.name)[..]));
    Ok(json::decode::<ImageDetails>(&raw).unwrap())
  }

  pub fn history(self) -> Result<Vec<History>> {
    let raw = try!(self.docker.get(&format!("/images/{}/history", self.name)[..]));
    Ok(json::decode::<Vec<History>>(&raw).unwrap())
  }

  pub fn delete(self) -> Result<String> {
    self.docker.delete(&format!("/images/{}", self.name)[..])
  }
}

/// Interface for docker images
pub struct Images<'a> {
  docker: &'a mut Docker
}

impl<'a> Images<'a> {
  pub fn new(docker: &'a mut Docker) -> Images<'a> {
    Images { docker: docker }
  }

  pub fn list(self) -> Result<Vec<ImageRep>> {
    let raw = try!(self.docker.get("/images/json"));
    Ok(json::decode::<Vec<ImageRep>>(&raw).unwrap())
  }

  pub fn get(&'a mut self, name: &'a str) -> Image {
    Image::new(self.docker, name)
  }

  pub fn search(self, term: &str) -> Result<Vec<SearchResult>> {
    let raw = try!(self.docker.get(&format!("/images/search?term={}", term)[..]));
    Ok(json::decode::<Vec<SearchResult>>(&raw).unwrap())
  }

  pub fn create(self, from: &str) -> Result<Box<Read>> {
    self.docker.stream_post(&format!("/images/create?fromImage={}", from)[..])
  }
}

/// Interface for accessing and manipulating a docker container
pub struct Container<'a, 'b> {
  docker: &'a mut Docker,
  id: &'b str
}

impl<'a, 'b> Container<'a, 'b> {
  pub fn new(docker: &'a mut Docker, id: &'b str) -> Container<'a, 'b> {
    Container { docker: docker, id: id }
  }

  pub fn inspect(self) -> Result<ContainerDetails> {
    let raw = try!(self.docker.get(&format!("/containers/{}/json", self.id)[..]));
    Ok(json::decode::<ContainerDetails>(&raw).unwrap())
  }

  pub fn top(self) -> Result<Top> {
    let raw = try!(self.docker.get(&format!("/containers/{}/top", self.id)[..]));
    Ok(json::decode::<Top>(&raw).unwrap())
  }

  pub fn logs(self) -> Result<Box<Read>> {
    let query = format!(
      "follow={}&stdout={}&stderr={}&timestamps={}&tail={}",
      true, true, true, true, "all");
    self.docker.stream_get(&format!("/containers/{}/logs?{}", self.id, query)[..])
  }

  pub fn changes(self) -> Result<Vec<Change>> {
    let raw = try!(self.docker.get(&format!("/containers/{}/changes", self.id)[..]));
    Ok(json::decode::<Vec<Change>>(&raw).unwrap())
  }

  pub fn export(self) -> Result<Box<Read>> {
    self.docker.stream_get(&format!("/containers/{}/export", self.id)[..])
  }

  pub fn stats(self) -> Result<Box<Read>> {
    self.docker.stream_get(&format!("/containers/{}/stats", self.id)[..])
  }

  pub fn start(self) -> Result<String> {
    self.docker.post(&format!("/containers/{}/start", self.id)[..], None)
  }

  pub fn stop(self) -> Result<String> {
    self.docker.post(&format!("/containers/{}/stop", self.id)[..], None)
  }

  pub fn restart(self) -> Result<String> {
    self.docker.post(&format!("/containers/{}/restart", self.id)[..], None)
  }

  pub fn kill(self) -> Result<String> {
    self.docker.post(&format!("/containers/{}/kill", self.id)[..], None)
  }

  pub fn rename(self, name: &str) -> Result<String> {
    self.docker.post(&format!("/containers/{}/rename?name={}", self.id, name)[..], None)
  }

  pub fn pause(self) -> Result<String> {
    self.docker.post(&format!("/containers/{}/pause", self.id)[..], None)
  }

  pub fn unpause(self) -> Result<String> {
    self.docker.post(&format!("/containers/{}/unpause", self.id)[..], None)
  }

  pub fn wait(self) -> Result<String> {
    self.docker.post(&format!("/containers/{}/wait", self.id)[..], None)
  }

  pub fn delete(self) -> Result<String> {
    self.docker.delete(&format!("/containers/{}", self.id)[..])
  }

  // todo attach, attach/ws,
}

/// Interface for docker containers
pub struct Containers<'a> {
  docker: &'a mut Docker
}

impl<'a> Containers<'a> {
  pub fn new(docker: &'a mut Docker) -> Containers<'a> {
    Containers { docker: docker }
  }

  pub fn list(self) -> Result<Vec<ContainerRep>> {
    let raw = try!(self.docker.get("/containers/json"));
    Ok(json::decode::<Vec<ContainerRep>>(&raw).unwrap())
  }

  pub fn get(&'a mut self, name: &'a str) -> Container {
    Container::new(self.docker, name)
  }

  pub fn create(&'a mut self, image: &'a str) -> ContainerBuilder {
    ContainerBuilder::new(self.docker, image)
  }
}

// https://docs.docker.com/reference/api/docker_remote_api_v1.17/
impl Docker {
  pub fn new() -> Docker {
    let fallback: std::result::Result<String, VarError> = Ok("unix:///var/run/docker.sock".to_string());
    let host = env::var("DOCKER_HOST")
        .or(fallback)
        .map(|h| Url::parse(&h).ok()
             .expect("invalid url"))
         .ok()
         .expect("expected host");
    let domain = match host.scheme_data {
        SchemeData::NonRelative(s) => s,
        SchemeData::Relative(RelativeSchemeData { host: host, .. }) =>
          match host {
              Host::Domain(s) => s,
              Host::Ipv6(a)   => a.to_string()
          }
    };
    match &host.scheme[..] {
      "unix" => {
        let stream =
          match UnixStream::connect(domain) {
            Err(_) => panic!("failed to connect to socket"),
            Ok(s) => s
          };
        Docker { transport: Box::new(stream) }
      },
          _  => {
        let mut client = Client::new();
        client.set_ssl_verifier(Box::new(|ssl_ctx| {
          match env::var("DOCKER_CERT_PATH").ok() {
            Some(ref certs) => {
              let cert = &format!("{}/cert.pem", certs);
              let key = &format!("{}/key.pem", certs);
              ssl_ctx.set_certificate_file(&Path::new(cert), X509FileType::PEM);
              ssl_ctx.set_private_key_file(&Path::new(key), X509FileType::PEM);
              match env::var("DOCKER_TLS_VERIFY").ok() {
                Some(_) => {
                  let ca = &format!("{}/ca.pem", certs);
                  ssl_ctx.set_CA_file(&Path::new(ca));
                }, _ => ()
              };
              ()
            },  _ => ()
          }
        }));
        let tup = (client, format!("https:{}", domain.to_string()));
        Docker { transport: Box::new(tup) }
      }
    }
  }

  pub fn images<'a>(&'a mut self) -> Images {
    Images::new(self)
  }

  pub fn containers<'a>(&'a mut self) -> Containers {
    Containers::new(self)
  }

  pub fn version(&mut self) -> Result<Version> {
    let raw = try!(self.get("/version"));
    Ok(json::decode::<Version>(&raw).unwrap())
  }

  pub fn info(&mut self) -> Result<Info> {
    let raw = try!(self.get("/info"));
    Ok(json::decode::<Info>(&raw).unwrap())
  }

  pub fn ping(&mut self) -> Result<String> {
    self.get("/_ping")
  }

  // todo stream
  pub fn events(&mut self) -> Result<Box<Read>> {
    self.stream_get("/events?since=1374067924")
  }

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

  fn post(&mut self, endpoint: &str, body: Option<Body>) -> Result<String> {
    (*self.transport).request(Method::Post, endpoint, body)
  }

  fn delete(&mut self, endpoint: &str) -> Result<String> {
    (*self.transport).request(Method::Delete, endpoint, None)
  }

  fn stream_post(&mut self, endpoint: &str) -> Result<Box<Read>> {
    (*self.transport).stream(Method::Post, endpoint, None)
  }

  fn stream_get(&mut self, endpoint: &str) -> Result<Box<Read>> {
    (*self.transport).stream(Method::Get, endpoint, None)
  }
}
<commit_msg>no content response should have unit responses<commit_after>//! Shiplift is a multi-transport for utility for maneuvering [docker](https://www.docker.com/) containers
//!
//! # examples
//!
//! ```
//! extern crate shiplift;
//!
//! let mut docker = shiplift::Docker::new();
//! let mut images = docker.images().list().unwrap();
//! println!("docker images in stock");
//! for i in images {
//!   println!("{:?}", i.RepoTags);
//! }
//! ```

extern crate hyper;
extern crate openssl;
extern crate rustc_serialize;
extern crate unix_socket;
extern crate url;

pub mod builder;
pub mod rep;
pub mod transport;

use builder::ContainerBuilder;
use hyper::{ Client, Url };
use hyper::method::Method;
use openssl::x509::X509FileType;
use rustc_serialize::json;
use rep::Image as ImageRep;
use rep::Container as ContainerRep;
use rep::{
  Change, ContainerDetails, Exit, History, ImageDetails, Info, SearchResult, Top, Version
};
use std::env::{ self, VarError };
use std::path::Path;
use std::io::{ Read, Result };
use transport::{ Body, Transport };
use unix_socket::UnixStream;
use url::{ Host, RelativeSchemeData, SchemeData };

/// Entrypoint interface for communicating with docker daemon
pub struct Docker {
  transport: Box<Transport>
}

/// Interface for accessing and manipulating a named docker image
pub struct Image<'a, 'b> {
  docker: &'a mut Docker,
  name: &'b str
}

impl<'a, 'b> Image<'a, 'b> {
  pub fn new(docker: &'a mut Docker, name: &'b str) -> Image<'a, 'b> {
    Image { docker: docker, name: name }
  }

  pub fn inspect(self) -> Result<ImageDetails> {
    let raw = try!(self.docker.get(&format!("/images/{}/json", self.name)[..]));
    Ok(json::decode::<ImageDetails>(&raw).unwrap())
  }

  pub fn history(self) -> Result<Vec<History>> {
    let raw = try!(self.docker.get(&format!("/images/{}/history", self.name)[..]));
    Ok(json::decode::<Vec<History>>(&raw).unwrap())
  }

  pub fn delete(self) -> Result<String> {
    self.docker.delete(&format!("/images/{}", self.name)[..])
  }
}

/// Interface for docker images
pub struct Images<'a> {
  docker: &'a mut Docker
}

impl<'a> Images<'a> {
  pub fn new(docker: &'a mut Docker) -> Images<'a> {
    Images { docker: docker }
  }

  pub fn list(self) -> Result<Vec<ImageRep>> {
    let raw = try!(self.docker.get("/images/json"));
    Ok(json::decode::<Vec<ImageRep>>(&raw).unwrap())
  }

  pub fn get(&'a mut self, name: &'a str) -> Image {
    Image::new(self.docker, name)
  }

  pub fn search(self, term: &str) -> Result<Vec<SearchResult>> {
    let raw = try!(self.docker.get(&format!("/images/search?term={}", term)[..]));
    Ok(json::decode::<Vec<SearchResult>>(&raw).unwrap())
  }

  pub fn create(self, from: &str) -> Result<Box<Read>> {
    self.docker.stream_post(&format!("/images/create?fromImage={}", from)[..])
  }
}

/// Interface for accessing and manipulating a docker container
pub struct Container<'a, 'b> {
  docker: &'a mut Docker,
  id: &'b str
}

impl<'a, 'b> Container<'a, 'b> {
  pub fn new(docker: &'a mut Docker, id: &'b str) -> Container<'a, 'b> {
    Container { docker: docker, id: id }
  }

  pub fn inspect(self) -> Result<ContainerDetails> {
    let raw = try!(self.docker.get(&format!("/containers/{}/json", self.id)[..]));
    Ok(json::decode::<ContainerDetails>(&raw).unwrap())
  }

  pub fn top(self) -> Result<Top> {
    let raw = try!(self.docker.get(&format!("/containers/{}/top", self.id)[..]));
    Ok(json::decode::<Top>(&raw).unwrap())
  }

  pub fn logs(self) -> Result<Box<Read>> {
    let query = format!(
      "follow={}&stdout={}&stderr={}&timestamps={}&tail={}",
      true, true, true, true, "all");
    self.docker.stream_get(&format!("/containers/{}/logs?{}", self.id, query)[..])
  }

  pub fn changes(self) -> Result<Vec<Change>> {
    let raw = try!(self.docker.get(&format!("/containers/{}/changes", self.id)[..]));
    Ok(json::decode::<Vec<Change>>(&raw).unwrap())
  }

  pub fn export(self) -> Result<Box<Read>> {
    self.docker.stream_get(&format!("/containers/{}/export", self.id)[..])
  }

  pub fn stats(self) -> Result<Box<Read>> {
    self.docker.stream_get(&format!("/containers/{}/stats", self.id)[..])
  }

  pub fn start(self) -> Result<()> {
    self.docker.post(&format!("/containers/{}/start", self.id)[..], None).map(|_| ())
  }

  pub fn stop(self) -> Result<()> {
    self.docker.post(&format!("/containers/{}/stop", self.id)[..], None).map(|_| ())
  }

  pub fn restart(self) -> Result<()> {
    self.docker.post(&format!("/containers/{}/restart", self.id)[..], None).map(|_| ())
  }

  pub fn kill(self) -> Result<()> {
    self.docker.post(&format!("/containers/{}/kill", self.id)[..], None).map(|_| ())
  }

  pub fn rename(self, name: &str) -> Result<()> {
    self.docker.post(&format!("/containers/{}/rename?name={}", self.id, name)[..], None).map(|_| ())
  }

  pub fn pause(self) -> Result<()> {
    self.docker.post(&format!("/containers/{}/pause", self.id)[..], None).map(|_| ())
  }

  pub fn unpause(self) -> Result<()> {
    self.docker.post(&format!("/containers/{}/unpause", self.id)[..], None).map(|_| ())
  }

  pub fn wait(self) -> Result<Exit> {
    let raw = try!(self.docker.post(&format!("/containers/{}/wait", self.id)[..], None));
    Ok(json::decode::<Exit>(&raw).unwrap())
  }

  pub fn delete(self) -> Result<()> {
    self.docker.delete(&format!("/containers/{}", self.id)[..]).map(|_| ())
  }

  // todo attach, attach/ws,
}

/// Interface for docker containers
pub struct Containers<'a> {
  docker: &'a mut Docker
}

impl<'a> Containers<'a> {
  pub fn new(docker: &'a mut Docker) -> Containers<'a> {
    Containers { docker: docker }
  }

  pub fn list(self) -> Result<Vec<ContainerRep>> {
    let raw = try!(self.docker.get("/containers/json"));
    Ok(json::decode::<Vec<ContainerRep>>(&raw).unwrap())
  }

  pub fn get(&'a mut self, name: &'a str) -> Container {
    Container::new(self.docker, name)
  }

  pub fn create(&'a mut self, image: &'a str) -> ContainerBuilder {
    ContainerBuilder::new(self.docker, image)
  }
}

// https://docs.docker.com/reference/api/docker_remote_api_v1.17/
impl Docker {
  pub fn new() -> Docker {
    let fallback: std::result::Result<String, VarError> = Ok("unix:///var/run/docker.sock".to_string());
    let host = env::var("DOCKER_HOST")
        .or(fallback)
        .map(|h| Url::parse(&h).ok()
             .expect("invalid url"))
         .ok()
         .expect("expected host");
    let domain = match host.scheme_data {
        SchemeData::NonRelative(s) => s,
        SchemeData::Relative(RelativeSchemeData { host: host, .. }) =>
          match host {
              Host::Domain(s) => s,
              Host::Ipv6(a)   => a.to_string()
          }
    };
    match &host.scheme[..] {
      "unix" => {
        let stream =
          match UnixStream::connect(domain) {
            Err(_) => panic!("failed to connect to socket"),
            Ok(s) => s
          };
        Docker { transport: Box::new(stream) }
      },
          _  => {
        let mut client = Client::new();
        client.set_ssl_verifier(Box::new(|ssl_ctx| {
          match env::var("DOCKER_CERT_PATH").ok() {
            Some(ref certs) => {
              let cert = &format!("{}/cert.pem", certs);
              let key = &format!("{}/key.pem", certs);
              ssl_ctx.set_certificate_file(&Path::new(cert), X509FileType::PEM);
              ssl_ctx.set_private_key_file(&Path::new(key), X509FileType::PEM);
              match env::var("DOCKER_TLS_VERIFY").ok() {
                Some(_) => {
                  let ca = &format!("{}/ca.pem", certs);
                  ssl_ctx.set_CA_file(&Path::new(ca));
                }, _ => ()
              };
              ()
            },  _ => ()
          }
        }));
        let tup = (client, format!("https:{}", domain.to_string()));
        Docker { transport: Box::new(tup) }
      }
    }
  }

  pub fn images<'a>(&'a mut self) -> Images {
    Images::new(self)
  }

  pub fn containers<'a>(&'a mut self) -> Containers {
    Containers::new(self)
  }

  pub fn version(&mut self) -> Result<Version> {
    let raw = try!(self.get("/version"));
    Ok(json::decode::<Version>(&raw).unwrap())
  }

  pub fn info(&mut self) -> Result<Info> {
    let raw = try!(self.get("/info"));
    Ok(json::decode::<Info>(&raw).unwrap())
  }

  pub fn ping(&mut self) -> Result<String> {
    self.get("/_ping")
  }

  // todo stream
  pub fn events(&mut self) -> Result<Box<Read>> {
    self.stream_get("/events?since=1374067924")
  }

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

  fn post(&mut self, endpoint: &str, body: Option<Body>) -> Result<String> {
    (*self.transport).request(Method::Post, endpoint, body)
  }

  fn delete(&mut self, endpoint: &str) -> Result<String> {
    (*self.transport).request(Method::Delete, endpoint, None)
  }

  fn stream_post(&mut self, endpoint: &str) -> Result<Box<Read>> {
    (*self.transport).stream(Method::Post, endpoint, None)
  }

  fn stream_get(&mut self, endpoint: &str) -> Result<Box<Read>> {
    (*self.transport).stream(Method::Get, endpoint, None)
  }
}
<|endoftext|>


<commit_before>extern crate libc;

use std::*;
use libc::*;

#[allow(dead_code, non_camel_case_types)]
mod bladerf;
use bladerf::*;

pub struct BladerfDevice {
    pub device: *mut *mut Struct_bladerf,
}

//impl fmt::Display for Struct_bladerf_devinfo {
//    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//        write!(f, "serial: UNIMPLEMENTED, bus: {}, address: {})", self.usb_bus, self.usb_addr)
//    }
//}

pub fn get_device_list() -> Result<Vec<Struct_bladerf_devinfo>, isize> {

	unsafe{
		let devices: *mut Struct_bladerf_devinfo = mem::uninitialized();

		let n = bladerf_get_device_list(&devices) as isize;

		// Catch bladerf function errors
		if n > 0 {

			// Cast array to slice and create a safe array to return
			let device_slice = std::slice::from_raw_parts(devices, n as usize);
			let mut safe_device_list: Vec<Struct_bladerf_devinfo> = Vec::new();

			for i in 0..n {
				let local_device = device_slice[i as usize];
				//Safe if this is a copy, unsafe if it is not?
				safe_device_list.push(local_device);
			}
			bladerf_free_device_list(devices);

			// Return rust save device info array
			Ok(safe_device_list)

		} else {
			// Return error code
			Err(n)
		}
	}
}

pub fn set_usb_reset_on_open(enabled: bool) {
    unsafe{
    	bladerf_set_usb_reset_on_open(enabled as uint8_t);
    }
}

pub fn open_with_devinfo(devinfo: &Struct_bladerf_devinfo) -> Result<*mut Struct_bladerf, isize> {
	unsafe {
		let device_ptr: *mut Struct_bladerf = mem::uninitialized();
		let unsafe_devinfo: *const Struct_bladerf_devinfo = devinfo as *const Struct_bladerf_devinfo;

		let res = bladerf_open_with_devinfo(&device_ptr, unsafe_devinfo) as isize;

		if res >= 0 {
			Ok(device_ptr)
		} else {
			Err(res)
		}
	}
}

pub fn fw_version(dev: *mut Struct_bladerf) -> Result<Struct_bladerf_version, isize> {
	unsafe {
		let mut version: Struct_bladerf_version = mem::uninitialized();

		let res = bladerf_fw_version(dev, &mut version as *mut Struct_bladerf_version) as isize;

		if res >= 0 {
			Ok(version)
		} else {
			Err(res)
		}
	}
}

pub fn fpga_version(dev: *mut Struct_bladerf) -> Result<Struct_bladerf_version, isize> {
	unsafe {
		let mut version: Struct_bladerf_version = mem::uninitialized();

		let res = bladerf_fpga_version(dev, &mut version as *mut Struct_bladerf_version) as isize;

		if res >= 0 {
			Ok(version)
		} else {
			Err(res)
		}
	}
}

pub fn get_serial(dev: *mut Struct_bladerf) -> Result<String, isize> {
	unsafe {
		// Create raw data array for serial return
		let serial_data : Vec<::libc::c_char> = vec![0; 33];

		// Call underlying c method
		let res = bladerf_get_serial(dev, serial_data.as_ptr()) as isize;

		if res >= 0 {
			// Map ::libc::c_char back to u8 as required for string manipulation
			let serial_u8: Vec<u8>= serial_data.iter().map(|&x| x as u8).collect();

			// Build String
			let serial_cstr = ffi::CString::from_vec_unchecked(serial_u8);
			let serial_str = serial_cstr.into_string().unwrap();

			Ok(serial_str)
		} else {
			Err(res as isize)
		}
	}
}

pub fn close_device(device: *mut Struct_bladerf) {
	unsafe {
		bladerf_close(device)
	}
}

#[cfg(test)]
mod tests {

	#[test]
	fn list_devices() {
		match super::get_device_list() {
			Ok(devices) => {
				println!("Discovered {:?} devices", devices.len());
			},
			Err(code) => {
				println!("Error {:?} listing devices", code);
				assert!(false);
			}
		}
	}

	#[test]
	fn get_version() {
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();
		let version = super::fw_version(device).unwrap();
		println!("Version {:?}", version);
		super::close_device(device);
	}

	#[test]
	fn get_serial() {
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();
		let serial = super::get_serial(device).unwrap();
		println!("Serial: {:?}", serial);
		assert!(serial.len() == 33);
		super::close_device(device);
	}

}
<commit_msg>All the functions Well, some of them. Working towards being useful.<commit_after>extern crate libc;

use std::*;
use libc::*;

#[allow(dead_code, non_camel_case_types)]
mod bladerf;
use bladerf::*;

// Macro to simplify integer returns
macro_rules! handle_res {
    ($res:expr) => (
    	if $res >= 0 {
			Ok($res as isize)
		} else {
			Err($res as isize)
		}
	);
	($res:expr, $out: expr) => (
		if $res >= 0 {
			Ok($out)
		} else {
			Err($res as isize)
		}
	);
}

pub struct BladerfDevice {
    pub device: *mut *mut Struct_bladerf,
}

//impl fmt::Display for Struct_bladerf_devinfo {
//    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//        write!(f, "serial: UNIMPLEMENTED, bus: {}, address: {})", self.usb_bus, self.usb_addr)
//    }
//}

pub fn get_device_list() -> Result<Vec<Struct_bladerf_devinfo>, isize> {

	unsafe{
		let devices: *mut Struct_bladerf_devinfo = mem::uninitialized();

		let n = bladerf_get_device_list(&devices) as isize;

		// Catch bladerf function errors
		if n > 0 {

			// Cast array to slice and create a safe array to return
			let device_slice = std::slice::from_raw_parts(devices, n as usize);
			let mut safe_device_list: Vec<Struct_bladerf_devinfo> = Vec::new();

			for i in 0..n {
				let local_device = device_slice[i as usize];
				//Safe if this is a copy, unsafe if it is not?
				safe_device_list.push(local_device);
			}
			bladerf_free_device_list(devices);

			// Return rust save device info array
			Ok(safe_device_list)

		} else {
			// Return error code
			Err(n)
		}
	}
}

pub fn set_usb_reset_on_open(enabled: bool) {
    unsafe{
    	bladerf_set_usb_reset_on_open(enabled as uint8_t);
    }
}

pub fn open_with_devinfo(devinfo: &Struct_bladerf_devinfo) -> Result<*mut Struct_bladerf, isize> {
	unsafe {
		let device_ptr: *mut Struct_bladerf = mem::uninitialized();
		let unsafe_devinfo: *const Struct_bladerf_devinfo = devinfo as *const Struct_bladerf_devinfo;

		let res = bladerf_open_with_devinfo(&device_ptr, unsafe_devinfo) as isize;

		if res >= 0 {
			Ok(device_ptr)
		} else {
			Err(res)
		}
	}
}

pub fn fw_version(dev: *mut Struct_bladerf) -> Result<Struct_bladerf_version, isize> {
	unsafe {
		let mut version: Struct_bladerf_version = mem::uninitialized();

		let res = bladerf_fw_version(dev, &mut version as *mut Struct_bladerf_version) as isize;

		if res >= 0 {
			Ok(version)
		} else {
			Err(res)
		}
	}
}

pub fn fpga_version(dev: *mut Struct_bladerf) -> Result<Struct_bladerf_version, isize> {
	unsafe {
		let mut version: Struct_bladerf_version = mem::uninitialized();

		let res = bladerf_fpga_version(dev, &mut version as *mut Struct_bladerf_version) as isize;

		if res >= 0 {
			Ok(version)
		} else {
			Err(res)
		}
	}
}

pub fn get_serial(dev: *mut Struct_bladerf) -> Result<String, isize> {
	unsafe {
		// Create raw data array for serial return
		let serial_data : Vec<::libc::c_char> = vec![0; 33];

		// Call underlying c method
		let res = bladerf_get_serial(dev, serial_data.as_ptr()) as isize;

		if res >= 0 {
			// Map ::libc::c_char back to u8 as required for string manipulation
			let serial_u8: Vec<u8>= serial_data.iter().map(|&x| x as u8).collect();

			// Build String
			let serial_cstr = ffi::CString::from_vec_unchecked(serial_u8);
			let serial_str = serial_cstr.into_string().unwrap();

			Ok(serial_str)
		} else {
			Err(res as isize)
		}
	}
}

pub fn enable_module(device: *mut Struct_bladerf, module: bladerf_module, enable: bool) -> Result<isize, isize> {
	unsafe {
		let res = bladerf_enable_module(device, module, enable as u8) as isize;

		if res >= 0 {
			Ok(res)
		} else {
			Err(res as isize)
		}
	}
}

pub fn set_loopback(device: *mut Struct_bladerf, loopback: bladerf_loopback) -> Result<isize, isize> {
	unsafe {
		let res = bladerf_set_loopback(device, loopback) as isize;

		if res >= 0 {
			Ok(res)
		} else {
			Err(res as isize)
		}
	}
}

pub fn get_loopback(device: *mut Struct_bladerf) -> Result<bladerf_loopback, isize> {
	unsafe {
		let mut loopback: bladerf_loopback = mem::uninitialized();;
		let loopback_ptr: *mut bladerf_loopback = &mut loopback;

		let res = bladerf_get_loopback(device, loopback_ptr) as isize;

		if res >= 0 {
			Ok(loopback)
		} else {
			Err(res as isize)
		}
	}
}

pub fn select_band(device: *mut Struct_bladerf, module: bladerf_module, frequency: u32) -> Result<isize, isize> {
	unsafe {
		let res = bladerf_select_band(device, module, frequency) as isize;

		if res >= 0 {
			Ok(res as isize)
		} else {
			Err(res as isize)
		}
	}
}

pub fn set_frequency(device: *mut Struct_bladerf, module: bladerf_module, frequency: u32) -> Result<isize, isize> {
	unsafe {
		let res = bladerf_set_frequency(device, module, frequency) as isize;

		if res >= 0 {
			Ok(res as isize)
		} else {
			Err(res as isize)
		}
	}
}

pub fn get_frequency(device: *mut Struct_bladerf, module: bladerf_module) -> Result<u32, isize> {
	unsafe {
		let mut freq: u32 = 0;
		let freq_ptr: *mut u32 = &mut freq;

		let res = bladerf_get_frequency(device, module, freq_ptr) as isize;

		if res >= 0 {
			Ok(freq)
		} else {
			Err(res as isize)
		}
	}
}

pub fn schedule_retune(device: *mut Struct_bladerf, module: bladerf_module, time: u64, frequency: u32, quick_tune: Option<Struct_bladerf_quick_tune>) -> Result<isize, isize> {
	unsafe {

		let mut quick_tune_int: Struct_bladerf_quick_tune;
		let p: *mut Struct_bladerf_quick_tune;

		// Check whether quick tune exists and map pointer as appropriate
		match quick_tune {
			Some(qt) => {
				quick_tune_int = qt;
				p = &mut quick_tune_int;
			},
			None => {
				p = ptr::null_mut();
			}
		}

		// Call underlying function
		let res = bladerf_schedule_retune(device, module, time, frequency, p) as isize;

		// Process response
		handle_res!(res)
	}
}

pub fn cancel_scheduled_retune(device: *mut Struct_bladerf, module: bladerf_module) -> Result<isize, isize> {
	unsafe {
		let res = bladerf_cancel_scheduled_retunes(device, module) as isize;

		if res >= 0 {
			Ok(res as isize)
		} else {
			Err(res as isize)
		}
	}
}

pub fn get_quick_tune(device: *mut Struct_bladerf, module: bladerf_module) -> Result<Struct_bladerf_quick_tune, isize> {
	unsafe {
		let mut quick_tune: Struct_bladerf_quick_tune = mem::uninitialized();
		let quick_tune_ptr: *mut Struct_bladerf_quick_tune = &mut quick_tune;

		let res = bladerf_get_quick_tune(device, module, quick_tune_ptr) as isize;

		if res >= 0 {
			Ok(quick_tune)
		} else {
			Err(res as isize)
		}
	}
}

pub fn set_tuning_mode(device: *mut Struct_bladerf, mode: bladerf_tuning_mode) -> Result<isize, isize> {
	unsafe {
		let res = bladerf_set_tuning_mode(device, mode) as isize;

		if res >= 0 {
			Ok(res as isize)
		} else {
			Err(res as isize)
		}
	}
}

pub fn close_device(device: *mut Struct_bladerf) {
	unsafe {
		bladerf_close(device)
	}
}

#[cfg(test)]
mod tests {

	#[test]
	fn list_devices() {
		match super::get_device_list() {
			Ok(devices) => {
				println!("Discovered {:?} devices", devices.len());
			},
			Err(code) => {
				println!("Error {:?} listing devices", code);
				assert!(false);
			}
		}
	}

	#[test]
	fn get_version() {
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();
		let version = super::fw_version(device).unwrap();
		println!("Version {:?}", version);
		super::close_device(device);
	}

	#[test]
	fn get_serial() {
		let devices = super::get_device_list().unwrap();
		assert!(devices.len() != 0);
		let device = super::open_with_devinfo(&devices[0]).unwrap();
		let serial = super::get_serial(device).unwrap();
		println!("Serial: {:?}", serial);
		assert!(serial.len() == 33);
		super::close_device(device);
	}

}
<|endoftext|>


<commit_before>extern crate fringe;
extern crate tokio_core;
#[macro_use(task_local)]
extern crate futures;

use futures::Async;

use std::cell::{RefCell, UnsafeCell};

/// Convenient macro to suspend and retry async operation
/// just as it was blocking operation
#[macro_export]
macro_rules! poll {
    ($e:expr) => {{
        let res;
        loop {
             match $e {
                Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => {
                    $crate::yield_now();
                }
                other => {
                    res = Some(other);
                    break
                },
            }
        }
        res.unwrap()
        }}
}

task_local! {
    static TL_YIELDER : RefCell<Vec<YielderRefStore>> = RefCell::new(vec!())
}

// Unsafe magic to for task-local yidler
//
// TODO: Need wiser people to verify this not not buggy
//
// `fringe` gives coroutine `&'a mut Yielder<I, O>`
//
// to have access to it from `yield_now`, use
// an escape hatch and be extremely careful
struct YielderRefStore(UnsafeCell<&'static Yield>);

impl YielderRefStore {
    unsafe fn new<'a>(y : &'a Yield) -> YielderRefStore {
        YielderRefStore (
             UnsafeCell::new(std::mem::transmute(y))
        )
    }
}

unsafe impl Send for YielderRefStore {}

// Wrapper over `fringe::Yielder` to make put it in `task_local`
trait Yield {
    fn suspend(&self);
}

impl<I : Send, O : Send, E : Send> Yield for fringe::generator::Yielder<I, SuspendCommand<O, E>> {
    fn suspend(&self) {
        let _ = self.suspend(Ok(Async::NotReady));
    }
}
// We wake up coroutine passing this to it's inside
enum ResumeCommand {
    Unblock
}

// We suspend coroutine passing this to the outside
pub type SuspendCommand<O, E> = futures::Poll<O, E>;

unsafe fn yielder_tl_push(y : &Yield) {
    TL_YIELDER.with(|tl_yielder| {
        let mut tl_yielder = tl_yielder.borrow_mut();
        tl_yielder.push(YielderRefStore::new(y));
    });
}

unsafe fn yielder_tl_pop() -> &'static Yield {
    let yielder : YielderRefStore  = TL_YIELDER.with(|tl_yielder| {
        let mut tl_yielder = tl_yielder.borrow_mut();
        tl_yielder.pop().unwrap()
    });

    yielder.0.into_inner()
}

pub fn yield_now() {
    let y = unsafe { yielder_tl_pop() };

    y.suspend();

    unsafe { yielder_tl_push(y) }
}

pub struct Fiber<'a, O : Send+'a, E : Send+'a> {
    co : fringe::Generator<'a, ResumeCommand, SuspendCommand<O, E>, fringe::OsStack>,
}

impl<'a, O : Send, E : Send> Fiber<'a, O, E> {
    pub fn new<F>(f : F) -> Self
        where
        F: FnOnce() -> Result<O, E> + Send +'a {
            let stack = fringe::OsStack::new(1 << 20).unwrap();
            let gen = fringe::Generator::new(stack, move |yielder, _resume_cmd : ResumeCommand| {
                unsafe { yielder_tl_push(yielder) };

                let res = f();

                // pop the `Yield`, but use the "typed" version
                let _pop_and_discard = unsafe { yielder_tl_pop() };
                // TODO: can any optimizations prevent `yielder` to see
                // changes introduced when task-local version was used?

                yielder.suspend(match res {
                    Ok(t) => Ok(Async::Ready(t)),
                    Err(e) => Err(e)
                });
            });

            Fiber {
                co : gen
            }
         }
}

impl<'a, O : Send, E : Send> futures::Future for Fiber<'a, O, E> {
    type Item = O;
    type Error = E;
    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.co.resume(ResumeCommand::Unblock).expect("poll on finished Fiber is illegal")
    }
}
<commit_msg>Add `await`<commit_after>extern crate fringe;
extern crate tokio_core;
#[macro_use(task_local)]
extern crate futures;

use futures::Async;

use std::cell::{RefCell, UnsafeCell};

/// Convenient macro to suspend and retry async operation
/// just as it was blocking operation
#[macro_export]
macro_rules! poll {
    ($e:expr) => {{
        let res;
        loop {
             match $e {
                Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => {
                    $crate::yield_now();
                }
                other => {
                    res = Some(other);
                    break
                },
            }
        }
        res.unwrap()
        }}
}

task_local! {
    static TL_YIELDER : RefCell<Vec<YielderRefStore>> = RefCell::new(vec!())
}

// Unsafe magic to for task-local yidler
//
// TODO: Need wiser people to verify this not not buggy
//
// `fringe` gives coroutine `&'a mut Yielder<I, O>`
//
// to have access to it from `yield_now`, use
// an escape hatch and be extremely careful
struct YielderRefStore(UnsafeCell<&'static Yield>);

impl YielderRefStore {
    unsafe fn new<'a>(y : &'a Yield) -> YielderRefStore {
        YielderRefStore (
             UnsafeCell::new(std::mem::transmute(y))
        )
    }
}

unsafe impl Send for YielderRefStore {}

// Wrapper over `fringe::Yielder` to make put it in `task_local`
trait Yield {
    fn suspend(&self);
}

impl<I : Send, O : Send, E : Send> Yield for fringe::generator::Yielder<I, SuspendCommand<O, E>> {
    fn suspend(&self) {
        let _ = self.suspend(Ok(Async::NotReady));
    }
}
// We wake up coroutine passing this to it's inside
enum ResumeCommand {
    Unblock
}

// We suspend coroutine passing this to the outside
pub type SuspendCommand<O, E> = futures::Poll<O, E>;

unsafe fn yielder_tl_push(y : &Yield) {
    TL_YIELDER.with(|tl_yielder| {
        let mut tl_yielder = tl_yielder.borrow_mut();
        tl_yielder.push(YielderRefStore::new(y));
    });
}

unsafe fn yielder_tl_pop() -> &'static Yield {
    let yielder : YielderRefStore  = TL_YIELDER.with(|tl_yielder| {
        let mut tl_yielder = tl_yielder.borrow_mut();
        tl_yielder.pop().unwrap()
    });

    yielder.0.into_inner()
}

pub struct Fiber<'a, O : Send+'a, E : Send+'a> {
    co : fringe::Generator<'a, ResumeCommand, SuspendCommand<O, E>, fringe::OsStack>,
}

impl<'a, O : Send, E : Send> Fiber<'a, O, E> {
    pub fn new<F>(f : F) -> Self
        where
        F: FnOnce() -> Result<O, E> + Send +'a {
            let stack = fringe::OsStack::new(1 << 20).unwrap();
            let gen = fringe::Generator::new(stack, move |yielder, _resume_cmd : ResumeCommand| {
                unsafe { yielder_tl_push(yielder) };

                let res = f();

                // pop the `Yield`, but use the "typed" version
                let _pop_and_discard = unsafe { yielder_tl_pop() };
                // TODO: can any optimizations prevent `yielder` to see
                // changes introduced when task-local version was used?

                yielder.suspend(match res {
                    Ok(t) => Ok(Async::Ready(t)),
                    Err(e) => Err(e)
                });
            });

            Fiber {
                co : gen
            }
         }
}

impl<'a, O : Send, E : Send> futures::Future for Fiber<'a, O, E> {
    type Item = O;
    type Error = E;
    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.co.resume(ResumeCommand::Unblock).expect("poll on finished Fiber is illegal")
    }
}

/// Yield the current fiber
///
/// Block current fiber. It will be resumed and thus this function will return,
/// when the event loop decides it might be ready. This includes: previously
/// blocked IO becoming unblocked etc.
pub fn yield_now() {
    let y = unsafe { yielder_tl_pop() };

    y.suspend();

    unsafe { yielder_tl_push(y) }
}

/// Block current fiber to wait for result of another future
pub fn await<F: futures::Future>(mut f: F) -> Result<F::Item, F::Error> {
    loop {
        match f.poll() {
            Ok(Async::NotReady) => yield_now(),
            Ok(Async::Ready(val)) => return Ok(val),
            Err(e) => return Err(e),
        };
    }
}
<|endoftext|>


<commit_before>//! # aHash
//!
//! This hashing algorithm is intended to be a high performance, (hardware specific), keyed hash function.
//! This can be seen as a DOS resistant alternative to FxHash, or a fast equivalent to SipHash.
//! It provides a high speed hash algorithm, but where the result is not predictable without knowing a Key.
//! This allows it to be used in a HashMap without allowing for the possibility that an malicious user can
//! induce a collision.
//!
//! # How aHash works
//!
//! aHash uses the hardware AES instruction on x86 processors to provide a keyed hash function.
//! It uses two rounds of AES per hash. So it should not be considered cryptographically secure.

#![feature(core_intrinsics)]
extern crate const_random;
extern crate arrayref;

#[macro_use]
mod convert;

mod fallback_hash;
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
mod aes_hash;
#[cfg(test)]
mod hash_quality_test;

use const_random::const_random;
use std::collections::HashMap;
use std::hash::{BuildHasher};

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
pub use crate::aes_hash::AHasher;

#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
pub use crate::fallback_hash::AHasher;

/// A `HashMap` using a `BuildHasherDefault` BuildHasher to hash the items.
pub type AHashMap<K, V> = HashMap<K, V, ABuildHasher>;

///Const random provides randomized keys with no runtime cost.
const DEFAULT_KEYS: [u64; 2] = [const_random!(u64), const_random!(u64)];

/// Provides a default [Hasher] compile time generated constants for keys.
/// This is typically used in conjunction with [BuildHasherDefault] to create
/// [AHasher]s in order to hash the keys of the map.
///
/// # Example
/// ```
/// use std::hash::BuildHasherDefault;
/// use ahash::{AHasher, ABuildHasher};
/// use std::collections::HashMap;
///
/// let mut map: HashMap<i32, i32, ABuildHasher> = HashMap::default();
/// map.insert(12, 34);
/// ```
///
/// [BuildHasherDefault]: std::hash::BuildHasherDefault
/// [Hasher]: std::hash::Hasher
/// [HashMap]: std::collections::HashMap
impl Default for AHasher {

    /// Constructs a new [AHasher] with compile time generated constants for keys.
    /// This means the keys will be the same from one instance to another,
    /// but different from build to the next. So if it is possible for a potential
    /// attacker to have access to the compiled binary it would be better
    /// to specify keys generated at runtime.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::AHasher;
    /// use std::hash::Hasher;
    ///
    /// let mut hasher_1 = AHasher::default();
    /// let mut hasher_2 = AHasher::default();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    /// ```
    #[inline]
    fn default() -> AHasher {
        AHasher::new_with_key(DEFAULT_KEYS, 0)
    }
}

/// Provides a [Hasher] factory. This is typically used (e.g. by [HashMap]) to create
/// [AHasher]s in order to hash the keys of the map. See `build_hasher` below.
///
/// [build_hasher]: ahash::
/// [Hasher]: std::hash::Hasher
/// [BuildHasher]: std::hash::BuildHasher
/// [HashMap]: std::collections::HashMap
pub struct ABuildHasher{}

impl ABuildHasher {
    #[inline]
    pub fn new() -> ABuildHasher {
        ABuildHasher{}
    }
}

impl Default for ABuildHasher {
    #[inline]
    fn default() -> ABuildHasher {
        ABuildHasher{}
    }
}

impl BuildHasher for ABuildHasher {
    type Hasher = AHasher;

    /// Constructs a new [AHasher] with keys based on compile time generated constants and the location
    /// of the this object in memory. This means that two different [BuildHasher]s will will generate
    /// [AHasher]s that will return different hashcodes, but [Hasher]s created from the same [BuildHasher]
    /// will generate the same hashes for the same input data.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::{AHasher, ABuildHasher};
    /// use std::hash::{Hasher, BuildHasher};
    ///
    /// let build_hasher = ABuildHasher::new();
    /// let mut hasher_1 = build_hasher.build_hasher();
    /// let mut hasher_2 = build_hasher.build_hasher();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    ///
    /// let other_build_hasher = ABuildHasher::new();
    /// let mut different_hasher = other_build_hasher.build_hasher();
    /// different_hasher.write_u32(1234);
    /// assert_ne!(different_hasher.finish(), hasher_1.finish());
    /// ```
    /// [Hasher]: std::hash::Hasher
    /// [BuildHasher]: std::hash::BuildHasher
    /// [HashMap]: std::collections::HashMap
    #[inline]
    fn build_hasher(&self) -> AHasher {
        let mem_loc = self as *const _ as usize;
        #[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
        return AHasher::new_with_key(DEFAULT_KEYS[0], mem_loc as u64);
        #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
        return AHasher::new_with_key(DEFAULT_KEYS, mem_loc);
    }
}

#[inline(never)]
#[no_mangle]
fn hash_test_final(input: usize) -> u64 {
    use std::hash::{Hasher};
    let builder = ABuildHasher::default();
    let mut hasher = builder.build_hasher();
    hasher.write_usize(input);
    hasher.finish()
}

#[cfg(test)]
mod test {
    use std::hash::BuildHasherDefault;
    use crate::convert::Convert;
    use crate::*;

    #[test]
    fn test_default_builder() {
        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }
    #[test]
    fn test_builder() {
        let mut map = HashMap::<u32, u64, ABuildHasher>::default();
        map.insert(1, 3);
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }
}
<commit_msg>Fix bug in fallback path<commit_after>//! # aHash
//!
//! This hashing algorithm is intended to be a high performance, (hardware specific), keyed hash function.
//! This can be seen as a DOS resistant alternative to FxHash, or a fast equivalent to SipHash.
//! It provides a high speed hash algorithm, but where the result is not predictable without knowing a Key.
//! This allows it to be used in a HashMap without allowing for the possibility that an malicious user can
//! induce a collision.
//!
//! # How aHash works
//!
//! aHash uses the hardware AES instruction on x86 processors to provide a keyed hash function.
//! It uses two rounds of AES per hash. So it should not be considered cryptographically secure.

#![feature(core_intrinsics)]
extern crate const_random;
extern crate arrayref;

#[macro_use]
mod convert;

mod fallback_hash;
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
mod aes_hash;
#[cfg(test)]
mod hash_quality_test;

use const_random::const_random;
use std::collections::HashMap;
use std::hash::{BuildHasher};

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
pub use crate::aes_hash::AHasher;

#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
pub use crate::fallback_hash::AHasher;

/// A `HashMap` using a `BuildHasherDefault` BuildHasher to hash the items.
pub type AHashMap<K, V> = HashMap<K, V, ABuildHasher>;

///Const random provides randomized keys with no runtime cost.
const DEFAULT_KEYS: [u64; 2] = [const_random!(u64), const_random!(u64)];

/// Provides a default [Hasher] compile time generated constants for keys.
/// This is typically used in conjunction with [BuildHasherDefault] to create
/// [AHasher]s in order to hash the keys of the map.
///
/// # Example
/// ```
/// use std::hash::BuildHasherDefault;
/// use ahash::{AHasher, ABuildHasher};
/// use std::collections::HashMap;
///
/// let mut map: HashMap<i32, i32, ABuildHasher> = HashMap::default();
/// map.insert(12, 34);
/// ```
///
/// [BuildHasherDefault]: std::hash::BuildHasherDefault
/// [Hasher]: std::hash::Hasher
/// [HashMap]: std::collections::HashMap
impl Default for AHasher {

    /// Constructs a new [AHasher] with compile time generated constants for keys.
    /// This means the keys will be the same from one instance to another,
    /// but different from build to the next. So if it is possible for a potential
    /// attacker to have access to the compiled binary it would be better
    /// to specify keys generated at runtime.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::AHasher;
    /// use std::hash::Hasher;
    ///
    /// let mut hasher_1 = AHasher::default();
    /// let mut hasher_2 = AHasher::default();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    /// ```
    #[inline]
    fn default() -> AHasher {
        #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
        return AHasher::new_with_key(DEFAULT_KEYS, 0);
        #[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
        return AHasher::new_with_key(DEFAULT_KEYS[0], 0);
    }
}

/// Provides a [Hasher] factory. This is typically used (e.g. by [HashMap]) to create
/// [AHasher]s in order to hash the keys of the map. See `build_hasher` below.
///
/// [build_hasher]: ahash::
/// [Hasher]: std::hash::Hasher
/// [BuildHasher]: std::hash::BuildHasher
/// [HashMap]: std::collections::HashMap
pub struct ABuildHasher{}

impl ABuildHasher {
    #[inline]
    pub fn new() -> ABuildHasher {
        ABuildHasher{}
    }
}

impl Default for ABuildHasher {
    #[inline]
    fn default() -> ABuildHasher {
        ABuildHasher{}
    }
}

impl BuildHasher for ABuildHasher {
    type Hasher = AHasher;

    /// Constructs a new [AHasher] with keys based on compile time generated constants and the location
    /// of the this object in memory. This means that two different [BuildHasher]s will will generate
    /// [AHasher]s that will return different hashcodes, but [Hasher]s created from the same [BuildHasher]
    /// will generate the same hashes for the same input data.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::{AHasher, ABuildHasher};
    /// use std::hash::{Hasher, BuildHasher};
    ///
    /// let build_hasher = ABuildHasher::new();
    /// let mut hasher_1 = build_hasher.build_hasher();
    /// let mut hasher_2 = build_hasher.build_hasher();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    ///
    /// let other_build_hasher = ABuildHasher::new();
    /// let mut different_hasher = other_build_hasher.build_hasher();
    /// different_hasher.write_u32(1234);
    /// assert_ne!(different_hasher.finish(), hasher_1.finish());
    /// ```
    /// [Hasher]: std::hash::Hasher
    /// [BuildHasher]: std::hash::BuildHasher
    /// [HashMap]: std::collections::HashMap
    #[inline]
    fn build_hasher(&self) -> AHasher {
        let mem_loc = self as *const _ as usize;
        #[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
        return AHasher::new_with_key(DEFAULT_KEYS[0], mem_loc as u64);
        #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
        return AHasher::new_with_key(DEFAULT_KEYS, mem_loc);
    }
}

#[inline(never)]
#[no_mangle]
fn hash_test_final(input: usize) -> u64 {
    use std::hash::{Hasher};
    let builder = ABuildHasher::default();
    let mut hasher = builder.build_hasher();
    hasher.write_usize(input);
    hasher.finish()
}

#[cfg(test)]
mod test {
    use std::hash::BuildHasherDefault;
    use crate::convert::Convert;
    use crate::*;

    #[test]
    fn test_default_builder() {
        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }
    #[test]
    fn test_builder() {
        let mut map = HashMap::<u32, u64, ABuildHasher>::default();
        map.insert(1, 3);
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }
}
<|endoftext|>


<commit_before>#![feature(custom_derive, plugin, rustc_macro)]
#![cfg_attr(test, feature(test))]
#[cfg(test)]
extern crate test;

#[macro_use] extern crate nom;
#[macro_use] extern crate log;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate serde_derive;
extern crate mio;
extern crate bytes;
extern crate time;
extern crate serde;
extern crate serde_json;
extern crate rand;
extern crate openssl;
extern crate pool;
extern crate uuid;
extern crate net2;
extern crate libc;
extern crate slab;

pub mod network;
pub mod parser;
pub mod messages;
<commit_msg>missing compiler feature for current nightly and serde_derive<commit_after>#![feature(custom_derive, plugin, rustc_macro, proc_macro)]
#![cfg_attr(test, feature(test))]
#[cfg(test)]
extern crate test;

#[macro_use] extern crate nom;
#[macro_use] extern crate log;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate serde_derive;
extern crate mio;
extern crate bytes;
extern crate time;
extern crate serde;
extern crate serde_json;
extern crate rand;
extern crate openssl;
extern crate pool;
extern crate uuid;
extern crate net2;
extern crate libc;
extern crate slab;

pub mod network;
pub mod parser;
pub mod messages;
<|endoftext|>