<commit_before>use assert_matches::assert_matches;
use futures::{
    future::{ready, Ready},
    prelude::*,
};
use std::io;
use tarpc::{
    client::{self},
    context, serde_transport,
    server::{self, BaseChannel, Channel, Handler},
    transport::channel,
};
use tokio_serde::formats::Json;

#[tarpc_plugins::service]
trait Service {
    async fn add(x: i32, y: i32) -> i32;
    async fn hey(name: String) -> String;
}

#[derive(Clone)]
struct Server;

impl Service for Server {
    type AddFut = Ready<i32>;

    fn add(self, _: context::Context, x: i32, y: i32) -> Self::AddFut {
        ready(x + y)
    }

    type HeyFut = Ready<String>;

    fn hey(self, _: context::Context, name: String) -> Self::HeyFut {
        ready(format!("Hey, {}.", name))
    }
}

#[tokio::test(threaded_scheduler)]
async fn sequential() -> io::Result<()> {
    let _ = env_logger::try_init();

    let (tx, rx) = channel::unbounded();

    tokio::spawn(
        BaseChannel::new(server::Config::default(), rx)
            .respond_with(Server.serve())
            .execute(),
    );

    let mut client = ServiceClient::new(client::Config::default(), tx).spawn()?;

    assert_matches!(client.add(context::current(), 1, 2).await, Ok(3));
    assert_matches!(
        client.hey(context::current(), "Tim".into()).await,
        Ok(ref s) if s == "Hey, Tim.");

    Ok(())
}

#[cfg(feature = "serde1")]
#[tokio::test(threaded_scheduler)]
async fn serde() -> io::Result<()> {
    let _ = env_logger::try_init();

    let transport = serde_transport::tcp::listen("localhost:56789", Json::default).await?;
    let addr = transport.local_addr();
    tokio::spawn(
        tarpc::Server::default()
            .incoming(transport.take(1).filter_map(|r| async { r.ok() }))
            .respond_with(Server.serve()),
    );

    let transport = serde_transport::tcp::connect(addr, Json::default()).await?;
    let mut client = ServiceClient::new(client::Config::default(), transport).spawn()?;

    assert_matches!(client.add(context::current(), 1, 2).await, Ok(3));
    assert_matches!(
        client.hey(context::current(), "Tim".to_string()).await,
        Ok(ref s) if s == "Hey, Tim."
    );

    Ok(())
}

#[tokio::test(threaded_scheduler)]
async fn concurrent() -> io::Result<()> {
    let _ = env_logger::try_init();

    let (tx, rx) = channel::unbounded();
    tokio::spawn(
        tarpc::Server::default()
            .incoming(stream::once(ready(rx)))
            .respond_with(Server.serve()),
    );

    let client = ServiceClient::new(client::Config::default(), tx).spawn()?;

    let mut c = client.clone();
    let req1 = c.add(context::current(), 1, 2);

    let mut c = client.clone();
    let req2 = c.add(context::current(), 3, 4);

    let mut c = client.clone();
    let req3 = c.hey(context::current(), "Tim".to_string());

    assert_matches!(req1.await, Ok(3));
    assert_matches!(req2.await, Ok(7));
    assert_matches!(req3.await, Ok(ref s) if s == "Hey, Tim.");

    Ok(())
}
<commit_msg>Add concurrent tests using `join` and `join_all`<commit_after>use assert_matches::assert_matches;
use futures::{
    future::{join_all, ready, Ready},
    prelude::*,
};
use std::io;
use tarpc::{
    client::{self},
    context, serde_transport,
    server::{self, BaseChannel, Channel, Handler},
    transport::channel,
};
use tokio::join;
use tokio_serde::formats::Json;

#[tarpc_plugins::service]
trait Service {
    async fn add(x: i32, y: i32) -> i32;
    async fn hey(name: String) -> String;
}

#[derive(Clone)]
struct Server;

impl Service for Server {
    type AddFut = Ready<i32>;

    fn add(self, _: context::Context, x: i32, y: i32) -> Self::AddFut {
        ready(x + y)
    }

    type HeyFut = Ready<String>;

    fn hey(self, _: context::Context, name: String) -> Self::HeyFut {
        ready(format!("Hey, {}.", name))
    }
}

#[tokio::test(threaded_scheduler)]
async fn sequential() -> io::Result<()> {
    let _ = env_logger::try_init();

    let (tx, rx) = channel::unbounded();

    tokio::spawn(
        BaseChannel::new(server::Config::default(), rx)
            .respond_with(Server.serve())
            .execute(),
    );

    let mut client = ServiceClient::new(client::Config::default(), tx).spawn()?;

    assert_matches!(client.add(context::current(), 1, 2).await, Ok(3));
    assert_matches!(
        client.hey(context::current(), "Tim".into()).await,
        Ok(ref s) if s == "Hey, Tim.");

    Ok(())
}

#[cfg(feature = "serde1")]
#[tokio::test(threaded_scheduler)]
async fn serde() -> io::Result<()> {
    let _ = env_logger::try_init();

    let transport = serde_transport::tcp::listen("localhost:56789", Json::default).await?;
    let addr = transport.local_addr();
    tokio::spawn(
        tarpc::Server::default()
            .incoming(transport.take(1).filter_map(|r| async { r.ok() }))
            .respond_with(Server.serve()),
    );

    let transport = serde_transport::tcp::connect(addr, Json::default()).await?;
    let mut client = ServiceClient::new(client::Config::default(), transport).spawn()?;

    assert_matches!(client.add(context::current(), 1, 2).await, Ok(3));
    assert_matches!(
        client.hey(context::current(), "Tim".to_string()).await,
        Ok(ref s) if s == "Hey, Tim."
    );

    Ok(())
}

#[tokio::test(threaded_scheduler)]
async fn concurrent() -> io::Result<()> {
    let _ = env_logger::try_init();

    let (tx, rx) = channel::unbounded();
    tokio::spawn(
        tarpc::Server::default()
            .incoming(stream::once(ready(rx)))
            .respond_with(Server.serve()),
    );

    let client = ServiceClient::new(client::Config::default(), tx).spawn()?;

    let mut c = client.clone();
    let req1 = c.add(context::current(), 1, 2);

    let mut c = client.clone();
    let req2 = c.add(context::current(), 3, 4);

    let mut c = client.clone();
    let req3 = c.hey(context::current(), "Tim".to_string());

    assert_matches!(req1.await, Ok(3));
    assert_matches!(req2.await, Ok(7));
    assert_matches!(req3.await, Ok(ref s) if s == "Hey, Tim.");

    Ok(())
}

#[tokio::test(threaded_scheduler)]
async fn concurrent_join() -> io::Result<()> {
    let _ = env_logger::try_init();

    let (tx, rx) = channel::unbounded();
    tokio::spawn(
        tarpc::Server::default()
            .incoming(stream::once(ready(rx)))
            .respond_with(Server.serve()),
    );

    let client = ServiceClient::new(client::Config::default(), tx).spawn()?;

    let mut c = client.clone();
    let req1 = c.add(context::current(), 1, 2);

    let mut c = client.clone();
    let req2 = c.add(context::current(), 3, 4);

    let mut c = client.clone();
    let req3 = c.hey(context::current(), "Tim".to_string());

    let (resp1, resp2, resp3) = join!(req1, req2, req3);
    assert_matches!(resp1, Ok(3));
    assert_matches!(resp2, Ok(7));
    assert_matches!(resp3, Ok(ref s) if s == "Hey, Tim.");

    Ok(())
}

#[tokio::test(threaded_scheduler)]
async fn concurrent_join_all() -> io::Result<()> {
    let _ = env_logger::try_init();

    let (tx, rx) = channel::unbounded();
    tokio::spawn(
        tarpc::Server::default()
            .incoming(stream::once(ready(rx)))
            .respond_with(Server.serve()),
    );

    let client = ServiceClient::new(client::Config::default(), tx).spawn()?;

    let mut c1 = client.clone();
    let mut c2 = client.clone();

    let req1 = c1.add(context::current(), 1, 2);
    let req2 = c2.add(context::current(), 3, 4);

    let responses = join_all(vec![req1, req2]).await;
    assert_matches!(responses[0], Ok(3));
    assert_matches!(responses[1], Ok(7));

    Ok(())
}
<|endoftext|>


<commit_before>extern crate redis;

pub use self::redis::{RedisError};

/// A DataStore needs to implement store and retrieve methods.
pub trait DataStore : Send {
    fn store(&self, key: &str, value: &str) -> Result<(), DataStoreError>;
    fn retrieve(&self, key: &str) -> Result<String, DataStoreError>;
    fn delete(&self, key: &str) -> Result<(), DataStoreError>;
}

/// A struct representing a datastore error.
#[derive(Debug)]
pub struct DataStoreError {
    pub repr: ErrorKind,
}

/// An enum containing all possible error kinds.
#[derive(Debug)]
pub enum ErrorKind {
    RedisError(redis::RedisError),
}

impl From<redis::RedisError> for DataStoreError {
    fn from(err: redis::RedisError) -> DataStoreError {
        DataStoreError { repr: ErrorKind::RedisError(err) }
    }
}
<commit_msg>datastore: Cleanup DataStoreError<commit_after>extern crate redis;

pub use self::redis::{RedisError};

/// A DataStore needs to implement store and retrieve methods.
pub trait DataStore : Send {
    fn store(&self, key: &str, value: &str) -> Result<(), DataStoreError>;
    fn retrieve(&self, key: &str) -> Result<String, DataStoreError>;
    fn delete(&self, key: &str) -> Result<(), DataStoreError>;
}

/// An enum representing a datastore error.
#[derive(Debug)]
pub enum DataStoreError {
    RedisError(redis::RedisError),
}

impl From<redis::RedisError> for DataStoreError {
    fn from(err: redis::RedisError) -> DataStoreError {
        DataStoreError::RedisError(err)
    }
}

<|endoftext|>


<commit_before>#![feature(old_io, old_path)]

// Generate the git version string.

use std::old_io::process::{Command, ProcessOutput};
use std::old_io::{File};

fn git_version() -> String {
    match Command::new("git")
        .arg("log").arg("--pretty=format:%h").arg("-1").output() {
        Ok(ProcessOutput { status: exit, output: out, error: err }) => {
            if exit.success() {
                return String::from_utf8(out).unwrap();
            } else {
                println!("Error getting git version: {}", String::from_utf8(err).unwrap());
            }
        }
        Err(err) => {
            println!("Error getting git version: {}", err);
        }
    }
    return "unknown".to_string();
}

fn rustc_version() -> String {
    match Command::new("rustc")
        .arg("--version").output() {
        Ok(ProcessOutput { status: exit, output: out, error: err }) => {
            if exit.success() {
                return String::from_utf8(out).unwrap();
            } else {
                println!("Error getting rustc version: {}", String::from_utf8(err).unwrap());
            }
        }
        Err(err) => {
            println!("Error getting rustc version: {}", err);
        }
    }
    return "unknown".to_string();
}

fn open(path: &str) -> File {
    match File::create(&Path::new(path)) {
        Ok(f) => f, Err(e) => panic!("file error: {}", e),
    }
}

