<commit_before>
use std::fmt;
use std::ops::{Add, Div, Mul, Neg, Sub};

extern crate num;
use num::{Num, Float, Zero, One};

#[cfg(test)]
use std::f32::consts;
#[cfg(test)]
use std::f32;

/// Dual Numbers
#[derive(Copy, Clone, PartialEq, Hash, Debug)]
pub struct Dual<F> {
    pub real: F,
    pub dual: F,
}

pub type Dual32 = Dual<f32>;
pub type Dual64 = Dual<f64>;

impl<F: Copy + Num> Dual<F> {
    pub fn new(real: F, deriv: F) -> Dual<F> {
        Dual {
            real: real,
            dual: deriv,
        }
    }

    pub fn derivative(self) -> F {
        self.dual
    }
}

impl<F: Copy + Num> Zero for Dual<F> {
    fn zero() -> Dual<F> {
        Dual::new(F::zero(), F::zero())
    }

    fn is_zero(&self) -> bool {
        self.real.is_zero() && self.dual.is_zero()
    }
}

impl<F: Copy + Num> One for Dual<F> {
    fn one() -> Dual<F> {
        Dual::new(One::one(), One::one())
    }
}

impl<F: Copy + Num> Add<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn add(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real + other.real, self.dual + other.dual)
    }
}

#[test]
fn test_add_struct() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(2.0, 3.0);

    let z = x + y;
    assert!(z.real == 5.0);
    assert!(z.dual == 7.0);
}

impl<F: Copy + Num> Sub<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn sub(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real - other.real, self.dual - other.dual)
    }
}

#[test]
fn test_sub() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(2.0, 12.0);

    let z = x - y;
    assert!(z.real == 1.0);
    assert!(z.dual == -8.0);
}

impl<F: Copy + Num + Neg<Output = F>> Neg for Dual<F> {
    type Output = Dual<F>;

    fn neg(self) -> Dual<F> {
        Dual::new(-self.real, -self.dual)
    }
}

#[test]
fn test_neg_plus() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(2.0, 12.0);

    let z1 = x - y;
    let z2 = x + (-y);
    assert!(z1 == z2);
}

#[test]
fn test_neg_zero() {
    let x = Dual::new(3.0, 4.0);
    let zero: Dual32 = Zero::zero();

    let z1 = -x;
    let z2 = zero - x;
    assert!(z1 == z2);
}

impl<F: Copy + Num> Mul<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn mul(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real * other.real,
                  (self.real * other.dual) + (self.dual * other.real))
    }
}

#[test]
fn test_mul() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(1.0, 2.0);

    let z = x * y;
    assert!(z.real == 3.0);
    assert!(z.dual == 10.0);
}

impl<F: Copy + Num> Div<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn div(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real / other.real,
                  ((self.dual * other.real) - (self.real * other.dual)) / (other.real * other.real))
    }
}

#[test]
fn test_div() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(1.0, 2.0);

    let z = x / y;
    assert!(z.real == 3.0);
    assert!(z.dual == -2.0);
}

impl<F: Copy + Float> Dual<F> {
    pub fn sin(self) -> Dual<F> {
        Dual::new(self.real.sin(), self.dual * self.real.cos())
    }

    pub fn cos(self) -> Dual<F> {
        Dual::new(self.real.cos(), (-F::one()) * self.dual * self.real.sin())
    }

    pub fn tan(self) -> Dual<F> {
        self.sin() / self.cos()
    }

    pub fn exp(self) -> Dual<F> {
        Dual::new(self.real.exp(), self.dual * self.real.exp())
    }

    pub fn ln(self) -> Dual<F> {
        Dual::new(self.real.ln(), self.dual / self.real)
    }

    pub fn sqrt(self) -> Dual<F> {
        let two = F::one() + F::one();
        Dual::new(self.real.sqrt(),
                  self.dual / (two * self.real.sqrt()))
    }
}

impl<F: Copy + Num> From<F> for Dual<F> {
    fn from(real: F) -> Dual<F> {
        Dual::new(real, F::one())
    }
}

impl<F> fmt::Display for Dual<F>
    where F: fmt::Display + Num + PartialOrd + Copy
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.real < Zero::zero() {
            write!(f, "{}-{}ε", self.real, F::zero() - self.dual)
        } else {
            write!(f, "{}+{}ε", self.real, self.dual)
        }
    }
}

#[cfg(test)]
fn diff(x : f32, y : f32) -> f32 {
    (x - y).abs()
}

#[test]
fn test_sin() {
    let x: Dual32 = From::from(0.0);
    let y = x.sin();

    let real_diff = diff(y.real, 0.0);
    let dual_diff = diff(y.dual, 1.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_cos() {
    let x: Dual32 = From::from(consts::PI);
    let y = x.cos();

    let real_diff = diff(y.real, -1.0);
    let dual_diff = diff(y.dual, 0.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_tan() {
    let x: Dual32 = From::from(0.0);
    let y = x.tan();

    let real_diff = diff(y.real, 0.0);
    let dual_diff = diff(y.dual, 1.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_exp() {
    let x: Dual32 = From::from(1.0);
    let y = x.exp();

    let real_diff = diff(y.real, consts::E);
    let dual_diff = diff(y.dual, consts::E);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_ln() {
    let x: Dual32 = From::from(1.0);
    let y = x.ln();

    let real_diff = diff(y.real, 0.0);
    let dual_diff = diff(y.dual, 1.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_sqrt() {
    let x: Dual32 = From::from(4.0);
    let y = x.sqrt();

    println!("{}", y);

    let real_diff = diff(y.real, 2.0);
    let dual_diff = diff(y.dual, 0.25);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}
<commit_msg>Formatting<commit_after>
use std::fmt;
use std::ops::{Add, Div, Mul, Neg, Sub};

extern crate num;
use num::{Num, Float, Zero, One};

#[cfg(test)]
use std::f32::consts;
#[cfg(test)]
use std::f32;

/// Dual Numbers
#[derive(Copy, Clone, PartialEq, Hash, Debug)]
pub struct Dual<F> {
    pub real: F,
    pub dual: F,
}

pub type Dual32 = Dual<f32>;
pub type Dual64 = Dual<f64>;

impl<F: Copy + Num> Dual<F> {
    pub fn new(real: F, deriv: F) -> Dual<F> {
        Dual {
            real: real,
            dual: deriv,
        }
    }

    pub fn derivative(self) -> F {
        self.dual
    }
}

impl<F: Copy + Num> Zero for Dual<F> {
    fn zero() -> Dual<F> {
        Dual::new(F::zero(), F::zero())
    }

    fn is_zero(&self) -> bool {
        self.real.is_zero() && self.dual.is_zero()
    }
}

impl<F: Copy + Num> One for Dual<F> {
    fn one() -> Dual<F> {
        Dual::new(One::one(), One::one())
    }
}

impl<F: Copy + Num> Add<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn add(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real + other.real, self.dual + other.dual)
    }
}

#[test]
fn test_add_struct() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(2.0, 3.0);

    let z = x + y;
    assert!(z.real == 5.0);
    assert!(z.dual == 7.0);
}

impl<F: Copy + Num> Sub<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn sub(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real - other.real, self.dual - other.dual)
    }
}

#[test]
fn test_sub() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(2.0, 12.0);

    let z = x - y;
    assert!(z.real == 1.0);
    assert!(z.dual == -8.0);
}

impl<F: Copy + Num + Neg<Output = F>> Neg for Dual<F> {
    type Output = Dual<F>;

    fn neg(self) -> Dual<F> {
        Dual::new(-self.real, -self.dual)
    }
}

#[test]
fn test_neg_plus() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(2.0, 12.0);

    let z1 = x - y;
    let z2 = x + (-y);
    assert!(z1 == z2);
}

#[test]
fn test_neg_zero() {
    let x = Dual::new(3.0, 4.0);
    let zero: Dual32 = Zero::zero();

    let z1 = -x;
    let z2 = zero - x;
    assert!(z1 == z2);
}

impl<F: Copy + Num> Mul<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn mul(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real * other.real,
                  (self.real * other.dual) + (self.dual * other.real))
    }
}

#[test]
fn test_mul() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(1.0, 2.0);

    let z = x * y;
    assert!(z.real == 3.0);
    assert!(z.dual == 10.0);
}

impl<F: Copy + Num> Div<Dual<F>> for Dual<F> {
    type Output = Dual<F>;

    fn div(self, other: Dual<F>) -> Dual<F> {
        Dual::new(self.real / other.real,
                  ((self.dual * other.real) - (self.real * other.dual)) / (other.real * other.real))
    }
}

#[test]
fn test_div() {
    let x = Dual::new(3.0, 4.0);
    let y = Dual::new(1.0, 2.0);

    let z = x / y;
    assert!(z.real == 3.0);
    assert!(z.dual == -2.0);
}

impl<F: Copy + Float> Dual<F> {
    pub fn sin(self) -> Dual<F> {
        Dual::new(self.real.sin(), self.dual * self.real.cos())
    }

    pub fn cos(self) -> Dual<F> {
        Dual::new(self.real.cos(), (-F::one()) * self.dual * self.real.sin())
    }

    pub fn tan(self) -> Dual<F> {
        self.sin() / self.cos()
    }

    pub fn exp(self) -> Dual<F> {
        Dual::new(self.real.exp(), self.dual * self.real.exp())
    }

    pub fn ln(self) -> Dual<F> {
        Dual::new(self.real.ln(), self.dual / self.real)
    }

    pub fn sqrt(self) -> Dual<F> {
        let two = F::one() + F::one();
        Dual::new(self.real.sqrt(), self.dual / (two * self.real.sqrt()))
    }
}

impl<F: Copy + Num> From<F> for Dual<F> {
    fn from(real: F) -> Dual<F> {
        Dual::new(real, F::one())
    }
}

impl<F> fmt::Display for Dual<F>
    where F: fmt::Display + Num + PartialOrd + Copy
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.real < Zero::zero() {
            write!(f, "{}-{}ε", self.real, F::zero() - self.dual)
        } else {
            write!(f, "{}+{}ε", self.real, self.dual)
        }
    }
}

#[cfg(test)]
fn diff(x: f32, y: f32) -> f32 {
    (x - y).abs()
}

