<commit_before>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A micro-benchmarking library.
//!
//! # Example
//!
//! ```
//! use std::time::{Duration};
//! use microbench::{self, Options};
//!
//! fn fibonacci_iterative(n: u64) -> u64 {
//!     let (mut x, mut y, mut z) = (0, 1, 1);
//!     for _ in 0..n { x = y; y = z; z = x + y; }
//!     x
//! }
//!
//! fn fibonacci_recursive(n: u64) -> u64 {
//!     if n < 2 {
//!         n
//!     } else {
//!         fibonacci_recursive(n - 2) + fibonacci_recursive(n - 1)
//!     }
//! }
//!
//! let options = Options::default().maximum(Duration::new(1, 0));
//! microbench::bench(&options, "iterative_16", || fibonacci_iterative(16));
//! microbench::bench(&options, "recursive_16", || fibonacci_recursive(16));
//! ```
//!
//! Example output:
//!
//! ```console
//! iterative_16 ... bench:          284.161 ns/iter (1.000 R²)
//! recursive_16 ... bench:          9222.037 ns/iter (1.000 R²)
//! ```

#![feature(test)]

#![warn(missing_copy_implementations, missing_debug_implementations, missing_docs)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", warn(clippy))]
#![cfg_attr(feature="clippy", allow(new_without_default_derive))]

extern crate test;
extern crate time;

use std::time::{Duration};

//================================================
// Structs
//================================================

// Analysis ______________________________________

/// An analysis of a set of timing data.
#[derive(Copy, Clone, Debug)]
pub struct Analysis {
    /// The slope of the linear regression estimator.
    pub beta: f64,
    /// The goodness of fit of the linear regression estimator.
    pub r2: f64,
}

// GeometricSequence _____________________________

/// Generates unique values from a geometric sequence.
#[derive(Copy, Clone, Debug)]
pub struct GeometricSequence {
    current: f64,
    factor: f64,
}

impl GeometricSequence {
    //- Constructors -----------------------------

    /// Constructs a new `GeometricSequence`.
    pub fn new(start: u64, factor: f64) -> Self {
        GeometricSequence { current: start as f64, factor: factor }
    }
}

impl Iterator for GeometricSequence {
    type Item = u64;

    fn next(&mut self) -> Option<Self::Item> {
        let start = self.current as u64;
        while self.current as u64 == start { self.current *= self.factor; }
        Some(start)
    }
}

// Measurement ___________________________________

/// A measurement of the execution time of a function.
#[derive(Copy, Clone, Debug)]
pub struct Measurement {
    /// The number of times the function was called.
    pub iterations: u64,
    /// The number of nanoseconds that elapsed while calling the function.
    pub nanoseconds: u64,
}

impl Measurement {
    //- Constructors -----------------------------

    /// Constructs a new `Measurement`.
    pub fn new(iterations: u64, nanoseconds: u64) -> Self {
        Measurement { iterations: iterations, nanoseconds: nanoseconds }
    }
}

// Options _______________________________________

/// Micro-benchmarking options.
#[derive(Copy, Clone, Debug)]
pub struct Options {
    factor: f64,
    maximum: u64,
}

impl Default for Options {
    fn default() -> Options {
        Options { factor: 1.01, maximum: 5_000_000_000 }
    }
}

impl Options {
    //- Consumers --------------------------------

    /// Sets the geometric growth factor.
    ///
    /// **Default:** `1.01`
    pub fn factor(mut self, factor: f64) -> Self {
        self.factor = factor;
        self
    }

    /// Sets the maximum amount of time a micro-benchmark will run for.
    ///
    /// **Default:** `Duration::new(5, 0)`
    pub fn maximum(mut self, maximum: Duration) -> Self {
        self.maximum = (maximum.as_secs() * 1_000_000_000) + maximum.subsec_nanos() as u64;
        self
    }
}

// Stopwatch _____________________________________

/// A high-precision stopwatch.
#[derive(Clone, Copy, Debug)]
pub struct Stopwatch {
    start: u64,
}

impl Stopwatch {
    //- Constructors -----------------------------

    /// Constructs a new `Stopwatch`.
    pub fn new() -> Self {
        Stopwatch { start: time::precise_time_ns() }
    }

    //- Accessors --------------------------------

    /// Returns the elapsed nanoseconds since this stopwatch was constructed or reset.
    pub fn elapsed(&self) -> u64 {
        time::precise_time_ns() - self.start
    }

    //- Mutators ---------------------------------

    /// Resets this stopwatch.
    pub fn reset(&mut self) {
        self.start = time::precise_time_ns();
    }
}

//================================================
// Functions
//================================================

fn mean<I>(iterator: I) -> f64 where I: Iterator<Item=f64> {
    let (sum, len) = iterator.fold((0.0, 0), |a, f| (a.0 + f, a.1 + 1));
    sum / len as f64
}

/// Analyzes the supplied timing data and returns the resulting analysis.
pub fn analyze(measurements: &[Measurement]) -> Analysis {
    let xmean = mean(measurements.iter().map(|m| m.iterations as f64));
    let ymean = mean(measurements.iter().map(|m| m.nanoseconds as f64));

    // Ordinary least squares estimator.
    let numerator = measurements.iter().map(|m| {
        (m.iterations as f64 - xmean) * (m.nanoseconds as f64 - ymean)
    }).sum::<f64>();
    let denominator = measurements.iter().map(|m| {
        (m.iterations as f64 - xmean).powf(2.0)
    }).sum::<f64>();
    let beta = numerator / denominator;
    let alpha = ymean - (beta * xmean);
    let estimator = |x: u64| (beta * x as f64) + alpha;

    // Ordinary least squares goodness of fit.
    let numerator = measurements.iter().map(|m| {
        (estimator(m.iterations) - ymean).powf(2.0)
    }).sum::<f64>();
    let denominator = measurements.iter().map(|m| {
        (m.nanoseconds as f64 - ymean).powf(2.0)
    }).sum::<f64>();
    let r2 = numerator / denominator;

    Analysis { beta: beta, r2: r2 }
}

/// Micro-benchmarks the supplied function.
pub fn bench<T, F>(options: &Options, name: &str, f: F) where F: FnMut() -> T {
    let analysis = analyze(&measure(options, f));
    let prefix = format!("{} ... bench:", name);
    println!("{:<32} {:.3} ns/iter ({:.3} R²)", prefix, analysis.beta, analysis.r2);
}

/// Measures the execution time of the supplied function and returns the resulting samples.
pub fn measure<T, F>(options: &Options, mut f: F) -> Vec<Measurement> where F: FnMut() -> T {
    let mut measurements = vec![];
    let mut sequence = GeometricSequence::new(1, options.factor);
    let total = Stopwatch::new();
    while total.elapsed() < options.maximum {
        let iterations = sequence.next().unwrap();
        let sample = Stopwatch::new();
        for _ in 0..iterations { retain(f()); }
        measurements.push(Measurement::new(iterations, sample.elapsed()));
    }
    measurements
}

/// A function that prevents the optimizer from eliminating the supplied value.
pub fn retain<T>(value: T) -> T {
    test::black_box(value)
}
<commit_msg>Improve documentation<commit_after>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A micro-benchmarking library.
//!
//! `microbench` uses linear regression to estimate the execution time of code segments. For
//! example, the following table might represent data collected by `microbench` about a code
//! segment.
//!
//! | Iterations | Time (ns) |
//! |------------|-----------|
//! | 1          | 19        |
//! | 2          | 25        |
//! | 3          | 37        |
//! | 4          | 47        |
//! | 5          | 56        |
//!
//! `microbench` of course takes many more than 5 samples and the number of iterations grows
//! geometrically rather than linearly, but the concept remains the same. After collecting data like
//! this, `microbench` uses ordinary least squares (OLS) linear regression to estimate the actual
//! execution time of the code segment. Using OLS with the above data would yield an estimated
//! execution time of `9.6` nanoseconds with a goodness of fit (R²) of `0.992`.
//!
//! # Example
//!
//! ```
//! use std::time::{Duration};
//! use microbench::{self, Options};
//!
//! fn fibonacci_iterative(n: u64) -> u64 {
//!     let (mut x, mut y, mut z) = (0, 1, 1);
//!     for _ in 0..n { x = y; y = z; z = x + y; }
//!     x
//! }
//!
//! fn fibonacci_recursive(n: u64) -> u64 {
//!     if n < 2 {
//!         n
//!     } else {
//!         fibonacci_recursive(n - 2) + fibonacci_recursive(n - 1)
//!     }
//! }
//!
//! let options = Options::default().maximum(Duration::new(1, 0));
//! microbench::bench(&options, "iterative_16", || fibonacci_iterative(16));
//! microbench::bench(&options, "recursive_16", || fibonacci_recursive(16));
//! ```
//!
//! Example output:
//!
//! ```console
//! iterative_16 ... bench:          284.161 ns/iter (1.000 R²)
//! recursive_16 ... bench:          9222.037 ns/iter (1.000 R²)
//! ```

#![feature(test)]

#![warn(missing_copy_implementations, missing_debug_implementations, missing_docs)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", warn(clippy))]
#![cfg_attr(feature="clippy", allow(new_without_default_derive))]

extern crate test;
extern crate time;

use std::time::{Duration};