pub fn main() {
    // Write the current Git HEAD hash into the version file.
    write!(&mut open("src/git_hash.inc"), "{}", git_version()).unwrap();
    write!(&mut open("rustc_version.txt"), "{}", rustc_version()).unwrap();
}
<commit_msg>Update build.rs to modern IO<commit_after>// Generate the git version string.

use std::io::prelude::*;
use std::process::{Command, Output};
use std::fs::{File};

fn git_version() -> String {
    match Command::new("git")
        .arg("log").arg("--pretty=format:%h").arg("-1").output() {
        Ok(Output { status: exit, stdout: out, stderr: err }) => {
            if exit.success() {
                return String::from_utf8(out).unwrap();
            } else {
                println!("Error getting git version: {}", String::from_utf8(err).unwrap());
            }
        }
        Err(err) => {
            println!("Error getting git version: {}", err);
        }
    }
    return "unknown".to_string();
}

fn rustc_version() -> String {
    match Command::new("rustc")
        .arg("--version").output() {
        Ok(Output { status: exit, stdout: out, stderr: err }) => {
            if exit.success() {
                return String::from_utf8(out).unwrap();
            } else {
                println!("Error getting rustc version: {}", String::from_utf8(err).unwrap());
            }
        }
        Err(err) => {
            println!("Error getting rustc version: {}", err);
        }
    }
    return "unknown".to_string();
}

fn open(path: &str) -> File {
    match File::create(path) {
        Ok(f) => f, Err(e) => panic!("file error: {}", e),
    }
}

pub fn main() {
    // Write the current Git HEAD hash into the version file.
    write!(&mut open("src/git_hash.inc"), "{}", git_version()).unwrap();
    write!(&mut open("rustc_version.txt"), "{}", rustc_version()).unwrap();
}
<|endoftext|>


<commit_before>// Bitcoin secp256k1 bindings
// Written in 2015 by
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Build script

// Coding conventions
#![deny(non_upper_case_globals)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
#![warn(missing_docs)]

extern crate gcc;

fn main() {
    let mut base_config = gcc::Config::new();
    base_config.include("depend/secp256k1/")
               .include("depend/secp256k1/include")
               .include("depend/secp256k1/src")
               .flag("-g")
               // TODO these three should be changed to use libgmp, at least until secp PR 290 is merged
               .define("USE_NUM_NONE", Some("1"))
               .define("USE_FIELD_INV_BUILTIN", Some("1"))
               .define("USE_SCALAR_INV_BUILTIN", Some("1"))
               // TODO these should use 64-bit variants on 64-bit systems
               .define("USE_FIELD_10X26", Some("1"))
               .define("USE_SCALAR_8X32", Some("1"))
               .define("USE_ENDOMORPHISM", Some("1"))
               // These all are OK.
               .define("ENABLE_MODULE_ECDH", Some("1"))
               .define("ENABLE_MODULE_SCHNORR", Some("1"))
               .define("ENABLE_MODULE_RECOVERY", Some("1"));

    // secp256k1
    base_config.file("depend/secp256k1/contrib/lax_der_parsing.c")
               .file("depend/secp256k1/src/secp256k1.c")
               .compile("libsecp256k1.a");
}

<commit_msg>rename gcc::Config to gcc::Build<commit_after>// Bitcoin secp256k1 bindings
// Written in 2015 by
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Build script

// Coding conventions
#![deny(non_upper_case_globals)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
#![warn(missing_docs)]

extern crate gcc;

fn main() {
    let mut base_config = gcc::Build::new();
    base_config.include("depend/secp256k1/")
               .include("depend/secp256k1/include")
               .include("depend/secp256k1/src")
               .flag("-g")
               // TODO these three should be changed to use libgmp, at least until secp PR 290 is merged
               .define("USE_NUM_NONE", Some("1"))
               .define("USE_FIELD_INV_BUILTIN", Some("1"))
               .define("USE_SCALAR_INV_BUILTIN", Some("1"))
               // TODO these should use 64-bit variants on 64-bit systems
               .define("USE_FIELD_10X26", Some("1"))
               .define("USE_SCALAR_8X32", Some("1"))
               .define("USE_ENDOMORPHISM", Some("1"))
               // These all are OK.
               .define("ENABLE_MODULE_ECDH", Some("1"))
               .define("ENABLE_MODULE_SCHNORR", Some("1"))
               .define("ENABLE_MODULE_RECOVERY", Some("1"));

    // secp256k1
    base_config.file("depend/secp256k1/contrib/lax_der_parsing.c")
               .file("depend/secp256k1/src/secp256k1.c")
               .compile("libsecp256k1.a");
}

<|endoftext|>


<commit_before>use std::num::{ Float, FloatMath, from_f64 };
use std::mem::size_of;

use music;
use reader;
use wave;

pub fn quantize<T>(input: f64) -> T where T: FromPrimitive {
    let quantization_levels = 2.0.powf(size_of::<T>() as f64 * 8.0) - 1.0;
    // Convert from [-1, 1] to take up full quantization range
    from_f64::<T>(input * (quantization_levels / 2.0)).expect("failed to quantize to given type")
}

pub fn quantize_samples<T>(input: Vec<f64>) -> Vec<T> where T: FromPrimitive {
    input.iter().map(|s| { quantize::<T>(*s) }).collect()
}

pub fn generate<F>(x: f64, f: F) -> f64 where F: Fn<(f64, ), f64> {
    f(x)
}

pub fn make_samples<F>(length: f64, sample_rate: uint, waveform: F) -> Vec<f64> where F: Fn<(f64, ), f64>+Copy {
    let num_samples = (sample_rate as f64 * length).floor() as uint;
    let mut samples: Vec<f64> = Vec::with_capacity(num_samples);

    for i in range(0u, num_samples) {
        let t = i as f64 / sample_rate as f64;
        samples.push(generate(t, waveform));
    }

    samples
}

pub fn normalize(samples: Vec<f64>) -> Vec<f64> {
    let peak = samples.iter().fold(0.0f64, |acc, sample| {
        acc.max(*sample)
    });

    samples.iter().map(|sample| {
        *sample / peak
    }).collect()
}

// This is really awful, is there a more elegant way to do this?
// TODO: Split out volume normalization into a function
pub fn make_samples_from_midi(sample_rate: uint, bpm: f64, filename: &str) -> Vec<f64> {
    let song = reader::read_midi(filename).unwrap();
    let length = (60.0 * song.max_time as f64) / (bpm * song.time_unit as f64);

    let mut notes_on_for_ticks: Vec<Vec<u8>> = Vec::new();
    for _ in range(0, song.max_time) {
        let notes_on_for_tick: Vec<u8> = Vec::new();
        notes_on_for_ticks.push(notes_on_for_tick);
    }

    for track in song.tracks.iter() {
        for i in range(0, track.messages.len()) {
            let event = track.messages[i];
            if event.message_type == 9 {
                let from_tick = event.time;
                let note = event.value1;

                let mut to_tick = song.max_time;
                for j in range(i, track.messages.len()) {
                    let event_to = track.messages[j];
                    if event_to.message_type == 8 && event_to.value1 == note {
                        to_tick = event_to.time;
                        break;
                    }
                }

                for tick in range(from_tick, to_tick) {
                    notes_on_for_ticks[tick].push(note);
                }
            }
        }
    }

    let midi_frequency_function = |t: f64| -> f64 {
        let tick = (t * bpm * song.time_unit as f64 / 60.0) as uint;
        let mut out = 0.0;

        if tick < notes_on_for_ticks.len() {
            for note in notes_on_for_ticks[tick].iter() {
                let frequency = music::note_midi(440.0, *note as uint);
                out += wave::SineWave(frequency)(t)
            }
        }

        out
    };

    let num_samples = (sample_rate as f64 * length).floor() as uint;
    let mut samples: Vec<f64> = Vec::with_capacity(num_samples);

    for i in range(0u, num_samples) {
        let t = i as f64 / sample_rate as f64;
        samples.push(midi_frequency_function(t));
    }

    normalize(samples)
}
<commit_msg>Hack to reduce MIDI synthesis popping<commit_after>use std::num::{ Float, FloatMath, from_f64 };
use std::mem::size_of;

use music;
use reader;
use wave;

pub fn quantize<T>(input: f64) -> T where T: FromPrimitive {
    let quantization_levels = 2.0.powf(size_of::<T>() as f64 * 8.0) - 1.0;
    // Convert from [-1, 1] to take up full quantization range
    from_f64::<T>(input * (quantization_levels / 2.0)).expect("failed to quantize to given type")
}

pub fn quantize_samples<T>(input: Vec<f64>) -> Vec<T> where T: FromPrimitive {
    input.iter().map(|s| { quantize::<T>(*s) }).collect()
}

pub fn generate<F>(x: f64, f: F) -> f64 where F: Fn<(f64, ), f64> {
    f(x)
}

pub fn make_samples<F>(length: f64, sample_rate: uint, waveform: F) -> Vec<f64> where F: Fn<(f64, ), f64>+Copy {
    let num_samples = (sample_rate as f64 * length).floor() as uint;
    let mut samples: Vec<f64> = Vec::with_capacity(num_samples);

    for i in range(0u, num_samples) {
        let t = i as f64 / sample_rate as f64;
        samples.push(generate(t, waveform));
    }

    samples
}

pub fn normalize(samples: Vec<f64>) -> Vec<f64> {
    let peak = samples.iter().fold(0.0f64, |acc, sample| {
        acc.max(*sample)
    });

    samples.iter().map(|sample| {
        *sample / peak
    }).collect()
}

// This is really awful, is there a more elegant way to do this?
// TODO: Split out volume normalization into a function
pub fn make_samples_from_midi(sample_rate: uint, bpm: f64, filename: &str) -> Vec<f64> {
    let song = reader::read_midi(filename).unwrap();
    let length = (60.0 * song.max_time as f64) / (bpm * song.time_unit as f64);

    let mut notes_on_for_ticks: Vec<Vec<u8>> = Vec::new();
    for _ in range(0, song.max_time) {
        let notes_on_for_tick: Vec<u8> = Vec::new();
        notes_on_for_ticks.push(notes_on_for_tick);
    }

    for track in song.tracks.iter() {
        for i in range(0, track.messages.len()) {
            let event = track.messages[i];
            if event.message_type == 9 {
                let from_tick = event.time;
                let note = event.value1;

                let mut to_tick = song.max_time;
                for j in range(i, track.messages.len()) {
                    let event_to = track.messages[j];
                    if event_to.message_type == 8 && event_to.value1 == note {
                        to_tick = event_to.time;
                        break;
                    }
                }

                for tick in range(from_tick, to_tick) {
                    notes_on_for_ticks[tick].push(note);
                }
            }
        }
    }

    let midi_frequency_function = |t: f64| -> f64 {
        let tick = (t * bpm * song.time_unit as f64 / 60.0) as uint;
        let mut out = 0.0;

        if tick < notes_on_for_ticks.len() {
            for note in notes_on_for_ticks[tick].iter() {
                let frequency = music::note_midi(440.0, *note as uint);
                out += (wave::SquareWave(frequency)(t) + wave::SquareWave(frequency)(t)) / 2.0
            }
        }

        out
    };

    let num_samples = (sample_rate as f64 * length).floor() as uint;
    let mut samples: Vec<f64> = Vec::with_capacity(num_samples);

    for i in range(0u, num_samples) {
        let t = i as f64 / sample_rate as f64;
        samples.push(midi_frequency_function(t));
    }

    normalize(samples)
}
<|endoftext|>