#[test]
fn test_sin() {
    let x: Dual32 = From::from(0.0);
    let y = x.sin();

    let real_diff = diff(y.real, 0.0);
    let dual_diff = diff(y.dual, 1.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_cos() {
    let x: Dual32 = From::from(consts::PI);
    let y = x.cos();

    let real_diff = diff(y.real, -1.0);
    let dual_diff = diff(y.dual, 0.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_tan() {
    let x: Dual32 = From::from(0.0);
    let y = x.tan();

    let real_diff = diff(y.real, 0.0);
    let dual_diff = diff(y.dual, 1.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_exp() {
    let x: Dual32 = From::from(1.0);
    let y = x.exp();

    let real_diff = diff(y.real, consts::E);
    let dual_diff = diff(y.dual, consts::E);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_ln() {
    let x: Dual32 = From::from(1.0);
    let y = x.ln();

    let real_diff = diff(y.real, 0.0);
    let dual_diff = diff(y.dual, 1.0);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}

#[test]
fn test_sqrt() {
    let x: Dual32 = From::from(4.0);
    let y = x.sqrt();

    println!("{}", y);

    let real_diff = diff(y.real, 2.0);
    let dual_diff = diff(y.dual, 0.25);

    assert!(real_diff < f32::EPSILON);
    assert!(dual_diff < f32::EPSILON);
}
<|endoftext|>


<commit_before>extern crate libc;

pub mod assembler;
pub use assembler::{Arch, Reloc, assemble, assemble2};

#[test]
fn x86_int3() {
    //assert_eq!(assemble(Arch::X86, "int3").unwrap(), [0xcc]);
}

#[test]
fn x86_jcc() {
    let bytes = assemble(Arch::X86_64, "nop; jz here; nop; nop; here:").expect("couldn't compile the code");
    assert_eq!(bytes, [0x90, 0x74, 0x02, 0x90, 0x90]);
}

#[test]
fn x86_jmp_rel() {
    let addr = 0x1000;
    let reloc = Reloc::new("here", 0x1003);
    let bytes = assemble2(Arch::X86_64, "jmp here", addr, &[reloc]).expect("couldn't compile the code");
    assert_eq!(bytes, [0xeb, 0x01]);
}
<commit_msg>fixing and prettifying tests<commit_after>extern crate libc;

pub mod assembler;
pub use assembler::{Arch, Reloc, assemble, assemble2};

#[test]
fn x86_int3() {
    assert_eq!(assemble(Arch::X86, "int3").unwrap(), [0xcc]);
}

#[test]
fn x86_jcc() {
    let bytes = assemble(Arch::X86_64, "nop; jz here; nop; nop; here:").unwrap();
    assert_eq!(bytes, [0x90, 0x74, 0x02, 0x90, 0x90]);
}

#[test]
fn x86_jmp_rel() {
    let addr = 0x1000;
    let reloc = Reloc::new("here", 0x1003);
    let bytes = assemble2(Arch::X86_64, "jmp here", addr, &[reloc]).unwrap();
    assert_eq!(bytes, [0xeb, 0x01]);
}

#[test]
fn missing_label() {
    assert_eq!(assemble(Arch::X86_64, "jz here"), None);
}
<|endoftext|>


<commit_before>//! Access secure credentials at runtime with multiple backends.
//!
//! For more information, see [the
//! homepage](https://github.com/emk/credentials).
//!
//! ```
//! use credentials;
//! use std::env;
//!
//! env::set_var("PASSWORD", "secret");
//! assert_eq!("secret", credentials::var("PASSWORD").unwrap());
//! ```

#[macro_use]
extern crate hyper;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate regex;
extern crate rustc_serialize;
#[cfg(test)] #[macro_use]
extern crate yup_hyper_mock as hyper_mock;

use backend::Backend;
use errors::{ErrorNew, err};
use std::cell::RefCell;
use std::convert::AsRef;
use std::ops::DerefMut;
use std::path::Path;
use std::sync::{Mutex, MutexGuard};

// Be very careful not to export any more of the Secretfile API than
// strictly necessary, because we don't want to stablize too much at this
// point.
pub use secretfile::{Secretfile, SecretfileKeys};
pub use errors::Error;

#[macro_use]
mod errors;

mod backend;
mod chained;
mod envvar;
mod secretfile;
mod vault;

/// A client which fetches secrets.  Under normal circumstances, it's
/// usually easier to use the static `credentials::var` and
/// `credentials::file` methods instead, but you may need to use this to
/// customize behavior.
pub struct Client {
    secretfile: Secretfile,
    backend: chained::Client,
}

impl Client {
    /// Create a new client using the default `Secretfile`.
    fn new() -> Result<Client, Error> {
        Client::with_secretfile(try!(Secretfile::default()))
    }

    /// Create a new client using the specified `Secretfile`.
    fn with_secretfile(secretfile: Secretfile) -> Result<Client, Error> {
        Ok(Client {
            secretfile: secretfile,
            backend: try!(chained::Client::new_default()),
        })
    }

    /// Fetch the value of an environment-variable-style credential.
    pub fn var<S: AsRef<str>>(&mut self, name: S) -> Result<String, Error> {
        let name_ref = name.as_ref();
        trace!("getting secure credential {}", name_ref);
        self.backend.var(&self.secretfile, name_ref).map_err(|e| {
            let err = Error::credential(name_ref, e);
            warn!("{}", err);
            err
        })
    }

    /// Fetch the value of a file-style credential.
    pub fn file<S: AsRef<Path>>(&mut self, path: S) -> Result<String, Error> {
        let path_ref = path.as_ref();
        let path_str = try!(path_ref.to_str().ok_or_else(|| {
            Error::credential("(invalid path)", err!("Path is not valid Unicode"))
        }));
        trace!("getting secure credential {}", path_str);
        self.backend.file(&self.secretfile, path_str).map_err(|e| {
            let err = Error::credential(path_str, e);
            warn!("{}", err);
            err
        })
    }
}

lazy_static! {
    // Our shared global client, initialized by `lazy_static!` and
    // protected by a Mutex.
    //
    // Rust deliberately makes it a nuisance to use mutable global
    // variables.  In this case, the `Mutex` provides thread-safe locking,
    // the `RefCell` makes this assignable, and the `Option` makes this
    // optional.  This is a message from the language saying, "Really? A
    // mutable global that might be null? Have you really thought about
    // this?"  But the global default client is only for convenience, so
    // we're OK with it, at least so far.
    static ref CLIENT: Mutex<RefCell<Option<Client>>> =
        Mutex::new(RefCell::new(None));
}

/// Set the default global `Client` to the value specified.  This is
/// normally used to specify non-default configuration options, and it
/// should ideally be run before spawning threads or fetching credentials.
pub fn set_client(client: Client) {
    // This is a bit subtle: First we need to lock our Mutex, and then--if
    // our Mutex was poisoned by a panic in another thread--we want to
    // propagate the panic in this thread using `unwrap()`.  See
    // https://doc.rust-lang.org/std/sync/struct.Mutex.html for details.
    let client_cell: MutexGuard<_> = CLIENT.lock().unwrap();

    // Set our global client.
    *client_cell.borrow_mut() = Some(client);
}

/// Call `body` with the default global client, or return an error if we
/// can't allocate a default global client.
fn with_client<F>(body: F) -> Result<String, Error>
    where F: FnOnce(&mut Client) -> Result<String, Error>
{
    let client_cell: MutexGuard<_> = CLIENT.lock().unwrap();

    // Try to set up the client if we haven't already.
    if client_cell.borrow().is_none() {
        *client_cell.borrow_mut() = Some(try!(Client::new()));
    }

    // Call the provided function.  I have to break out `result` separately
    // for mysterious reasons related to the borrow checker and global
    // mutable state.
    let result = match client_cell.borrow_mut().deref_mut() {
        &mut Some(ref mut client) => body(client),
        // We theoretically handed this just above, and exited if we
        // failed.
        &mut None => panic!("Should have a client, but we don't")
    };
    result
}

/// Fetch the value of an environment-variable-style credential.
pub fn var<S: AsRef<str>>(name: S) -> Result<String, Error> {
    with_client(|client| client.var(name))
}

/// Fetch the value of a file-style credential.
pub fn file<S: AsRef<Path>>(path: S) -> Result<String, Error> {
    with_client(|client| client.file(path))
}

#[cfg(test)]
mod test {
    use std::fs;
    use std::io::Read;
    use super::file;

    #[test]
    fn test_file() {
        // Some arbitrary file contents.
        let mut f = fs::File::open("Cargo.toml").unwrap();
        let mut expected = String::new();
        f.read_to_string(&mut expected).unwrap();

        assert_eq!(expected, file("Cargo.toml").unwrap());
        assert!(file("nosuchfile.txt").is_err());
    }
}
<commit_msg>Provide access to Secretfile<commit_after>//! Access secure credentials at runtime with multiple backends.
//!
//! For more information, see [the
//! homepage](https://github.com/emk/credentials).
//!
//! ```
//! use credentials;
//! use std::env;
//!
//! env::set_var("PASSWORD", "secret");
//! assert_eq!("secret", credentials::var("PASSWORD").unwrap());
//! ```

#[macro_use]
extern crate hyper;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate regex;
extern crate rustc_serialize;
#[cfg(test)] #[macro_use]
extern crate yup_hyper_mock as hyper_mock;

use backend::Backend;
use errors::{ErrorNew, err};
use std::cell::RefCell;
use std::convert::AsRef;
use std::ops::DerefMut;
use std::path::Path;
use std::sync::{Mutex, MutexGuard};

// Be very careful not to export any more of the Secretfile API than
// strictly necessary, because we don't want to stablize too much at this
// point.
pub use secretfile::{Secretfile, SecretfileKeys};
pub use errors::Error;

#[macro_use]
mod errors;

mod backend;
mod chained;
mod envvar;
mod secretfile;
mod vault;

/// A client which fetches secrets.  Under normal circumstances, it's
/// usually easier to use the static `credentials::var` and
/// `credentials::file` methods instead, but you may need to use this to
/// customize behavior.
pub struct Client {
    sf: Secretfile,
    backend: chained::Client,
}

impl Client {
    /// Create a new client using the default `Secretfile`.
    fn new() -> Result<Client, Error> {
        Client::with_secretfile(try!(Secretfile::default()))
    }

    /// Create a new client using the specified `Secretfile`.
    fn with_secretfile(secretfile: Secretfile) -> Result<Client, Error> {
        Ok(Client {
            sf: secretfile,
            backend: try!(chained::Client::new_default()),
        })
    }

    /// Provide access to a copy of the Secretfile we're using.
    pub fn secretfile(&self) -> &Secretfile {
        &self.sf
    }

    /// Fetch the value of an environment-variable-style credential.
    pub fn var<S: AsRef<str>>(&mut self, name: S) -> Result<String, Error> {
        let name_ref = name.as_ref();
        trace!("getting secure credential {}", name_ref);
        self.backend.var(&self.sf, name_ref).map_err(|e| {
            let err = Error::credential(name_ref, e);
            warn!("{}", err);
            err
        })
    }

    /// Fetch the value of a file-style credential.
    pub fn file<S: AsRef<Path>>(&mut self, path: S) -> Result<String, Error> {
        let path_ref = path.as_ref();
        let path_str = try!(path_ref.to_str().ok_or_else(|| {
            Error::credential("(invalid path)", err!("Path is not valid Unicode"))
        }));
        trace!("getting secure credential {}", path_str);
        self.backend.file(&self.sf, path_str).map_err(|e| {
            let err = Error::credential(path_str, e);
            warn!("{}", err);
            err
        })
    }
}

lazy_static! {
    // Our shared global client, initialized by `lazy_static!` and
    // protected by a Mutex.
    //
    // Rust deliberately makes it a nuisance to use mutable global
    // variables.  In this case, the `Mutex` provides thread-safe locking,
    // the `RefCell` makes this assignable, and the `Option` makes this
    // optional.  This is a message from the language saying, "Really? A
    // mutable global that might be null? Have you really thought about
    // this?"  But the global default client is only for convenience, so
    // we're OK with it, at least so far.
    static ref CLIENT: Mutex<RefCell<Option<Client>>> =
        Mutex::new(RefCell::new(None));
}

/// Set the default global `Client` to the value specified.  This is
/// normally used to specify non-default configuration options, and it
/// should ideally be run before spawning threads or fetching credentials.
pub fn set_client(client: Client) {
    // This is a bit subtle: First we need to lock our Mutex, and then--if
    // our Mutex was poisoned by a panic in another thread--we want to
    // propagate the panic in this thread using `unwrap()`.  See
    // https://doc.rust-lang.org/std/sync/struct.Mutex.html for details.
    let client_cell: MutexGuard<_> = CLIENT.lock().unwrap();

    // Set our global client.
    *client_cell.borrow_mut() = Some(client);
}

/// Call `body` with the default global client, or return an error if we
/// can't allocate a default global client.
fn with_client<F>(body: F) -> Result<String, Error>
    where F: FnOnce(&mut Client) -> Result<String, Error>
{
    let client_cell: MutexGuard<_> = CLIENT.lock().unwrap();

    // Try to set up the client if we haven't already.
    if client_cell.borrow().is_none() {
        *client_cell.borrow_mut() = Some(try!(Client::new()));
    }

    // Call the provided function.  I have to break out `result` separately
    // for mysterious reasons related to the borrow checker and global
    // mutable state.
    let result = match client_cell.borrow_mut().deref_mut() {
        &mut Some(ref mut client) => body(client),
        // We theoretically handed this just above, and exited if we
        // failed.
        &mut None => panic!("Should have a client, but we don't")
    };
    result
}

/// Fetch the value of an environment-variable-style credential.
pub fn var<S: AsRef<str>>(name: S) -> Result<String, Error> {
    with_client(|client| client.var(name))
}

/// Fetch the value of a file-style credential.
pub fn file<S: AsRef<Path>>(path: S) -> Result<String, Error> {
    with_client(|client| client.file(path))
}

#[cfg(test)]
mod test {
    use std::fs;
    use std::io::Read;
    use super::file;

    #[test]
    fn test_file() {
        // Some arbitrary file contents.
        let mut f = fs::File::open("Cargo.toml").unwrap();
        let mut expected = String::new();
        f.read_to_string(&mut expected).unwrap();

        assert_eq!(expected, file("Cargo.toml").unwrap());
        assert!(file("nosuchfile.txt").is_err());
    }
}
<|endoftext|>


<commit_before>//! This crate allows one-liners to read from a terminal
//! A minimal example to get an i32 from the command line is
//!
//! ```rust,no_run
//! use text_io::read;
//!
//! fn main() {
//!     let i: i32 = read!();
//! }
//! ```
//!
//! The `read!()` macro will always read until the next ascii whitespace character
//! (`\n`, `\r`, `\t` or space).
//!
//! Any type that implements the `FromStr` trait can be read with the `read!` macro.
//!
//! # Advanced
//! Text parsing can be done similar to `println!` by adding a format string
//! to the macro:
//!
//! ```rust,no_run
//! use text_io::read;
//!
//! let i: i32 = read!("The answer: {}!");
//! ```
//!
//! This will read `"The answer: "`, then an integer, then an exclamation mark. Any deviation from
//! the format string will result in a panic.
//!
//! Note: only a single value can be read per `read!` invocation.

use std::error;
use std::fmt;
use std::str::FromStr;

#[non_exhaustive]
#[derive(Debug, PartialEq)]
pub enum Error {
    MissingMatch,
    MissingClosingBrace,
    UnexpectedValue(u8, Option<u8>),
    InvalidUtf8(Vec<u8>),
    PartialUtf8(usize, Vec<u8>),
    Parse(String, &'static str),
}

impl error::Error for Error {}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use crate::Error::*;
        use std::str::from_utf8;

        match *self {
            InvalidUtf8(ref raw) => write!(f, "input was not valid utf8: {:?}", raw),
            Parse(ref s, arg) => write!(f, "could not parse {} as target type of {}", s, arg),
            UnexpectedValue(exp, act) => write!(
                f,
                "found value {:?} not matching the pattern value {}",
                act.map(|b| b as char),
                exp as char
            ),
            PartialUtf8(n, ref raw) => write!(
                f,
                "input was only partially valid utf8: \"{}\" followed by {:?}",
                from_utf8(&raw[..n]).unwrap(),
                &raw[n..]
            ),
            MissingMatch => write!(f, "Bad read! format string: did not contain {{}}"),
            MissingClosingBrace => write!(
                f,
                "found single open curly brace at the end of the format string"
            ),
        }
    }
}

pub fn match_next(expected: u8, iter: &mut dyn Iterator<Item = u8>) -> Result<(), Error> {
    let next = iter.next();
    if next != Some(expected) {
        return Err(Error::UnexpectedValue(expected, next));
    }
    Ok(())
}

pub fn parse_capture<T>(
    name: &'static str,
    next: Option<u8>,
    iter: &mut dyn Iterator<Item = u8>,
) -> Result<T, Error>
where
    T: FromStr,
    <T as FromStr>::Err: ::std::fmt::Debug,
{
    static WHITESPACES: &[u8] = b"\t\r\n ";
    let raw: Vec<u8> = match next {
        Some(c) => iter.take_while(|&ch| ch != c).collect(),
        None => iter
            .skip_while(|ch| WHITESPACES.contains(ch))
            .take_while(|ch| !WHITESPACES.contains(ch))
            .collect(),
    };
    match String::from_utf8(raw) {
        Ok(s) => FromStr::from_str(&s).map_err(|_| Error::Parse(s, name)),
        Err(e) => {
            let n = e.utf8_error().valid_up_to();
            let raw = e.into_bytes();
            if n == 0 {
                Err(Error::InvalidUtf8(raw))
            } else {
                Err(Error::PartialUtf8(n, raw))
            }
        }
    }
}

/// ```rust,no_run
/// use text_io::try_read;
///
/// let i: i32 = try_read!("The answer: {}!").unwrap();
/// let i: Result<i32, _> = try_read!("The {}{{}}!", "The answer is 42!".bytes());
/// assert!(i.is_err());
/// ```
///
/// ```rust
/// use text_io::try_read;
///
/// let i: Result<i32, _> = try_read!("The answer is {}!", "The answer is 42!".bytes());
/// assert!(i.is_ok());
///
/// let i: Result<i32, _> = try_read!("The {}{{}}!", "The answer is 42!".bytes());
/// assert!(i.is_err());
/// ```
#[macro_export]
macro_rules! try_read(
    () => { $crate::try_read!("{}") };
    ($text:expr) => {{
        (|| -> std::result::Result<_, $crate::Error> {
            use std::io::Write;
            std::io::stdout().flush().unwrap();
            let __try_read_var__;
            $crate::try_scan!($text, __try_read_var__);
            Ok(__try_read_var__)
        })()
    }};
    ($text:expr, $input:expr) => {{
        (|| -> std::result::Result<_, $crate::Error> {
            use std::io::Write;
            std::io::stdout().flush().unwrap();
            let __try_read_var__;
            $crate::try_scan!($input => $text, __try_read_var__);
            Ok(__try_read_var__)
        })()
    }};
);

/// ```rust,no_run
/// use text_io::try_scan;
///
/// fn parser() -> Result<i32, Box<dyn std::error::Error>> {
///     let i: i32;
///     let text = "The answer is 42!";
///
///     try_scan!(text.bytes() => "The answer is {}!", i);
///
///     assert_eq!(i, 1);
///     Ok(i)
/// }
/// ```
#[macro_export]
macro_rules! try_scan(
    ($pattern:expr, $($arg:expr),*) => {
        use ::std::io::Read;
        $crate::try_scan!(::std::io::stdin().bytes().map(std::result::Result::unwrap) => $pattern, $($arg),*);
    };
    ($input:expr => $pattern:expr, $($arg:expr),*) => {{
        $crate::try_scan!(@impl question_mark; $input => $pattern, $($arg),*)
    }};
    (@question_mark: $($e:tt)+) => {{
        ($($e)+)?
    }};
    (@unwrap: $($e:tt)+) => {{
        ($($e)+).unwrap()
    }};
    (@impl $action:tt; $input:expr => $pattern:expr, $($arg:expr),*) => {{
        #![allow(clippy::try_err)]
        use $crate::{Error, match_next, parse_capture};

        // typesafe macros :)
        let pattern: &'static str = $pattern;
        let stdin: &mut dyn Iterator<Item = u8> = &mut ($input);

        let mut pattern = pattern.bytes();

        $(
            $arg = loop {
                match $crate::try_scan!(@$action: pattern.next().ok_or(Error::MissingMatch)) {
                    b'{' => match $crate::try_scan!(@$action: pattern.next().ok_or(Error::MissingClosingBrace)) {
                        b'{' => $crate::try_scan!(@$action: match_next(b'{', stdin)),
                        b'}' => break $crate::try_scan!(@$action: parse_capture(stringify!($arg), pattern.next(), stdin)),
                        _ => return $crate::try_scan!(@$action: Err(Error::MissingClosingBrace)),
                    },
                    c => $crate::try_scan!(@$action: match_next(c, stdin)),
                }
            };
        )*

        for c in pattern {
            $crate::try_scan!(@$action: match_next(c, stdin))
        }

        format_args!($pattern, $($arg),*);
    }};
);

/// All text input is handled through this macro
#[macro_export]
macro_rules! read(
    ($($arg:tt)*) => {
        $crate::try_read!($($arg)*).unwrap()
    };
);

/// This macro allows to pass several variables so multiple values can be read
#[macro_export]
macro_rules! scan(
    ($text:expr, $($arg:expr),*) => {
        {
            use ::std::io::Read;
            $crate::scan!(::std::io::stdin().bytes().map(std::result::Result::unwrap) => $text, $($arg),*);
        }
    };
    ($input:expr => $pattern:expr, $($arg:expr),*) => {{
        $crate::try_scan!(@impl unwrap; $input => $pattern, $($arg),*)
    }};
);
<commit_msg>Clippy<commit_after>//! This crate allows one-liners to read from a terminal
//! A minimal example to get an i32 from the command line is
//!
//! ```rust,no_run
//! use text_io::read;
//!
//! let i: i32 = read!();
//! ```
//!
//! The `read!()` macro will always read until the next ascii whitespace character
//! (`\n`, `\r`, `\t` or space).
//!
//! Any type that implements the `FromStr` trait can be read with the `read!` macro.
//!
//! # Advanced
//! Text parsing can be done similar to `println!` by adding a format string
//! to the macro:
//!
//! ```rust,no_run
//! use text_io::read;
//!
//! let i: i32 = read!("The answer: {}!");
//! ```
//!
//! This will read `"The answer: "`, then an integer, then an exclamation mark. Any deviation from
//! the format string will result in a panic.
//!
//! Note: only a single value can be read per `read!` invocation.

use std::error;
use std::fmt;
use std::str::FromStr;

#[non_exhaustive]
#[derive(Debug, PartialEq)]
pub enum Error {
    MissingMatch,
    MissingClosingBrace,
    UnexpectedValue(u8, Option<u8>),
    InvalidUtf8(Vec<u8>),
    PartialUtf8(usize, Vec<u8>),
    Parse(String, &'static str),
}

impl error::Error for Error {}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use crate::Error::*;
        use std::str::from_utf8;

        match *self {
            InvalidUtf8(ref raw) => write!(f, "input was not valid utf8: {:?}", raw),
            Parse(ref s, arg) => write!(f, "could not parse {} as target type of {}", s, arg),
            UnexpectedValue(exp, act) => write!(
                f,
                "found value {:?} not matching the pattern value {}",
                act.map(|b| b as char),
                exp as char
            ),
            PartialUtf8(n, ref raw) => write!(
                f,
                "input was only partially valid utf8: \"{}\" followed by {:?}",
                from_utf8(&raw[..n]).unwrap(),
                &raw[n..]
            ),
            MissingMatch => write!(f, "Bad read! format string: did not contain {{}}"),
            MissingClosingBrace => write!(
                f,
                "found single open curly brace at the end of the format string"
            ),
        }
    }
}

pub fn match_next(expected: u8, iter: &mut dyn Iterator<Item = u8>) -> Result<(), Error> {
    let next = iter.next();
    if next != Some(expected) {
        return Err(Error::UnexpectedValue(expected, next));
    }
    Ok(())
}

pub fn parse_capture<T>(
    name: &'static str,
    next: Option<u8>,
    iter: &mut dyn Iterator<Item = u8>,
) -> Result<T, Error>
where
    T: FromStr,
    <T as FromStr>::Err: ::std::fmt::Debug,
{
    static WHITESPACES: &[u8] = b"\t\r\n ";
    let raw: Vec<u8> = match next {
        Some(c) => iter.take_while(|&ch| ch != c).collect(),
        None => iter
            .skip_while(|ch| WHITESPACES.contains(ch))
            .take_while(|ch| !WHITESPACES.contains(ch))
            .collect(),
    };
    match String::from_utf8(raw) {
        Ok(s) => FromStr::from_str(&s).map_err(|_| Error::Parse(s, name)),
        Err(e) => {
            let n = e.utf8_error().valid_up_to();
            let raw = e.into_bytes();
            if n == 0 {
                Err(Error::InvalidUtf8(raw))
            } else {
                Err(Error::PartialUtf8(n, raw))
            }
        }
    }
}

/// ```rust,no_run
/// use text_io::try_read;
///
/// let i: i32 = try_read!("The answer: {}!").unwrap();
/// let i: Result<i32, _> = try_read!("The {}{{}}!", "The answer is 42!".bytes());
/// assert!(i.is_err());
/// ```
///
/// ```rust
/// use text_io::try_read;
///
/// let i: Result<i32, _> = try_read!("The answer is {}!", "The answer is 42!".bytes());
/// assert!(i.is_ok());
///
/// let i: Result<i32, _> = try_read!("The {}{{}}!", "The answer is 42!".bytes());
/// assert!(i.is_err());
/// ```
#[macro_export]
macro_rules! try_read(
    () => { $crate::try_read!("{}") };
    ($text:expr) => {{
        (|| -> std::result::Result<_, $crate::Error> {
            use std::io::Write;
            std::io::stdout().flush().unwrap();
            let __try_read_var__;
            $crate::try_scan!($text, __try_read_var__);
            Ok(__try_read_var__)
        })()
    }};
    ($text:expr, $input:expr) => {{
        (|| -> std::result::Result<_, $crate::Error> {
            use std::io::Write;
            std::io::stdout().flush().unwrap();
            let __try_read_var__;
            $crate::try_scan!($input => $text, __try_read_var__);
            Ok(__try_read_var__)
        })()
    }};
);

/// ```rust,no_run
/// use text_io::try_scan;
///
/// fn parser() -> Result<i32, Box<dyn std::error::Error>> {
///     let i: i32;
///     let text = "The answer is 42!";
///
///     try_scan!(text.bytes() => "The answer is {}!", i);
///
///     assert_eq!(i, 1);
///     Ok(i)
/// }
/// ```
#[macro_export]
macro_rules! try_scan(
    ($pattern:expr, $($arg:expr),*) => {
        use ::std::io::Read;
        $crate::try_scan!(::std::io::stdin().bytes().map(std::result::Result::unwrap) => $pattern, $($arg),*);
    };
    ($input:expr => $pattern:expr, $($arg:expr),*) => {{
        $crate::try_scan!(@impl question_mark; $input => $pattern, $($arg),*)
    }};
    (@question_mark: $($e:tt)+) => {{
        ($($e)+)?
    }};
    (@unwrap: $($e:tt)+) => {{
        ($($e)+).unwrap()
    }};
    (@impl $action:tt; $input:expr => $pattern:expr, $($arg:expr),*) => {{
        #![allow(clippy::try_err)]
        use $crate::{Error, match_next, parse_capture};

        // typesafe macros :)
        let pattern: &'static str = $pattern;
        let stdin: &mut dyn Iterator<Item = u8> = &mut ($input);

        let mut pattern = pattern.bytes();

        $(
            $arg = loop {
                match $crate::try_scan!(@$action: pattern.next().ok_or(Error::MissingMatch)) {
                    b'{' => match $crate::try_scan!(@$action: pattern.next().ok_or(Error::MissingClosingBrace)) {
                        b'{' => $crate::try_scan!(@$action: match_next(b'{', stdin)),
                        b'}' => break $crate::try_scan!(@$action: parse_capture(stringify!($arg), pattern.next(), stdin)),
                        _ => return $crate::try_scan!(@$action: Err(Error::MissingClosingBrace)),
                    },
                    c => $crate::try_scan!(@$action: match_next(c, stdin)),
                }
            };
        )*

        for c in pattern {
            $crate::try_scan!(@$action: match_next(c, stdin))
        }

        format_args!($pattern, $($arg),*);
    }};
);

/// All text input is handled through this macro
#[macro_export]
macro_rules! read(
    ($($arg:tt)*) => {
        $crate::try_read!($($arg)*).unwrap()
    };
);

/// This macro allows to pass several variables so multiple values can be read
#[macro_export]
macro_rules! scan(
    ($text:expr, $($arg:expr),*) => {
        {
            use ::std::io::Read;
            $crate::scan!(::std::io::stdin().bytes().map(std::result::Result::unwrap) => $text, $($arg),*);
        }
    };
    ($input:expr => $pattern:expr, $($arg:expr),*) => {{
        $crate::try_scan!(@impl unwrap; $input => $pattern, $($arg),*)
    }};
);
<|endoftext|>


<commit_before>// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

//! Terminal formatting library.
//!
//! This crate provides the `Terminal` trait, which abstracts over an [ANSI
//! Terminal][ansi] to provide color printing, among other things. There are two
//! implementations, the `TerminfoTerminal`, which uses control characters from
//! a [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console
//! API][win].
//!
//! # Examples
//!
//! ```no_run
//! extern crate term;
//! use std::io::prelude::*;
//!
//! fn main() {
//!     let mut t = term::stdout().unwrap();
//!
//!     t.fg(term::color::GREEN).unwrap();
//!     (write!(t, "hello, ")).unwrap();
//!
//!     t.fg(term::color::RED).unwrap();
//!     (writeln!(t, "world!")).unwrap();
//!
//!     assert!(t.reset().unwrap());
//! }
//! ```
//!
//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code
//! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
//! [ti]: https://en.wikipedia.org/wiki/Terminfo

#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

use std::io::prelude::*;

pub use terminfo::TerminfoTerminal;
#[cfg(windows)]
pub use win::WinConsole;

use std::io::{self, Stdout, Stderr};

pub mod terminfo;

#[cfg(windows)]
mod win;

/// Alias for stderr terminals.
pub type StdoutTerminal = Terminal<Output=Stdout> + Send;
/// Alias for stderr terminals.
pub type StderrTerminal = Terminal<Output=Stderr> + Send;

#[cfg(not(windows))]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<StdoutTerminal>> {
    TerminfoTerminal::new(io::stdout()).map(|t| {
        Box::new(t) as Box<StdoutTerminal>
    })
}

#[cfg(windows)]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<StdoutTerminal>> {
    TerminfoTerminal::new(io::stdout()).map(|t| {
        Box::new(t) as Box<StdoutTerminal>
    }).or_else(|| WinConsole::new(io::stdout()).ok().map(|t| {
        Box::new(t) as Box<StdoutTerminal>
    }))
}

#[cfg(not(windows))]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<StderrTerminal>> {
    TerminfoTerminal::new(io::stderr()).map(|t| {
        Box::new(t) as Box<StderrTerminal>
    })
}

#[cfg(windows)]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<StderrTerminal>> {
    TerminfoTerminal::new(io::stderr()).map(|t| {
        Box::new(t) as Box<StderrTerminal>
    }).or_else(|| WinConsole::new(io::stderr()).ok().map(|t| {
        Box::new(t) as Box<StderrTerminal>
    }))
}

/// Terminal color definitions
pub mod color {
    /// Number for a terminal color
    pub type Color = u16;

    pub const BLACK:   Color = 0;
    pub const RED:     Color = 1;
    pub const GREEN:   Color = 2;
    pub const YELLOW:  Color = 3;
    pub const BLUE:    Color = 4;
    pub const MAGENTA: Color = 5;
    pub const CYAN:    Color = 6;
    pub const WHITE:   Color = 7;

    pub const BRIGHT_BLACK:   Color = 8;
    pub const BRIGHT_RED:     Color = 9;
    pub const BRIGHT_GREEN:   Color = 10;
    pub const BRIGHT_YELLOW:  Color = 11;
    pub const BRIGHT_BLUE:    Color = 12;
    pub const BRIGHT_MAGENTA: Color = 13;
    pub const BRIGHT_CYAN:    Color = 14;
    pub const BRIGHT_WHITE:   Color = 15;
}

/// Terminal attributes for use with term.attr().
///
/// Most attributes can only be turned on and must be turned off with term.reset().
/// The ones that can be turned off explicitly take a boolean value.
/// Color is also represented as an attribute for convenience.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Attr {
    /// Bold (or possibly bright) mode
    Bold,
    /// Dim mode, also called faint or half-bright. Often not supported
    Dim,
    /// Italics mode. Often not supported
    Italic(bool),
    /// Underline mode
    Underline(bool),
    /// Blink mode
    Blink,
    /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold
    Standout(bool),
    /// Reverse mode, inverts the foreground and background colors
    Reverse,
    /// Secure mode, also called invis mode. Hides the printed text
    Secure,
    /// Convenience attribute to set the foreground color
    ForegroundColor(color::Color),
    /// Convenience attribute to set the background color
    BackgroundColor(color::Color)
}