//================================================
// Structs
//================================================

// Analysis ______________________________________

/// An analysis of a set of timing data.
#[derive(Copy, Clone, Debug)]
pub struct Analysis {
    /// The slope of the linear regression estimator.
    pub beta: f64,
    /// The goodness of fit of the linear regression estimator.
    pub r2: f64,
}

// GeometricSequence _____________________________

/// Generates unique values from a geometric sequence.
#[derive(Copy, Clone, Debug)]
pub struct GeometricSequence {
    current: f64,
    factor: f64,
}

impl GeometricSequence {
    //- Constructors -----------------------------

    /// Constructs a new `GeometricSequence`.
    pub fn new(start: u64, factor: f64) -> Self {
        GeometricSequence { current: start as f64, factor: factor }
    }
}

impl Iterator for GeometricSequence {
    type Item = u64;

    fn next(&mut self) -> Option<Self::Item> {
        let start = self.current as u64;
        while self.current as u64 == start { self.current *= self.factor; }
        Some(start)
    }
}

// Measurement ___________________________________

/// A measurement of the execution time of a function.
#[derive(Copy, Clone, Debug)]
pub struct Measurement {
    /// The number of times the function was called.
    pub iterations: u64,
    /// The number of nanoseconds that elapsed while calling the function.
    pub nanoseconds: u64,
}

impl Measurement {
    //- Constructors -----------------------------

    /// Constructs a new `Measurement`.
    pub fn new(iterations: u64, nanoseconds: u64) -> Self {
        Measurement { iterations: iterations, nanoseconds: nanoseconds }
    }
}

// Options _______________________________________

/// Benchmarking options.
#[derive(Copy, Clone, Debug)]
pub struct Options {
    factor: f64,
    maximum: u64,
}

impl Default for Options {
    fn default() -> Options {
        Options { factor: 1.01, maximum: 5_000_000_000 }
    }
}

impl Options {
    //- Consumers --------------------------------

    /// Sets the geometric growth factor for sample iterations.
    ///
    /// **Default:** `1.01`
    pub fn factor(mut self, factor: f64) -> Self {
        self.factor = factor;
        self
    }

    /// Sets the maximum amount of time a benchmark will run for.
    ///
    /// **Default:** `Duration::new(5, 0)`
    pub fn maximum(mut self, maximum: Duration) -> Self {
        self.maximum = (maximum.as_secs() * 1_000_000_000) + maximum.subsec_nanos() as u64;
        self
    }
}

// Stopwatch _____________________________________

/// A high-precision stopwatch.
#[derive(Clone, Copy, Debug)]
pub struct Stopwatch {
    start: u64,
}

impl Stopwatch {
    //- Constructors -----------------------------

    /// Constructs a new `Stopwatch`.
    pub fn new() -> Self {
        Stopwatch { start: time::precise_time_ns() }
    }

    //- Accessors --------------------------------

    /// Returns the elapsed nanoseconds since this stopwatch was constructed or reset.
    pub fn elapsed(&self) -> u64 {
        time::precise_time_ns() - self.start
    }

    //- Mutators ---------------------------------

    /// Resets this stopwatch.
    pub fn reset(&mut self) {
        self.start = time::precise_time_ns();
    }
}

//================================================
// Functions
//================================================

fn mean<I>(iterator: I) -> f64 where I: Iterator<Item=f64> {
    let (sum, len) = iterator.fold((0.0, 0), |a, f| (a.0 + f, a.1 + 1));
    sum / len as f64
}

/// Analyzes the supplied timing data and returns the resulting analysis.
pub fn analyze(measurements: &[Measurement]) -> Analysis {
    let xmean = mean(measurements.iter().map(|m| m.iterations as f64));
    let ymean = mean(measurements.iter().map(|m| m.nanoseconds as f64));

    // Ordinary least squares linear regression.
    let numerator = measurements.iter().map(|m| {
        (m.iterations as f64 - xmean) * (m.nanoseconds as f64 - ymean)
    }).sum::<f64>();
    let denominator = measurements.iter().map(|m| {
        (m.iterations as f64 - xmean).powf(2.0)
    }).sum::<f64>();
    let beta = numerator / denominator;
    let alpha = ymean - (beta * xmean);
    let estimator = |x: u64| (beta * x as f64) + alpha;

    // Ordinary least squares goodness of fit.
    let numerator = measurements.iter().map(|m| {
        (estimator(m.iterations) - ymean).powf(2.0)
    }).sum::<f64>();
    let denominator = measurements.iter().map(|m| {
        (m.nanoseconds as f64 - ymean).powf(2.0)
    }).sum::<f64>();
    let r2 = numerator / denominator;

    Analysis { beta: beta, r2: r2 }
}

/// Benchmarks the supplied function and prints the results.
pub fn bench<T, F>(options: &Options, name: &str, f: F) where F: FnMut() -> T {
    let analysis = analyze(&measure(options, f));
    let prefix = format!("{} ... bench:", name);
    println!("{:<32} {:.3} ns/iter ({:.3} R²)", prefix, analysis.beta, analysis.r2);
}

/// Measures the execution time of the supplied function and returns the resulting timing data.
pub fn measure<T, F>(options: &Options, mut f: F) -> Vec<Measurement> where F: FnMut() -> T {
    let mut measurements = vec![];
    let mut sequence = GeometricSequence::new(1, options.factor);
    let total = Stopwatch::new();
    while total.elapsed() < options.maximum {
        let iterations = sequence.next().unwrap();
        let sample = Stopwatch::new();
        for _ in 0..iterations { retain(f()); }
        measurements.push(Measurement::new(iterations, sample.elapsed()));
    }
    measurements
}

/// A function that prevents the optimizer from eliminating the supplied value.
pub fn retain<T>(value: T) -> T {
    test::black_box(value)
}
<|endoftext|>


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

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

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

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

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

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

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

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

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

  // todo: rep Untagged, Deleted stream
  pub fn delete(self) -> Result<Vec<Status>> {
    let raw = try!(self.docker.delete(&format!("/images/{}", self.name)[..]));
    Ok(match Json::from_str(&raw).unwrap() {
      Json::Array(ref xs) => xs.iter().map(|j| {
        let obj = j.as_object().unwrap();
        obj.get("Untagged").map(|sha| Status::Untagged(sha.as_string().unwrap().to_string()))
           .or(obj.get("Deleted").map(|sha| Status::Deleted(sha.as_string().unwrap().to_string())))
           .unwrap()
      }),
      _ => unreachable!("")
    }.collect())
  }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

  pub fn stats(self) -> Result<Box<Iterator<Item=Stats>>> {
    let raw = try!(self.docker.stream_get(&format!("/containers/{}/stats", self.id)[..]));
    let it = jed::Iter::new(raw).into_iter().map(|j| {
      let s = json::encode(&j).unwrap();
      json::decode::<Stats>(&s).unwrap()
    });
    Ok(Box::new(it))
  }

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

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

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

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

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

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

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

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

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

  // todo attach, attach/ws,
}

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

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

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

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

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

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

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

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

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

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

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

  pub fn events(&mut self) -> Result<Box<Iterator<Item=Event>>> {
    let raw = try!(self.stream_get("/events?since=1374067924"));
    let it = jed::Iter::new(raw).into_iter().map(|j| {
     let s = json::encode(&j).unwrap();
     json::decode::<Event>(&s).unwrap()
    });
    Ok(Box::new(it))
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

  // todo: rep Untagged, Deleted stream
  pub fn delete(self) -> Result<Vec<Status>> {
    let raw = try!(self.docker.delete(&format!("/images/{}", self.name)[..]));
    Ok(match Json::from_str(&raw).unwrap() {
      Json::Array(ref xs) => xs.iter().map(|j| {
        let obj = j.as_object().unwrap();
        obj.get("Untagged").map(|sha| Status::Untagged(sha.as_string().unwrap().to_string()))
           .or(obj.get("Deleted").map(|sha| Status::Deleted(sha.as_string().unwrap().to_string())))
           .unwrap()
      }),
      _ => unreachable!("")
    }.collect())
  }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

  pub fn stats(self) -> Result<Box<Iterator<Item=Stats>>> {
    let raw = try!(self.docker.stream_get(&format!("/containers/{}/stats", self.id)[..]));
    let it = jed::Iter::new(raw).into_iter().map(|j| {
      let s = json::encode(&j).unwrap();
      json::decode::<Stats>(&s).unwrap()
    });
    Ok(Box::new(it))
  }

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

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

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

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

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

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

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

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

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

  // todo attach, attach/ws,
}

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

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

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

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

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

// https://docs.docker.com/reference/api/docker_remote_api_v1.17/
impl Docker {
  /// constructs a new Docker instance for a docker host listening at a url specified by an env var `DOCKER_HOST`,
  /// falling back on unix:///var/run/docker.sock
  pub fn new() -> Docker {
    let fallback: std::result::Result<String, VarError> = Ok("unix:///var/run/docker.sock".to_string());
    let host = env::var("DOCKER_HOST")
        .or(fallback)
        .map(|h| Url::parse(&h).ok()
             .expect("invalid url"))
         .ok()
         .expect("expected host");
    Docker::host(host)
  }