<commit_before>extern crate syn;
extern crate walkdir;

use std::env;
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;
use syn::visit::Visitor;

fn main() {
    // Parse all .rs files to collect everything which implements Command.
    // This code won't work properly with lib.rs or mod.rs.
    let mut commands = Vec::new();

    for entry in walkdir::WalkDir::new("src")
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|e| !e.file_type().is_dir()) {
        let mut path = String::new();

        for name in entry.path().with_extension("").iter().skip(1) {
            path.push_str(&format!("::{}", name.to_str().unwrap()));
        }

        commands.extend(get_commands(entry.path())
            .into_iter()
            .map(|c| format!("{}::{}", &path, c)))
    }

    let command_array = make_array(commands);

    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("command_array.rs");
    let mut f = File::create(&dest_path).unwrap();
    write!(f, "{}", command_array).unwrap();

    // Output OUT_DIR for rustdoc in Travis
    let mut f = File::create("out_dir").unwrap();
    write!(f, "{}", out_dir).unwrap();
}

fn get_commands(path: &Path) -> Vec<String> {
    let mut source = String::new();
    File::open(path).unwrap().read_to_string(&mut source).unwrap();

    let _crate = syn::parse_crate(&source).expect("Error parsing the code");

    let mut visitor = CommandVisitor::new();
    visitor.visit_crate(&_crate);

    visitor.commands
}

fn make_array(commands: Vec<String>) -> String {
    let mut buf = format!("pub static COMMANDS: [&Command; {}] = [", commands.len());

    let mut iter = commands.into_iter();

    if let Some(first) = iter.next() {
        buf.push_str(&format!("&{}", first));
    }

    for command in iter {
        buf.push_str(&format!(", &{}", command));
    }

    buf.push_str("];");

    buf
}

struct CommandVisitor {
    commands: Vec<String>,
}

impl CommandVisitor {
    fn new() -> Self {
        Self {
            commands: Vec::new(),
        }
    }
}

impl Visitor for CommandVisitor {
    fn visit_mac(&mut self, mac: &syn::Mac) {
        if mac.path == "command".into() {
            if let Some(&syn::TokenTree::Delimited(ref delimited)) = mac.tts.iter().next() {
                if let Some(&syn::TokenTree::Token(ref token)) = delimited.tts.iter().next() {
                    if let &syn::Token::Ident(ref ident) = token {
                        self.commands.push(ident.as_ref().to_owned());
                    }
                }
            }
        }

        syn::visit::walk_mac(self, mac);
    }
}
<commit_msg>Format build.rs with rustfmt<commit_after>extern crate syn;
extern crate walkdir;

use std::env;
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;
use syn::visit::Visitor;

fn main() {
    // Parse all .rs files to collect everything which implements Command.
    // This code won't work properly with lib.rs or mod.rs.
    let mut commands = Vec::new();

    for entry in walkdir::WalkDir::new("src")
            .into_iter()
            .filter_map(|e| e.ok())
            .filter(|e| !e.file_type().is_dir()) {
        let mut path = String::new();

        for name in entry.path().with_extension("").iter().skip(1) {
            path.push_str(&format!("::{}", name.to_str().unwrap()));
        }

        commands.extend(get_commands(entry.path())
                            .into_iter()
                            .map(|c| format!("{}::{}", &path, c)))
    }

    let command_array = make_array(commands);

    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("command_array.rs");
    let mut f = File::create(&dest_path).unwrap();
    write!(f, "{}", command_array).unwrap();

    // Output OUT_DIR for rustdoc in Travis
    let mut f = File::create("out_dir").unwrap();
    write!(f, "{}", out_dir).unwrap();
}

fn get_commands(path: &Path) -> Vec<String> {
    let mut source = String::new();
    File::open(path)
        .unwrap()
        .read_to_string(&mut source)
        .unwrap();

    let _crate = syn::parse_crate(&source).expect("Error parsing the code");

    let mut visitor = CommandVisitor::new();
    visitor.visit_crate(&_crate);

    visitor.commands
}

fn make_array(commands: Vec<String>) -> String {
    let mut buf = format!("pub static COMMANDS: [&Command; {}] = [", commands.len());

    let mut iter = commands.into_iter();

    if let Some(first) = iter.next() {
        buf.push_str(&format!("&{}", first));
    }

    for command in iter {
        buf.push_str(&format!(", &{}", command));
    }

    buf.push_str("];");

    buf
}

struct CommandVisitor {
    commands: Vec<String>,
}

impl CommandVisitor {
    fn new() -> Self {
        Self { commands: Vec::new() }
    }
}

impl Visitor for CommandVisitor {
    fn visit_mac(&mut self, mac: &syn::Mac) {
        if mac.path == "command".into() {
            if let Some(&syn::TokenTree::Delimited(ref delimited)) = mac.tts.iter().next() {
                if let Some(&syn::TokenTree::Token(ref token)) = delimited.tts.iter().next() {
                    if let &syn::Token::Ident(ref ident) = token {
                        self.commands.push(ident.as_ref().to_owned());
                    }
                }
            }
        }

        syn::visit::walk_mac(self, mac);
    }
}
<|endoftext|>


<commit_before>pub mod syscall_table;

use libc;
use std::ffi::CStr;
use std::{ptr, slice};
use std::mem::size_of;
use std::collections::HashMap;
use chrono::{DateTime, UTC};
use value::Value;

#[repr(C, packed)]
pub struct SyscallHdr {
    /// timestamp in nanoseconds from epoch
    pub ts: u64,
    /// the thread id that generated the syscall
    pub tid: u64,
    /// length of the syscall + header
    pub len: u32,
    /// the identifier of the syscall
    pub id: u16
}

pub struct SyscallMeta {
    /// name of the system call
    pub name: &'static str,
    /// syscall category
    pub category: Category,
    /// flags for this syscall
    pub flags: Vec<Flags>,
    /// the number of parameters
    pub nparams: usize,
    /// the list of syscall's parameters
    pub params: Vec<SyscallParam>
}

pub struct SyscallParam {
    /// parameter name
    pub name: &'static str,
    /// parameter type
    pub kind: ParamType,
    /// parameter rendering format
    pub fmt: ParamFormat
}

#[derive(Serialize, Debug)]
pub struct Syscall {
    /// timestamp expressed as UTC date/time structure
    pub ts: DateTime<UTC>,
    /// name of the system call
    pub name: String,
    /// syscall's parameter map
    pub params: HashMap<String, Value>

}

/// determines the syscall category
pub enum Category {
    Unknown,
    Other,
    File,
    Net,
    IPC,
    Memory,
    Process,
    Sleep,
    System,
    Signal,
    User,
    Time,
    Processing,
    IOBase,
    IORead,
    IOWrite,
    IOOther,
    Wait,
    Scheduler,
    Internal

}

pub enum Flags {
    None,
    CreatesFd,
    DestroysFd,
    UsesFd,
    ReadsFromFd,
    WritesToFd,
    ModifiesState,
    Unused,
    Waits,
    SkipParser,
    OldVesion

}

pub enum ParamType {
    None,
    Int8,
    Int16,
    Int32,
    Int64,
    UInt8,
    UInt16,
    UInt32,
    UInt64,
    /// a NULL terminated printable buffer of bytes
    CharBuffer,
    ByteBuffer,
    ErrNo,
    SockAddr,
    SockTuple,
    Fd,
    Pid,
    FdList,
    FsPath,
    SyscallId,
    SigType,
    /// a relative time
    RelTime,
    /// an absolute time interval
    AbsTime,
    Port,
    L4Proto,
    SockFamily,
    Bool,
    Ipv4Addr,
    Dyn,
    Flags8,
    Flags16,
    Flags32,
    Uid,
    Gid,
    Double,
    Sigset,
    CharBufferArray,
    CharBufferPairArray,
    Ipv4Net
}

pub enum ParamFormat {
    Na,
    Dec,
    Hex,
    PaddedDec,
    Id,
    Dir
}

pub enum Direction {
    Enter,
    Exit
}

impl SyscallMeta {
    /// Populates the syscall parameter map by applying pointer arithmetic
    /// operations on the system call header structure. The parameter's buffer is extracted
    /// from the slice which is constructed from syscall header structure pointer
    /// and the number of parameters.
    /// For each parameter found in the slice, the parsing stage is delegated to
    /// the `SyscallParam::parse` method. The return value of the previous method is being put into
    /// the hash map and indexed by parameter name.
    ///
    pub fn build_params<'a>(&self, syscall_hdr: *mut SyscallHdr) -> HashMap<String, Value> {
        let mut params = HashMap::<String, Value>::default();
        unsafe {
            let lens = syscall_hdr.offset(1) as *const u16;
            let mut buf = lens.offset(self.nparams as isize) as *const u8;
            let mut i = 0;

            for len in slice::from_raw_parts(lens, self.nparams) {
                let ref param = self.params[i];
                params.insert(param.name.to_string(), param.parse(buf));
                buf = buf.offset(*len as isize);
                i += 1;
            }
        }
        params
    }
}

impl SyscallParam {
    /// Transforms the raw buffer which contains the parameter value to a native
    /// data type suitable for serialization.
    pub fn parse(&self, buf: *const u8) -> Value {
        match self.kind {
            ParamType::Int8 => {
                unsafe { Value::Int8(*(buf as *const i8)) }
            },
            ParamType::Int16 => {
                unsafe { Value::Int16(*(buf as *const i16)) }
            },
            ParamType::Int32 => {
                unsafe { Value::Int32(*(buf as *const i32)) }
            },
            ParamType::Int64 => {
                unsafe { Value::Int64(*(buf as *const i64)) }
            },
            ParamType::UInt8 => {
                unsafe { Value::UInt8(*(buf as *const u8)) }
            },
            ParamType::UInt16 => {
                unsafe { Value::UInt16(*(buf as *const u16)) }
            },
            ParamType::UInt32 => {
                unsafe { Value::UInt32(*(buf as *const u32)) }
            },
            ParamType::UInt64 => {
                unsafe { Value::UInt64(*(buf as *const u64)) }
            },
            ParamType::FsPath => {
                Value::String(self.to_string(buf))
            },
            ParamType::ErrNo => {
                unsafe { Value::Int64(*(buf as *const i64)) }
            },
            ParamType::Fd => {
                unsafe { Value::Int64(*(buf as *const i64)) }
            },
            ParamType::Pid => {
                unsafe { Value::Int64(*(buf as *const i64)) }
            },
            ParamType::Uid | ParamType::Gid  => {
                unsafe { Value::UInt32(*(buf as *const u32)) }
            },
            ParamType::SyscallId => {
                unsafe { Value::UInt16(*(buf as *const u16)) }
            },
            ParamType::CharBuffer => {
                Value::String(self.to_string(buf))
            },
            ParamType::ByteBuffer => {
                Value::String(self.to_string(buf))
            }
            _ => Value::None
        }
    }

    fn to_string(&self, buf: *const u8) -> String {
        unsafe {
            CStr::from_ptr(buf as *const libc::c_char).to_string_lossy().into_owned()
        }
    }
}<commit_msg>removed unused lifetime parameter<commit_after>pub mod syscall_table;

use libc;
use std::ffi::CStr;
use std::{ptr, slice};
use std::mem::size_of;
use std::collections::HashMap;
use chrono::{DateTime, UTC};
use value::Value;