/// A terminal with similar capabilities to an ANSI Terminal
/// (foreground/background colors etc).
pub trait Terminal: Write {
    /// The terminal's output writer type.
    type Output: Write;

    /// Sets the foreground color to the given color.
    ///
    /// If the color is a bright color, but the terminal only supports 8 colors,
    /// the corresponding normal color will be used instead.
    ///
    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn fg(&mut self, color: color::Color) -> io::Result<bool>;

    /// Sets the background color to the given color.
    ///
    /// If the color is a bright color, but the terminal only supports 8 colors,
    /// the corresponding normal color will be used instead.
    ///
    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn bg(&mut self, color: color::Color) -> io::Result<bool>;

    /// Sets the given terminal attribute, if supported.  Returns `Ok(true)`
    /// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if
    /// there was an I/O error.
    fn attr(&mut self, attr: Attr) -> io::Result<bool>;

    /// Returns whether the given terminal attribute is supported.
    fn supports_attr(&self, attr: Attr) -> bool;

    /// Resets all terminal attributes and color to the default.
    ///
    /// Returns `Ok(true)` if the terminal was reset, `Ok(false)` otherwise, and `Err(e)` if there
    /// was an I/O error.
    fn reset(&mut self) -> io::Result<bool>;

    /// Moves the cursor up one line.
    ///
    /// Returns `Ok(true)` if the cursor was moved, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn cursor_up(&mut self) -> io::Result<bool>;