  /// constructs a new Docker instance for docker host listening at the given host url
  pub fn host(host: Url) -> Docker {
    let domain = match host.scheme_data {
        SchemeData::NonRelative(s) => s,
        SchemeData::Relative(RelativeSchemeData { host: host, .. }) =>
          match host {
              Host::Domain(s) => s,
              Host::Ipv6(a)   => a.to_string()
          }
    };
    match &host.scheme[..] {
      "unix" => {
        let stream =
          match UnixStream::connect(domain) {
            Err(_) => panic!("failed to connect to socket"),
            Ok(s) => s
          };
        Docker { transport: Box::new(stream) }
      },
          _  => {
        let mut client = Client::new();
        client.set_ssl_verifier(Box::new(|ssl_ctx| {
          match env::var("DOCKER_CERT_PATH").ok() {
            Some(ref certs) => {
              let cert = &format!("{}/cert.pem", certs);
              let key = &format!("{}/key.pem", certs);
              ssl_ctx.set_certificate_file(&Path::new(cert), X509FileType::PEM);
              ssl_ctx.set_private_key_file(&Path::new(key), X509FileType::PEM);
              match env::var("DOCKER_TLS_VERIFY").ok() {
                Some(_) => {
                  let ca = &format!("{}/ca.pem", certs);
                  ssl_ctx.set_CA_file(&Path::new(ca));
                }, _ => ()
              };
              ()
            },  _ => ()
          }
        }));
        let tup = (client, format!("https:{}", domain.to_string()));
        Docker { transport: Box::new(tup) }
      }
    }
  }

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

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

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

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

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

  pub fn events(&mut self) -> Result<Box<Iterator<Item=Event>>> {
    let raw = try!(self.stream_get("/events?since=1374067924"));
    let it = jed::Iter::new(raw).into_iter().map(|j| {
     let s = json::encode(&j).unwrap();
     json::decode::<Event>(&s).unwrap()
    });
    Ok(Box::new(it))
  }

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

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

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

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

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


<commit_before>use std::io::IoResult;

pub struct PeekableReader<R> {
    inner: R,
    peeked_result: Option<IoResult<u8>>,
}

impl<R: Reader> PeekableReader<R> {
    /// Initializes a new `PeekableReader` which wraps the given underlying
    /// reader.
    pub fn new(reader: R) -> PeekableReader<R> {
        PeekableReader {
            inner: reader,
            peeked_result: None,
        }
    }

    pub fn peek(&mut self) -> IoResult<u8> {
        // Return either the currently cached peeked byte or obtain a new one
        // from the underlying reader.
        match self.peeked_result {
            Some(ref old_res) => old_res.clone(),
            None => {
                // First get the result of the read from the underlying reader
                self.peeked_result = Some(self.inner.read_byte());

                // Now just return that
                self.peeked_result.clone().unwrap()
            }
        }
    }
}

mod tests {
    use super::PeekableReader;
    use std::io::{MemReader, IoError, IoErrorKind, IoResult};

    /// Helper function which checks whether the given result indicated EOF.
    fn is_eof<T>(res: IoResult<T>) -> bool {
        match res {
            Err(IoError {
                kind: IoErrorKind::EndOfFile,
                ..
            }) => true,
            _ => false,
        }
    }

    /// Tests that it is possible to invoke the `peek` method multiple times
    /// with the same effect, when there are no intermediate reads.
    #[test]
    fn multiple_peeks_idempotent() {
        let b = 1;
        let mut reader = PeekableReader::new(MemReader::new(vec!(b, b + 1)));

        // The first peek is correct?
        assert_eq!(b, reader.peek().unwrap());
        // The second peek (with no reads in between) still returns the same
        // byte?
        assert_eq!(b, reader.peek().unwrap());
    }

    #[test]
    fn single_byte_reader_peek() {
        let b = 5u8;
        let mut reader = PeekableReader::new(MemReader::new(vec!(b)));

        // When we peek, we get the correct byte back?
        assert_eq!(b, reader.peek().unwrap());
    }

    #[test]
    fn empty_underlying_reader() {
        let mut reader = PeekableReader::new(MemReader::new(vec!()));

        // Must return EOF since the underlying reader is empty
        assert!(is_eof(reader.peek()));
    }
}
<commit_msg>Add a mock `Reader` implementation<commit_after>use std::io::IoResult;

pub struct PeekableReader<R> {
    inner: R,
    peeked_result: Option<IoResult<u8>>,
}

impl<R: Reader> PeekableReader<R> {
    /// Initializes a new `PeekableReader` which wraps the given underlying
    /// reader.
    pub fn new(reader: R) -> PeekableReader<R> {
        PeekableReader {
            inner: reader,
            peeked_result: None,
        }
    }

    pub fn peek(&mut self) -> IoResult<u8> {
        // Return either the currently cached peeked byte or obtain a new one
        // from the underlying reader.
        match self.peeked_result {
            Some(ref old_res) => old_res.clone(),
            None => {
                // First get the result of the read from the underlying reader
                self.peeked_result = Some(self.inner.read_byte());

                // Now just return that
                self.peeked_result.clone().unwrap()
            }
        }
    }
}

impl<R: Reader> Reader for PeekableReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        if buf.len() == 0 {
            return Ok(0);
        }

        // First, put the byte that was read off the underlying reader in a
        // (possible) previous peek operation (if such a byte is indeed cached)
        let offset = match self.peeked_result.clone() {
            Some(Err(e)) => {
                self.peeked_result = None;
                return Err(e);
            },
            Some(Ok(b)) => {
                buf[0] = b;
                self.peeked_result = None;
                1
            },
            None => 0,
        };

        if offset == 1 && buf.len() == 1 {
            // We've filled the buffer by using the previously peeked byte
            Ok(1)
        } else {
            // We are still missing more bytes, so we read them from the
            // underlying reader and place them directly in the correct place
            // in the buffer.
            let (_, leftover) = buf.split_at_mut(offset);
            Ok(try!(self.inner.read(leftover)) + offset)
        }
    }
}

mod tests {
    use super::PeekableReader;
    use std::io::{MemReader, IoError, IoErrorKind, IoResult};

    /// A mock implementation of the `Reader` trait that returns a given
    /// IoError after a certain number of bytes has been read. The error is
    /// returned only once, with subsequent read calls completing successfully
    /// again.
    /// When the Reader successfully reads a byte, it is always `0u8`.
    struct MockReaderWithError {
        error: IoError,
        after: uint,
        bytes_read: uint,
        errored: bool,
    }

    impl MockReaderWithError {
        fn new(error: IoError, after: uint) -> MockReaderWithError {
            MockReaderWithError {
                error: error,
                after: after,
                bytes_read: 0,
                errored: false,
            }
        }
    }

    impl Reader for MockReaderWithError {
        fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
            self.bytes_read += buf.len();
            if self.bytes_read <= self.after || self.errored {
                for b in buf.iter_mut() {
                    *b = 0;
                }

                Ok(buf.len())
            } else {
                self.errored = true;
                Err(self.error.clone())
            }
        }
    }

    /// Helper function which checks whether the given result indicated EOF.
    fn is_eof<T>(res: IoResult<T>) -> bool {
        match res {
            Err(IoError {
                kind: IoErrorKind::EndOfFile,
                ..
            }) => true,
            _ => false,
        }
    }

    /// Tests that it is possible to invoke the `peek` method multiple times
    /// with the same effect, when there are no intermediate reads.
    #[test]
    fn multiple_peeks_idempotent() {
        let b = 1;
        let mut reader = PeekableReader::new(MemReader::new(vec!(b, b + 1)));

        // The first peek is correct?
        assert_eq!(b, reader.peek().unwrap());
        // The second peek (with no reads in between) still returns the same
        // byte?
        assert_eq!(b, reader.peek().unwrap());
    }

    #[test]
    fn single_byte_reader_peek() {
        let b = 5u8;
        let mut reader = PeekableReader::new(MemReader::new(vec!(b)));

        // When we peek, we get the correct byte back?
        assert_eq!(b, reader.peek().unwrap());
    }

    #[test]
    fn empty_underlying_reader() {
        let mut reader = PeekableReader::new(MemReader::new(vec!()));

        // Must return EOF since the underlying reader is empty
        assert!(is_eof(reader.peek()));
    }

    /// Test for the MockReaderWithError helper mock class...
    #[test]
    fn mock_sanity_check() {
        {
            let err = IoError {
                kind: IoErrorKind::OtherIoError,
                desc: "Dummy error",
                detail: None,
            };
            let mut reader = MockReaderWithError::new(err.clone(), 1);

            // First byte is not a problem.
            assert_eq!(0, reader.read_byte().unwrap());
            // However, now the read fails...
            assert!(is_err(&err, reader.read_byte()),
                    "Expected an IoError on the read byte");
            // But, already on the next one, we're out of the woods.
            assert_eq!(0, reader.read_byte().unwrap());
        }
        {
            let err = IoError {
                kind: IoErrorKind::OtherIoError,
                desc: "Dummy error",
                detail: None,
            };
            let mut reader = MockReaderWithError::new(err.clone(), 0);

            // The read fails on the first one...
            assert!(is_err(&err, reader.read_byte()),
                    "Expected an IoError on the read byte");
            // ...but now we're good.
            assert_eq!(0, reader.read_byte().unwrap());
        }
    }

}
<|endoftext|>