#[repr(C, packed)]
pub struct SyscallHdr {
    /// timestamp in nanoseconds from epoch
    pub ts: u64,
    /// the thread id that generated the syscall
    pub tid: u64,
    /// length of the syscall + header
    pub len: u32,
    /// the identifier of the syscall
    pub id: u16
}

pub struct SyscallMeta {
    /// name of the system call
    pub name: &'static str,
    /// syscall category
    pub category: Category,
    /// flags for this syscall
    pub flags: Vec<Flags>,
    /// the number of parameters
    pub nparams: usize,
    /// the list of syscall's parameters
    pub params: Vec<SyscallParam>
}

pub struct SyscallParam {
    /// parameter name
    pub name: &'static str,
    /// parameter type
    pub kind: ParamType,
    /// parameter rendering format
    pub fmt: ParamFormat
}

#[derive(Serialize, Debug)]
pub struct Syscall {
    /// timestamp expressed as UTC date/time structure
    pub ts: DateTime<UTC>,
    /// name of the system call
    pub name: String,
    /// syscall's parameter map
    pub params: HashMap<String, Value>

}

/// determines the syscall category
pub enum Category {
    Unknown,
    Other,
    File,
    Net,
    IPC,
    Memory,
    Process,
    Sleep,
    System,
    Signal,
    User,
    Time,
    Processing,
    IOBase,
    IORead,
    IOWrite,
    IOOther,
    Wait,
    Scheduler,
    Internal

}

pub enum Flags {
    None,
    CreatesFd,
    DestroysFd,
    UsesFd,
    ReadsFromFd,
    WritesToFd,
    ModifiesState,
    Unused,
    Waits,
    SkipParser,
    OldVesion

}

pub enum ParamType {
    None,
    Int8,
    Int16,
    Int32,
    Int64,
    UInt8,
    UInt16,
    UInt32,
    UInt64,
    /// a NULL terminated printable buffer of bytes
    CharBuffer,
    ByteBuffer,
    ErrNo,
    SockAddr,
    SockTuple,
    Fd,
    Pid,
    FdList,
    FsPath,
    SyscallId,
    SigType,
    /// a relative time
    RelTime,
    /// an absolute time interval
    AbsTime,
    Port,
    L4Proto,
    SockFamily,
    Bool,
    Ipv4Addr,
    Dyn,
    Flags8,
    Flags16,
    Flags32,
    Uid,
    Gid,
    Double,
    Sigset,
    CharBufferArray,
    CharBufferPairArray,
    Ipv4Net
}

pub enum ParamFormat {
    Na,
    Dec,
    Hex,
    PaddedDec,
    Id,
    Dir
}

pub enum Direction {
    Enter,
    Exit
}

impl SyscallMeta {
    /// Populates the syscall parameter map by applying pointer arithmetic
    /// operations on the system call header structure. The parameter's buffer is extracted
    /// from the slice which is constructed from syscall header structure pointer
    /// and the number of parameters.
    /// For each parameter found in the slice, the parsing stage is delegated to
    /// the `SyscallParam::parse` method. The return value of the previous method is being put into
    /// the hash map and indexed by parameter name.
    ///
    pub fn build_params(&self, syscall_hdr: *mut SyscallHdr) -> HashMap<String, Value> {
        let mut params = HashMap::<String, Value>::default();
        unsafe {
            let lens = syscall_hdr.offset(1) as *const u16;
            let mut buf = lens.offset(self.nparams as isize) as *const u8;
            let mut i = 0;

            for len in slice::from_raw_parts(lens, self.nparams) {
                let ref param = self.params[i];
                params.insert(param.name.to_string(), param.parse(buf));
                buf = buf.offset(*len as isize);
                i += 1;
            }
        }
        params
    }
}

impl SyscallParam {
    /// Transforms the raw buffer which contains the parameter value to a native
    /// data type suitable for serialization.
    pub fn parse(&self, buf: *const u8) -> Value {
        match self.kind {
            ParamType::Int8 => {
                unsafe { Value::Int8(*(buf as *const i8)) }
            },
            ParamType::Int16 => {
                unsafe { Value::Int16(*(buf as *const i16)) }
            },
            ParamType::Int32 => {
                unsafe { Value::Int32(*(buf as *const i32)) }
            },
            ParamType::Int64 => {
                unsafe { Value::Int64(*(buf as *const i64)) }
            },
            ParamType::UInt8 => {
                unsafe { Value::UInt8(*(buf as *const u8)) }
            },
            ParamType::UInt16 => {
                unsafe { Value::UInt16(*(buf as *const u16)) }
            },
            ParamType::UInt32 => {
                unsafe { Value::UInt32(*(buf as *const u32)) }
            },
            ParamType::UInt64 => {
                unsafe { Value::UInt64(*(buf as *const u64)) }
            },
            ParamType::FsPath => {
                Value::String(self.to_string(buf))
            },
            ParamType::ErrNo => {
                unsafe { Value::Int64(*(buf as *const i64)) }
            },
            ParamType::Fd => {
                unsafe { Value::Int64(*(buf as *const i64)) }
            },
            ParamType::Pid => {
                unsafe { Value::Int64(*(buf as *const i64)) }
            },
            ParamType::Uid | ParamType::Gid  => {
                unsafe { Value::UInt32(*(buf as *const u32)) }
            },
            ParamType::SyscallId => {
                unsafe { Value::UInt16(*(buf as *const u16)) }
            },
            ParamType::CharBuffer => {
                Value::String(self.to_string(buf))
            },
            ParamType::ByteBuffer => {
                Value::String(self.to_string(buf))
            }
            _ => Value::None
        }
    }

    fn to_string(&self, buf: *const u8) -> String {
        unsafe {
            CStr::from_ptr(buf as *const libc::c_char).to_string_lossy().into_owned()
        }
    }
}<|endoftext|>


<commit_before>#![allow(unused_variables)]

extern crate bindgen;
extern crate make_cmd;

use make_cmd::make;

use std::env;
use std::path::Path;
use std::process::Command;

const LIBSIXEL_DIR: &str = "libsixel";

fn main() {

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(&out_dir);

    println!("cargo:rustc-link-lib=dylib=sixel");
    // println!("cargo:rustc-link-lib=static=sixel");
    println!("cargo:rustc-link-search=native={}", out_dir.join("lib").display());

    if 1 == 1 {
        return;
    }

    let curl = has_feature("curl");
    let jpeg = has_feature("jpeg");
    let pixbuf = has_feature("pixbuf");
    let png = has_feature("png");
    let gd = has_feature("gd");
    let python_interface = has_feature("python_interface");

    let sixel_dir = Path::new(LIBSIXEL_DIR);

    {
        let mut cmd = Command::new("./configure");
        cmd.current_dir(sixel_dir)
            .arg("--prefix")
            .arg(out_dir);

        // cmd.arg("-fPIC");

        if curl {
            cmd.arg("--with-libcurl");
        }
        if gd {
            cmd.arg("--with-gd");
        }
        if pixbuf {
            cmd.arg("--with-gdk-pixbuf");
        }
        if jpeg {
            cmd.arg("--with-jpeg");
        }
        if png {
            cmd.arg("--with-png");
        }
        if !python_interface {
            cmd.arg("--without-python");
        }

        cmd.status().expect("Failed to execute ./configure");

        make()
            .arg("install")
            .current_dir(sixel_dir)
            .status().expect("Failed to execute make");

    }

    let bindings = bindgen::Builder::default()
        .no_unstable_rust()
        .header("wrapper.h")
        .hide_type("max_align_t")
        .generate()
        .expect("Unable to generate bindings");

    bindings
        .write_to_file(out_dir.join("bindings.rs"))
        .expect("Couldn't write bindings");
}

const FEATURE_PREFIX: &str = "CARGO_FEATURE_";
fn has_feature(feature: &'static str) -> bool {
    let feature = feature.to_owned().to_uppercase();
    let mut name = FEATURE_PREFIX.to_owned();
    name.push_str(&feature);
    env::var(name).is_ok()
}
<commit_msg>Remove short-circuit in build script<commit_after>#![allow(unused_variables)]

extern crate bindgen;
extern crate make_cmd;

use make_cmd::make;

use std::env;
use std::path::Path;
use std::process::Command;

const LIBSIXEL_DIR: &str = "libsixel";

fn main() {

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(&out_dir);

    println!("cargo:rustc-link-lib=dylib=sixel");
    // println!("cargo:rustc-link-lib=static=sixel");
    println!("cargo:rustc-link-search=native={}", out_dir.join("lib").display());

    let curl = has_feature("curl");
    let jpeg = has_feature("jpeg");
    let pixbuf = has_feature("pixbuf");
    let png = has_feature("png");
    let gd = has_feature("gd");
    let python_interface = has_feature("python_interface");

    let sixel_dir = Path::new(LIBSIXEL_DIR);

    {
        let mut cmd = Command::new("./configure");
        cmd.current_dir(sixel_dir)
            .arg("--prefix")
            .arg(out_dir);

        // cmd.arg("-fPIC");

        if curl {
            cmd.arg("--with-libcurl");
        }
        if gd {
            cmd.arg("--with-gd");
        }
        if pixbuf {
            cmd.arg("--with-gdk-pixbuf");
        }
        if jpeg {
            cmd.arg("--with-jpeg");
        }
        if png {
            cmd.arg("--with-png");
        }
        if !python_interface {
            cmd.arg("--without-python");
        }

        cmd.status().expect("Failed to execute ./configure");

        make()
            .arg("install")
            .current_dir(sixel_dir)
            .status().expect("Failed to execute make");

    }

    let bindings = bindgen::Builder::default()
        .no_unstable_rust()
        .header("wrapper.h")
        .hide_type("max_align_t")
        .generate()
        .expect("Unable to generate bindings");

    bindings
        .write_to_file(out_dir.join("bindings.rs"))
        .expect("Couldn't write bindings");
}

const FEATURE_PREFIX: &str = "CARGO_FEATURE_";
fn has_feature(feature: &'static str) -> bool {
    let feature = feature.to_owned().to_uppercase();
    let mut name = FEATURE_PREFIX.to_owned();
    name.push_str(&feature);
    env::var(name).is_ok()
}
<|endoftext|>


<commit_before>
use Error;
use Result;
use std::io::Cursor;
use byteorder::{BigEndian, ReadBytesExt};

/// A record of horizontal metrics.
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct LongHorizontalMetric {
    pub advance_width: u16,
    pub left_side_bearing: i16,
}

/// A table of horizontal metrics.
///
/// The 'hmtx' table contains metric information for the horizontal layout
/// each of the glyphs in the font.
#[derive(Debug, Default)]
pub struct HMTX {
    metrics: Vec<LongHorizontalMetric>,
    left_side_bearings: Vec<i16>,
}