    /// Deletes the text from the cursor location to the end of the line.
    ///
    /// Returns `Ok(true)` if the text was deleted, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn delete_line(&mut self) -> io::Result<bool>;

    /// Moves the cursor to the left edge of the current line.
    ///
    /// Returns `Ok(true)` if the text was deleted, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn carriage_return(&mut self) -> io::Result<bool>;

    /// Gets an immutable reference to the stream inside
    fn get_ref<'a>(&'a self) -> &'a Self::Output;

    /// Gets a mutable reference to the stream inside
    fn get_mut<'a>(&'a mut self) -> &'a mut Self::Output;
}

/// A terminal which can be unwrapped.
pub trait UnwrappableTerminal: Terminal {
    /// Returns the contained stream, destroying the `Terminal`
    fn unwrap(self) -> Self::Output;
}
<commit_msg>Add usage in tree<commit_after>// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

//! Terminal formatting library.
//!
//! This crate provides the `Terminal` trait, which abstracts over an [ANSI
//! Terminal][ansi] to provide color printing, among other things. There are two
//! implementations, the `TerminfoTerminal`, which uses control characters from
//! a [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console
//! API][win].
//!
//! # Usage
//!
//! This crates is [on crates.io](https://crates.io/crates/term) and can be
//! used by adding `rand` to your dependencies in your project's `Cargo.toml`.
//!
//! ```toml
//! [dependencies]
//!
//! term = "*"
//! ```
//!
//! and this to your crate root:
//!
//! ```rust
//! extern crate term;
//! ```
//!
//! # Examples
//!
//! ```no_run
//! extern crate term;
//! use std::io::prelude::*;
//!
//! fn main() {
//!     let mut t = term::stdout().unwrap();
//!
//!     t.fg(term::color::GREEN).unwrap();
//!     (write!(t, "hello, ")).unwrap();
//!
//!     t.fg(term::color::RED).unwrap();
//!     (writeln!(t, "world!")).unwrap();
//!
//!     assert!(t.reset().unwrap());
//! }
//! ```
//!
//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code
//! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
//! [ti]: https://en.wikipedia.org/wiki/Terminfo

#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

use std::io::prelude::*;

pub use terminfo::TerminfoTerminal;
#[cfg(windows)]
pub use win::WinConsole;

use std::io::{self, Stdout, Stderr};

pub mod terminfo;

#[cfg(windows)]
mod win;

/// Alias for stderr terminals.
pub type StdoutTerminal = Terminal<Output=Stdout> + Send;
/// Alias for stderr terminals.
pub type StderrTerminal = Terminal<Output=Stderr> + Send;

#[cfg(not(windows))]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<StdoutTerminal>> {
    TerminfoTerminal::new(io::stdout()).map(|t| {
        Box::new(t) as Box<StdoutTerminal>
    })
}

#[cfg(windows)]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<StdoutTerminal>> {
    TerminfoTerminal::new(io::stdout()).map(|t| {
        Box::new(t) as Box<StdoutTerminal>
    }).or_else(|| WinConsole::new(io::stdout()).ok().map(|t| {
        Box::new(t) as Box<StdoutTerminal>
    }))
}

#[cfg(not(windows))]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<StderrTerminal>> {
    TerminfoTerminal::new(io::stderr()).map(|t| {
        Box::new(t) as Box<StderrTerminal>
    })
}

#[cfg(windows)]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<StderrTerminal>> {
    TerminfoTerminal::new(io::stderr()).map(|t| {
        Box::new(t) as Box<StderrTerminal>
    }).or_else(|| WinConsole::new(io::stderr()).ok().map(|t| {
        Box::new(t) as Box<StderrTerminal>
    }))
}

/// Terminal color definitions
pub mod color {
    /// Number for a terminal color
    pub type Color = u16;

    pub const BLACK:   Color = 0;
    pub const RED:     Color = 1;
    pub const GREEN:   Color = 2;
    pub const YELLOW:  Color = 3;
    pub const BLUE:    Color = 4;
    pub const MAGENTA: Color = 5;
    pub const CYAN:    Color = 6;
    pub const WHITE:   Color = 7;

    pub const BRIGHT_BLACK:   Color = 8;
    pub const BRIGHT_RED:     Color = 9;
    pub const BRIGHT_GREEN:   Color = 10;
    pub const BRIGHT_YELLOW:  Color = 11;
    pub const BRIGHT_BLUE:    Color = 12;
    pub const BRIGHT_MAGENTA: Color = 13;
    pub const BRIGHT_CYAN:    Color = 14;
    pub const BRIGHT_WHITE:   Color = 15;
}