<commit_before>//! A toolkit for building command-line programs in Rust.
//!
//! `cli` aims to
//!
//! - reduce boilerplate
//! - canonicalize output formatting
//! - encourage adherence to the conventions of standard streams
//!   (e.g. when to print to stderr vs stdout)
//! - encourage appropriate use of exit statuses
//!
//! Concretely, `cli` is a collection of simple functions for formatting
//! command-line output, defining flags, and (eventually) things like
//! integrating with sysexits.
//!
//! It uses [getopts](http://doc.rust-lang.org/getopts/) for argument parsing
//! and thus currently inherits `getopt`'s `experimental` stability level.
//!
//! ## Usage
//!
//! The following example shows how to integrate `cli` functions into a program's
//! `main` function in order to avoid `getopts` boilerplate. Sane defaults are
//! provided for help and version output without forcing consuming code to buy into
//! an application framework.
//!
//!     extern crate cli;
//!     extern crate getopts;
//!
//!     fn main() {
//!         let opts = &[
//!             cli::helpopt(),
//!             cli::versionopt(),
//!             getopts::optopt("o", "", "Set output file name", "FILENAME"),
//!         ];
//!
//!         let matches = cli::parse_args(opts);
//!         if matches.opt_present("h") {
//!             println!("{}", cli::usage_string(opts));
//!             return;
//!         }
//!         if matches.opt_present("version") {
//!             println!("{}", cli::version_string("0.0.1"));
//!             return;
//!         }
//!
//!         ...
//!     }

#![crate_name = "cli"]
#![experimental]
#![crate_type="rlib"]

extern crate getopts;
use getopts::{Matches, OptGroup, getopts, optflag, short_usage, usage};
use std::{io, os};

mod test;

/// The name by which the executed program was called.
///
/// Typically the file name or path of the invoked executable.
pub fn argv0() -> String {
    os::args()[0].clone()
}

/// Construct a canonical usage string from a collection of `OptGroup`s.
///
/// Usage string format:
///
///```ignore
///     Usage: <argv0> [option synopsis]...
///
///     Options:
///         [option description]...
///```
pub fn usage_string(opts: &[OptGroup]) -> String {
    format!("{}", usage(short_usage(argv0().as_slice(), opts).as_slice(), opts))
}

/// Construct a version string.
///
/// Intended for use as output in response to `--version` as defined by
/// `cli::versionopt`.
///
/// Version string format:
///
///```ignore
///     <argv0> version <version>
///```
pub fn version_string(version: &str) -> String {
    format!("{} version {}", argv0(), version)
}

/// Parse the command-line arguments with which the program was executed
/// according to a collection of `OptGroup`s.
///
/// Any flag parsing failure results in task panic. The program's usage string
/// is printed to stderr prior to panic. Panic is induced in order to avoid
/// program execution with undefined configuration. In such cases, the presence
/// of unrecognized flags or invalid flag values implies confusion on the part
/// of the executor. While perhaps overbearing, it is preferable to halt
/// execution abruptly than to continue with the risk of unwanted behavior.
pub fn parse_args(opts: &[OptGroup]) -> Matches {
    match getopts(os::args().tail(), opts) {
        Ok(matches) => matches,
        Err(getopts_error) => {
            // Write usage string to stderr, then panic.
            match io::stderr().write_str(usage_string(opts).as_slice()) {
                Ok(()) => panic!(getopts_error.to_string()),
                Err(write_error) =>
                    // Write to stderr failed -- panic with both error messages.
                    panic!("{}\n{}", getopts_error.to_string(), write_error.to_string())
            }
        }
    }
}

/// Create a help flag `OptGroup`.
///
/// The returned `OptGroup` is an optional long option for the input `-h`
/// and `--help`.
pub fn helpopt() -> OptGroup {
    optflag("h", "help", "Print this help menu")
}

/// Create a version flag `OptGroup`.
///
/// The returned `OptGroup` is an optional long option for the input
/// `--version`. `-v` and `-V` are avoided in order to prevent confusion in the
/// event when a flag is needed for enabling verbose output.
pub fn versionopt() -> OptGroup {
    optflag("", "version", format!("Print the version of {} being run", argv0()).as_slice())
}
<commit_msg>Replace `argv0` with `exec_path`, which resolves symlinks and returns a Path<commit_after>//! A toolkit for building command-line programs in Rust.
//!
//! `cli` aims to
//!
//! - reduce boilerplate
//! - canonicalize output formatting
//! - encourage adherence to the conventions of standard streams
//!   (e.g. when to print to stderr vs stdout)
//! - encourage appropriate use of exit statuses
//!
//! Concretely, `cli` is a collection of simple functions for formatting
//! command-line output, defining flags, and (eventually) things like
//! integrating with sysexits.
//!
//! It uses [getopts](http://doc.rust-lang.org/getopts/) for argument parsing
//! and thus currently inherits `getopt`'s `experimental` stability level.
//!
//! ## Usage
//!
//! The following example shows how to integrate `cli` functions into a program's
//! `main` function in order to avoid `getopts` boilerplate. Sane defaults are
//! provided for help and version output without forcing consuming code to buy into
//! an application framework.
//!
//!     extern crate cli;
//!     extern crate getopts;
//!
//!     fn main() {
//!         let opts = &[
//!             cli::helpopt(),
//!             cli::versionopt(),
//!             getopts::optopt("o", "", "Set output file name", "FILENAME"),
//!         ];
//!
//!         let matches = cli::parse_args(opts);
//!         if matches.opt_present("h") {
//!             println!("{}", cli::usage_string(opts));
//!             return;
//!         }
//!         if matches.opt_present("version") {
//!             println!("{}", cli::version_string("0.0.1"));
//!             return;
//!         }
//!
//!         ...
//!     }

#![crate_name = "cli"]
#![experimental]
#![crate_type="rlib"]

extern crate getopts;
use getopts::{Matches, OptGroup, getopts, optflag, short_usage, usage};
use std::{io, os};
use std::io::fs;

mod test;

/// The file path of the executed program.
///
/// Typically the file path of the invoked executable. If the invocation target
/// is a symlink, then it will be resolved to the executable it links to.
pub fn exec_path() -> Path {
    let path = Path::new(os::args()[0].clone());
    fs::readlink(&path).unwrap_or(path)
}

/// Construct a canonical usage string from a collection of `OptGroup`s.
///
/// Usage string format:
///
///```ignore
///     Usage: <program name> [option synopsis]...
///
///     Options:
///         [option description]...
///```
pub fn usage_string(opts: &[OptGroup]) -> String {
    let exec_path = exec_path();
    let exec_path = exec_path.as_str().unwrap_or_else(|| "");
    format!("{}", usage(short_usage(exec_path, opts).as_slice(), opts))
}

/// Construct a version string.
///
/// Intended for use as output in response to `--version` as defined by
/// `cli::versionopt`.
///
/// Version string format:
///
///```ignore
///     <program name> version <version>
///```
pub fn version_string(version: &str) -> String {
    format!("{} version {}", exec_path().display(), version)
}

/// Parse the command-line arguments with which the program was executed
/// according to a collection of `OptGroup`s.
///
/// Any flag parsing failure results in task panic. The program's usage string
/// is printed to stderr prior to panic. Panic is induced in order to avoid
/// program execution with undefined configuration. In such cases, the presence
/// of unrecognized flags or invalid flag values implies confusion on the part
/// of the executor. While perhaps overbearing, it is preferable to halt
/// execution abruptly than to continue with the risk of unwanted behavior.
pub fn parse_args(opts: &[OptGroup]) -> Matches {
    match getopts(os::args().tail(), opts) {
        Ok(matches) => matches,
        Err(getopts_error) => {
            // Write usage string to stderr, then panic.
            match io::stderr().write_str(usage_string(opts).as_slice()) {
                Ok(()) => panic!(getopts_error.to_string()),
                Err(write_error) =>
                    // Write to stderr failed -- panic with both error messages.
                    panic!("{}\n{}", getopts_error.to_string(), write_error.to_string())
            }
        }
    }
}

/// Create a help flag `OptGroup`.
///
/// The returned `OptGroup` is an optional long option for the input `-h`
/// and `--help`.
pub fn helpopt() -> OptGroup {
    optflag("h", "help", "Print this help menu")
}