impl HMTX {
    /// Returns `hmtx` font table.
    ///
    /// Attempts to read `data` starting from `offset` position.
    /// `metrics` is a number of long horizontal metrics taken from `hhea`
    /// font table.
    /// `glyphs` is a number of glyphs in the font.
    ///
    /// # Errors
    /// Returns error if there is not enough data to read or the number of
    /// `metrics` is greater than the number of `glyphs`.
    pub fn from_data(data: &[u8], offset: usize, metrics: usize, glyphs: usize) -> Result<HMTX> {
        if offset >= data.len() {
            return Err(Error::Malformed);
        }
        if metrics > glyphs {
            return Err(Error::Malformed);
        }
        let bearings = glyphs - metrics;

        let mut hmtx = HMTX {
            metrics: Vec::with_capacity(metrics),
            left_side_bearings: Vec::with_capacity(bearings),
        };

        let mut cursor = Cursor::new(&data[offset..]);
        for _ in 0..metrics {
            let w = try!(cursor.read_u16::<BigEndian>());
            let b = try!(cursor.read_i16::<BigEndian>());
            hmtx.metrics.push(LongHorizontalMetric { advance_width: w, left_side_bearing: b });
        }

        for _ in 0..bearings {
            hmtx.left_side_bearings.push(try!(cursor.read_i16::<BigEndian>()));
        }

        Ok(hmtx)
    }

    #[cfg(test)]
    fn bytes(&self) -> Vec<u8> {
        use byteorder::WriteBytesExt;

        let mut data = vec![];
        for metric in &self.metrics {
            data.write_u16::<BigEndian>(metric.advance_width).unwrap();
            data.write_i16::<BigEndian>(metric.left_side_bearing).unwrap();
        }
        for &bearing in &self.left_side_bearings {
            data.write_i16::<BigEndian>(bearing).unwrap();
        }
        data
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use Error::*;
    use expectest::prelude::*;

    #[test]
    fn smoke() {

    }
}
<commit_msg>Implement unit test for hmtx font table.<commit_after>
use Error;
use Result;
use std::io::Cursor;
use byteorder::{BigEndian, ReadBytesExt};

/// A record of horizontal metrics.
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct LongHorizontalMetric {
    pub advance_width: u16,
    pub left_side_bearing: i16,
}

/// A table of horizontal metrics.
///
/// The 'hmtx' table contains metric information for the horizontal layout
/// each of the glyphs in the font.
#[derive(Debug, Default)]
pub struct HMTX {
    metrics: Vec<LongHorizontalMetric>,
    left_side_bearings: Vec<i16>,
}

impl HMTX {
    /// Returns `hmtx` font table.
    ///
    /// Attempts to read `data` starting from `offset` position.
    /// `metrics` is a number of long horizontal metrics taken from `hhea`
    /// font table.
    /// `glyphs` is a number of glyphs in the font.
    ///
    /// # Errors
    /// Returns error if there is not enough data to read or the number of
    /// `metrics` is greater than the number of `glyphs`.
    pub fn from_data(data: &[u8], offset: usize, metrics: u32, glyphs: u32) -> Result<HMTX> {
        if offset >= data.len() {
            return Err(Error::Malformed);
        }
        if metrics > glyphs {
            return Err(Error::Malformed);
        }
        let bearings = glyphs - metrics;

        let mut hmtx = HMTX {
            metrics: Vec::with_capacity(metrics as usize),
            left_side_bearings: Vec::with_capacity(bearings as usize),
        };

        let mut cursor = Cursor::new(&data[offset..]);
        for _ in 0..metrics {
            let w = try!(cursor.read_u16::<BigEndian>());
            let b = try!(cursor.read_i16::<BigEndian>());
            hmtx.metrics.push(LongHorizontalMetric { advance_width: w, left_side_bearing: b });
        }

        for _ in 0..bearings {
            hmtx.left_side_bearings.push(try!(cursor.read_i16::<BigEndian>()));
        }

        Ok(hmtx)
    }

    #[cfg(test)]
    fn bytes(&self) -> Vec<u8> {
        use byteorder::WriteBytesExt;

        let mut data = vec![];
        for metric in &self.metrics {
            data.write_u16::<BigEndian>(metric.advance_width).unwrap();
            data.write_i16::<BigEndian>(metric.left_side_bearing).unwrap();
        }
        for &bearing in &self.left_side_bearings {
            data.write_i16::<BigEndian>(bearing).unwrap();
        }
        data
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use Error::*;
    use tables::{HHEA, MAXP};
    use expectest::prelude::*;

    #[test]
    fn smoke() {
        let data = ::utils::read_file("tests/Tuffy_Bold.ttf");
        let hhea_offset = ::utils::find_table_offset(&data, 0, b"hhea").unwrap().unwrap();
        let metrics = HHEA::from_data(&data, hhea_offset).unwrap().num_of_long_hor_metrics();
        let maxp_offset = ::utils::find_table_offset(&data, 0, b"maxp").unwrap().unwrap();
        let glyphs = MAXP::from_data(&data, maxp_offset).unwrap().num_glyphs();

        let size = (metrics * 4 + (glyphs - metrics) * 2) as usize;
        let hmtx_offset = ::utils::find_table_offset(&data, 0, b"hmtx").unwrap().unwrap();
        let hmtx = HMTX::from_data(&data, hmtx_offset, metrics, glyphs).unwrap();
        assert_eq!(hmtx.bytes(), &data[hmtx_offset..hmtx_offset + size]);

        expect!(HMTX::from_data(&data, data.len(), metrics, glyphs)).to(be_err().value(Malformed));
        expect!(HMTX::from_data(&data, hmtx_offset, 1, 0)).to(be_err().value(Malformed));
    }
}
<|endoftext|>


<commit_before>use super::Token;
use std::char;

pub struct TokenCollection {
    pub open_brace: Token,
    pub close_brace: Token,
    pub open_bracket: Token,
    pub close_bracket: Token,
    pub comma: Token,
    pub colon: Token,
    pub identifier: Token,
    pub stringlit: Token,
    pub integerlit: Token,
    pub floatlit: Token,
}

impl TokenCollection {
    pub fn new() -> Self {
        TokenCollection {
            open_brace: Token::new(r"\{").unwrap(),
            close_brace: Token::new(r"\}").unwrap(),
            open_bracket: Token::new(r"\[").unwrap(),
            close_bracket: Token::new(r"\]").unwrap(),
            comma: Token::new(r",").unwrap(),
            colon: Token::new(r":").unwrap(),
            identifier: Token::new(r#"(?x)
                [
                    \p{L} # letters
                    \p{M} # combining marks
                    \p{Pc} # connector punctuation (e.g. _)
                ]
                \w* # all word characters
            "#).unwrap(),
            stringlit: Token::new(r#"(?x)
                  "(?: [^"\n\\] | \\n | \\r | \\t | \\\\ | \\b
                    | \\f | \\/ | \\" | \\' | \\u[0-9a-fA-F]{4} )*"
                | '(?: [^'\n\\] | \\n | \\r | \\t | \\\\ | \\b
                    | \\f | \\/ | \\" | \\' | \\u[0-9a-fA-F]{4} )*'
            "#).unwrap(),
            integerlit: Token::new(r#"(?x)
                  0[xX][0-9a-fA-F_]+
                | 0[oO][0-8_]+
                | 0[bB][10_]+
                | 0[dD][\d_]+
                | [+-]?[\d_]+
            "#).unwrap(),
            floatlit: Token::new(r#"(?x)
                [-+]? # optional sign
                (?:
                      \d+\.\d*  # numbers <dot> <optional numbers>
                    | \.\d+     # <dot> numbers
                )
                (?:
                    [eE]  # begin exponent
                    [+-]? # sign
                    \d+   # exponent
                )? # optional exponent part
            "#).unwrap(),
        }
    }
}

pub fn parse_string(inp: String) -> String {
    let mut escaped = false;
    let mut unicode = false;
    let mut uindex = 0;
    let mut uvalue = 0;
    let quote_char = inp.chars().next().expect("parse_string is parsing an empty string");
    inp.chars().filter_map(|character| {
        if escaped {
            escaped = false;
            match character {
                'n' => Some('\n'),
                'r' => Some('\r'),
                't' => Some('\t'),
                'b' => Some('\x08'),
                'f' => Some('\x0c'),
                'u' => { unicode = true; uvalue = 0; uindex = 0; None }
                 _  => Some(character),
            }
        } else if unicode {
            // code adapted from https://github.com/rust-lang/rustc-serialize/blob/master/src/json.rs#L1608-L1624
            // original licensed under MIT/Apache-2.0
            uvalue = match character {
                ctr @ '0'...'9' => uvalue * 16 + ((ctr as u16) - ('0' as u16)),
                ctr @ 'a'...'f' => uvalue * 16 + (10 + (ctr as u16) - ('a' as u16)),
                ctr @ 'A'...'F' => uvalue * 16 + (10 + (ctr as u16) - ('A' as u16)),
                _ => return None,
            };
            if uindex < 3 {
                uindex += 1;
                None
            } else {
                unicode = false;
                char::from_u32(uvalue as u32)
            }
        } else if character == quote_char {
            None
        } else if character == '\\' {
            escaped = true;
            None
        } else {
            Some(character)
        }
    }).collect()
}

pub fn parse_integer(inp: String) -> i64 {
    if inp.starts_with("0d") || inp.starts_with("0D") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 10).unwrap()
    } else if inp.starts_with("0x") || inp.starts_with("0X") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 16).unwrap()
    } else if inp.starts_with("0o") || inp.starts_with("0O") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 8).unwrap()
    } else if inp.starts_with("0b") || inp.starts_with("0B") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 2).unwrap()
    } else if inp.starts_with("+") {
        i64::from_str_radix(&inp.chars().skip(1).collect::<String>(), 10).unwrap()
    } else {
        i64::from_str_radix(&inp, 10).unwrap()
    }
}