/// Terminal attributes for use with term.attr().
///
/// Most attributes can only be turned on and must be turned off with term.reset().
/// The ones that can be turned off explicitly take a boolean value.
/// Color is also represented as an attribute for convenience.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Attr {
    /// Bold (or possibly bright) mode
    Bold,
    /// Dim mode, also called faint or half-bright. Often not supported
    Dim,
    /// Italics mode. Often not supported
    Italic(bool),
    /// Underline mode
    Underline(bool),
    /// Blink mode
    Blink,
    /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold
    Standout(bool),
    /// Reverse mode, inverts the foreground and background colors
    Reverse,
    /// Secure mode, also called invis mode. Hides the printed text
    Secure,
    /// Convenience attribute to set the foreground color
    ForegroundColor(color::Color),
    /// Convenience attribute to set the background color
    BackgroundColor(color::Color)
}

/// A terminal with similar capabilities to an ANSI Terminal
/// (foreground/background colors etc).
pub trait Terminal: Write {
    /// The terminal's output writer type.
    type Output: Write;

    /// Sets the foreground color to the given color.
    ///
    /// If the color is a bright color, but the terminal only supports 8 colors,
    /// the corresponding normal color will be used instead.
    ///
    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn fg(&mut self, color: color::Color) -> io::Result<bool>;

    /// Sets the background color to the given color.
    ///
    /// If the color is a bright color, but the terminal only supports 8 colors,
    /// the corresponding normal color will be used instead.
    ///
    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn bg(&mut self, color: color::Color) -> io::Result<bool>;

    /// Sets the given terminal attribute, if supported.  Returns `Ok(true)`
    /// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if
    /// there was an I/O error.
    fn attr(&mut self, attr: Attr) -> io::Result<bool>;

    /// Returns whether the given terminal attribute is supported.
    fn supports_attr(&self, attr: Attr) -> bool;

    /// Resets all terminal attributes and color to the default.
    ///
    /// Returns `Ok(true)` if the terminal was reset, `Ok(false)` otherwise, and `Err(e)` if there
    /// was an I/O error.
    fn reset(&mut self) -> io::Result<bool>;

    /// Moves the cursor up one line.
    ///
    /// Returns `Ok(true)` if the cursor was moved, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn cursor_up(&mut self) -> io::Result<bool>;

    /// Deletes the text from the cursor location to the end of the line.
    ///
    /// Returns `Ok(true)` if the text was deleted, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn delete_line(&mut self) -> io::Result<bool>;

    /// Moves the cursor to the left edge of the current line.
    ///
    /// Returns `Ok(true)` if the text was deleted, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn carriage_return(&mut self) -> io::Result<bool>;

    /// Gets an immutable reference to the stream inside
    fn get_ref<'a>(&'a self) -> &'a Self::Output;

    /// Gets a mutable reference to the stream inside
    fn get_mut<'a>(&'a mut self) -> &'a mut Self::Output;
}

/// A terminal which can be unwrapped.
pub trait UnwrappableTerminal: Terminal {
    /// Returns the contained stream, destroying the `Terminal`
    fn unwrap(self) -> Self::Output;
}
<|endoftext|>


<commit_before>#![crate_name = "amethyst"]
#![crate_type = "lib"]
#![doc(html_logo_url = "https://raw.githubusercontent.com/ebkalderon/amethyst/master/book/images/amethyst_thumb.png")]

//! Amethyst is a free and open source game engine written in idiomatic
//! [Rust][rs] for building video games and interactive multimedia applications.
//! The source code is available for download on [GitHub][gh].
//!
//! [rs]: https://www.rust-lang.org/
//! [gh]: https://github.com/ebkalderon/amethyst
//!
//! This project is a work in progress and is very incomplete. Pardon the dust!
//!
//! # Example
//!
//! ```ignore
//! extern crate amethyst;
//!
//! use amethyst::*;
//!
//! struct GameState;
//!
//! impl State for GameState {
//!     fn handle_events(&mut self, events: &Vec<Event>) -> Trans {
//!         for e in events {
//!             match e {
//!                 Event::Closed => Trans::Quit,
//!                 Event::Resized(x, y) => println!("x: {}, y: {}", x, y),
//!                 Event::KeyPressed(k) => if k == Key::Esc { Trans::Quit },
//!             }
//!         }
//!         Trans::None
//!     }
//!
//!     fn update(&mut self, _delta: Duration) -> Trans {
//!         println!("Computing some more whoop-ass...");
//!         Trans::None
//!     }
//! }
//!
//! fn main() {
//!     let mut game = Application::new(GameState);
//!     game.run();
//! }
//! ```

mod engine;
pub mod renderer;

pub use self::engine::app::Application;
pub use self::engine::state::{State, StateMachine, Trans};
pub use self::engine::timing::{Duration, Stopwatch};
<commit_msg>replace current html_logo_url with tinyurl<commit_after>#![crate_name = "amethyst"]
#![crate_type = "lib"]
#![doc(html_logo_url = "http://tinyurl.com/hgsb45k")]

//! Amethyst is a free and open source game engine written in idiomatic
//! [Rust][rs] for building video games and interactive multimedia applications.
//! The source code is available for download on [GitHub][gh].
//!
//! [rs]: https://www.rust-lang.org/
//! [gh]: https://github.com/ebkalderon/amethyst
//!
//! This project is a work in progress and is very incomplete. Pardon the dust!
//!
//! # Example
//!
//! ```ignore
//! extern crate amethyst;
//!
//! use amethyst::*;
//!
//! struct GameState;
//!
//! impl State for GameState {
//!     fn handle_events(&mut self, events: &Vec<Event>) -> Trans {
//!         for e in events {
//!             match e {
//!                 Event::Closed => Trans::Quit,
//!                 Event::Resized(x, y) => println!("x: {}, y: {}", x, y),
//!                 Event::KeyPressed(k) => if k == Key::Esc { Trans::Quit },
//!             }
//!         }
//!         Trans::None
//!     }
//!
//!     fn update(&mut self, _delta: Duration) -> Trans {
//!         println!("Computing some more whoop-ass...");
//!         Trans::None
//!     }
//! }
//!
//! fn main() {
//!     let mut game = Application::new(GameState);
//!     game.run();
//! }
//! ```

mod engine;
pub mod renderer;

pub use self::engine::app::Application;
pub use self::engine::state::{State, StateMachine, Trans};
pub use self::engine::timing::{Duration, Stopwatch};
<|endoftext|>


<commit_before>//! ODBC types those representation is compatible with the ODBC C API.
//!
//! This layer has not been created using automatic code generation. It is incomplete, i.e. it does
//! not contain every symbol or constant defined in the ODBC C headers. Symbols which are
//! deprecated since ODBC 3 have been left out intentionally. While some extra type safety has been
//! added by grouping some of C's `#define` constants into `enum`-types it mostly offers the same
//! power (all) and safety guarantess(none) as the wrapped C-API.
//! ODBC 4.0 is still under development by Microsoft, so these symbols are deactivated by default
//! in the cargo.toml

pub use self::{
    attributes::*, bulk_operation::*, c_data_type::*, fetch_orientation::*, info_type::*,
    nullable::*, param_type::*, sqlreturn::*, functions::*, interval::*
};
use std::os::raw::{c_int, c_void};

mod attributes;
mod bulk_operation;
mod c_data_type;
mod fetch_orientation;
mod functions;
mod info_type;
mod nullable;
mod param_type;
mod sqlreturn;
mod interval;

//These types can never be instantiated in Rust code.
pub enum Obj {}

pub enum Env {}

pub enum Dbc {}

pub enum Stmt {}

pub enum Desc {}

pub type Handle = *mut Obj;
pub type HEnv = *mut Env;
pub type HDesc = *mut Desc;

/// The connection handle references storage of all information about the connection to the data
/// source, including status, transaction state, and error information.
pub type HDbc = *mut Dbc;
pub type HStmt = *mut Stmt;

pub type SmallInt = i16;
pub type USmallInt = u16;
pub type Integer = i32;
pub type UInteger = u32;
pub type Pointer = *mut c_void;
pub type Char = u8;
pub type WChar = u16;

#[cfg(target_pointer_width = "64")]
pub type Len = i64;
#[cfg(target_pointer_width = "32")]
pub type SQLLEN = SQLINTEGER;

#[cfg(target_pointer_width = "64")]
pub type ULen = u64;
#[cfg(target_pointer_width = "32")]
pub type SQLULEN = SQLUINTEGER;

pub type HWnd = Pointer;

pub type RetCode = i16;

// flags for null-terminated string
pub const NTS: SmallInt = -3;
pub const NTSL: Integer = -3;

/// Maximum message length
pub const MAX_MESSAGE_LENGTH: SmallInt = 512;
pub const SQLSTATE_SIZE: usize = 5;
pub const SQLSTATE_SIZEW: usize = 10;

// Special SQLGetData indicator values
pub const NULL_DATA: Len = -1;
pub const NO_TOTAL: Len = -4;
pub const SS_LENGTH_UNLIMITED: ULen = 0;

/// SQL Free Statement options
#[repr(u16)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum FreeStmtOption {
    /// Closes the cursor associated with StatementHandle (if one was defined) and discards all
    /// pending results. The application can reopen this cursor later by executing a SELECT
    /// statement again with the same or different parameter values. If no cursor is open, this
    /// option has no effect for the application. `SQLCloseCursor` can also be called to close a
    /// cursor.
    Close = 0,
    // SQL_DROP = 1, is deprecated in favour of SQLFreeHandle
    /// Sets the `SQL_DESC_COUNT` field of the ARD to 0, releasing all column buffers bound by
    /// `SQLBindCol` for the given StatementHandle. This does not unbind the bookmark column; to do
    /// that, the `SQL_DESC_DATA_PTR` field of the ARD for the bookmark column is set to NULL.
    /// Notice that if this operation is performed on an explicitly allocated descriptor that is
    /// shared by more than one statement, the operation will affect the bindings of all statements
    /// that share the descriptor.
    Unbind = 2,
    /// Sets the `SQL_DESC_COUNT` field of the APD to 0, releasing all parameter buffers set by
    /// `SQLBindParameter` for the given StatementHandle. If this operation is performed on an
    /// explicitly allocated descriptor that is shared by more than one statement, this operation
    /// will affect the bindings of all the statements that share the descriptor.
    ResetParams = 3,
}

/// SQL Data Types
#[repr(i16)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SqlDataType {
    UnknownType = 0,
    // also called SQL_VARIANT_TYPE since odbc 4.0
    Char = 1,
    Numeric = 2,
    Decimal = 3,
    Integer = 4,
    Smallint = 5,
    Float = 6,
    Real = 7,
    Double = 8,
    Datetime = 9,
    Varchar = 12,
    #[cfg(feature = "odbc_version_4")]
    Udt = 17,
    #[cfg(feature = "odbc_version_4")]
    Row = 19,
    #[cfg(feature = "odbc_version_4")]
    Array = 50,
    #[cfg(feature = "odbc_version_4")]
    Multiset = 55,

    // one-parameter shortcuts for date/time data types
    Date = 91,
    Time = 92,
    Timestamp = 93,
    #[cfg(feature = "odbc_version_4")]
    TimeWithTimezone = 94,
    #[cfg(feature = "odbc_version_4")]
    TimestampWithTimezone = 95,

    //SQL extended datatypes:
    ExtTimeOrInterval = 10,
    ExtTimestamp = 11,
    ExtLongVarchar = -1,
    ExtBinary = -2,
    ExtVarBinary = -3,
    ExtLongVarBinary = -4,
    ExtBigInt = -5,
    ExtTinyInt = -6,
    ExtBit = -7,
    ExtWChar = -8,
    ExtWVarChar = -9,
    ExtWLongVarChar = -10,
    ExtGuid = -11,
    SsVariant = -150,
    SsUdt = -151,
    SsXml = -152,
    SsTable = -153,
    SsTime2 = -154,
    SsTimestampOffset = -155,
}

/// Represented in C headers as SQLSMALLINT
#[repr(i16)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum HandleType {
    Env = 1,
    Dbc = 2,
    Stmt = 3,
    Desc = 4,
}

/// Options for `SQLDriverConnect`
#[repr(u16)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum DriverConnectOption {
    NoPrompt = 0,
    Complete = 1,
    Prompt = 2,
    CompleteRequired = 3,
}

#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SqlAttributeStringLength {
    /// SQL_IS_POINTER
    Pointer = -4,
    /// SQL_IS_UINTEGER
    UInteger = -5,
    /// SQL_IS_INTEGER
    Integer = -6,
    /// SQL_IS_USMALLINT
    USmallInt = -7,
    /// SQL_IS_SMALLINT
    SmallInt = -8,
}