/// Create a version flag `OptGroup`.
///
/// The returned `OptGroup` is an optional long option for the input
/// `--version`. `-v` and `-V` are avoided in order to prevent confusion in the
/// event when a flag is needed for enabling verbose output.
pub fn versionopt() -> OptGroup {
    optflag(
        "",
        "version",
        format!("Print the version of {} being run", exec_path().display()).as_slice()
    )
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

#[macro_use]
extern crate log;
extern crate libc;
extern crate errno;
extern crate threadpool;
extern crate simple_slab;

use std::io::Error;
use std::sync::Arc;
use std::cell::UnsafeCell;
use std::os::unix::io::{RawFd, AsRawFd};

use config::Config;

pub mod config;

mod server;

pub trait Stream : AsRawFd + Send + Sync {
    fn recv(&mut self) -> Result<Vec<Vec<u8>>, Error>;
    fn send(&mut self, buf: &[u8]) -> Result<usize, Error>;
}

pub trait Handler {
    fn on_new_connection(&mut self, fd: RawFd) -> Arc<UnsafeCell<Stream>>;
    fn on_data_received(&mut self, stream: Stream, buf: Vec<u8>);
    fn on_error(&mut self, err: Error);
    fn on_connection_removed(&mut self, fd: RawFd);
}

pub fn begin<T>(handler: Box<T>, cfg: Config)
    where T: EventHandler + Send + Sync + 'static
{
    server::begin(handler, cfg);
}
<commit_msg>Remote compiling<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

#[macro_use]
extern crate log;
extern crate libc;
extern crate errno;
extern crate threadpool;
extern crate simple_slab;

use std::io::Error;
use std::sync::Arc;
use std::cell::UnsafeCell;
use std::os::unix::io::{RawFd, AsRawFd};

use config::Config;

pub mod config;

mod server;

pub trait Stream : AsRawFd + Send + Sync {
    fn recv(&mut self) -> Result<Vec<Vec<u8>>, Error>;
    fn send(&mut self, buf: &[u8]) -> Result<usize, Error>;
}

pub trait Handler {
    fn on_new_connection(&mut self, fd: RawFd) -> Arc<UnsafeCell<Stream>>;
    fn on_data_received(&mut self, stream: Stream, buf: Vec<u8>);
    fn on_error(&mut self, err: Error);
    fn on_connection_removed(&mut self, fd: RawFd);
}

pub fn begin<T>(handler: Box<T>, cfg: Config)
    where T: Handler + Send + Sync + 'static
{
    server::begin(handler, cfg);
}
<|endoftext|>


<commit_before>
//! **mprovision** is a tool that helps iOS developers to manage mobileprovision
//! files. Main purpose of this crate is to contain functions and types
//! for **mprovision**.

use std::fs::{self, DirEntry};
use std::path::{Path, PathBuf};
use std::env;

/// Returns an iterator over the `*.mobileprovision` entries within a given
/// directory.
///
/// # Errors
/// This function will return an error in the following cases:
///
/// - the user lacks the requisite permissions
/// - there is no entry in the filesystem at the provided path
/// - the provided path is not a directory
pub fn files<P>(path: P) -> Result<Box<Iterator<Item=DirEntry>>, String> where P: AsRef<Path> {
    let metadata = try!(fs::metadata(&path).map_err(|err| err.to_string()));
    if !metadata.is_dir() {
        return Err(format!("{:?} is not a directory", path.as_ref()));
    }
    let entries = try!(fs::read_dir(&path).map_err(|err| err.to_string()));
    let filtered = entries
        .filter_map(|entry| entry.ok())
        .filter_map(|entry| {
            if let Some(ext) = entry.path().extension() {
                if ext == "mobileprovision" {
                    return Some(entry);
                }
            }
            None
        });
    Ok(Box::new(filtered))
}

/// Returns the path to the directory that contains installed mobile
/// provisioning profiles.
///
/// Should return `~/Library/MobileDevice/Provisioning Profiles` directory.
///
/// # Errors
/// This function will return an error if 'HOME' environment variable is not set
/// or equal to the empty string.
pub fn directory() -> Result<PathBuf, String> {
    env::home_dir()
        .map(|path| path.join("Library/MobileDevice/Provisioning Profiles"))
        .ok_or("couldn't find home directory".into())
}
<commit_msg>Add Result type alias.<commit_after>
//! **mprovision** is a tool that helps iOS developers to manage mobileprovision
//! files. Main purpose of this crate is to contain functions and types
//! for **mprovision**.

use std::fs::{self, DirEntry};
use std::path::{Path, PathBuf};
use std::env;

/// A Result type for this crate.
pub type Result<T> = std::result::Result<T, String>;

/// Returns an iterator over the `*.mobileprovision` entries within a given
/// directory.
///
/// # Errors
/// This function will return an error in the following cases:
///
/// - the user lacks the requisite permissions
/// - there is no entry in the filesystem at the provided path
/// - the provided path is not a directory
pub fn files<P>(path: P) -> Result<Box<Iterator<Item=DirEntry>>> where P: AsRef<Path> {
    let metadata = try!(fs::metadata(&path).map_err(|err| err.to_string()));
    if !metadata.is_dir() {
        return Err(format!("{:?} is not a directory", path.as_ref()));
    }
    let entries = try!(fs::read_dir(&path).map_err(|err| err.to_string()));
    let filtered = entries
        .filter_map(|entry| entry.ok())
        .filter_map(|entry| {
            if let Some(ext) = entry.path().extension() {
                if ext == "mobileprovision" {
                    return Some(entry);
                }
            }
            None
        });
    Ok(Box::new(filtered))
}

/// Returns the path to the directory that contains installed mobile
/// provisioning profiles.
///
/// Should return `~/Library/MobileDevice/Provisioning Profiles` directory.
///
/// # Errors
/// This function will return an error if 'HOME' environment variable is not set
/// or equal to the empty string.
pub fn directory() -> Result<PathBuf> {
    env::home_dir()
        .map(|path| path.join("Library/MobileDevice/Provisioning Profiles"))
        .ok_or("couldn't find home directory".into())
}
<|endoftext|>


<commit_before>extern crate websocket;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_core;

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

#[macro_use]
extern crate log;

use std::collections::BTreeMap;

use tokio_core::reactor::Core;

use futures::future::Future;
use futures::Stream;
use futures::Sink;
use futures::stream;
use futures::sync::mpsc;
use futures_cpupool::CpuPool;

use websocket::message::OwnedMessage;

use std::collections::BinaryHeap;
use std::sync::Mutex;
use std::sync::Arc;

mod test;
mod gateway;

const DISCORD_GATEWAY_URL: &str = "wss://gateway.discord.gg/?v=6&encoding=json";

pub struct Client {
    core: Core,
    pool: Arc<CpuPool>,
    message_queue: Arc<Mutex<BinaryHeap<gateway::ClientMessage>>>,
}

impl Client {
    pub fn new(token: String) -> Client {
        let core = Core::new().expect("Could not create event loop core.");
        let pool = CpuPool::new(5);
        let message_queue = Arc::new(Mutex::new(BinaryHeap::<gateway::ClientMessage>::new()));

        Client::gateway_autenticate(token.clone(), message_queue.clone());

        Client {
            core,
            pool: Arc::new(pool),
            message_queue,
        }
    }

    pub fn authenticate(&mut self) {
        let queue_ref1 = self.message_queue.clone();
        let queue_ref2 = self.message_queue.clone();
        let pool = self.pool.clone();

        let handle = self.core.handle();
        let socket = websocket::ClientBuilder::new(DISCORD_GATEWAY_URL)
            .expect("Could not construct client.")
            .add_protocol("rust-websocket")
            .async_connect(None, &handle)
            .and_then(move |(duplex, _)| {
                let (tx, rx) = duplex.split();
                println!("\nConnected to websocket\n");
                let inner_pool = pool.clone();
                let mut core = Core::new().expect("Could not create event loop core.");
                let (ready_sender, ready_receiver) = mpsc::unbounded::<&str>();
                let (message_sender, message_receiver) = mpsc::unbounded::<String>();

                let rx_worker = pool.spawn_fn(move || {
                    println!("\nReceiving worker is live\n");
                    rx.for_each(move |message| {
                        println!("\nGot a message\n");
                        let queue_ref = &queue_ref1;
                        let inner_queue = queue_ref.clone();
                        let worker_channel = ready_sender.clone();

                        //let mut rx_handling_core = Core::new().expect("Could not create event loop core.");
                        let message_handler = inner_pool.spawn_fn(move || {
                            println!("\nHandling a message in a new thread\n");
                            Client::handle_stream(message, inner_queue);
                            println!("\nSending ready\n");
                            worker_channel.send("ready").map_err(|err| {
                                ()
                            }).map(|result| {
                                ()
                            })
                        }).map_err(|e| {
                            websocket::WebSocketError::NoDataAvailable //FIXME: hack
                        }).map(|result| {
                            ()
                        });
                        //rx_handling_core.run(message_handler);

                        message_handler
                        //let all_ok: Result<(), websocket::WebSocketError> = Ok(());
                        //all_ok
                    }).map_err(|e| {
                        websocket::WebSocketError::NoDataAvailable //FIXME: hack
                    }).map(|result| {
                        ()
                    })
                });

                let tx_stream_worker = pool.spawn_fn(move || {
                    println!("\nFiltering worker is live\n");
                    let inner_message_sender = message_sender;
                    ready_receiver.for_each(move |message| {
                        println!("\nReceiving ready\n");

                        let queue_ref = &queue_ref2;
                        let mut queue = queue_ref.lock().unwrap();
                        let mut messages = Vec::<Result<String, mpsc::SendError<String>>>::new();

                        while let Some(message) = queue.pop() {
                            println!("\nPopping a message off the queue\n");
                            &messages.push(Ok(message.body));
                        }

                        let message_stream = messages.into_iter();
                        stream::iter(message_stream)
                            .forward(inner_message_sender.clone())
                            .map_err(|e| {
                                () //FIXME: hack
                            }).map(|result| {
                                ()
                            })
                    }).map_err(|e| {
                        websocket::WebSocketError::NoDataAvailable //FIXME: hack
                    }).map(|result| {
                        ()
                    })
                });

                let tx_worker = pool.spawn_fn(move || {
                    println!("\nTransmitting worker is live\n");
                    message_receiver.map(|message| {
                        OwnedMessage::Text(message)
                    })
                    .map_err(|_| { websocket::WebSocketError::NoDataAvailable })
                    .forward(tx)
                });

                //rx_worker
                rx_worker.join(tx_stream_worker.join(tx_worker))
            });

        self.core.run(socket);
    }

    fn gateway_autenticate(token: String, message_queue: Arc<Mutex<BinaryHeap<gateway::ClientMessage>>>) {
        let mut queue = message_queue.lock().unwrap();

        let mut properties = BTreeMap::new();
        properties.insert(String::from("$os"), String::from("Linux"));

        let identity = gateway::identity::Identity {
            token,
            properties,
            compress: None,
            large_threshold: None,
        };

        let identification_message_body = gateway::MessageBody {
            op: 2,
            d: identity,
            s: None,
            t: None,
        };

        let identification_message = gateway::ClientMessage {
            body: serde_json::to_string(&identification_message_body)
                                 .expect("Could not serialize response."),
            priority: 0,
        };

        queue.push(identification_message);
    }

    fn handle_stream(message: websocket::OwnedMessage, message_queue: Arc<Mutex<BinaryHeap<gateway::ClientMessage>>>) -> Result<(), websocket::WebSocketError> {
        let mut queue = message_queue.lock().unwrap();

        if let OwnedMessage::Text(text) = message {
            let deserialized_dispatch: gateway::ServerMessage = serde_json::from_str(&text)
                                                                     .expect("Could not parse JSON.");
            let serialized_data = deserialized_dispatch.d;
            let title = deserialized_dispatch.t;

            match title {
                Some(t) => {
                    match t.trim() {
                        "READY" => {
                            let deserialized_data: gateway::ready::Ready = serde_json::from_value(serialized_data)
                                                                      .expect("Could not parse JSON.");
                            println!("\nServer: READY\n");
                            Ok(())
                        }
                        _ => {
                            println!("\nUnknown server message\n");
                            Ok(())
                        }
                    }

                }
                None => {
                    let deserialized_data: gateway::hello::Hello = serde_json::from_value(serialized_data)
                                                                      .expect("Could not parse JSON.");
                    println!("\nServer: IDENTIFY\n");
                    Ok(())
                }
            }
        } else {
            println!("\nUnknown server message format\n");
            Ok(())
        }
    }
}
<commit_msg>core event loop functional<commit_after>extern crate websocket;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_core;

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

#[macro_use]
extern crate log;

use std::collections::BTreeMap;

use tokio_core::reactor::Core;

use futures::future::Future;
use futures::future::Loop;
use futures::future::LoopFn;
use futures::future::loop_fn;
use futures::Stream;
use futures::Sink;
use futures::stream;
use futures::sync::mpsc;
use futures_cpupool::CpuPool;

use websocket::message::OwnedMessage;

use std::collections::BinaryHeap;
use std::sync::Mutex;
use std::sync::Arc;
use std::{thread, time};

mod test;
mod gateway;

const DISCORD_GATEWAY_URL: &str = "wss://gateway.discord.gg/?v=6&encoding=json";

pub struct Client {
    core: Core,
    pool: Arc<CpuPool>,
    message_queue: Arc<Mutex<BinaryHeap<gateway::ClientMessage>>>,
}

impl Client {
    pub fn new(token: String) -> Client {
        let core = Core::new().expect("Could not create event loop core.");
        let pool = CpuPool::new(7);
        let message_queue = Arc::new(Mutex::new(BinaryHeap::<gateway::ClientMessage>::new()));

        Client::gateway_autenticate(token.clone(), message_queue.clone());

        Client {
            core,
            pool: Arc::new(pool),
            message_queue,
        }
    }

    pub fn authenticate(&mut self) {
        let queue_ref1 = self.message_queue.clone();
        let queue_ref2 = self.message_queue.clone();
        let queue_ref3 = self.message_queue.clone();
        let pool = self.pool.clone();

        let handle = self.core.handle();
        let socket = websocket::ClientBuilder::new(DISCORD_GATEWAY_URL)
            .expect("Could not construct client.")
            .add_protocol("rust-websocket")
            .async_connect(None, &handle)
            .and_then(move |(duplex, _)| {
                let (tx, rx) = duplex.split();
                println!("\nConnected to websocket\n");
                let inner_pool = pool.clone();
                let mut core = Core::new().expect("Could not create event loop core.");
                let (ready_sender, ready_receiver) = mpsc::unbounded::<&str>();
                let (message_sender, message_receiver) = mpsc::unbounded::<String>();
                let (heartbeat_trigger_sender, heartbeat_trigger_receiver) = mpsc::unbounded();
                let (heartbeat_control_sender, heartbeat_control_receiver) = std::sync::mpsc::channel::<String>();

                let heartbeat_ready_sender = ready_sender.clone();

                let rx_worker = pool.spawn_fn(move || {
                    println!("\nReceiving worker is live\n");
                    rx.for_each(move |message| {
                        println!("\nGot a message\n");
                        let queue_ref = &queue_ref1;
                        let inner_queue = queue_ref.clone();
                        let worker_channel = ready_sender.clone();

                        let message_handler = inner_pool.spawn_fn(move || {
                            println!("\nHandling a message in a new thread\n");
                            Client::handle_stream(message, inner_queue);
                            println!("\nSending ready\n");
                            worker_channel.send("ready").map_err(|err| {
                                ()
                            }).map(|result| {
                                ()
                            })
                        }).map_err(|e| {
                            websocket::WebSocketError::NoDataAvailable //FIXME: hack
                        }).map(|result| {
                            ()
                        });

                        message_handler
                    }).map_err(|e| {
                        websocket::WebSocketError::NoDataAvailable //FIXME: hack
                    }).map(|result| {
                        ()
                    })
                });

                let tx_stream_worker = pool.spawn_fn(move || {
                    println!("\nFiltering worker is live\n");
                    let inner_message_sender = message_sender;
                    ready_receiver.for_each(move |message| {
                        println!("\nReceiving ready\n");

                        let queue_ref = &queue_ref2;
                        let mut queue = queue_ref.lock().expect("Could not get lock on queue.");
                        let mut messages = Vec::<Result<String, mpsc::SendError<String>>>::new();

                        while let Some(message) = queue.pop() {
                            println!("\nPopping a message off the queue\n");
                            &messages.push(Ok(message.body));
                        }

                        let message_stream = messages.into_iter();
                        stream::iter(message_stream)
                            .forward(inner_message_sender.clone())
                            .map_err(|e| {
                                () //FIXME: hack
                            }).map(|result| {
                                ()
                            })
                    }).map_err(|e| {
                        websocket::WebSocketError::NoDataAvailable //FIXME: hack
                    }).map(|result| {
                        ()
                    })
                });

                let tx_worker = pool.spawn_fn(move || {
                    println!("\nTransmitting worker is live\n");
                    message_receiver.map(|message| {
                        println!("\nSending a message\n");
                        OwnedMessage::Text(message)
                    })
                    .map_err(|_| { websocket::WebSocketError::NoDataAvailable })
                    .forward(tx)
                });

                let heartbeat_worker = pool.spawn_fn(move || {
                    loop_fn((heartbeat_trigger_sender, heartbeat_control_receiver), move |(trigger_channel, control)| {
                        if control.try_recv().is_err() {
                            let trigger_channel_next = trigger_channel.clone();

                            println!("\nSending heartbeat...\n");
                            trigger_channel.send("trigger").wait();

                            thread::sleep(time::Duration::from_secs(5));
                            Ok(Loop::Continue((trigger_channel_next, control)))
                        } else {
                            Ok(Loop::Break(()))
                        }
                    })
                });

                let heartbeat_sender_worker = pool.spawn_fn(move || { //required as LoopFn does not unlock the mutex
                    let queue_ref = queue_ref3;
                    let worker_channel = heartbeat_ready_sender;
                    heartbeat_trigger_receiver.for_each(move |message| {
                        let inner_queue_ref = queue_ref.clone();
                        let mut queue = inner_queue_ref.lock().expect("Could not get lock on queue.");
                        worker_channel.clone().send("ready").map_err(|e| {
                            ()
                        }).map(|result| {
                            ()
                        })
                    }).map_err(|e| {
                        websocket::WebSocketError::NoDataAvailable //FIXME: hack
                    }).map(|result| {
                        ()
                    })
                });

                rx_worker.join4(tx_stream_worker, tx_worker, heartbeat_worker.join(heartbeat_sender_worker))
            });

        self.core.run(socket);
    }

    fn gateway_autenticate(token: String, message_queue: Arc<Mutex<BinaryHeap<gateway::ClientMessage>>>) {
        let mut queue = message_queue.lock().expect("Could not get lock on queue.");

        let mut properties = BTreeMap::new();
        properties.insert(String::from("$os"), String::from("Linux"));

        let identity = gateway::identity::Identity {
            token,
            properties,
            compress: None,
            large_threshold: None,
        };

        let identification_message_body = gateway::MessageBody {
            op: 2,
            d: identity,
            s: None,
            t: None,
        };

        let identification_message = gateway::ClientMessage {
            body: serde_json::to_string(&identification_message_body)
                                 .expect("Could not serialize response."),
            priority: 0,
        };

        queue.push(identification_message);
    }

    fn handle_stream(message: websocket::OwnedMessage, message_queue: Arc<Mutex<BinaryHeap<gateway::ClientMessage>>>) -> Result<(), websocket::WebSocketError> {
        let mut queue = message_queue.lock().expect("Could not get lock on queue.");

        if let OwnedMessage::Text(text) = message {
            let deserialized_dispatch: gateway::ServerMessage = serde_json::from_str(&text)
                                                                     .expect("Could not parse JSON.");
            let serialized_data = deserialized_dispatch.d;
            let title = deserialized_dispatch.t;

            match title {
                Some(t) => {
                    match t.trim() {
                        "READY" => {
                            let deserialized_data: gateway::ready::Ready = serde_json::from_value(serialized_data)
                                                                      .expect("Could not parse JSON.");
                            println!("\nServer: READY\n {:?} \n", deserialized_data);
                            Ok(())
                        }
                        _ => {
                            println!("\nUnknown server message\n {:?} \n", serialized_data);
                            Ok(())
                        }
                    }

                }
                None => {
                    let deserialized_data: gateway::hello::Hello = serde_json::from_value(serialized_data)
                                                                      .expect("Could not parse JSON.");
                    println!("\nServer: HELLO:\n {:?} \n", deserialized_data);
                    Ok(())
                }
            }
        } else {
            println!("\nUnknown server message format\n");
            Ok(())
        }
    }
}
<|endoftext|>


<commit_before>//! # A CHIP-8 cpu simulator and instruction coding/decoding library.
//!
//! `chip8` provides tools to enable working with
//! [CHIP-8 virtual machine](https://en.wikipedia.org/wiki/CHIP-8)
//! instructions, and a CHIP-8 virtual machine simulator. No GUI is provided,
//! `chip8` is intended to be used by another crate. For example, this crate could be used to:
//!
//!  * encode abstract instructions into machine code for a CHIP-8 assembler
//!  * decode binary machine code into abstract instruction for a CHIP-8 disassembler
//!  * simulate the execution of instructions in a CHIP-8 virtual machine for a GUI CHIP-8 emulator
//!
//! ```rust
//! use chip8::{Simulator, Simulate};
//! use chip8::instruction::Src::Register;
//! let mut chip8 = Simulator::default().unwrap();
//! // A simple program:   LD v6, 25    LD v7, 17    ADD v6, v7
//! chip8.load_program( &[ 0x66, 0x19,  0x67, 0x11,  0x86, 0x74 ] ).unwrap();
//! // Execute the three instructions.
//! chip8.step_n(3).unwrap();
//! // Fetch the result from register v6.
//! let result = chip8.load(Register(6)).unwrap();
//! assert_eq!( result, 25+17 );
//! ```
//!
//! ## Instructions
//! An `instruction::Definition` is a combination of an `OperationKind` like *Add* or *Jump* and
//! a `Pattern` that specifies how the codword is structured.
//!
//! An `instruction::Set` contains one or more `Definition`. The `Set` can decode
//! machine codewords into `Operation`s and encode `Operation`s into codewords.
//!
//! ## Simulation
//! A `Chip8` represents the state of a CHIP-8 system, including CPU and peripherals.
//! It implements the `Execute` trait, so it is able to execute `Operation`s.
//!
//! A `Simulator` contains a `Chip8` and an `instruction::Set`, which allows it to decode
//! instructions and simulate their execution. The `Simulator` provides thread-safe mechanisms
//! for control of execution and inspection of machine state.

#![feature(inclusive_range_syntax, plugin, custom_attribute)]
#![feature(question_mark)]
#![plugin(drawbytes)]

// enable errors for some additional lints
#![deny(trivial_casts, trivial_numeric_casts, unsafe_code,
        unused_qualifications)]