pub fn parse_float(inp: String) -> f64 {
    if inp.starts_with("+") {
        inp.chars().skip(1).collect::<String>().parse().unwrap()
    } else {
       inp.parse().unwrap()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_string() {
        assert_eq!(parse_string("'hello'".to_string()), "hello");
        assert_eq!(parse_string(r#""hello""#.to_string()), "hello");
        assert_eq!(parse_string("'he\\nllo'".to_string()), "he\nllo");
        assert_eq!(parse_string(r#"'he"llo'"#.to_string()), "he\"llo");
        assert_eq!(parse_string(r"'\u0058'".to_string()), "\u{0058}");
    }

    #[test]
    fn test_parse_integer() {
        assert_eq!(parse_integer("0d5".to_string()), 5);
        assert_eq!(parse_integer("0D5474".to_string()), 5474);
        assert_eq!(parse_integer("0x4f3".to_string()), 0x4f3);
        assert_eq!(parse_integer("0X7Df31".to_string()), 0x7df31);
        assert_eq!(parse_integer("0o443".to_string()), 3 + (8*4) + (64*4));
        assert_eq!(parse_integer("0O70131".to_string()), 28761);
        assert_eq!(parse_integer("0b01101".to_string()), 0b01101);
        assert_eq!(parse_integer("0B10010".to_string()), 0b10010);
        assert_eq!(parse_integer("32353".to_string()), 32353);
        assert_eq!(parse_integer("-1234".to_string()), -1234);
        assert_eq!(parse_integer("+4321".to_string()), 4321);
    }

    #[test]
    fn test_parse_float() {
        println!("run");
        assert_eq!(parse_float("+1.2".to_string()), 1.2);
        println!("run");
        assert_eq!(parse_float("-1.2".to_string()), -1.2);
        println!("run");
        assert_eq!(parse_float("3.4".to_string()), 3.4);
        println!("run");
        assert_eq!(parse_float("3.".to_string()), 3.0);
        println!("run");
        assert_eq!(parse_float(".2".to_string()), 0.2);
        println!("run");
        assert_eq!(parse_float("1.2e2".to_string()), 1.2E+2);
        println!("run");
        assert_eq!(parse_float("1.2e+2".to_string()), 1.2E+2);
        println!("run");
        assert_eq!(parse_float("1.2e-2".to_string()), 1.2E-2);
        println!("run");
        assert_eq!(parse_float("1.2E2".to_string()), 1.2E+2);
        println!("run");
        assert_eq!(parse_float("1.2E+2".to_string()), 1.2E+2);
        println!("run");
        assert_eq!(parse_float("1.2E-2".to_string()), 1.2E-2);
    }

    #[test]
    fn literals_match() {
        let tk = TokenCollection::new();
        assert_eq!(tk.open_brace.get_match("{"), Some(1));
        assert_eq!(tk.open_brace.get_match("}"), None);
        assert_eq!(tk.close_brace.get_match("}"), Some(1));
        assert_eq!(tk.close_brace.get_match("d"), None);
        assert_eq!(tk.open_bracket.get_match("["), Some(1));
        assert_eq!(tk.open_bracket.get_match(" "), None);
        assert_eq!(tk.close_bracket.get_match("]"), Some(1));
        assert_eq!(tk.close_bracket.get_match("["), None);
        assert_eq!(tk.comma.get_match(","), Some(1));
        assert_eq!(tk.comma.get_match(""), None);
        assert_eq!(tk.colon.get_match(":"), Some(1));
        assert_eq!(tk.colon.get_match(";"), None);
    }

    #[test]
    fn identifier_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.identifier.get_match("hello"), Some(5));
        assert_eq!(tk.identifier.get_match("HELLO"), Some(5));
        assert_eq!(tk.identifier.get_match("45fefe"), None);
        assert_eq!(tk.identifier.get_match("fefe45"), Some(6));
        assert_eq!(tk.identifier.get_match("true"), Some(4));
        assert_eq!(tk.identifier.get_match("$"), None);
    }

    #[test]
    fn string_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.stringlit.get_match(""), None);
        assert_eq!(tk.stringlit.get_match("hello"), None);
        assert_eq!(tk.stringlit.get_match("'hello'"), Some(7));
        assert_eq!(tk.stringlit.get_match("{}[],: 'string'"), None);
        assert_eq!(tk.stringlit.get_match(r#""hello""#), Some(7));
        assert_eq!(tk.stringlit.get_match(r"'hello\n'"), Some(9));
        assert_eq!(tk.stringlit.get_match(r"'hello\''"), Some(9));
        assert_eq!(tk.stringlit.get_match(r"'
            no newline in strings'"), None);
    }

    #[test]
    fn integer_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.integerlit.get_match("345"), Some(3));
        assert_eq!(tk.integerlit.get_match("3_4_5"), Some(5));
        assert_eq!(tk.integerlit.get_match("0d3_4_5"), Some(7));
        assert_eq!(tk.integerlit.get_match("0x45"), Some(4));
        assert_eq!(tk.integerlit.get_match("0Xff"), Some(4));
        assert_eq!(tk.integerlit.get_match("0xf_f"), Some(5));
        assert_eq!(tk.integerlit.get_match("0xgg"), Some(1));
        assert_eq!(tk.integerlit.get_match("0o44"), Some(4));
        assert_eq!(tk.integerlit.get_match("0O44"), Some(4));
        assert_eq!(tk.integerlit.get_match("0o99"), Some(1));
    }

    #[test]
    fn float_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.floatlit.get_match("300."), Some(4));
        assert_eq!(tk.floatlit.get_match("30.0"), Some(4));
        assert_eq!(tk.floatlit.get_match(".300"), Some(4));
        assert_eq!(tk.floatlit.get_match("300"), None);
        assert_eq!(tk.floatlit.get_match("3.e5"), Some(4));
        assert_eq!(tk.floatlit.get_match("3.e-5"), Some(5));
        assert_eq!(tk.floatlit.get_match("3.E-5"), Some(5));
    }
}
<commit_msg>Remove extraneous print statements<commit_after>use super::Token;
use std::char;

pub struct TokenCollection {
    pub open_brace: Token,
    pub close_brace: Token,
    pub open_bracket: Token,
    pub close_bracket: Token,
    pub comma: Token,
    pub colon: Token,
    pub identifier: Token,
    pub stringlit: Token,
    pub integerlit: Token,
    pub floatlit: Token,
}

impl TokenCollection {
    pub fn new() -> Self {
        TokenCollection {
            open_brace: Token::new(r"\{").unwrap(),
            close_brace: Token::new(r"\}").unwrap(),
            open_bracket: Token::new(r"\[").unwrap(),
            close_bracket: Token::new(r"\]").unwrap(),
            comma: Token::new(r",").unwrap(),
            colon: Token::new(r":").unwrap(),
            identifier: Token::new(r#"(?x)
                [
                    \p{L} # letters
                    \p{M} # combining marks
                    \p{Pc} # connector punctuation (e.g. _)
                ]
                \w* # all word characters
            "#).unwrap(),
            stringlit: Token::new(r#"(?x)
                  "(?: [^"\n\\] | \\n | \\r | \\t | \\\\ | \\b
                    | \\f | \\/ | \\" | \\' | \\u[0-9a-fA-F]{4} )*"
                | '(?: [^'\n\\] | \\n | \\r | \\t | \\\\ | \\b
                    | \\f | \\/ | \\" | \\' | \\u[0-9a-fA-F]{4} )*'
            "#).unwrap(),
            integerlit: Token::new(r#"(?x)
                  0[xX][0-9a-fA-F_]+
                | 0[oO][0-8_]+
                | 0[bB][10_]+
                | 0[dD][\d_]+
                | [+-]?[\d_]+
            "#).unwrap(),
            floatlit: Token::new(r#"(?x)
                [-+]? # optional sign
                (?:
                      \d+\.\d*  # numbers <dot> <optional numbers>
                    | \.\d+     # <dot> numbers
                )
                (?:
                    [eE]  # begin exponent
                    [+-]? # sign
                    \d+   # exponent
                )? # optional exponent part
            "#).unwrap(),
        }
    }
}

pub fn parse_string(inp: String) -> String {
    let mut escaped = false;
    let mut unicode = false;
    let mut uindex = 0;
    let mut uvalue = 0;
    let quote_char = inp.chars().next().expect("parse_string is parsing an empty string");
    inp.chars().filter_map(|character| {
        if escaped {
            escaped = false;
            match character {
                'n' => Some('\n'),
                'r' => Some('\r'),
                't' => Some('\t'),
                'b' => Some('\x08'),
                'f' => Some('\x0c'),
                'u' => { unicode = true; uvalue = 0; uindex = 0; None }
                 _  => Some(character),
            }
        } else if unicode {
            // code adapted from https://github.com/rust-lang/rustc-serialize/blob/master/src/json.rs#L1608-L1624
            // original licensed under MIT/Apache-2.0
            uvalue = match character {
                ctr @ '0'...'9' => uvalue * 16 + ((ctr as u16) - ('0' as u16)),
                ctr @ 'a'...'f' => uvalue * 16 + (10 + (ctr as u16) - ('a' as u16)),
                ctr @ 'A'...'F' => uvalue * 16 + (10 + (ctr as u16) - ('A' as u16)),
                _ => return None,
            };
            if uindex < 3 {
                uindex += 1;
                None
            } else {
                unicode = false;
                char::from_u32(uvalue as u32)
            }
        } else if character == quote_char {
            None
        } else if character == '\\' {
            escaped = true;
            None
        } else {
            Some(character)
        }
    }).collect()
}

pub fn parse_integer(inp: String) -> i64 {
    if inp.starts_with("0d") || inp.starts_with("0D") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 10).unwrap()
    } else if inp.starts_with("0x") || inp.starts_with("0X") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 16).unwrap()
    } else if inp.starts_with("0o") || inp.starts_with("0O") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 8).unwrap()
    } else if inp.starts_with("0b") || inp.starts_with("0B") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 2).unwrap()
    } else if inp.starts_with("+") {
        i64::from_str_radix(&inp.chars().skip(1).collect::<String>(), 10).unwrap()
    } else {
        i64::from_str_radix(&inp, 10).unwrap()
    }
}