pub use self::SqlAttributeStringLength::*;

/// SQL_YEAR_MONTH_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct YearMonth {
    pub year: UInteger,
    pub month: UInteger,
}

/// SQL_DAY_SECOND_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct DaySecond {
    pub day: UInteger,
    pub hour: UInteger,
    pub minute: UInteger,
    pub second: UInteger,
    pub fraction: UInteger,
}

/// SQL_INTERVAL_UNION
#[repr(C)]
#[derive(Copy, Clone)]
pub union IntervalUnion {
    pub year_month: YearMonth,
    pub day_second: DaySecond,
}

/// SQL_INTERVAL_STRUCT
#[repr(C)]
#[derive(Clone, Copy)]
pub struct IntervalStruct {
    pub interval_type: c_int,
    pub interval_sign: SmallInt,
    pub interval_value: IntervalUnion,
}

/// SQL_DATE_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct Date {
    pub year: SmallInt,
    pub month: USmallInt,
    pub day: USmallInt,
}

/// SQL_TIME_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct Time {
    pub hour: USmallInt,
    pub minute: USmallInt,
    pub second: USmallInt,
}

/// SQL_TIMESTAMP_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct Timestamp {
    pub year: SmallInt,
    pub month: USmallInt,
    pub day: USmallInt,
    pub hour: USmallInt,
    pub minute: USmallInt,
    pub second: USmallInt,
    pub fraction: UInteger,
}

/// SQLGUID
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct Guid {
    pub d1: u32,
    pub d2: u16,
    pub d3: u16,
    pub d4: [u8; 8],
}

/// SQL_SS_TIME2_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct SsTime2 {
    pub hour: USmallInt,
    pub minute: USmallInt,
    pub second: USmallInt,
    pub fraction: UInteger,
}

/// SQL_SS_TIMESTAMPOFFSET_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct SsTimestampOffset {
    pub year: SmallInt,
    pub month: USmallInt,
    pub day: USmallInt,
    pub hour: USmallInt,
    pub minute: USmallInt,
    pub second: USmallInt,
    pub fraction: UInteger,
    pub timezone_hour: SmallInt,
    pub timezone_minute: SmallInt,
}

/// Statement attributes for `SQLSetStmtAttr`
#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum StatementAttribute {
    AsyncEnable = 4,
    ParamBindType = 18,
    ParamsetSize = 22,
    RowBindType = 5,
    RowArraySize = 27,
    RowsFetchedPtr = 26,
    AsyncStmtEvent = 29,
}

/// Connection attributes for `SQLSetConnectAttr`
#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum ConnectionAttribute {
    AsyncEnable = 4,
    AccessMode = 101,
    AutoCommit = 102,
    LoginTimeout = 103,
    Trace = 104,
    TraceFile = 105,
    TranslateLib = 106,
    TranslateOption = 107,
    TxnIsolation = 108,
    CurrentCatalog = 109,
    OdbcCursors = 110,
    QuietMode = 111,
    PacketSize = 112,
    ConnectionTimeout = 113,
    DisconnectBehaviour = 114,
    AsyncDbcFunctionsEnable = 117,
    AsyncDbcEvent = 119,
    EnlistInDtc = 1207,
    EnlistInXa = 1208,
    ConnectionDead = 1209,
    AutoIpd = 10001,
    MetadataId = 10014,
}

/// `DiagIdentifier` for `SQLGetDiagField`
#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum HeaderDiagnosticIdentifier {
    /// SQL_DIAG_RETURNCODE
    ReturnCode = 1,
    /// SQL_DIAG_NUMBER
    Number = 2,
    /// SQL_DIAG_ROW_COUNT
    RowCount = 3,
    /// SQL_DIAG_SQLSTATE
    SqlState = 4,
    /// SQL_DIAG_NATIVE
    Native = 5,
    /// SQL_DIAG_MESSAGE_TEXT
    MessageText = 6,
    /// SQL_DIAG_DYNAMIC_FUNCTION
    DynamicFunction = 7,
    /// SQL_DIAG_CLASS_ORIGIN
    ClassOrigin = 8,
    /// SQL_DIAG_SUBCLASS_ORIGIN
    SubclassOrigin = 9,
    /// SQL_DIAG_CONNECTION_NAME
    ConnectionName = 10,
    /// SQL_DIAG_SERVER_NAME
    ServerName = 11,
    /// SQL_DIAG_DYNAMIC_FUNCTION_CODE
    DynamicFunctionCode = 12,
    /// SQL_DIAG_CURSOR_ROW_COUNT
    CursorRowCount = -1249,
    /// SQL_DIAG_ROW_NUMBER
    RowNumber = -1248,
    /// SQL_DIAG_COLUMN_NUMBER
    ColumnNumber = -1247,
}

#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum AsyncConnectionBehavior {
    /// SQL_ASYNC_DBC_ENABLE_ON
    On = 1,
    /// SQL_ASYNC_DBC_ENABLE_OFF = 0,
    Off = 0,
}

impl Default for AsyncConnectionBehavior {
    fn default() -> AsyncConnectionBehavior {
        AsyncConnectionBehavior::Off
    }
}

#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum DynamicDiagnosticIdentifier {
    /// SQL_DIAG_ALTER_DOMAIN
    AlterDomain = 3,
    /// SQL_DIAG_ALTER_TABLE,
    AlterTable = 4,
    /// SQL_DIAG_CALL
    Call = 7,
    /// SQL_DIAG_CREATE_ASSERTION
    CreateAssertion = 6,
    /// SQL_DIAG_CREATE_CHARACTER_SET
    CreateCharacterSet = 8,
    /// SQL_DIAG_CREATE_COLLATION,
    CreateCollation = 10,
    /// SQL_DIAG_CREATE_DOMAIN
    CreateDomain = 23,
    /// SQL_DIAG_CREATE_INDEX
    CreateIndex = -1,
    /// SQL_DIAG_CREATE_SCHEMA
    CreateSchema = 64,
    /// SQL_DIAG_CREATE_TABLE
    CreateTable = 77,
    /// SQL_DIAG_CREATE_TRANSLATION
    CreateTranslation = 79,
    /// SQL_DIAG_CREATE_VIEW
    CreateView = 84,
    /// SQL_DIAG_DELETE_WHERE
    DeleteWhere = 19,
    /// SQL_DIAG_DROP_ASSERTION
    DropAssertion = 24,
    /// SQL_DIAG_DROP_CHARACTER_SET
    DropCharacterSet = 25,
    /// SQL_DIAG_DROP_COLLATION
    DropCollation = 26,
    /// SQL_DIAG_DROP_DOMAIN
    DropDomain = 27,
    /// SQL_DIAG_DROP_INDEX
    DropIndex = -2,
    /// SQL_DIAG_DROP_SCHEMA
    DropSchema = 31,
    /// SQL_DIAG_DROP_TABLE
    DropTable = 32,
    /// SQL_DIAG_DROP_TRANSLATION
    DropTranslation = 33,
    /// SQL_DIAG_DROP_VIEW
    DropView = 36,
    /// SQL_DIAG_DYNAMIC_DELETE_CURSOR
    DynamicDeleteCursor = 38,
    /// SQL_DIAG_DYNAMIC_UPDATE_CURSOR
    DynamicUpdateCursor = 81,
    /// SQL_DIAG_GRANT
    Grant = 48,
    /// SQL_DIAG_INSERT
    Insert = 50,
    /// SQL_DIAG_REVOKE
    Revoke = 59,
    // SQL_DIAG_SELECT_CURSOR
    SelectCursor = 85,
    /// SQL_DIAG_UNKNOWN_STATEMENT = 0,
    UnknownStatement = 0,
    /// SQL_DIAG_UPDATE_WHERE = 82,
    UpdateWhere = 82,
}

/// Completion types for `SQLEndTrans`
#[repr(i16)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CompletionType {
    Commit = 0,
    Rollback = 1,
}
<commit_msg>fix 32 bit definitiots<commit_after>//! ODBC types those representation is compatible with the ODBC C API.
//!
//! This layer has not been created using automatic code generation. It is incomplete, i.e. it does
//! not contain every symbol or constant defined in the ODBC C headers. Symbols which are
//! deprecated since ODBC 3 have been left out intentionally. While some extra type safety has been
//! added by grouping some of C's `#define` constants into `enum`-types it mostly offers the same
//! power (all) and safety guarantess(none) as the wrapped C-API.
//! ODBC 4.0 is still under development by Microsoft, so these symbols are deactivated by default
//! in the cargo.toml

pub use self::{
    attributes::*, bulk_operation::*, c_data_type::*, fetch_orientation::*, info_type::*,
    nullable::*, param_type::*, sqlreturn::*, functions::*, interval::*
};
use std::os::raw::{c_int, c_void};

mod attributes;
mod bulk_operation;
mod c_data_type;
mod fetch_orientation;
mod functions;
mod info_type;
mod nullable;
mod param_type;
mod sqlreturn;
mod interval;

//These types can never be instantiated in Rust code.
pub enum Obj {}

pub enum Env {}

pub enum Dbc {}

pub enum Stmt {}

pub enum Desc {}

pub type Handle = *mut Obj;
pub type HEnv = *mut Env;
pub type HDesc = *mut Desc;

/// The connection handle references storage of all information about the connection to the data
/// source, including status, transaction state, and error information.
pub type HDbc = *mut Dbc;
pub type HStmt = *mut Stmt;

pub type SmallInt = i16;
pub type USmallInt = u16;
pub type Integer = i32;
pub type UInteger = u32;
pub type Pointer = *mut c_void;
pub type Char = u8;
pub type WChar = u16;

#[cfg(target_pointer_width = "64")]
pub type Len = i64;
#[cfg(target_pointer_width = "32")]
pub type Len = Integer;

#[cfg(target_pointer_width = "64")]
pub type ULen = u64;
#[cfg(target_pointer_width = "32")]
pub type ULen = UInteger;

pub type HWnd = Pointer;

pub type RetCode = i16;

// flags for null-terminated string
pub const NTS: SmallInt = -3;
pub const NTSL: Integer = -3;

/// Maximum message length
pub const MAX_MESSAGE_LENGTH: SmallInt = 512;
pub const SQLSTATE_SIZE: usize = 5;
pub const SQLSTATE_SIZEW: usize = 10;

// Special SQLGetData indicator values
pub const NULL_DATA: Len = -1;
pub const NO_TOTAL: Len = -4;
pub const SS_LENGTH_UNLIMITED: ULen = 0;

/// SQL Free Statement options
#[repr(u16)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum FreeStmtOption {
    /// Closes the cursor associated with StatementHandle (if one was defined) and discards all
    /// pending results. The application can reopen this cursor later by executing a SELECT
    /// statement again with the same or different parameter values. If no cursor is open, this
    /// option has no effect for the application. `SQLCloseCursor` can also be called to close a
    /// cursor.
    Close = 0,
    // SQL_DROP = 1, is deprecated in favour of SQLFreeHandle
    /// Sets the `SQL_DESC_COUNT` field of the ARD to 0, releasing all column buffers bound by
    /// `SQLBindCol` for the given StatementHandle. This does not unbind the bookmark column; to do
    /// that, the `SQL_DESC_DATA_PTR` field of the ARD for the bookmark column is set to NULL.
    /// Notice that if this operation is performed on an explicitly allocated descriptor that is
    /// shared by more than one statement, the operation will affect the bindings of all statements
    /// that share the descriptor.
    Unbind = 2,
    /// Sets the `SQL_DESC_COUNT` field of the APD to 0, releasing all parameter buffers set by
    /// `SQLBindParameter` for the given StatementHandle. If this operation is performed on an
    /// explicitly allocated descriptor that is shared by more than one statement, this operation
    /// will affect the bindings of all the statements that share the descriptor.
    ResetParams = 3,
}