//#![cfg_attr(feature = "lints", warn(missing_docs))]
#![cfg_attr(feature = "lints", plugin(clippy))]
#![cfg_attr(feature = "lints", deny(clippy))]
#![cfg_attr(feature = "lints", deny(if_not_else, invalid_upcast_comparisons, items_after_statements,
                                    mem_forget, mut_mut, mutex_integer, non_ascii_literal,
                                    nonminimal_bool, shadow_same,
                                    similar_names, single_match_else, string_add, string_add_assign,
                                    unicode_not_nfc, wrong_pub_self_convention ))]
//#![cfg_attr(feature = "lints", warn(option_unwrap_used, result_unwrap_used))]
//#![cfg_attr(feature = "lints", warn(shadow_unrelated, shadow_reuse))]
#![cfg_attr(feature = "lints", warn(missing_debug_implementations, unused_import_braces,missing_copy_implementations))]
#![cfg_attr(feature = "lints", allow(doc_markdown))]
// #![cfg_attr(feature = "lints", cast_possible_truncation, cast_possible_wrap, cast_sign_loss))]

//#![allow(unused_imports, unused_variables, unused_mut)]
#![warn(print_stdout)]

extern crate rand;
extern crate strfmt;

pub mod config;
pub mod fonts;
pub mod instruction;
mod simulator;
mod state;
mod types;