pub fn parse_float(inp: String) -> f64 {
    if inp.starts_with("+") {
        inp.chars().skip(1).collect::<String>().parse().unwrap()
    } else {
       inp.parse().unwrap()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_string() {
        assert_eq!(parse_string("'hello'".to_string()), "hello");
        assert_eq!(parse_string(r#""hello""#.to_string()), "hello");
        assert_eq!(parse_string("'he\\nllo'".to_string()), "he\nllo");
        assert_eq!(parse_string(r#"'he"llo'"#.to_string()), "he\"llo");
        assert_eq!(parse_string(r"'\u0058'".to_string()), "\u{0058}");
    }

    #[test]
    fn test_parse_integer() {
        assert_eq!(parse_integer("0d5".to_string()), 5);
        assert_eq!(parse_integer("0D5474".to_string()), 5474);
        assert_eq!(parse_integer("0x4f3".to_string()), 0x4f3);
        assert_eq!(parse_integer("0X7Df31".to_string()), 0x7df31);
        assert_eq!(parse_integer("0o443".to_string()), 3 + (8*4) + (64*4));
        assert_eq!(parse_integer("0O70131".to_string()), 28761);
        assert_eq!(parse_integer("0b01101".to_string()), 0b01101);
        assert_eq!(parse_integer("0B10010".to_string()), 0b10010);
        assert_eq!(parse_integer("32353".to_string()), 32353);
        assert_eq!(parse_integer("-1234".to_string()), -1234);
        assert_eq!(parse_integer("+4321".to_string()), 4321);
    }

    #[test]
    fn test_parse_float() {
        assert_eq!(parse_float("+1.2".to_string()), 1.2);
        assert_eq!(parse_float("-1.2".to_string()), -1.2);
        assert_eq!(parse_float("3.4".to_string()), 3.4);
        assert_eq!(parse_float("3.".to_string()), 3.0);
        assert_eq!(parse_float(".2".to_string()), 0.2);
        assert_eq!(parse_float("1.2e2".to_string()), 1.2E+2);
        assert_eq!(parse_float("1.2e+2".to_string()), 1.2E+2);
        assert_eq!(parse_float("1.2e-2".to_string()), 1.2E-2);
        assert_eq!(parse_float("1.2E2".to_string()), 1.2E+2);
        assert_eq!(parse_float("1.2E+2".to_string()), 1.2E+2);
        assert_eq!(parse_float("1.2E-2".to_string()), 1.2E-2);
    }

    #[test]
    fn literals_match() {
        let tk = TokenCollection::new();
        assert_eq!(tk.open_brace.get_match("{"), Some(1));
        assert_eq!(tk.open_brace.get_match("}"), None);
        assert_eq!(tk.close_brace.get_match("}"), Some(1));
        assert_eq!(tk.close_brace.get_match("d"), None);
        assert_eq!(tk.open_bracket.get_match("["), Some(1));
        assert_eq!(tk.open_bracket.get_match(" "), None);
        assert_eq!(tk.close_bracket.get_match("]"), Some(1));
        assert_eq!(tk.close_bracket.get_match("["), None);
        assert_eq!(tk.comma.get_match(","), Some(1));
        assert_eq!(tk.comma.get_match(""), None);
        assert_eq!(tk.colon.get_match(":"), Some(1));
        assert_eq!(tk.colon.get_match(";"), None);
    }

    #[test]
    fn identifier_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.identifier.get_match("hello"), Some(5));
        assert_eq!(tk.identifier.get_match("HELLO"), Some(5));
        assert_eq!(tk.identifier.get_match("45fefe"), None);
        assert_eq!(tk.identifier.get_match("fefe45"), Some(6));
        assert_eq!(tk.identifier.get_match("true"), Some(4));
        assert_eq!(tk.identifier.get_match("$"), None);
    }

    #[test]
    fn string_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.stringlit.get_match(""), None);
        assert_eq!(tk.stringlit.get_match("hello"), None);
        assert_eq!(tk.stringlit.get_match("'hello'"), Some(7));
        assert_eq!(tk.stringlit.get_match("{}[],: 'string'"), None);
        assert_eq!(tk.stringlit.get_match(r#""hello""#), Some(7));
        assert_eq!(tk.stringlit.get_match(r"'hello\n'"), Some(9));
        assert_eq!(tk.stringlit.get_match(r"'hello\''"), Some(9));
        assert_eq!(tk.stringlit.get_match(r"'
            no newline in strings'"), None);
    }

    #[test]
    fn integer_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.integerlit.get_match("345"), Some(3));
        assert_eq!(tk.integerlit.get_match("3_4_5"), Some(5));
        assert_eq!(tk.integerlit.get_match("0d3_4_5"), Some(7));
        assert_eq!(tk.integerlit.get_match("0x45"), Some(4));
        assert_eq!(tk.integerlit.get_match("0Xff"), Some(4));
        assert_eq!(tk.integerlit.get_match("0xf_f"), Some(5));
        assert_eq!(tk.integerlit.get_match("0xgg"), Some(1));
        assert_eq!(tk.integerlit.get_match("0o44"), Some(4));
        assert_eq!(tk.integerlit.get_match("0O44"), Some(4));
        assert_eq!(tk.integerlit.get_match("0o99"), Some(1));
    }

    #[test]
    fn float_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.floatlit.get_match("300."), Some(4));
        assert_eq!(tk.floatlit.get_match("30.0"), Some(4));
        assert_eq!(tk.floatlit.get_match(".300"), Some(4));
        assert_eq!(tk.floatlit.get_match("300"), None);
        assert_eq!(tk.floatlit.get_match("3.e5"), Some(4));
        assert_eq!(tk.floatlit.get_match("3.e-5"), Some(5));
        assert_eq!(tk.floatlit.get_match("3.E-5"), Some(5));
    }
}
<|endoftext|>


<commit_before>use Configuration;
use deque;
use deque::{Worker, Stealer, Stolen};
use job::JobRef;
use latch::{Latch, LockLatch, SpinLatch};
#[allow(unused_imports)]
use log::Event::*;
use rand;
use std::cell::Cell;
use std::sync::{Arc, Condvar, Mutex, Once, ONCE_INIT};
use std::thread;
use std::collections::VecDeque;
use std::mem;
use util::leak;
use num_cpus;

///////////////////////////////////////////////////////////////////////////

pub struct Registry {
    thread_infos: Vec<ThreadInfo>,
    state: Mutex<RegistryState>,
    work_available: Condvar,
}

struct RegistryState {
    terminate: bool,
    threads_at_work: usize,
    injected_jobs: VecDeque<JobRef>,
}

///////////////////////////////////////////////////////////////////////////
// Initialization

static mut THE_REGISTRY: Option<&'static Registry> = None;
static THE_REGISTRY_SET: Once = ONCE_INIT;

/// Starts the worker threads (if that has not already happened). If
/// initialization has not already occurred, use the default
/// configuration.
pub fn get_registry() -> &'static Registry {
    THE_REGISTRY_SET.call_once(|| unsafe { init_registry(Configuration::new()) });
    unsafe { THE_REGISTRY.unwrap() }
}

/// Starts the worker threads (if that has not already happened) with
/// the given configuration.
pub fn get_registry_with_config(config: Configuration) -> &'static Registry {
    THE_REGISTRY_SET.call_once(|| unsafe { init_registry(config) });
    unsafe { THE_REGISTRY.unwrap() }
}

/// Initializes the global registry with the given configuration.
/// Meant to be called from within the `THE_REGISTRY_SET` once
/// function. Declared `unsafe` because it writes to `THE_REGISTRY` in
/// an unsynchronized fashion.
unsafe fn init_registry(config: Configuration) {
    let registry = leak(Registry::new(config.num_threads()));
    THE_REGISTRY = Some(registry);
}

enum Work {
    None,
    Job(JobRef),
    Terminate,
}

impl Registry {
    pub fn new(num_threads: Option<usize>) -> Arc<Registry> {
        let limit_value = match num_threads {
            Some(value) => value,
            None => num_cpus::get()
        };

        let (workers, stealers) : (Vec<_>, Vec<_>) =
            (0..limit_value).map(|_| deque::new()).unzip();

        let registry = Arc::new(Registry {
            thread_infos: stealers.into_iter().map(|s| ThreadInfo::new(s))
                                          .collect(),
            state: Mutex::new(RegistryState::new()),
            work_available: Condvar::new(),
        });

        for (index, worker) in workers.into_iter().enumerate() {
            let registry = registry.clone();
            thread::spawn(move || unsafe { main_loop(worker, registry, index) });
        }

        registry
    }

    pub fn num_threads(&self) -> usize {
        self.thread_infos.len()
    }

    /// Waits for the worker threads to get up and running.  This is
    /// meant to be used for benchmarking purposes, primarily, so that
    /// you can get more consistent numbers by having everything
    /// "ready to go".
    pub fn wait_until_primed(&self) {
        for info in &self.thread_infos {
            info.primed.wait();
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // MAIN LOOP
    //
    // So long as all of the worker threads are hanging out in their
    // top-level loop, there is no work to be done.

    fn start_working(&self, index: usize) {
        log!(StartWorking { index: index });
        let mut state = self.state.lock().unwrap();
        state.threads_at_work += 1;
        self.work_available.notify_all();
    }

    pub unsafe fn inject(&self, injected_jobs: &[JobRef]) {
        log!(InjectJobs { count: injected_jobs.len() });
        let mut state = self.state.lock().unwrap();
        if state.terminate {
            drop(state);
            // We can only reach this point if these conditions are met:
            // 1) This must be the global thread pool
            // 2) The only way to terminate the global thread pool is if a
            //    worker thread panics.
            // 3) A worker thread can only panic if a job panicked and was not
            //    caught by panic::recover.
            panic!("rayon thread pool is contaminated by a previous panic; recovery is only available on nightly compilers");
        }
        state.injected_jobs.extend(injected_jobs);
        self.work_available.notify_all();
    }

    fn wait_for_work(&self, _worker: usize, was_active: bool) -> Work {
        log!(WaitForWork { worker: _worker, was_active: was_active });

        let mut state = self.state.lock().unwrap();

        if was_active {
            state.threads_at_work -= 1;
        }

        loop {
            // Check if we need to terminate.
            if state.terminate {
                return Work::Terminate;
            }

            // Otherwise, if anything was injected from outside,
            // return that.  Note that this gives preference to
            // injected items over stealing from others, which is a
            // bit dubious, but then so is the opposite.
            if let Some(job) = state.injected_jobs.pop_front() {
                state.threads_at_work += 1;
                self.work_available.notify_all();
                return Work::Job(job);
            }

            // If any of the threads are running a job, we should spin
            // up, since they may generate subworkitems.
            if state.threads_at_work > 0 {
                return Work::None;
            }

            state = self.work_available.wait(state).unwrap();
        }
    }

    pub fn terminate(&self) {
        let mut state = self.state.lock().unwrap();
        state.terminate = true;
        for job in state.injected_jobs.drain(..) {
            unsafe {
                (*job.0).abort();
            }
        }
        self.work_available.notify_all();
    }
}

impl RegistryState {
    pub fn new() -> RegistryState {
        RegistryState {
            threads_at_work: 0,
            injected_jobs: VecDeque::new(),
            terminate: false,
        }
    }
}

struct ThreadInfo {
    // latch is set once thread has started and we are entering into
    // the main loop
    primed: LockLatch,
    stealer: Stealer<JobRef>,
}

impl ThreadInfo {
    fn new(stealer: Stealer<JobRef>) -> ThreadInfo {
        ThreadInfo {
            primed: LockLatch::new(),
            stealer: stealer,
        }
    }
}

///////////////////////////////////////////////////////////////////////////
// WorkerThread identifiers

pub struct WorkerThread {
    worker: Worker<JobRef>,
    registry: Arc<Registry>,
    index: usize
}

// This is a bit sketchy, but basically: the WorkerThread is
// allocated on the stack of the worker on entry and stored into this
// thread local variable. So it will remain valid at least until the
// worker is fully unwound. Using an unsafe pointer avoids the need
// for a RefCell<T> etc.
thread_local! {
    static WORKER_THREAD_STATE: Cell<*const WorkerThread> =
        Cell::new(0 as *const WorkerThread)
}

impl WorkerThread {
    /// Gets the `WorkerThread` index for the current thread; returns
    /// NULL if this is not a worker thread. This pointer is valid
    /// anywhere on the current thread.
    #[inline]
    pub unsafe fn current() -> *const WorkerThread {
        WORKER_THREAD_STATE.with(|t| t.get())
    }

    /// Sets `self` as the worker thread index for the current thread.
    /// This is done during worker thread startup.
    unsafe fn set_current(&self) {
        WORKER_THREAD_STATE.with(|t| {
            assert!(t.get().is_null());
            t.set(self);
        });
    }

    #[inline]
    pub fn index(&self) -> usize {
        self.index
    }

    #[inline]
    pub unsafe fn push(&self, job: JobRef) {
        self.worker.push(job);
    }

    /// Pop `job` from top of stack, returning `false` if it has been
    /// stolen.
    #[inline]
    pub unsafe fn pop(&self) -> bool {
        self.worker.pop().is_some()
    }

    #[cold]
    pub unsafe fn steal_until(&self, latch: &SpinLatch) {
        // If another thread stole our job when we panic, we must halt unwinding
        // until that thread is finished using it.
        struct PanicGuard<'a>(&'a SpinLatch);
        impl<'a> Drop for PanicGuard<'a> {
            fn drop(&mut self) {
                while !self.0.probe() {
                    thread::yield_now();
                }
            }
        }

        let guard = PanicGuard(&latch);
        while !latch.probe() {
            if let Some(job) = steal_work(&self.registry, self.index) {
                (*job.0).execute();
            } else {
                thread::yield_now();
            }
        }
        mem::forget(guard);
    }
}

///////////////////////////////////////////////////////////////////////////

unsafe fn main_loop(worker: Worker<JobRef>, registry: Arc<Registry>, index: usize) {
    let worker_thread = WorkerThread {
        worker: worker,
        registry: registry.clone(),
        index: index,
    };
    worker_thread.set_current();

    // let registry know we are ready to do work
    registry.thread_infos[index].primed.set();

    // If a worker thread panics, bring down the entire thread pool
    struct PanicGuard;
    impl Drop for PanicGuard {
        fn drop(&mut self) {
            unsafe {
                (*WorkerThread::current()).registry.terminate();
            }
        }
    }
    let _guard = PanicGuard;

    let mut was_active = false;
    loop {
        match registry.wait_for_work(index, was_active) {
            Work::Job(injected_job) => {
                (*injected_job.0).execute();
                was_active = true;
                continue;
            }
            Work::Terminate => break,
            Work::None => {},
        }

        if let Some(stolen_job) = steal_work(&registry, index) {
            log!(StoleWork { worker: index });
            registry.start_working(index);
            (*stolen_job.0).execute();
            was_active = true;
        } else {
            was_active = false;
        }
    }
}

unsafe fn steal_work(registry: &Registry, index: usize) -> Option<JobRef> {
    let num_threads = registry.num_threads();
    let start = rand::random::<usize>() % num_threads;
    (start .. num_threads)
        .chain(0 .. start)
        .filter(|&i| i != index)
        .flat_map(|i| match registry.thread_infos[i].stealer.steal() {
            Stolen::Empty => None,
            Stolen::Abort => None, // loop?
            Stolen::Data(v) => Some(v),
        })
        .next()
}
<commit_msg>thread_pool: clone stealers into WorkerThread<commit_after>use Configuration;
use deque;
use deque::{Worker, Stealer, Stolen};
use job::JobRef;
use latch::{Latch, LockLatch, SpinLatch};
#[allow(unused_imports)]
use log::Event::*;
use rand;
use std::cell::Cell;
use std::sync::{Arc, Condvar, Mutex, Once, ONCE_INIT};
use std::thread;
use std::collections::VecDeque;
use std::mem;
use util::leak;
use num_cpus;

///////////////////////////////////////////////////////////////////////////

pub struct Registry {
    thread_infos: Vec<ThreadInfo>,
    state: Mutex<RegistryState>,
    work_available: Condvar,
}

struct RegistryState {
    terminate: bool,
    threads_at_work: usize,
    injected_jobs: VecDeque<JobRef>,
}

///////////////////////////////////////////////////////////////////////////
// Initialization

static mut THE_REGISTRY: Option<&'static Registry> = None;
static THE_REGISTRY_SET: Once = ONCE_INIT;

/// Starts the worker threads (if that has not already happened). If
/// initialization has not already occurred, use the default
/// configuration.
pub fn get_registry() -> &'static Registry {
    THE_REGISTRY_SET.call_once(|| unsafe { init_registry(Configuration::new()) });
    unsafe { THE_REGISTRY.unwrap() }
}