/// SQL Data Types
#[repr(i16)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SqlDataType {
    UnknownType = 0,
    // also called SQL_VARIANT_TYPE since odbc 4.0
    Char = 1,
    Numeric = 2,
    Decimal = 3,
    Integer = 4,
    Smallint = 5,
    Float = 6,
    Real = 7,
    Double = 8,
    Datetime = 9,
    Varchar = 12,
    #[cfg(feature = "odbc_version_4")]
    Udt = 17,
    #[cfg(feature = "odbc_version_4")]
    Row = 19,
    #[cfg(feature = "odbc_version_4")]
    Array = 50,
    #[cfg(feature = "odbc_version_4")]
    Multiset = 55,

    // one-parameter shortcuts for date/time data types
    Date = 91,
    Time = 92,
    Timestamp = 93,
    #[cfg(feature = "odbc_version_4")]
    TimeWithTimezone = 94,
    #[cfg(feature = "odbc_version_4")]
    TimestampWithTimezone = 95,

    //SQL extended datatypes:
    ExtTimeOrInterval = 10,
    ExtTimestamp = 11,
    ExtLongVarchar = -1,
    ExtBinary = -2,
    ExtVarBinary = -3,
    ExtLongVarBinary = -4,
    ExtBigInt = -5,
    ExtTinyInt = -6,
    ExtBit = -7,
    ExtWChar = -8,
    ExtWVarChar = -9,
    ExtWLongVarChar = -10,
    ExtGuid = -11,
    SsVariant = -150,
    SsUdt = -151,
    SsXml = -152,
    SsTable = -153,
    SsTime2 = -154,
    SsTimestampOffset = -155,
}

/// Represented in C headers as SQLSMALLINT
#[repr(i16)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum HandleType {
    Env = 1,
    Dbc = 2,
    Stmt = 3,
    Desc = 4,
}

/// Options for `SQLDriverConnect`
#[repr(u16)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum DriverConnectOption {
    NoPrompt = 0,
    Complete = 1,
    Prompt = 2,
    CompleteRequired = 3,
}

#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SqlAttributeStringLength {
    /// SQL_IS_POINTER
    Pointer = -4,
    /// SQL_IS_UINTEGER
    UInteger = -5,
    /// SQL_IS_INTEGER
    Integer = -6,
    /// SQL_IS_USMALLINT
    USmallInt = -7,
    /// SQL_IS_SMALLINT
    SmallInt = -8,
}

pub use self::SqlAttributeStringLength::*;

/// SQL_YEAR_MONTH_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct YearMonth {
    pub year: UInteger,
    pub month: UInteger,
}

/// SQL_DAY_SECOND_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct DaySecond {
    pub day: UInteger,
    pub hour: UInteger,
    pub minute: UInteger,
    pub second: UInteger,
    pub fraction: UInteger,
}

/// SQL_INTERVAL_UNION
#[repr(C)]
#[derive(Copy, Clone)]
pub union IntervalUnion {
    pub year_month: YearMonth,
    pub day_second: DaySecond,
}

/// SQL_INTERVAL_STRUCT
#[repr(C)]
#[derive(Clone, Copy)]
pub struct IntervalStruct {
    pub interval_type: c_int,
    pub interval_sign: SmallInt,
    pub interval_value: IntervalUnion,
}

/// SQL_DATE_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct Date {
    pub year: SmallInt,
    pub month: USmallInt,
    pub day: USmallInt,
}

/// SQL_TIME_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct Time {
    pub hour: USmallInt,
    pub minute: USmallInt,
    pub second: USmallInt,
}

/// SQL_TIMESTAMP_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct Timestamp {
    pub year: SmallInt,
    pub month: USmallInt,
    pub day: USmallInt,
    pub hour: USmallInt,
    pub minute: USmallInt,
    pub second: USmallInt,
    pub fraction: UInteger,
}

/// SQLGUID
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct Guid {
    pub d1: u32,
    pub d2: u16,
    pub d3: u16,
    pub d4: [u8; 8],
}

/// SQL_SS_TIME2_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct SsTime2 {
    pub hour: USmallInt,
    pub minute: USmallInt,
    pub second: USmallInt,
    pub fraction: UInteger,
}

/// SQL_SS_TIMESTAMPOFFSET_STRUCT
#[repr(C)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, Hash)]
pub struct SsTimestampOffset {
    pub year: SmallInt,
    pub month: USmallInt,
    pub day: USmallInt,
    pub hour: USmallInt,
    pub minute: USmallInt,
    pub second: USmallInt,
    pub fraction: UInteger,
    pub timezone_hour: SmallInt,
    pub timezone_minute: SmallInt,
}

/// Statement attributes for `SQLSetStmtAttr`
#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum StatementAttribute {
    AsyncEnable = 4,
    ParamBindType = 18,
    ParamsetSize = 22,
    RowBindType = 5,
    RowArraySize = 27,
    RowsFetchedPtr = 26,
    AsyncStmtEvent = 29,
}

/// Connection attributes for `SQLSetConnectAttr`
#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum ConnectionAttribute {
    AsyncEnable = 4,
    AccessMode = 101,
    AutoCommit = 102,
    LoginTimeout = 103,
    Trace = 104,
    TraceFile = 105,
    TranslateLib = 106,
    TranslateOption = 107,
    TxnIsolation = 108,
    CurrentCatalog = 109,
    OdbcCursors = 110,
    QuietMode = 111,
    PacketSize = 112,
    ConnectionTimeout = 113,
    DisconnectBehaviour = 114,
    AsyncDbcFunctionsEnable = 117,
    AsyncDbcEvent = 119,
    EnlistInDtc = 1207,
    EnlistInXa = 1208,
    ConnectionDead = 1209,
    AutoIpd = 10001,
    MetadataId = 10014,
}

/// `DiagIdentifier` for `SQLGetDiagField`
#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum HeaderDiagnosticIdentifier {
    /// SQL_DIAG_RETURNCODE
    ReturnCode = 1,
    /// SQL_DIAG_NUMBER
    Number = 2,
    /// SQL_DIAG_ROW_COUNT
    RowCount = 3,
    /// SQL_DIAG_SQLSTATE
    SqlState = 4,
    /// SQL_DIAG_NATIVE
    Native = 5,
    /// SQL_DIAG_MESSAGE_TEXT
    MessageText = 6,
    /// SQL_DIAG_DYNAMIC_FUNCTION
    DynamicFunction = 7,
    /// SQL_DIAG_CLASS_ORIGIN
    ClassOrigin = 8,
    /// SQL_DIAG_SUBCLASS_ORIGIN
    SubclassOrigin = 9,
    /// SQL_DIAG_CONNECTION_NAME
    ConnectionName = 10,
    /// SQL_DIAG_SERVER_NAME
    ServerName = 11,
    /// SQL_DIAG_DYNAMIC_FUNCTION_CODE
    DynamicFunctionCode = 12,
    /// SQL_DIAG_CURSOR_ROW_COUNT
    CursorRowCount = -1249,
    /// SQL_DIAG_ROW_NUMBER
    RowNumber = -1248,
    /// SQL_DIAG_COLUMN_NUMBER
    ColumnNumber = -1247,
}

#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum AsyncConnectionBehavior {
    /// SQL_ASYNC_DBC_ENABLE_ON
    On = 1,
    /// SQL_ASYNC_DBC_ENABLE_OFF = 0,
    Off = 0,
}

impl Default for AsyncConnectionBehavior {
    fn default() -> AsyncConnectionBehavior {
        AsyncConnectionBehavior::Off
    }
}

#[repr(i32)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum DynamicDiagnosticIdentifier {
    /// SQL_DIAG_ALTER_DOMAIN
    AlterDomain = 3,
    /// SQL_DIAG_ALTER_TABLE,
    AlterTable = 4,
    /// SQL_DIAG_CALL
    Call = 7,
    /// SQL_DIAG_CREATE_ASSERTION
    CreateAssertion = 6,
    /// SQL_DIAG_CREATE_CHARACTER_SET
    CreateCharacterSet = 8,
    /// SQL_DIAG_CREATE_COLLATION,
    CreateCollation = 10,
    /// SQL_DIAG_CREATE_DOMAIN
    CreateDomain = 23,
    /// SQL_DIAG_CREATE_INDEX
    CreateIndex = -1,
    /// SQL_DIAG_CREATE_SCHEMA
    CreateSchema = 64,
    /// SQL_DIAG_CREATE_TABLE
    CreateTable = 77,
    /// SQL_DIAG_CREATE_TRANSLATION
    CreateTranslation = 79,
    /// SQL_DIAG_CREATE_VIEW
    CreateView = 84,
    /// SQL_DIAG_DELETE_WHERE
    DeleteWhere = 19,
    /// SQL_DIAG_DROP_ASSERTION
    DropAssertion = 24,
    /// SQL_DIAG_DROP_CHARACTER_SET
    DropCharacterSet = 25,
    /// SQL_DIAG_DROP_COLLATION
    DropCollation = 26,
    /// SQL_DIAG_DROP_DOMAIN
    DropDomain = 27,
    /// SQL_DIAG_DROP_INDEX
    DropIndex = -2,
    /// SQL_DIAG_DROP_SCHEMA
    DropSchema = 31,
    /// SQL_DIAG_DROP_TABLE
    DropTable = 32,
    /// SQL_DIAG_DROP_TRANSLATION
    DropTranslation = 33,
    /// SQL_DIAG_DROP_VIEW
    DropView = 36,
    /// SQL_DIAG_DYNAMIC_DELETE_CURSOR
    DynamicDeleteCursor = 38,
    /// SQL_DIAG_DYNAMIC_UPDATE_CURSOR
    DynamicUpdateCursor = 81,
    /// SQL_DIAG_GRANT
    Grant = 48,
    /// SQL_DIAG_INSERT
    Insert = 50,
    /// SQL_DIAG_REVOKE
    Revoke = 59,
    // SQL_DIAG_SELECT_CURSOR
    SelectCursor = 85,
    /// SQL_DIAG_UNKNOWN_STATEMENT = 0,
    UnknownStatement = 0,
    /// SQL_DIAG_UPDATE_WHERE = 82,
    UpdateWhere = 82,
}

/// Completion types for `SQLEndTrans`
#[repr(i16)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CompletionType {
    Commit = 0,
    Rollback = 1,
}
<|endoftext|>


<commit_before>#![deny(trivial_casts, trivial_numeric_casts,
        unstable_features,
        unused_import_braces, unused_qualifications)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

extern crate libc;
extern crate nix;

use nix::sys::wait;
use std::io::{self, Read, Write};
use std::os::unix::io::{AsRawFd, RawFd};

mod ffi;

macro_rules! unsafe_try {
    ( $x:expr ) => {
        try!($crate::to_result(unsafe { $x }))
    };
}

/// A type representing child process' pty.
#[derive(Clone)]
pub struct ChildPTY {
    fd: libc::c_int,
}

/// A type representing child process.
#[derive(Clone)]
pub struct Child {
    pid: libc::pid_t,
    pty: Option<ChildPTY>,
}

impl Child {
    /// Returns its pid.
    pub fn pid(&self) -> libc::pid_t {
        self.pid
    }

    /// Returns a copy of its pty.
    pub fn pty(&self) -> Option<ChildPTY> {
        self.pty.clone()
    }

    /// Waits until it's terminated. Then closes its pty.
    pub fn wait(&self) -> Result<(), &str> {
        loop {
            let res = wait::waitpid(self.pid, None);

            match res {
                Ok(status) => {
                    match status {
                        wait::WaitStatus::StillAlive => continue,
                        _ => {
                            self.pty().unwrap().close();

                            return Ok(());
                        }
                    }
                }
                Err(e) => return Err(e.errno().desc()),
            }
        }
    }
}

impl ChildPTY {
    /// Closes own file descriptor.
    pub fn close(&self) -> i32 {
        unsafe { libc::close(self.as_raw_fd()) }
    }
}

impl AsRawFd for ChildPTY {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}

impl Read for ChildPTY {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match to_result(unsafe {
            libc::read(self.fd,
                       buf.as_mut_ptr() as *mut libc::c_void,
                       buf.len() as libc::size_t)
        }) {
            Ok(nread) => Ok(nread as usize),
            Err(_) => Ok(0),
        }
    }
}

impl Write for ChildPTY {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let ret = unsafe_try!(libc::write(self.fd,
                                          buf.as_ptr() as *const libc::c_void,
                                          buf.len() as libc::size_t));