pub use config::Config;
pub use types::*;
pub use state::Chip8;
pub use simulator::{Simulate, Simulator, SimulatorTask};
<commit_msg>Put the print_stdout list behind the lints feature flag<commit_after>//! # A CHIP-8 cpu simulator and instruction coding/decoding library.
//!
//! `chip8` provides tools to enable working with
//! [CHIP-8 virtual machine](https://en.wikipedia.org/wiki/CHIP-8)
//! instructions, and a CHIP-8 virtual machine simulator. No GUI is provided,
//! `chip8` is intended to be used by another crate. For example, this crate could be used to:
//!
//!  * encode abstract instructions into machine code for a CHIP-8 assembler
//!  * decode binary machine code into abstract instruction for a CHIP-8 disassembler
//!  * simulate the execution of instructions in a CHIP-8 virtual machine for a GUI CHIP-8 emulator
//!
//! ```rust
//! use chip8::{Simulator, Simulate};
//! use chip8::instruction::Src::Register;
//! let mut chip8 = Simulator::default().unwrap();
//! // A simple program:   LD v6, 25    LD v7, 17    ADD v6, v7
//! chip8.load_program( &[ 0x66, 0x19,  0x67, 0x11,  0x86, 0x74 ] ).unwrap();
//! // Execute the three instructions.
//! chip8.step_n(3).unwrap();
//! // Fetch the result from register v6.
//! let result = chip8.load(Register(6)).unwrap();
//! assert_eq!( result, 25+17 );
//! ```
//!
//! ## Instructions
//! An `instruction::Definition` is a combination of an `OperationKind` like *Add* or *Jump* and
//! a `Pattern` that specifies how the codword is structured.
//!
//! An `instruction::Set` contains one or more `Definition`. The `Set` can decode
//! machine codewords into `Operation`s and encode `Operation`s into codewords.
//!
//! ## Simulation
//! A `Chip8` represents the state of a CHIP-8 system, including CPU and peripherals.
//! It implements the `Execute` trait, so it is able to execute `Operation`s.
//!
//! A `Simulator` contains a `Chip8` and an `instruction::Set`, which allows it to decode
//! instructions and simulate their execution. The `Simulator` provides thread-safe mechanisms
//! for control of execution and inspection of machine state.

#![feature(inclusive_range_syntax, plugin, custom_attribute)]
#![feature(question_mark)]
#![plugin(drawbytes)]

// enable errors for some additional lints
#![deny(trivial_casts, trivial_numeric_casts, unsafe_code,
        unused_qualifications)]

//#![cfg_attr(feature = "lints", warn(missing_docs))]
#![cfg_attr(feature = "lints", plugin(clippy))]
#![cfg_attr(feature = "lints", deny(clippy))]
#![cfg_attr(feature = "lints", deny(if_not_else, invalid_upcast_comparisons, items_after_statements,
                                    mem_forget, mut_mut, mutex_integer, non_ascii_literal,
                                    nonminimal_bool, shadow_same,
                                    similar_names, single_match_else, string_add, string_add_assign,
                                    unicode_not_nfc, wrong_pub_self_convention ))]
//#![cfg_attr(feature = "lints", warn(option_unwrap_used, result_unwrap_used))]
//#![cfg_attr(feature = "lints", warn(shadow_unrelated, shadow_reuse))]
#![cfg_attr(feature = "lints", warn(missing_debug_implementations, unused_import_braces,missing_copy_implementations))]
#![cfg_attr(feature = "lints", allow(doc_markdown))]
// #![cfg_attr(feature = "lints", cast_possible_truncation, cast_possible_wrap, cast_sign_loss))]

//#![allow(unused_imports, unused_variables, unused_mut)]
#![cfg_attr(feature = "lints", warn(print_stdout))]

extern crate rand;
extern crate strfmt;

pub mod config;
pub mod fonts;
pub mod instruction;
mod simulator;
mod state;
mod types;

pub use config::Config;
pub use types::*;
pub use state::Chip8;
pub use simulator::{Simulate, Simulator, SimulatorTask};
<|endoftext|>