/// Starts the worker threads (if that has not already happened) with
/// the given configuration.
pub fn get_registry_with_config(config: Configuration) -> &'static Registry {
    THE_REGISTRY_SET.call_once(|| unsafe { init_registry(config) });
    unsafe { THE_REGISTRY.unwrap() }
}

/// Initializes the global registry with the given configuration.
/// Meant to be called from within the `THE_REGISTRY_SET` once
/// function. Declared `unsafe` because it writes to `THE_REGISTRY` in
/// an unsynchronized fashion.
unsafe fn init_registry(config: Configuration) {
    let registry = leak(Registry::new(config.num_threads()));
    THE_REGISTRY = Some(registry);
}

enum Work {
    None,
    Job(JobRef),
    Terminate,
}

impl Registry {
    pub fn new(num_threads: Option<usize>) -> Arc<Registry> {
        let limit_value = match num_threads {
            Some(value) => value,
            None => num_cpus::get()
        };

        let (workers, stealers) : (Vec<_>, Vec<_>) =
            (0..limit_value).map(|_| deque::new()).unzip();

        let registry = Arc::new(Registry {
            thread_infos: stealers.into_iter().map(|s| ThreadInfo::new(s))
                                          .collect(),
            state: Mutex::new(RegistryState::new()),
            work_available: Condvar::new(),
        });

        for (index, worker) in workers.into_iter().enumerate() {
            let registry = registry.clone();
            thread::spawn(move || unsafe { main_loop(worker, registry, index) });
        }

        registry
    }

    pub fn num_threads(&self) -> usize {
        self.thread_infos.len()
    }

    /// Waits for the worker threads to get up and running.  This is
    /// meant to be used for benchmarking purposes, primarily, so that
    /// you can get more consistent numbers by having everything
    /// "ready to go".
    pub fn wait_until_primed(&self) {
        for info in &self.thread_infos {
            info.primed.wait();
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // MAIN LOOP
    //
    // So long as all of the worker threads are hanging out in their
    // top-level loop, there is no work to be done.

    fn start_working(&self, index: usize) {
        log!(StartWorking { index: index });
        let mut state = self.state.lock().unwrap();
        state.threads_at_work += 1;
        self.work_available.notify_all();
    }

    pub unsafe fn inject(&self, injected_jobs: &[JobRef]) {
        log!(InjectJobs { count: injected_jobs.len() });
        let mut state = self.state.lock().unwrap();
        if state.terminate {
            drop(state);
            // We can only reach this point if these conditions are met:
            // 1) This must be the global thread pool
            // 2) The only way to terminate the global thread pool is if a
            //    worker thread panics.
            // 3) A worker thread can only panic if a job panicked and was not
            //    caught by panic::recover.
            panic!("rayon thread pool is contaminated by a previous panic; recovery is only available on nightly compilers");
        }
        state.injected_jobs.extend(injected_jobs);
        self.work_available.notify_all();
    }

    fn wait_for_work(&self, _worker: usize, was_active: bool) -> Work {
        log!(WaitForWork { worker: _worker, was_active: was_active });

        let mut state = self.state.lock().unwrap();

        if was_active {
            state.threads_at_work -= 1;
        }

        loop {
            // Check if we need to terminate.
            if state.terminate {
                return Work::Terminate;
            }

            // Otherwise, if anything was injected from outside,
            // return that.  Note that this gives preference to
            // injected items over stealing from others, which is a
            // bit dubious, but then so is the opposite.
            if let Some(job) = state.injected_jobs.pop_front() {
                state.threads_at_work += 1;
                self.work_available.notify_all();
                return Work::Job(job);
            }

            // If any of the threads are running a job, we should spin
            // up, since they may generate subworkitems.
            if state.threads_at_work > 0 {
                return Work::None;
            }

            state = self.work_available.wait(state).unwrap();
        }
    }

    pub fn terminate(&self) {
        let mut state = self.state.lock().unwrap();
        state.terminate = true;
        for job in state.injected_jobs.drain(..) {
            unsafe {
                (*job.0).abort();
            }
        }
        self.work_available.notify_all();
    }
}

impl RegistryState {
    pub fn new() -> RegistryState {
        RegistryState {
            threads_at_work: 0,
            injected_jobs: VecDeque::new(),
            terminate: false,
        }
    }
}

struct ThreadInfo {
    // latch is set once thread has started and we are entering into
    // the main loop
    primed: LockLatch,
    stealer: Stealer<JobRef>,
}

impl ThreadInfo {
    fn new(stealer: Stealer<JobRef>) -> ThreadInfo {
        ThreadInfo {
            primed: LockLatch::new(),
            stealer: stealer,
        }
    }
}

///////////////////////////////////////////////////////////////////////////
// WorkerThread identifiers

pub struct WorkerThread {
    worker: Worker<JobRef>,
    stealers: Vec<Stealer<JobRef>>,
    registry: Arc<Registry>,
    index: usize
}

// This is a bit sketchy, but basically: the WorkerThread is
// allocated on the stack of the worker on entry and stored into this
// thread local variable. So it will remain valid at least until the
// worker is fully unwound. Using an unsafe pointer avoids the need
// for a RefCell<T> etc.
thread_local! {
    static WORKER_THREAD_STATE: Cell<*const WorkerThread> =
        Cell::new(0 as *const WorkerThread)
}

impl WorkerThread {
    /// Gets the `WorkerThread` index for the current thread; returns
    /// NULL if this is not a worker thread. This pointer is valid
    /// anywhere on the current thread.
    #[inline]
    pub unsafe fn current() -> *const WorkerThread {
        WORKER_THREAD_STATE.with(|t| t.get())
    }

    /// Sets `self` as the worker thread index for the current thread.
    /// This is done during worker thread startup.
    unsafe fn set_current(&self) {
        WORKER_THREAD_STATE.with(|t| {
            assert!(t.get().is_null());
            t.set(self);
        });
    }

    #[inline]
    pub fn index(&self) -> usize {
        self.index
    }

    #[inline]
    pub unsafe fn push(&self, job: JobRef) {
        self.worker.push(job);
    }

    /// Pop `job` from top of stack, returning `false` if it has been
    /// stolen.
    #[inline]
    pub unsafe fn pop(&self) -> bool {
        self.worker.pop().is_some()
    }

    #[cold]
    pub unsafe fn steal_until(&self, latch: &SpinLatch) {
        // If another thread stole our job when we panic, we must halt unwinding
        // until that thread is finished using it.
        struct PanicGuard<'a>(&'a SpinLatch);
        impl<'a> Drop for PanicGuard<'a> {
            fn drop(&mut self) {
                while !self.0.probe() {
                    thread::yield_now();
                }
            }
        }

        let guard = PanicGuard(&latch);
        while !latch.probe() {
            if let Some(job) = steal_work(&self.stealers) {
                (*job.0).execute();
            } else {
                thread::yield_now();
            }
        }
        mem::forget(guard);
    }
}

///////////////////////////////////////////////////////////////////////////

unsafe fn main_loop(worker: Worker<JobRef>, registry: Arc<Registry>, index: usize) {
    let stealers = registry.thread_infos.iter()
        .enumerate().filter(|&(i, _)| i != index)
        .map(|(_, ti)| ti.stealer.clone())
        .collect();

    let worker_thread = WorkerThread {
        worker: worker,
        stealers: stealers,
        registry: registry.clone(),
        index: index,
    };
    worker_thread.set_current();

    // let registry know we are ready to do work
    registry.thread_infos[index].primed.set();

    // If a worker thread panics, bring down the entire thread pool
    struct PanicGuard;
    impl Drop for PanicGuard {
        fn drop(&mut self) {
            unsafe {
                (*WorkerThread::current()).registry.terminate();
            }
        }
    }
    let _guard = PanicGuard;

    let mut was_active = false;
    loop {
        match registry.wait_for_work(index, was_active) {
            Work::Job(injected_job) => {
                (*injected_job.0).execute();
                was_active = true;
                continue;
            }
            Work::Terminate => break,
            Work::None => {},
        }

        if let Some(stolen_job) = steal_work(&worker_thread.stealers) {
            log!(StoleWork { worker: index });
            registry.start_working(index);
            (*stolen_job.0).execute();
            was_active = true;
        } else {
            was_active = false;
        }
    }
}

unsafe fn steal_work(stealers: &[Stealer<JobRef>]) -> Option<JobRef> {
    if stealers.is_empty() { return None }
    let start = rand::random::<usize>() % stealers.len();
    stealers[start..].iter()
        .chain(&stealers[..start])
        .filter_map(|stealer| match stealer.steal() {
            Stolen::Empty => None,
            Stolen::Abort => None, // loop?
            Stolen::Data(v) => Some(v),
        })
        .next()
}
<|endoftext|>