        Ok(ret as usize)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

/// Fork with new pseudo-terminal (PTY).
///
/// # Examples
///
/// ```rust
/// extern crate libc;
/// extern crate pty;
///
/// use std::ffi::CString;
/// use std::io::Read;
/// use std::ptr;
///
/// fn main()
/// {
///     match pty::fork() {
///         Ok(child) => {
///             if child.pid() == 0 {
///                 // Child process just exec `tty`
///                 let cmd  = CString::new("tty").unwrap().as_ptr();
///                 let args = [cmd, ptr::null()].as_mut_ptr();
///
///                 unsafe { libc::execvp(cmd, args) };
///             }
///             else {
///                 // Read output via PTY master
///                 let mut output     = String::new();
///                 let mut pty_master = child.pty().unwrap();
///
///                 match pty_master.read_to_string(&mut output) {
///                     Ok(_nread) => println!("child tty is: {}", output.trim()),
///                     Err(e)     => panic!("read error: {}", e)
///                 }
///
///                 let _ = child.wait();
///             }
///         },
///         Err(e)    => panic!("pty::fork error: {}", e)
///     }
/// }
/// ```
pub fn fork() -> io::Result<Child> {
    let pty_master = try!(open_ptm());
    let pid = unsafe_try!(libc::fork());

    if pid == 0 {
        try!(attach_pts(pty_master));

        Ok(Child {
            pid: pid,
            pty: None,
        })
    } else {
        Ok(Child {
            pid: pid,
            pty: Some(ChildPTY { fd: pty_master }),
        })
    }
}

fn open_ptm() -> io::Result<libc::c_int> {
    let pty_master = unsafe_try!(ffi::posix_openpt(libc::O_RDWR));

    unsafe_try!(ffi::grantpt(pty_master));
    unsafe_try!(ffi::unlockpt(pty_master));

    Ok(pty_master)
}

fn attach_pts(pty_master: libc::c_int) -> io::Result<()> {
    let pts_name = unsafe { ffi::ptsname(pty_master) };

    if (pts_name as *const i32) == std::ptr::null() {
        return Err(io::Error::last_os_error());
    }

    unsafe_try!(libc::close(pty_master));
    unsafe_try!(libc::setsid());

    let pty_slave = unsafe_try!(libc::open(pts_name, libc::O_RDWR, 0));

    unsafe_try!(libc::dup2(pty_slave, libc::STDIN_FILENO));
    unsafe_try!(libc::dup2(pty_slave, libc::STDOUT_FILENO));
    unsafe_try!(libc::dup2(pty_slave, libc::STDERR_FILENO));

    unsafe_try!(libc::close(pty_slave));

    Ok(())
}

// XXX use <T: Neg<Output=T> + One + PartialEq> trait instead
trait CReturnValue {
    fn as_c_return_value_is_error(&self) -> bool; }

macro_rules! impl_as_c_return_value_is_error {
    () => {
        fn as_c_return_value_is_error(&self) -> bool { *self == -1 }
    }
}

impl CReturnValue for i32 { impl_as_c_return_value_is_error!(); }
impl CReturnValue for i64 { impl_as_c_return_value_is_error!(); }

#[inline]
fn to_result<T: CReturnValue>(r: T) -> io::Result<T> {
    if r.as_c_return_value_is_error() {
        Err(io::Error::last_os_error())
    } else {
        Ok(r)
    }
}

#[cfg(test)]
mod tests {
    extern crate libc;

    use std::ffi::CString;
    use std::io::{Read, Write};
    use std::process::{Command, Stdio};
    use std::ptr;
    use std::string::String;
    use super::fork;

    #[test]
    fn it_fork_with_new_pty() {
        let child = fork().unwrap();

        if child.pid() == 0 {
            let mut ptrs = [CString::new("tty").unwrap().as_ptr(), ptr::null()];

            let _ = unsafe { libc::execvp(*ptrs.as_ptr(), ptrs.as_mut_ptr()) };
        } else {
            let mut pty = child.pty().unwrap();
            let mut string = String::new();

            match pty.read_to_string(&mut string) {
                Ok(_) => {
                    let output = Command::new("tty")
                                     .stdin(Stdio::inherit())
                                     .output()
                                     .unwrap()
                                     .stdout;

                    let parent_tty = String::from_utf8_lossy(&output);
                    let child_tty = string.trim();

                    assert!(child_tty != "");
                    assert!(child_tty != parent_tty);

                    let mut parent_tty_dir: Vec<&str> = parent_tty.split("/").collect();
                    let mut child_tty_dir: Vec<&str> = child_tty.split("/").collect();

                    parent_tty_dir.pop();
                    child_tty_dir.pop();

                    assert_eq!(parent_tty_dir, child_tty_dir);
                }
                Err(e) => panic!("{}", e),
            }
        }

        let _ = child.wait();
    }

    #[test]
    fn it_can_read_write() {
        let child = fork().unwrap();

        if child.pid() == 0 {
            let mut ptrs = [CString::new("bash").unwrap().as_ptr(), ptr::null()];

            print!(" "); // FIXME I'm not sure but this is needed to prevent read-block.

            let _ = unsafe { libc::execvp(*ptrs.as_ptr(), ptrs.as_mut_ptr()) };
        } else {
            let mut pty = child.pty().unwrap();
            let _ = pty.write("echo readme!\n".to_string().as_bytes());

            let mut string = String::new();

            match pty.read_to_string(&mut string) {
                Ok(_) => {
                    assert!(string.contains("readme!"));
                }
                Err(e) => panic!("{}", e),
            }

            let _ = pty.write("exit\n".to_string().as_bytes());
        }

        let _ = child.wait();
    }
}
<commit_msg>Improve error representation<commit_after>#![deny(trivial_casts, trivial_numeric_casts,
        unstable_features,
        unused_import_braces, unused_qualifications)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

extern crate libc;
extern crate nix;

use nix::errno;
use nix::sys::wait;
use std::fmt;
use std::io::{self, Read, Write};
use std::os::unix::io::{AsRawFd, RawFd};
use std::result;

mod ffi;

macro_rules! unsafe_try {
    ( $x:expr ) => {{
        let ret = unsafe { $x };

        if ret < 0 {
            return Err($crate::last_error());
        } else {
            ret
        }
    }};
}

#[derive(Debug)]
pub enum Error {
    Sys(i32),
}

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

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Sys(n) => errno::from_i32(n).desc()
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        std::error::Error::description(self).fmt(f)
    }
}

impl From<i32> for Error {
    fn from(n: i32) -> Error {
        Error::Sys(n)
    }
}

impl From<::nix::Error> for Error {
    fn from(e: ::nix::Error) -> Error {
        Error::Sys(e.errno() as i32)
    }
}

pub fn last_error() -> Error {
    Error::from(errno::errno())
}

/// A type representing child process' pty.
#[derive(Clone)]
pub struct ChildPTY {
    fd: libc::c_int,
}

/// A type representing child process.
#[derive(Clone)]
pub struct Child {
    pid: libc::pid_t,
    pty: Option<ChildPTY>,
}

impl Child {
    /// Returns its pid.
    pub fn pid(&self) -> libc::pid_t {
        self.pid
    }

    /// Returns a copy of its pty.
    pub fn pty(&self) -> Option<ChildPTY> {
        self.pty.clone()
    }

    /// Waits until it's terminated. Then closes its pty.
    pub fn wait(&self) -> Result<()> {
        loop {
            match try!(wait::waitpid(self.pid, None)) {
                wait::WaitStatus::StillAlive => continue,
                _ => return self.pty().unwrap().close(),
            }
        }
    }
}

impl ChildPTY {
    /// Closes own file descriptor.
    pub fn close(&self) -> Result<()> {
        if unsafe { libc::close(self.as_raw_fd()) } < 0 {
            Err(Error::from(errno::errno()))
        } else {
            Ok(())
        }
    }
}

impl AsRawFd for ChildPTY {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}

impl Read for ChildPTY {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let nread = unsafe {
            libc::read(self.fd,
               buf.as_mut_ptr() as *mut libc::c_void,
               buf.len() as libc::size_t)
        };

        if nread < 0 {
            Ok(0)
        } else {
            Ok(nread as usize)
        }
    }
}

impl Write for ChildPTY {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let ret = unsafe {
            libc::write(self.fd,
                buf.as_ptr() as *const libc::c_void,
                buf.len() as libc::size_t
            )
        };

        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(ret as usize)
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

/// Fork with new pseudo-terminal (PTY).
///
/// # Examples
///
/// ```rust
/// extern crate libc;
/// extern crate pty;
///
/// use std::ffi::CString;
/// use std::io::Read;
/// use std::ptr;
///
/// fn main()
/// {
///     match pty::fork() {
///         Ok(child) => {
///             if child.pid() == 0 {
///                 // Child process just exec `tty`
///                 let cmd  = CString::new("tty").unwrap().as_ptr();
///                 let args = [cmd, ptr::null()].as_mut_ptr();
///
///                 unsafe { libc::execvp(cmd, args) };
///             }
///             else {
///                 // Read output via PTY master
///                 let mut output     = String::new();
///                 let mut pty_master = child.pty().unwrap();
///
///                 match pty_master.read_to_string(&mut output) {
///                     Ok(_nread) => println!("child tty is: {}", output.trim()),
///                     Err(e)     => panic!("read error: {}", e)
///                 }
///
///                 let _ = child.wait();
///             }
///         },
///         Err(e)    => panic!("pty::fork error: {}", e)
///     }
/// }
/// ```
pub fn fork() -> Result<Child> {
    let pty_master = try!(open_ptm());
    let pid = unsafe_try!(libc::fork());

    if pid == 0 {
        try!(attach_pts(pty_master));

        Ok(Child {
            pid: pid,
            pty: None,
        })
    } else {
        Ok(Child {
            pid: pid,
            pty: Some(ChildPTY { fd: pty_master }),
        })
    }
}

fn open_ptm() -> Result<libc::c_int> {
    let pty_master = unsafe_try!(ffi::posix_openpt(libc::O_RDWR));

    unsafe_try!(ffi::grantpt(pty_master));
    unsafe_try!(ffi::unlockpt(pty_master));

    Ok(pty_master)
}

fn attach_pts(pty_master: libc::c_int) -> Result<()> {
    let pts_name = unsafe { ffi::ptsname(pty_master) };

    if (pts_name as *const i32) == std::ptr::null() {
        return Err(last_error());
    }

    unsafe_try!(libc::close(pty_master));
    unsafe_try!(libc::setsid());

    let pty_slave = unsafe_try!(libc::open(pts_name, libc::O_RDWR, 0));

    unsafe_try!(libc::dup2(pty_slave, libc::STDIN_FILENO));
    unsafe_try!(libc::dup2(pty_slave, libc::STDOUT_FILENO));
    unsafe_try!(libc::dup2(pty_slave, libc::STDERR_FILENO));

    unsafe_try!(libc::close(pty_slave));

    Ok(())
}

#[cfg(test)]
mod tests {
    extern crate libc;

    use std::ffi::CString;
    use std::io::{Read, Write};
    use std::process::{Command, Stdio};
    use std::ptr;
    use std::string::String;
    use super::fork;

    #[test]
    fn it_fork_with_new_pty() {
        let child = fork().unwrap();

        if child.pid() == 0 {
            let mut ptrs = [CString::new("tty").unwrap().as_ptr(), ptr::null()];

            let _ = unsafe { libc::execvp(*ptrs.as_ptr(), ptrs.as_mut_ptr()) };
        } else {
            let mut pty = child.pty().unwrap();
            let mut string = String::new();

            match pty.read_to_string(&mut string) {
                Ok(_) => {
                    let output = Command::new("tty")
                                     .stdin(Stdio::inherit())
                                     .output()
                                     .unwrap()
                                     .stdout;

                    let parent_tty = String::from_utf8_lossy(&output);
                    let child_tty = string.trim();

                    assert!(child_tty != "");
                    assert!(child_tty != parent_tty);

                    let mut parent_tty_dir: Vec<&str> = parent_tty.split("/").collect();
                    let mut child_tty_dir: Vec<&str> = child_tty.split("/").collect();

                    parent_tty_dir.pop();
                    child_tty_dir.pop();

                    assert_eq!(parent_tty_dir, child_tty_dir);
                }
                Err(e) => panic!("{}", e),
            }
        }

        let _ = child.wait();
    }

    #[test]
    fn it_can_read_write() {
        let child = fork().unwrap();

        if child.pid() == 0 {
            let mut ptrs = [CString::new("bash").unwrap().as_ptr(), ptr::null()];

            print!(" "); // FIXME I'm not sure but this is needed to prevent read-block.

            let _ = unsafe { libc::execvp(*ptrs.as_ptr(), ptrs.as_mut_ptr()) };
        } else {
            let mut pty = child.pty().unwrap();
            let _ = pty.write("echo readme!\n".to_string().as_bytes());

            let mut string = String::new();

            match pty.read_to_string(&mut string) {
                Ok(_) => {
                    assert!(string.contains("readme!"));
                }
                Err(e) => panic!("{}", e),
            }

            let _ = pty.write("exit\n".to_string().as_bytes());
        }

        let _ = child.wait();
    }
}
<|endoftext|>