<commit_before>//! Serenity is a Rust library for the Discord API.
//!
//! View the [examples] on how to make and structure a bot.
//!
//! Serenity supports bot user authentication via the use of [`Client::builder`].
//!
//! Once logged in, you may add handlers to your client to dispatch [`Event`]s,
//! such as [`EventHandler::message`]. This will cause your handler to be called
//! when a [`Event::MessageCreate`] is received. Each handler is given a
//! [`Context`], giving information about the event. See the
//! [client's module-level documentation].
//!
//! The [`Shard`] is transparently handled by the library, removing
//! unnecessary complexity. Sharded connections are automatically handled for
//! you. See the [gateway's documentation][gateway docs] for more information.
//!
//! A [`Cache`] is also provided for you. This will be updated automatically for
//! you as data is received from the Discord API via events. When calling a
//! method on a [`Context`], the cache will first be searched for relevant data
//! to avoid unnecessary HTTP requests to the Discord API. For more information,
//! see the [cache's module-level documentation][cache docs].
//!
//! Note that, although this documentation will try to be as up-to-date and
//! accurate as possible, Discord hosts [official documentation][docs]. If you
//! need to be sure that some information piece is sanctioned by Discord, refer
//! to their own documentation.
//!
//! ### Full Examples
//!
//! Full examples, detailing and explaining usage of the basic functionality of the
//! library, can be found in the [`examples`] directory.
//!
//! # Installation
//!
//! Add the following to your `Cargo.toml` file:
//!
//! ```toml
//! [dependencies]
//! serenity = "0.10"
//! ```
//!
//! [`Context`]: crate::client::Context
//! [`EventHandler::message`]: crate::client::EventHandler::message
//! [`Event`]: crate::model::event::Event
//! [`Event::MessageCreate`]: crate::model::event::Event::MessageCreate
//! [`Shard`]: crate::gateway::Shard
//! [`examples`]: https://github.com/serenity-rs/serenity/blob/current/examples
//! [cache docs]: crate::cache
//! [client's module-level documentation]: crate::client
//! [docs]: https://discord.com/developers/docs/intro
//! [examples]: https://github.com/serenity-rs/serenity/tree/current/examples
//! [gateway docs]: crate::gateway
#![doc(html_root_url = "https://docs.rs/serenity/*")]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![deny(rust_2018_idioms)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(
    clippy::unwrap_used,
    clippy::non_ascii_literal,
    clippy::missing_errors_doc,
    clippy::let_underscore_must_use
)]
#![type_length_limit = "3294819"] // needed so ShardRunner::run compiles with instrument.

#[macro_use]
extern crate serde;

#[cfg(all(feature = "tokio_compat", not(feature = "tokio")))]
extern crate tokio_compat as tokio;

#[cfg(all(feature = "reqwest_compat", not(feature = "reqwest")))]
extern crate reqwest_compat as reqwest;

#[cfg(all(feature = "async-tungstenite_compat", not(feature = "async-tungstenite")))]
extern crate async_tungstenite_compat as async_tungstenite;

#[cfg(all(feature = "bytes_compat", not(feature = "bytes")))]
extern crate bytes_compat as bytes;

#[macro_use]
mod internal;

pub mod constants;
pub mod json;
pub mod model;
pub mod prelude;

#[cfg(feature = "builder")]
pub mod builder;
#[cfg(feature = "cache")]
pub mod cache;
#[cfg(feature = "client")]
pub mod client;
#[cfg(feature = "collector")]
pub mod collector;
#[cfg(feature = "framework")]
pub mod framework;
#[cfg(feature = "gateway")]
pub mod gateway;
#[cfg(feature = "http")]
pub mod http;
#[cfg(feature = "utils")]
pub mod utils;

mod error;

#[cfg(feature = "client")]
use std::sync::Arc;
#[cfg(all(feature = "client", feature = "cache"))]
use std::time::Duration;

#[cfg(all(feature = "client", feature = "cache"))]
use crate::cache::Cache;
#[cfg(all(feature = "client", feature = "gateway"))]
pub use crate::client::Client;
pub use crate::error::{Error, Result};
#[cfg(feature = "client")]
use crate::http::Http;

#[cfg(feature = "client")]
#[derive(Clone, Default)]
#[non_exhaustive]
pub struct CacheAndHttp {
    #[cfg(feature = "cache")]
    pub cache: Arc<Cache>,
    #[cfg(feature = "cache")]
    pub update_cache_timeout: Option<Duration>,
    pub http: Arc<Http>,
}

// For the procedural macros in `command_attr`.
pub use async_trait::async_trait;
pub use futures;
pub use futures::future::FutureExt;
#[cfg(feature = "standard_framework")]
#[doc(hidden)]
pub use static_assertions;
<commit_msg>Remove `#[deny(broken_intra_doc_link)]` from the crate root<commit_after>//! Serenity is a Rust library for the Discord API.
//!
//! View the [examples] on how to make and structure a bot.
//!
//! Serenity supports bot user authentication via the use of [`Client::builder`].
//!
//! Once logged in, you may add handlers to your client to dispatch [`Event`]s,
//! such as [`EventHandler::message`]. This will cause your handler to be called
//! when a [`Event::MessageCreate`] is received. Each handler is given a
//! [`Context`], giving information about the event. See the
//! [client's module-level documentation].
//!
//! The [`Shard`] is transparently handled by the library, removing
//! unnecessary complexity. Sharded connections are automatically handled for
//! you. See the [gateway's documentation][gateway docs] for more information.
//!
//! A [`Cache`] is also provided for you. This will be updated automatically for
//! you as data is received from the Discord API via events. When calling a
//! method on a [`Context`], the cache will first be searched for relevant data
//! to avoid unnecessary HTTP requests to the Discord API. For more information,
//! see the [cache's module-level documentation][cache docs].
//!
//! Note that, although this documentation will try to be as up-to-date and
//! accurate as possible, Discord hosts [official documentation][docs]. If you
//! need to be sure that some information piece is sanctioned by Discord, refer
//! to their own documentation.
//!
//! ### Full Examples
//!
//! Full examples, detailing and explaining usage of the basic functionality of the
//! library, can be found in the [`examples`] directory.
//!
//! # Installation
//!
//! Add the following to your `Cargo.toml` file:
//!
//! ```toml
//! [dependencies]
//! serenity = "0.10"
//! ```
//!
//! [`Context`]: crate::client::Context
//! [`EventHandler::message`]: crate::client::EventHandler::message
//! [`Event`]: crate::model::event::Event
//! [`Event::MessageCreate`]: crate::model::event::Event::MessageCreate
//! [`Shard`]: crate::gateway::Shard
//! [`examples`]: https://github.com/serenity-rs/serenity/blob/current/examples
//! [cache docs]: crate::cache
//! [client's module-level documentation]: crate::client
//! [docs]: https://discord.com/developers/docs/intro
//! [examples]: https://github.com/serenity-rs/serenity/tree/current/examples
//! [gateway docs]: crate::gateway
#![doc(html_root_url = "https://docs.rs/serenity/*")]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![deny(rust_2018_idioms)]
#![deny(
    clippy::unwrap_used,
    clippy::non_ascii_literal,
    clippy::missing_errors_doc,
    clippy::let_underscore_must_use
)]
#![type_length_limit = "3294819"] // needed so ShardRunner::run compiles with instrument.

#[macro_use]
extern crate serde;

#[cfg(all(feature = "tokio_compat", not(feature = "tokio")))]
extern crate tokio_compat as tokio;

#[cfg(all(feature = "reqwest_compat", not(feature = "reqwest")))]
extern crate reqwest_compat as reqwest;

#[cfg(all(feature = "async-tungstenite_compat", not(feature = "async-tungstenite")))]
extern crate async_tungstenite_compat as async_tungstenite;

#[cfg(all(feature = "bytes_compat", not(feature = "bytes")))]
extern crate bytes_compat as bytes;

#[macro_use]
mod internal;

pub mod constants;
pub mod json;
pub mod model;
pub mod prelude;

#[cfg(feature = "builder")]
pub mod builder;
#[cfg(feature = "cache")]
pub mod cache;
#[cfg(feature = "client")]
pub mod client;
#[cfg(feature = "collector")]
pub mod collector;
#[cfg(feature = "framework")]
pub mod framework;
#[cfg(feature = "gateway")]
pub mod gateway;
#[cfg(feature = "http")]
pub mod http;
#[cfg(feature = "utils")]
pub mod utils;

mod error;

#[cfg(feature = "client")]
use std::sync::Arc;
#[cfg(all(feature = "client", feature = "cache"))]
use std::time::Duration;

#[cfg(all(feature = "client", feature = "cache"))]
use crate::cache::Cache;
#[cfg(all(feature = "client", feature = "gateway"))]
pub use crate::client::Client;
pub use crate::error::{Error, Result};
#[cfg(feature = "client")]
use crate::http::Http;

#[cfg(feature = "client")]
#[derive(Clone, Default)]
#[non_exhaustive]
pub struct CacheAndHttp {
    #[cfg(feature = "cache")]
    pub cache: Arc<Cache>,
    #[cfg(feature = "cache")]
    pub update_cache_timeout: Option<Duration>,
    pub http: Arc<Http>,
}

// For the procedural macros in `command_attr`.
pub use async_trait::async_trait;
pub use futures;
pub use futures::future::FutureExt;
#[cfg(feature = "standard_framework")]
#[doc(hidden)]
pub use static_assertions;
<|endoftext|>