<commit_before>// Copyright 2017 Matt LaChance
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[macro_use] extern crate hamcrest;

mod compared_to {

    use hamcrest::prelude::*;

    #[test]
    fn ints_less_than() {
        assert_that!(4, is(less_than(5)));
    }

    #[test]
    #[should_panic]
    fn unsuccessful_less_than() {
        assert_that!(4, is(less_than(3)));
    }

    #[test]
    fn ints_greater_than() {
        assert_that!(8, is(greater_than(5)));
    }

    #[test]
    #[should_panic]
    fn unsuccessful_greater_than() {
        assert_that!(1, is(greater_than(3)));
    }

}
<commit_msg>Be sure less_than and greater_than disallow equality<commit_after>// Copyright 2017 Matt LaChance
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[macro_use] extern crate hamcrest;

mod compared_to {

    use hamcrest::prelude::*;

    #[test]
    fn ints_less_than() {
        assert_that!(4, is(less_than(5)));
    }

    #[test]
    #[should_panic]
    fn unsuccessful_less_than() {
        assert_that!(4, is(less_than(3)));
    }

    #[test]
    #[should_panic]
    fn less_than_is_not_equal() {
        assert_that!(2, is(less_than(2)));
    }

    #[test]
    fn ints_greater_than() {
        assert_that!(8, is(greater_than(5)));
    }

    #[test]
    #[should_panic]
    fn unsuccessful_greater_than() {
        assert_that!(1, is(greater_than(3)));
    }

    #[test]
    #[should_panic]
    fn greater_than_is_not_equal() {
        assert_that!(2, is(greater_than(2)));
    }

}
<|endoftext|>


<commit_before>#![cfg(feature = "integration")]

use std::env;
use std::process::Command;

#[cfg_attr(feature = "integration", test)]
fn integration_test() {
    let repo_name = env::var("INTEGRATION").expect("`INTEGRATION` var not set");
    let repo_url = format!("https://github.com/{}", repo_name);
    let crate_name = repo_name
        .split('/')
        .nth(1)
        .expect("repo name should have format `<org>/<name>`");

    let repo_dir = tempfile::tempdir()
        .expect("couldn't create temp dir")
        .path()
        .join(crate_name);

    let st = Command::new("git")
        .args(&["clone", "--depth=1", &repo_url, repo_dir.to_str().unwrap()])
        .status()
        .expect("unstable to run git");
    assert!(st.success());

    let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let target_dir = std::path::Path::new(&root_dir).join("target");
    let clippy_binary = target_dir.join(env!("PROFILE")).join("cargo-clippy");

    let output = Command::new(clippy_binary)
        .current_dir(repo_dir)
        .env("RUST_BACKTRACE", "full")
        .env("CARGO_TARGET_DIR", target_dir)
        .args(&[
            "clippy",
            "--all-targets",
            "--all-features",
            "--",
            "--cap-lints",
            "warn",
            "-Wclippy::pedantic",
            "-Wclippy::nursery",
        ])
        .output()
        .expect("unable to run clippy");

    let stderr = String::from_utf8_lossy(&output.stderr);
    if stderr.contains("internal compiler error") {
        let backtrace_start = stderr
            .find("thread 'rustc' panicked at")
            .expect("start of backtrace not found");
        let backtrace_end = stderr
            .rfind("error: internal compiler error")
            .expect("end of backtrace not found");

        panic!(
            "internal compiler error\nBacktrace:\n\n{}",
            &stderr[backtrace_start..backtrace_end]
        );
    } else if stderr.contains("query stack during panic") {
        panic!("query stack during panic in the output");
    } else if stderr.contains("E0463") {
        panic!("error: E0463");
    } else if stderr.contains("E0514") {
        panic!("incompatible crate versions");
    } else if stderr.contains("failed to run `rustc` to learn about target-specific information") {
        panic!("couldn't find librustc_driver, consider setting `LD_LIBRARY_PATH`");
    }

    match output.status.code() {
        Some(code) => {
            if code == 0 {
                println!("Compilation successful");
            } else {
                eprintln!("Compilation failed. Exit code: {}", code);
            }
        },
        None => panic!("Process terminated by signal"),
    }
}
<commit_msg>Fix typo<commit_after>#![cfg(feature = "integration")]

use std::env;
use std::process::Command;

#[cfg_attr(feature = "integration", test)]
fn integration_test() {
    let repo_name = env::var("INTEGRATION").expect("`INTEGRATION` var not set");
    let repo_url = format!("https://github.com/{}", repo_name);
    let crate_name = repo_name
        .split('/')
        .nth(1)
        .expect("repo name should have format `<org>/<name>`");

    let repo_dir = tempfile::tempdir()
        .expect("couldn't create temp dir")
        .path()
        .join(crate_name);

    let st = Command::new("git")
        .args(&["clone", "--depth=1", &repo_url, repo_dir.to_str().unwrap()])
        .status()
        .expect("unable to run git");
    assert!(st.success());

    let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let target_dir = std::path::Path::new(&root_dir).join("target");
    let clippy_binary = target_dir.join(env!("PROFILE")).join("cargo-clippy");

    let output = Command::new(clippy_binary)
        .current_dir(repo_dir)
        .env("RUST_BACKTRACE", "full")
        .env("CARGO_TARGET_DIR", target_dir)
        .args(&[
            "clippy",
            "--all-targets",
            "--all-features",
            "--",
            "--cap-lints",
            "warn",
            "-Wclippy::pedantic",
            "-Wclippy::nursery",
        ])
        .output()
        .expect("unable to run clippy");

    let stderr = String::from_utf8_lossy(&output.stderr);
    if stderr.contains("internal compiler error") {
        let backtrace_start = stderr
            .find("thread 'rustc' panicked at")
            .expect("start of backtrace not found");
        let backtrace_end = stderr
            .rfind("error: internal compiler error")
            .expect("end of backtrace not found");

        panic!(
            "internal compiler error\nBacktrace:\n\n{}",
            &stderr[backtrace_start..backtrace_end]
        );
    } else if stderr.contains("query stack during panic") {
        panic!("query stack during panic in the output");
    } else if stderr.contains("E0463") {
        panic!("error: E0463");
    } else if stderr.contains("E0514") {
        panic!("incompatible crate versions");
    } else if stderr.contains("failed to run `rustc` to learn about target-specific information") {
        panic!("couldn't find librustc_driver, consider setting `LD_LIBRARY_PATH`");
    }

    match output.status.code() {
        Some(code) => {
            if code == 0 {
                println!("Compilation successful");
            } else {
                eprintln!("Compilation failed. Exit code: {}", code);
            }
        },
        None => panic!("Process terminated by signal"),
    }
}
<|endoftext|>


<commit_before>extern crate tokio_core;
extern crate env_logger;
extern crate futures;

use std::io;
use std::net::Shutdown;

use futures::{Future, Async, Poll};
use futures::stream::Stream;
use tokio_core::io::{FramedIo, write_all, read};
use tokio_core::easy::{Parse, Serialize, EasyFramed, EasyBuf};
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::reactor::Core;

pub struct LineParser;
pub struct LineSerialize;

impl Parse for LineParser {
    type Out = EasyBuf;

    fn parse(&mut self, buf: &mut EasyBuf) -> Poll<EasyBuf, io::Error> {
        match buf.as_slice().iter().position(|&b| b == b'\n') {
            Some(i) => Ok(buf.drain_to(i + 1).into()),
            None => Ok(Async::NotReady),
        }
    }

    fn done(&mut self, buf: &mut EasyBuf) -> io::Result<EasyBuf> {
        let amt = buf.len();
        Ok(buf.drain_to(amt))
    }
}

impl Serialize for LineSerialize {
    type In = EasyBuf;

    fn serialize(&mut self, msg: EasyBuf, into: &mut Vec<u8>) {
        into.extend_from_slice(msg.as_slice());
    }
}

pub struct EchoFramed<T> {
    inner: T,
}

impl<T, U> Future for EchoFramed<T>
    where T: FramedIo<In = U, Out = U>,
{
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        // Try to write out any buffered messages if we have them.
        if self.inner.flush().expect("flush error").is_not_ready() {
            return Ok(Async::NotReady)
        }

        // Wait until we can simultaneously read and write a message
        while self.inner.poll_read().is_ready() && self.inner.poll_write().is_ready() {
            let frame = match self.inner.read() {
                Ok(Async::Ready(frame)) => frame,
                Ok(Async::NotReady) => break,
                Err(e) => panic!("error in read: {}", e),
            };

            match self.inner.write(frame) {
                Ok(Async::Ready(())) => {}
                Ok(Async::NotReady) => break,
                Err(e) => panic!("error in write: {}", e),
            }
        }

        // If we wrote some frames try to flush again. Ignore whether this is
        // ready to finish or not as we're going to continue to return NotReady
        drop(self.inner.flush().expect("flush error"));

        Ok(Async::NotReady)
    }
}

#[test]
fn echo() {
    drop(env_logger::init());

    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &handle).unwrap();
    let addr = listener.local_addr().unwrap();
    let srv = listener.incoming().for_each(move |(socket, _)| {
        let framed = EasyFramed::new(socket, LineParser, LineSerialize);
        handle.spawn(EchoFramed { inner: framed });
        Ok(())
    });

    let handle = core.handle();
    handle.spawn(srv.map_err(|e| panic!("srv error: {}", e)));

    let client = TcpStream::connect(&addr, &handle);
    let client = core.run(client).unwrap();
    let (client, _) = core.run(write_all(client, b"a\n")).unwrap();
    let (client, buf, amt) = core.run(read(client, vec![0; 1024])).unwrap();
    assert_eq!(amt, 2);
    assert_eq!(&buf[..2], b"a\n");

    let (client, _) = core.run(write_all(client, b"\nb\n")).unwrap();
    let (client, buf, amt) = core.run(read(client, buf)).unwrap();
    assert_eq!(amt, 3);
    assert_eq!(&buf[..3], b"\nb\n");

    let (client, _) = core.run(write_all(client, b"b")).unwrap();
    client.shutdown(Shutdown::Write).unwrap();
    let (_client, buf, amt) = core.run(read(client, buf)).unwrap();
    assert_eq!(amt, 1);
    assert_eq!(&buf[..1], b"b");
}
<commit_msg>Fix tests<commit_after>extern crate tokio_core;
extern crate env_logger;
extern crate futures;

use std::io;
use std::net::Shutdown;

use futures::{Future, Async, Poll};
use futures::stream::Stream;
use tokio_core::io::{FramedIo, write_all, read};
use tokio_core::easy::{Parse, Serialize, EasyFramed, EasyBuf};
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::reactor::Core;

pub struct LineParser;
pub struct LineSerialize;

impl Parse for LineParser {
    type Out = EasyBuf;

    fn parse(&mut self, buf: &mut EasyBuf) -> Poll<EasyBuf, io::Error> {
        match buf.as_slice().iter().position(|&b| b == b'\n') {
            Some(i) => Ok(buf.drain_to(i + 1).into()),
            None => Ok(Async::NotReady),
        }
    }

    fn done(&mut self, buf: &mut EasyBuf) -> io::Result<EasyBuf> {
        let amt = buf.len();
        Ok(buf.drain_to(amt))
    }
}

impl Serialize for LineSerialize {
    type In = EasyBuf;

    fn serialize(&mut self, msg: EasyBuf, into: &mut Vec<u8>) {
        into.extend_from_slice(msg.as_slice());
    }
}

pub struct EchoFramed<T> {
    inner: T,
    eof: bool,
}

impl<T, U> Future for EchoFramed<T>
    where T: FramedIo<In = U, Out = Option<U>>,
{
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        // Try to write out any buffered messages if we have them.
        if self.inner.flush().expect("flush error").is_not_ready() {
            return Ok(Async::NotReady)
        }

        // Wait until we can simultaneously read and write a message
        while !self.eof &&
              self.inner.poll_read().is_ready() &&
              self.inner.poll_write().is_ready() {
            let frame = match self.inner.read() {
                Ok(Async::Ready(Some(frame))) => frame,
                Ok(Async::Ready(None)) => {
                    self.eof = true;
                    break
                }
                Ok(Async::NotReady) => break,
                Err(e) => panic!("error in read: {}", e),
            };

            match self.inner.write(frame) {
                Ok(Async::Ready(())) => {}
                Ok(Async::NotReady) => break,
                Err(e) => panic!("error in write: {}", e),
            }
        }

        // If we wrote some frames try to flush again. Ignore whether this is
        // ready to finish or not as we're going to continue to return NotReady
        if self.inner.flush().expect("flush error").is_ready() && self.eof {
            Ok(().into())
        } else {
            Ok(Async::NotReady)
        }
    }
}

#[test]
fn echo() {
    drop(env_logger::init());

    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &handle).unwrap();
    let addr = listener.local_addr().unwrap();
    let srv = listener.incoming().for_each(move |(socket, _)| {
        let framed = EasyFramed::new(socket, LineParser, LineSerialize);
        handle.spawn(EchoFramed { inner: framed, eof: false });
        Ok(())
    });

    let handle = core.handle();
    handle.spawn(srv.map_err(|e| panic!("srv error: {}", e)));

    let client = TcpStream::connect(&addr, &handle);
    let client = core.run(client).unwrap();
    let (client, _) = core.run(write_all(client, b"a\n")).unwrap();
    let (client, buf, amt) = core.run(read(client, vec![0; 1024])).unwrap();
    assert_eq!(amt, 2);
    assert_eq!(&buf[..2], b"a\n");

    let (client, _) = core.run(write_all(client, b"\nb\n")).unwrap();
    let (client, buf, amt) = core.run(read(client, buf)).unwrap();
    assert_eq!(amt, 3);
    assert_eq!(&buf[..3], b"\nb\n");

    let (client, _) = core.run(write_all(client, b"b")).unwrap();
    client.shutdown(Shutdown::Write).unwrap();
    let (_client, buf, amt) = core.run(read(client, buf)).unwrap();
    assert_eq!(amt, 1);
    assert_eq!(&buf[..1], b"b");
}
<|endoftext|>


<commit_before>extern crate torchrs;
#[macro_use]
extern crate modparse_derive;

use torchrs::nn::{Module, Conv2d, Linear};
use torchrs::nn::modules::module::*;
use torchrs::autograd::{Variable, BackwardArgs};
use torchrs::tensor::Tensor;
use torchrs::optim;

use torchrs::nn::functional::{dropout2d, MaxPool2dArgs, DropoutArgs};
use torchrs::nn::functional as F;
use std::vec;
use std::slice;

type Batch<dT, tT> = (Tensor<dT>, Tensor<tT>);
type Dataset<dT, tT> = Vec<Batch<dT, tT>>;
struct DataLoader<dT, tT> {
    dataset: Dataset<dT, tT>,
}

impl<dT, tT> DataLoader<dT, tT> {
    pub fn new() -> Self {
        DataLoader { dataset: Vec::new() }
    }
    pub fn iter(&self) -> slice::Iter<Batch<dT, tT>> {
        self.dataset.as_slice().iter()
    }
    pub fn iter_mut(&mut self) -> slice::IterMut<Batch<dT, tT>> {
        self.dataset.as_mut_slice().iter_mut()
    }
    pub fn len(&self) -> usize {
        self.dataset.len()
    }
}

#[derive(Default)]
struct NetArgs {
    log_interval: usize,
    cuda: bool,
}

#[derive(ModParse)]
struct Net {
    delegate: Module<f32>,
    conv1: Conv2d<f32>,
    conv2: Conv2d<f32>,
    fc1: Linear<f32>,
    fc2: Linear<f32>,
}

impl Net {
    pub fn new() -> Net {
        let mut t = Net {
            delegate: Module::new(),
            conv1: Conv2d::build(1, 10, 5).done(),
            conv2: Conv2d::build(10, 20, 5).done(),
            fc1: Linear::build(320, 50).done(),
            fc2: Linear::build(50, 10).done(),
        };
        t.init_module();
        t
    }
}
// The forward operations could take on one of two implementations.
// The first supporting a near verbatim version of the python
// implementation, and the second supporting a slightly more
// idiomatic to Rust method chaining.

// a) as a near verbatim implementation of the python version
impl ModIntf<f32> for Net {
    fn forward(&mut self, args: &mut Variable<f32>) -> Variable<f32> {
        let training = self.delegate.training;
        let pool_val = MaxPool2dArgs::default();
        let dropout_val = DropoutArgs::default();
        let mut x = F::relu(&F::max_pool2d(&self.conv1.f(args), (2, 2), &pool_val));
        let mut x = F::relu(&F::max_pool2d(&dropout2d(&self.conv2.f(&mut x), &dropout_val),
                                           (2, 2),
                                           &pool_val));
        let mut x = x.view(&[-1, 320]);
        let x = F::relu(&self.fc1.f(&mut x));
        let mut x = F::dropout(&x, &dropout_val);
        let x = self.fc2.f(&mut x);
        F::log_softmax(&x)
    }
    fn forwardv(&mut self, input: &mut Vec<Variable<f32>>) -> Vec<Variable<f32>> {
        panic!("not valid")
    }

    fn delegate(&mut self) -> &mut Module<f32> {
        &mut self.delegate
    }
}

fn train(model: &mut Net,
         args: &NetArgs,
         train_loader: &DataLoader<f32, i64>,
         epoch: u32,
         optimizer: &mut optim::OptIntf) {
    model.train();
    for (batch_idx, &(ref data, ref target)) in train_loader.iter().enumerate() {
        let (mut data, target) = if args.cuda {
            (Variable::new(data.cuda().clone()), Variable::new(target.cuda().clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        optimizer.zero_grad();
        let output = model.f(&mut data);
        let mut loss = F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        loss.backward(&BackwardArgs::default());
        optimizer.step();
        if batch_idx % args.log_interval == 0 {
            println!("Train Epoch: {} [{}/{} ({:.0}%)]\tLoss: {:.6}",
                     epoch,
                     batch_idx * data.data().len(),
                     train_loader.dataset.len(),
                     100. * (batch_idx as f32) / train_loader.len() as f32,
                     loss.data()[0]);
        }
    }
}

fn test(model: &mut Net, args: &NetArgs, data: &DataLoader<f32, i64>, epoch: u32) {
    model.eval()
}

fn main() {
    let epochs = 10;
    // no data loaders yet so demonstrate with Vec placeholder
    let train_loader: DataLoader<f32, i64> = DataLoader::new();
    let test_loader: DataLoader<f32, i64> = DataLoader::new();
    let args = NetArgs::default();
    let mut optimizer = optim::SGD::new();

    let mut model = Net::new();
    for epoch in 1..epochs + 1 {
        train(&mut model, &args, &train_loader, epoch, &mut optimizer);
        test(&mut model, &args, &test_loader, epoch);
    }
}
<commit_msg>narrow nn imports to interfaces<commit_after>extern crate torchrs;
#[macro_use]
extern crate modparse_derive;

use torchrs::autograd::{Variable, BackwardArgs};
use torchrs::tensor::Tensor;
use torchrs::optim;

use torchrs::nn;
use torchrs::nn::{ModuleStruct, ModIntf};
use torchrs::nn::functional::{dropout2d, MaxPool2dArgs, DropoutArgs};
use torchrs::nn::functional as F;
use std::vec;
use std::slice;

type Batch<dT, tT> = (Tensor<dT>, Tensor<tT>);
type Dataset<dT, tT> = Vec<Batch<dT, tT>>;
struct DataLoader<dT, tT> {
    dataset: Dataset<dT, tT>,
}

impl<dT, tT> DataLoader<dT, tT> {
    pub fn new() -> Self {
        DataLoader { dataset: Vec::new() }
    }
    pub fn iter(&self) -> slice::Iter<Batch<dT, tT>> {
        self.dataset.as_slice().iter()
    }
    pub fn iter_mut(&mut self) -> slice::IterMut<Batch<dT, tT>> {
        self.dataset.as_mut_slice().iter_mut()
    }
    pub fn len(&self) -> usize {
        self.dataset.len()
    }
}

#[derive(Default)]
struct NetArgs {
    log_interval: usize,
    cuda: bool,
}

#[derive(ModParse)]
struct Net {
    delegate: nn::Module<f32>,
    conv1: nn::Conv2d<f32>,
    conv2: nn::Conv2d<f32>,
    fc1: nn::Linear<f32>,
    fc2: nn::Linear<f32>,
}

impl Net {
    pub fn new() -> Net {
        let mut t = Net {
            delegate: nn::Module::new(),
            conv1: nn::Conv2d::build(1, 10, 5).done(),
            conv2: nn::Conv2d::build(10, 20, 5).done(),
            fc1: nn::Linear::build(320, 50).done(),
            fc2: nn::Linear::build(50, 10).done(),
        };
        t.init_module();
        t
    }
}
// The forward operations could take on one of two implementations.
// The first supporting a near verbatim version of the python
// implementation, and the second supporting a slightly more
// idiomatic to Rust method chaining.

// a) as a near verbatim implementation of the python version
impl ModIntf<f32> for Net {
    fn forward(&mut self, args: &mut Variable<f32>) -> Variable<f32> {
        let training = self.delegate.training;
        let pool_val = MaxPool2dArgs::default();
        let dropout_val = DropoutArgs::default();
        let mut x = F::relu(&F::max_pool2d(&self.conv1.f(args), (2, 2), &pool_val));
        let mut x = F::relu(&F::max_pool2d(&dropout2d(&self.conv2.f(&mut x), &dropout_val),
                                           (2, 2),
                                           &pool_val));
        let mut x = x.view(&[-1, 320]);
        let x = F::relu(&self.fc1.f(&mut x));
        let mut x = F::dropout(&x, &dropout_val);
        let x = self.fc2.f(&mut x);
        F::log_softmax(&x)
    }
    fn forwardv(&mut self, input: &mut Vec<Variable<f32>>) -> Vec<Variable<f32>> {
        panic!("not valid")
    }

    fn delegate(&mut self) -> &mut nn::Module<f32> {
        &mut self.delegate
    }
}

fn train(model: &mut Net,
         args: &NetArgs,
         train_loader: &DataLoader<f32, i64>,
         epoch: u32,
         optimizer: &mut optim::OptIntf) {
    model.train();
    for (batch_idx, &(ref data, ref target)) in train_loader.iter().enumerate() {
        let (mut data, target) = if args.cuda {
            (Variable::new(data.cuda().clone()), Variable::new(target.cuda().clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        optimizer.zero_grad();
        let output = model.f(&mut data);
        let mut loss = F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        loss.backward(&BackwardArgs::default());
        optimizer.step();
        if batch_idx % args.log_interval == 0 {
            println!("Train Epoch: {} [{}/{} ({:.0}%)]\tLoss: {:.6}",
                     epoch,
                     batch_idx * data.data().len(),
                     train_loader.dataset.len(),
                     100. * (batch_idx as f32) / train_loader.len() as f32,
                     loss.data()[0]);
        }
    }
}

fn test(model: &mut Net, args: &NetArgs, data: &DataLoader<f32, i64>, epoch: u32) {
    model.eval()
}

fn main() {
    let epochs = 10;
    // no data loaders yet so demonstrate with Vec placeholder
    let train_loader: DataLoader<f32, i64> = DataLoader::new();
    let test_loader: DataLoader<f32, i64> = DataLoader::new();
    let args = NetArgs::default();
    let mut optimizer = optim::SGD::new();

    let mut model = Net::new();
    for epoch in 1..epochs + 1 {
        train(&mut model, &args, &train_loader, epoch, &mut optimizer);
        test(&mut model, &args, &test_loader, epoch);
    }
}
<|endoftext|>


<commit_before>extern crate torchrs;
#[macro_use]
extern crate modparse_derive;

use torchrs::nn::{Module, Conv2d, Linear};
use torchrs::nn::modules::module::*;
use torchrs::autograd::variable::Variable;
use torchrs::tensor::Tensor;

use torchrs::nn::functional::{max_pool2d, relu, dropout, dropout2d, log_softmax, MaxPoolFArgs,
                              DropoutFArgs};
#[derive(ModParse)]
struct Net {
    delegate: Module<f32>,
    conv1: Conv2d<f32>,
    conv2: Conv2d<f32>,
    fc1: Linear<f32>,
    fc2: Linear<f32>,
}

impl Net {
    pub fn new() -> Net {
        let t = Net {
            delegate: Module::new(),
            conv1: Conv2d::build(1, 10, 5).done(),
            conv2: Conv2d::build(10, 20, 5).done(),
            fc1: Linear::build(320, 50).done(),
            fc2: Linear::build(50, 10).done(),
        };
        t.init_module();
        t
    }
}
// The forward operations could take on one of two implementations.
// The first supporting a near verbatim version of the python
// implementation, and the second supporting a slightly more
// idiomatic to Rust method chaining.

// a) as a near verbatim implementation of the python version
impl ModIntf<f32> for Net {
    fn forward(&mut self, args: &mut Variable<f32>) -> Variable<f32> {
        let training = self.delegate.training;
        let pool_val = MaxPoolFArgs::default();
        let dropout_val = DropoutFArgs::default();
        let x = relu(&max_pool2d(self.conv1(&args), (2, 2), pool_val), false);
        let x = relu(&max_pool2d(&dropout2d(self.conv2(&x), dropout_val), (2, 2), pool_val),
                     false);
        let x = x.view(-1, 320);
        let x = relu(self.fc1(&x), false);
        let x = dropout(&x, dropout_val);
        let x = self.fc2(&x);
        log_softmax(&x)
    }
    fn forwardv(&mut self, input: &mut Vec<Variable<f32>>) -> Vec<Variable<f32>> {
        panic!("not valid")
    }

    fn delegate(&mut self) -> &mut Module<f32> {
        &mut self.delegate
    }
}

fn main() {}
<commit_msg>update for recent changes<commit_after>extern crate torchrs;
#[macro_use]
extern crate modparse_derive;

use torchrs::nn::{Module, Conv2d, Linear};
use torchrs::nn::modules::module::*;
use torchrs::autograd::variable::Variable;
use torchrs::tensor::Tensor;

use torchrs::nn::functional::{max_pool2d, relu, dropout, dropout2d, log_softmax, MaxPool2dArgs,
                              DropoutArgs};
#[derive(ModParse)]
struct Net {
    delegate: Module<f32>,
    conv1: Conv2d<f32>,
    conv2: Conv2d<f32>,
    fc1: Linear<f32>,
    fc2: Linear<f32>,
}

impl Net {
    pub fn new() -> Net {
        let t = Net {
            delegate: Module::new(),
            conv1: Conv2d::build(1, 10, 5).done(),
            conv2: Conv2d::build(10, 20, 5).done(),
            fc1: Linear::build(320, 50).done(),
            fc2: Linear::build(50, 10).done(),
        };
        t.init_module();
        t
    }
}
// The forward operations could take on one of two implementations.
// The first supporting a near verbatim version of the python
// implementation, and the second supporting a slightly more
// idiomatic to Rust method chaining.

// a) as a near verbatim implementation of the python version
impl ModIntf<f32> for Net {
    fn forward(&mut self, args: &mut Variable<f32>) -> Variable<f32> {
        let training = self.delegate.training;
        let pool_val = MaxPool2dArgs::default();
        let dropout_val = DropoutArgs::default();
        let x = relu(&mut max_pool2d(self.conv1(&args), (2, 2), pool_val));
        let x = relu(&mut max_pool2d(&dropout2d(self.conv2(&x), dropout_val), (2, 2), pool_val));
        let x = x.view(-1, 320);
        let x = relu(&mut self.fc1(&x));
        let x = dropout(&x, dropout_val);
        let x = self.fc2(&x);
        log_softmax(&x)
    }
    fn forwardv(&mut self, input: &mut Vec<Variable<f32>>) -> Vec<Variable<f32>> {
        panic!("not valid")
    }

    fn delegate(&mut self) -> &mut Module<f32> {
        &mut self.delegate
    }
}

fn main() {}
<|endoftext|>


<commit_before>use super::job_queue::*;

use futures::prelude::*;
use futures::channel::oneshot;
use futures::task;

use std::sync::*;
use std::pin::{Pin};

///
/// Signalling structure used to return the result of a scheduler future
///
struct SchedulerFutureResult<T> {
    /// The result of the future, or None if it has not been generated yet
    result: Option<Result<T, oneshot::Canceled>>,

    /// The waker to be called when the future is available
    waker: Option<task::Waker>
}

///
/// Wrapper that cancels the future if it is dropped before it is signalled
///
pub (super) struct SchedulerFutureSignaller<T>(Arc<Mutex<SchedulerFutureResult<T>>>);

impl<T> Drop for SchedulerFutureSignaller<T> {
    fn drop(&mut self) {
        let mut result = self.0.lock().unwrap();

        // If no result has been generated
        if result.result.is_none() {
            // Mark the future as canceled
            result.result = Some(Err(oneshot::Canceled));

            // Wake up anything that was polling it
            let waker = result.waker.take();
            waker.map(|waker| waker.wake());
        }
    }
}

///
/// Future representing a task pending on a scheduler
///
/// If polled when no threads are available, this future will run synchronously on the current thread
/// (stealing its execution time rather than blocking)
///
pub struct SchedulerFuture<T> {
    /// The queue which will eventually evaluate the result of this future
    queue: Arc<JobQueue>,

    /// A container for the result of this scheduler future
    result: Arc<Mutex<SchedulerFutureResult<T>>>
}

impl<T> SchedulerFuture<T> {
    ///
    /// Creates a new scheduler future and the result needed to signal it
    ///
    pub (super) fn new(queue: &Arc<JobQueue>) -> (SchedulerFuture<T>, SchedulerFutureSignaller<T>) {
        // Create an unfinished result
        let result = SchedulerFutureResult {
            result: None,
            waker:  None
        };
        let result = Arc::new(Mutex::new(result));

        // Insert into a future
        let future = SchedulerFuture {
            queue:  Arc::clone(queue),
            result: Arc::clone(&result)
        };

        (future, SchedulerFutureSignaller(result))
    }
}

impl<T> Future for SchedulerFuture<T> {
    type Output = Result<T, oneshot::Canceled>;

    ///
    /// Polls this future
    ///
    fn poll(self: Pin<&mut Self>, context: &mut task::Context) -> task::Poll<Self::Output> {
        unimplemented!()
    }
}
<commit_msg>Finish the implementation of the signaller for our new future<commit_after>use super::job_queue::*;

use futures::prelude::*;
use futures::channel::oneshot;
use futures::task;

use std::sync::*;
use std::pin::{Pin};

///
/// Signalling structure used to return the result of a scheduler future
///
struct SchedulerFutureResult<T> {
    /// The result of the future, or None if it has not been generated yet
    result: Option<Result<T, oneshot::Canceled>>,

    /// The waker to be called when the future is available
    waker: Option<task::Waker>
}

///
/// Wrapper that cancels the future if it is dropped before it is signalled
///
pub (super) struct SchedulerFutureSignaller<T>(Arc<Mutex<SchedulerFutureResult<T>>>);

///
/// Future representing a task pending on a scheduler
///
/// If polled when no threads are available, this future will run synchronously on the current thread
/// (stealing its execution time rather than blocking)
///
pub struct SchedulerFuture<T> {
    /// The queue which will eventually evaluate the result of this future
    queue: Arc<JobQueue>,

    /// A container for the result of this scheduler future
    result: Arc<Mutex<SchedulerFutureResult<T>>>
}

impl<T> SchedulerFuture<T> {
    ///
    /// Creates a new scheduler future and the result needed to signal it
    ///
    pub (super) fn new(queue: &Arc<JobQueue>) -> (SchedulerFuture<T>, SchedulerFutureSignaller<T>) {
        // Create an unfinished result
        let result = SchedulerFutureResult {
            result: None,
            waker:  None
        };
        let result = Arc::new(Mutex::new(result));

        // Insert into a future
        let future = SchedulerFuture {
            queue:  Arc::clone(queue),
            result: Arc::clone(&result)
        };

        (future, SchedulerFutureSignaller(result))
    }
}

impl<T> Drop for SchedulerFutureSignaller<T> {
    fn drop(&mut self) {
        let waker = {
            let mut future_result = self.0.lock().unwrap();

            // If no result has been generated
            if future_result.result.is_none() {
                // Mark the future as canceled
                future_result.result = Some(Err(oneshot::Canceled));

                // Wake up anything that was polling it
                let waker = future_result.waker.take();
                waker
            } else {
                // Result is already set, so don't wake anything up
                None
            }
        };

        // If we need to wake the future, then do so here (note that we're outside of the lock when we do this)
        waker.map(|waker| waker.wake());
    }
}

impl<T> SchedulerFutureSignaller<T> {
    ///
    /// Signals that the result of the calculation is available
    ///
    fn signal(self, result: T) {
        let waker = {
            let mut future_result = self.0.lock().unwrap();

            // Set the result
            future_result.result = Some(Ok(result));

            // Retrieve the waker
            future_result.waker.take()
        };

        // If we retrieved a waker from the result, wake it up
        waker.map(|waker| waker.wake());
    }
}
impl<T> Future for SchedulerFuture<T> {
    type Output = Result<T, oneshot::Canceled>;

    ///
    /// Polls this future
    ///
    fn poll(self: Pin<&mut Self>, context: &mut task::Context) -> task::Poll<Self::Output> {
        unimplemented!()
    }
}
<|endoftext|>


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

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    extern crate libc;

    use self::OsRngInner::*;

    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::Result::{Ok, Err};
    use slice::SliceExt;
    use mem;
    use os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
        const NR_GETRANDOM: libc::c_long = 384;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0u)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        let len = v.len();
        while read < len {
            let result = getrandom(v.slice_from_mut(read));
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as uint;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8; 4] = [0u8; 4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8; 8] = [0u8; 8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};

        static GETRANDOM_CHECKED: AtomicBool = ATOMIC_BOOL_INIT;
        static GETRANDOM_AVAILABLE: AtomicBool = ATOMIC_BOOL_INIT;

        if !GETRANDOM_CHECKED.load(Ordering::Relaxed) {
            let mut buf: [u8; 0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = errno() as libc::c_int;
                err != libc::ENOSYS
            } else {
                true
            };
            GETRANDOM_AVAILABLE.store(available, Ordering::Relaxed);
            GETRANDOM_CHECKED.store(true, Ordering::Relaxed);
            available
        } else {
            GETRANDOM_AVAILABLE.load(Ordering::Relaxed)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    ///
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use io::{IoResult};
    use kinds::Sync;
    use mem;
    use os;
    use rand::Rng;
    use result::Result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::SliceExt;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    ///
    /// This does not block.
    #[allow(missing_copy_implementations)]
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside of this module
        _dummy: (),
    }

    #[repr(C)]
    struct SecRandom;

    unsafe impl Sync for *const SecRandom {}

    #[allow(non_upper_case_globals)]
    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::Result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::SliceExt;

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use prelude::v1::*;

    use sync::mpsc::channel;
    use rand::Rng;
    use super::OsRng;
    use thread::Thread;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8; 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);

            Thread::spawn(move|| {
                // wait until all the tasks are ready to go.
                rx.recv().unwrap();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                Thread::yield_now();
                let mut v = [0u8; 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    Thread::yield_now();
                    r.next_u64();
                    Thread::yield_now();
                    r.fill_bytes(&mut v);
                    Thread::yield_now();
                }
            }).detach();
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(()).unwrap();
        }
    }
}
<commit_msg>Use $crate and macro reexport to reduce duplicated code<commit_after>// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    extern crate libc;

    use self::OsRngInner::*;

    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::Result::Ok;
    use slice::SliceExt;
    use mem;
    use os::errno;

    // NOTE: for old macros; remove after the next snapshot
    #[cfg(stage0)] use result::Result::Err;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
        const NR_GETRANDOM: libc::c_long = 384;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0u)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        let len = v.len();
        while read < len {
            let result = getrandom(v.slice_from_mut(read));
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as uint;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8; 4] = [0u8; 4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8; 8] = [0u8; 8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};

        static GETRANDOM_CHECKED: AtomicBool = ATOMIC_BOOL_INIT;
        static GETRANDOM_AVAILABLE: AtomicBool = ATOMIC_BOOL_INIT;

        if !GETRANDOM_CHECKED.load(Ordering::Relaxed) {
            let mut buf: [u8; 0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = errno() as libc::c_int;
                err != libc::ENOSYS
            } else {
                true
            };
            GETRANDOM_AVAILABLE.store(available, Ordering::Relaxed);
            GETRANDOM_CHECKED.store(true, Ordering::Relaxed);
            available
        } else {
            GETRANDOM_AVAILABLE.load(Ordering::Relaxed)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    ///
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use io::{IoResult};
    use kinds::Sync;
    use mem;
    use os;
    use rand::Rng;
    use result::Result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::SliceExt;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    ///
    /// This does not block.
    #[allow(missing_copy_implementations)]
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside of this module
        _dummy: (),
    }

    #[repr(C)]
    struct SecRandom;

    unsafe impl Sync for *const SecRandom {}

    #[allow(non_upper_case_globals)]
    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::Result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::SliceExt;

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use prelude::v1::*;

    use sync::mpsc::channel;
    use rand::Rng;
    use super::OsRng;
    use thread::Thread;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8; 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);

            Thread::spawn(move|| {
                // wait until all the tasks are ready to go.
                rx.recv().unwrap();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                Thread::yield_now();
                let mut v = [0u8; 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    Thread::yield_now();
                    r.next_u64();
                    Thread::yield_now();
                    r.fill_bytes(&mut v);
                    Thread::yield_now();
                }
            }).detach();
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(()).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>/* 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/. */

use std::env;
use std::path::{Path, PathBuf};
use std::io::prelude::*;
use std::fs::{canonicalize, read_dir, File};

fn write_shaders(glsl_files: Vec<PathBuf>, shader_file_path: &Path) {
    let mut shader_file = File::create(shader_file_path).unwrap();

    write!(shader_file, "/// AUTO GENERATED BY build.rs\n\n").unwrap();
    write!(shader_file, "use std::collections::HashMap;\n").unwrap();
    write!(shader_file, "lazy_static! {{\n").unwrap();
    write!(shader_file, "  pub static ref SHADERS: HashMap<&'static str, &'static str> = {{\n").unwrap();
    write!(shader_file, "    let mut h = HashMap::with_capacity({});\n", glsl_files.len()).unwrap();
    for glsl in glsl_files {
        let shader_name = glsl.file_name().unwrap().to_str().unwrap();
        // strip .glsl
        let shader_name = shader_name.replace(".glsl", "");
        let full_path = canonicalize(&glsl).unwrap();
        let full_name = full_path.as_os_str().to_str().unwrap();
        // if someone is building on a network share, I'm sorry.
        let full_name = full_name.replace("\\\\?\\", "");
        let full_name = full_name.replace("\\", "/");
        write!(shader_file, "    h.insert(\"{}\", include_str!(\"{}\"));\n",
               shader_name, full_name).unwrap();
    }
    write!(shader_file, "    h\n").unwrap();
    write!(shader_file, "  }};\n").unwrap();
    write!(shader_file, "}}\n").unwrap();
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap_or("out".to_owned());

    let shaders_file = Path::new(&out_dir).join("shaders.rs");
    let mut glsl_files = vec![];

    let res_dir = Path::new("res");
    for entry in read_dir(res_dir).unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();
        if entry.file_name().to_str().unwrap().ends_with(".glsl") {
            glsl_files.push(path.to_owned());
        }
    }

    write_shaders(glsl_files, &shaders_file);
}
<commit_msg>Only rerun build.rs on changes to the res directory<commit_after>/* 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/. */

use std::env;
use std::path::{Path, PathBuf};
use std::io::prelude::*;
use std::fs::{canonicalize, read_dir, File};

fn write_shaders(glsl_files: Vec<PathBuf>, shader_file_path: &Path) {
    let mut shader_file = File::create(shader_file_path).unwrap();

    write!(shader_file, "/// AUTO GENERATED BY build.rs\n\n").unwrap();
    write!(shader_file, "use std::collections::HashMap;\n").unwrap();
    write!(shader_file, "lazy_static! {{\n").unwrap();
    write!(shader_file, "  pub static ref SHADERS: HashMap<&'static str, &'static str> = {{\n").unwrap();
    write!(shader_file, "    let mut h = HashMap::with_capacity({});\n", glsl_files.len()).unwrap();
    for glsl in glsl_files {
        let shader_name = glsl.file_name().unwrap().to_str().unwrap();
        // strip .glsl
        let shader_name = shader_name.replace(".glsl", "");
        let full_path = canonicalize(&glsl).unwrap();
        let full_name = full_path.as_os_str().to_str().unwrap();
        // if someone is building on a network share, I'm sorry.
        let full_name = full_name.replace("\\\\?\\", "");
        let full_name = full_name.replace("\\", "/");
        write!(shader_file, "    h.insert(\"{}\", include_str!(\"{}\"));\n",
               shader_name, full_name).unwrap();
    }
    write!(shader_file, "    h\n").unwrap();
    write!(shader_file, "  }};\n").unwrap();
    write!(shader_file, "}}\n").unwrap();
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap_or("out".to_owned());

    let shaders_file = Path::new(&out_dir).join("shaders.rs");
    let mut glsl_files = vec![];

    println!("cargo:rerun-if-changed=res");
    let res_dir = Path::new("res");
    for entry in read_dir(res_dir).unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();
        if entry.file_name().to_str().unwrap().ends_with(".glsl") {
            glsl_files.push(path.to_owned());
        }
    }

    write_shaders(glsl_files, &shaders_file);
}
<|endoftext|>


<commit_before>use std::path::Path;
use std::path::PathBuf;

use cargo_edit::{resolve_manifests, shell_status, shell_warn, upgrade_requirement, LocalManifest};
use clap::Args;

use crate::errors::*;
use crate::version::BumpLevel;
use crate::version::TargetVersion;

/// Change a package's version in the local manifest file (i.e. Cargo.toml).
#[derive(Debug, Args)]
#[command(version)]
#[command(group = clap::ArgGroup::new("ver").multiple(false))]
pub struct VersionArgs {
    /// Version to change manifests to
    #[arg(group = "ver")]
    target: Option<semver::Version>,

    /// Increment manifest version
    #[arg(long, group = "ver")]
    bump: Option<BumpLevel>,

    /// Specify the version metadata field (e.g. a wrapped libraries version)
    #[arg(short, long)]
    pub metadata: Option<String>,

    /// Path to the manifest to upgrade
    #[arg(long, value_name = "PATH")]
    manifest_path: Option<PathBuf>,

    /// Package id of the crate to change the version of.
    #[arg(
        long = "package",
        short = 'p',
        value_name = "PKGID",
        conflicts_with = "all",
        conflicts_with = "workspace"
    )]
    pkgid: Option<String>,

    /// Modify all packages in the workspace.
    #[arg(
        long,
        help = "[deprecated in favor of `--workspace`]",
        conflicts_with = "workspace",
        conflicts_with = "pkgid"
    )]
    all: bool,

    /// Modify all packages in the workspace.
    #[arg(long, conflicts_with = "all", conflicts_with = "pkgid")]
    workspace: bool,

    /// Print changes to be made without making them.
    #[arg(long)]
    dry_run: bool,

    /// Crates to exclude and not modify.
    #[arg(long)]
    exclude: Vec<String>,

    /// Run without accessing the network
    #[arg(long)]
    offline: bool,

    /// Require `Cargo.toml` to be up to date
    #[arg(long)]
    locked: bool,

    /// Unstable (nightly-only) flags
    #[arg(short = 'Z', value_name = "FLAG", global = true, value_enum)]
    unstable_features: Vec<UnstableOptions>,
}

impl VersionArgs {
    pub fn exec(self) -> CargoResult<()> {
        exec(self)
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, clap::ValueEnum)]
enum UnstableOptions {}

/// Main processing function. Allows us to return a `Result` so that `main` can print pretty error
/// messages.
fn exec(args: VersionArgs) -> CargoResult<()> {
    let VersionArgs {
        target,
        bump,
        metadata,
        manifest_path,
        pkgid,
        all,
        dry_run,
        workspace,
        exclude,
        locked,
        offline,
        unstable_features: _,
    } = args;

    let target = match (target, bump) {
        (None, None) => TargetVersion::Relative(BumpLevel::Release),
        (None, Some(level)) => TargetVersion::Relative(level),
        (Some(version), None) => TargetVersion::Absolute(version),
        (Some(_), Some(_)) => unreachable!("clap groups should prevent this"),
    };

    if all {
        shell_warn("The flag `--all` has been deprecated in favor of `--workspace`")?;
    }
    let all = workspace || all;
    let manifests = resolve_manifests(
        manifest_path.as_deref(),
        all,
        pkgid.as_deref().into_iter().collect::<Vec<_>>(),
    )?;

    let ws_metadata = resolve_ws(manifest_path.as_deref(), locked, offline)?;
    let workspace_members = find_ws_members(&ws_metadata);

    for package in manifests {
        if exclude.contains(&package.name) {
            continue;
        }
        let current = &package.version;
        let next = target.bump(current, metadata.as_deref())?;
        if let Some(next) = next {
            {
                let mut manifest = LocalManifest::try_new(Path::new(&package.manifest_path))?;
                manifest.set_package_version(&next);

                shell_status(
                    "Upgrading",
                    &format!("{} from {} to {}", package.name, current, next),
                )?;
                if !dry_run {
                    manifest.write()?;
                }
            }

            let crate_root =
                dunce::canonicalize(package.manifest_path.parent().expect("at least a parent"))?;
            for member in workspace_members.iter() {
                let mut dep_manifest = LocalManifest::try_new(member.manifest_path.as_std_path())?;
                let mut changed = false;
                let dep_crate_root = dep_manifest
                    .path
                    .parent()
                    .expect("at least a parent")
                    .to_owned();
                for dep in dep_manifest
                    .get_dependency_tables_mut()
                    .flat_map(|t| t.iter_mut().filter_map(|(_, d)| d.as_table_like_mut()))
                    .filter(|d| {
                        if !d.contains_key("version") {
                            return false;
                        }
                        match d.get("path").and_then(|i| i.as_str()).and_then(|relpath| {
                            dunce::canonicalize(dep_crate_root.join(relpath)).ok()
                        }) {
                            Some(dep_path) => dep_path == crate_root.as_path(),
                            None => false,
                        }
                    })
                {
                    let old_req = dep
                        .get("version")
                        .expect("filter ensures this")
                        .as_str()
                        .unwrap_or("*");
                    if let Some(new_req) = upgrade_requirement(old_req, &next)? {
                        shell_status(
                            "Updating",
                            &format!(
                                "{}'s dependency from {} to {}",
                                member.name, old_req, new_req
                            ),
                        )?;
                        dep.insert("version", toml_edit::value(new_req));
                        changed = true;
                    }
                }
                if changed && !dry_run {
                    dep_manifest.write()?;
                }
            }
        }
    }

    if args.dry_run {
        shell_warn("aborting set-version due to dry run")?;
    }

    Ok(())
}

fn resolve_ws(
    manifest_path: Option<&Path>,
    locked: bool,
    offline: bool,
) -> CargoResult<cargo_metadata::Metadata> {
    let mut cmd = cargo_metadata::MetadataCommand::new();
    if let Some(manifest_path) = manifest_path {
        cmd.manifest_path(manifest_path);
    }
    cmd.features(cargo_metadata::CargoOpt::AllFeatures);
    let mut other = Vec::new();
    if locked {
        other.push("--locked".to_owned());
    }
    if offline {
        other.push("--offline".to_owned());
    }
    cmd.other_options(other);

    let ws = cmd.exec().or_else(|_| {
        cmd.no_deps();
        cmd.exec()
    })?;
    Ok(ws)
}

fn find_ws_members(ws: &cargo_metadata::Metadata) -> Vec<cargo_metadata::Package> {
    let workspace_members: std::collections::HashSet<_> = ws.workspace_members.iter().collect();
    ws.packages
        .iter()
        .filter(|p| workspace_members.contains(&p.id))
        .cloned()
        .collect()
}
<commit_msg>refactor(version): Split out dependent updating<commit_after>use std::path::Path;
use std::path::PathBuf;

use cargo_edit::{resolve_manifests, shell_status, shell_warn, upgrade_requirement, LocalManifest};
use clap::Args;

use crate::errors::*;
use crate::version::BumpLevel;
use crate::version::TargetVersion;

/// Change a package's version in the local manifest file (i.e. Cargo.toml).
#[derive(Debug, Args)]
#[command(version)]
#[command(group = clap::ArgGroup::new("ver").multiple(false))]
pub struct VersionArgs {
    /// Version to change manifests to
    #[arg(group = "ver")]
    target: Option<semver::Version>,

    /// Increment manifest version
    #[arg(long, group = "ver")]
    bump: Option<BumpLevel>,

    /// Specify the version metadata field (e.g. a wrapped libraries version)
    #[arg(short, long)]
    pub metadata: Option<String>,

    /// Path to the manifest to upgrade
    #[arg(long, value_name = "PATH")]
    manifest_path: Option<PathBuf>,

    /// Package id of the crate to change the version of.
    #[arg(
        long = "package",
        short = 'p',
        value_name = "PKGID",
        conflicts_with = "all",
        conflicts_with = "workspace"
    )]
    pkgid: Option<String>,

    /// Modify all packages in the workspace.
    #[arg(
        long,
        help = "[deprecated in favor of `--workspace`]",
        conflicts_with = "workspace",
        conflicts_with = "pkgid"
    )]
    all: bool,

    /// Modify all packages in the workspace.
    #[arg(long, conflicts_with = "all", conflicts_with = "pkgid")]
    workspace: bool,

    /// Print changes to be made without making them.
    #[arg(long)]
    dry_run: bool,

    /// Crates to exclude and not modify.
    #[arg(long)]
    exclude: Vec<String>,

    /// Run without accessing the network
    #[arg(long)]
    offline: bool,

    /// Require `Cargo.toml` to be up to date
    #[arg(long)]
    locked: bool,

    /// Unstable (nightly-only) flags
    #[arg(short = 'Z', value_name = "FLAG", global = true, value_enum)]
    unstable_features: Vec<UnstableOptions>,
}

impl VersionArgs {
    pub fn exec(self) -> CargoResult<()> {
        exec(self)
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, clap::ValueEnum)]
enum UnstableOptions {}

/// Main processing function. Allows us to return a `Result` so that `main` can print pretty error
/// messages.
fn exec(args: VersionArgs) -> CargoResult<()> {
    let VersionArgs {
        target,
        bump,
        metadata,
        manifest_path,
        pkgid,
        all,
        dry_run,
        workspace,
        exclude,
        locked,
        offline,
        unstable_features: _,
    } = args;

    let target = match (target, bump) {
        (None, None) => TargetVersion::Relative(BumpLevel::Release),
        (None, Some(level)) => TargetVersion::Relative(level),
        (Some(version), None) => TargetVersion::Absolute(version),
        (Some(_), Some(_)) => unreachable!("clap groups should prevent this"),
    };

    if all {
        shell_warn("The flag `--all` has been deprecated in favor of `--workspace`")?;
    }
    let all = workspace || all;
    let manifests = resolve_manifests(
        manifest_path.as_deref(),
        all,
        pkgid.as_deref().into_iter().collect::<Vec<_>>(),
    )?;

    let ws_metadata = resolve_ws(manifest_path.as_deref(), locked, offline)?;
    let workspace_members = find_ws_members(&ws_metadata);

    for package in manifests {
        if exclude.contains(&package.name) {
            continue;
        }
        let current = &package.version;
        let next = target.bump(current, metadata.as_deref())?;
        if let Some(next) = next {
            {
                let mut manifest = LocalManifest::try_new(Path::new(&package.manifest_path))?;
                manifest.set_package_version(&next);

                shell_status(
                    "Upgrading",
                    &format!("{} from {} to {}", package.name, current, next),
                )?;
                if !dry_run {
                    manifest.write()?;
                }
            }

            let crate_root =
                dunce::canonicalize(package.manifest_path.parent().expect("at least a parent"))?;
            update_member_dependents(&workspace_members, &crate_root, &next, dry_run)?
        }
    }

    if args.dry_run {
        shell_warn("aborting set-version due to dry run")?;
    }

    Ok(())
}

fn update_member_dependents(
    workspace_members: &[cargo_metadata::Package],
    crate_root: &Path,
    next: &semver::Version,
    dry_run: bool,
) -> CargoResult<()> {
    for member in workspace_members.iter() {
        let mut dep_manifest = LocalManifest::try_new(member.manifest_path.as_std_path())?;
        let mut changed = false;
        let dep_crate_root = dep_manifest
            .path
            .parent()
            .expect("at least a parent")
            .to_owned();
        for dep in dep_manifest
            .get_dependency_tables_mut()
            .flat_map(|t| t.iter_mut().filter_map(|(_, d)| d.as_table_like_mut()))
            .filter(|d| {
                if !d.contains_key("version") {
                    return false;
                }
                match d
                    .get("path")
                    .and_then(|i| i.as_str())
                    .and_then(|relpath| dunce::canonicalize(dep_crate_root.join(relpath)).ok())
                {
                    Some(dep_path) => dep_path == crate_root,
                    None => false,
                }
            })
        {
            let old_req = dep
                .get("version")
                .expect("filter ensures this")
                .as_str()
                .unwrap_or("*");
            if let Some(new_req) = upgrade_requirement(old_req, &next)? {
                shell_status(
                    "Updating",
                    &format!(
                        "{}'s dependency from {} to {}",
                        member.name, old_req, new_req
                    ),
                )?;
                dep.insert("version", toml_edit::value(new_req));
                changed = true;
            }
        }
        if changed && !dry_run {
            dep_manifest.write()?;
        }
    }

    Ok(())
}

fn resolve_ws(
    manifest_path: Option<&Path>,
    locked: bool,
    offline: bool,
) -> CargoResult<cargo_metadata::Metadata> {
    let mut cmd = cargo_metadata::MetadataCommand::new();
    if let Some(manifest_path) = manifest_path {
        cmd.manifest_path(manifest_path);
    }
    cmd.features(cargo_metadata::CargoOpt::AllFeatures);
    let mut other = Vec::new();
    if locked {
        other.push("--locked".to_owned());
    }
    if offline {
        other.push("--offline".to_owned());
    }
    cmd.other_options(other);

    let ws = cmd.exec().or_else(|_| {
        cmd.no_deps();
        cmd.exec()
    })?;
    Ok(ws)
}

fn find_ws_members(ws: &cargo_metadata::Metadata) -> Vec<cargo_metadata::Package> {
    let workspace_members: std::collections::HashSet<_> = ws.workspace_members.iter().collect();
    ws.packages
        .iter()
        .filter(|p| workspace_members.contains(&p.id))
        .cloned()
        .collect()
}
<|endoftext|>


<commit_before>use Configuration;
#[cfg(feature = "unstable")]
use future::{Future, RayonFuture};
use latch::LockLatch;
#[allow(unused_imports)]
use log::Event::*;
use job::StackJob;
#[cfg(feature = "unstable")]
use spawn;
use std::sync::Arc;
use std::error::Error;
use registry::{Registry, WorkerThread};

mod test;

pub struct ThreadPool {
    registry: Arc<Registry>,
}

impl ThreadPool {
    /// Constructs a new thread pool with the given configuration. If
    /// the configuration is not valid, returns a suitable `Err`
    /// result.  See `InitError` for more details.
    pub fn new(configuration: Configuration) -> Result<ThreadPool, Box<Error>> {
        let registry = try!(Registry::new(configuration));
        Ok(ThreadPool { registry: registry })
    }

    /// Returns a handle to the global thread pool. This is the pool
    /// that Rayon will use by default when you perform a `join()` or
    /// `scope()` operatioon, if no other thread-pool is installed. If
    /// no global thread-pool has yet been started when this function
    /// is called, then the global thread-pool will be created (with
    /// the default configuration). If you wish to configure the
    /// global thread-pool differently, then you can use [the
    /// `rayon::initialize()` function][f] to do so.
    ///
    /// [f]: fn.initialize.html
    #[cfg(feature = "unstable")]
    pub fn global() -> &'static Arc<ThreadPool> {
        lazy_static! {
            static ref DEFAULT_THREAD_POOL: Arc<ThreadPool> =
                Arc::new(ThreadPool { registry: Registry::global() });
        }

        &DEFAULT_THREAD_POOL
    }

    /// Executes `op` within the threadpool. Any attempts to use
    /// `join`, `scope`, or parallel iterators will then operate
    /// within that threadpool.
    ///
    /// # Warning: thread-local data
    ///
    /// Because `op` is executing within the Rayon thread-pool,
    /// thread-local data from the current thread will not be
    /// accessible.
    ///
    /// # Panics
    ///
    /// If `op` should panic, that panic will be propagated.
    pub fn install<OP, R>(&self, op: OP) -> R
        where OP: FnOnce() -> R + Send
    {
        unsafe {
            let job_a = StackJob::new(op, LockLatch::new());
            self.registry.inject(&[job_a.as_job_ref()]);
            job_a.latch.wait();
            job_a.into_result()
        }
    }

    /// Returns the (current) number of threads in the thread pool.
    ///
    /// ### Future compatibility note
    ///
    /// Note that unless this thread-pool was created with a
    /// configuration that specifies the number of threads, then this
    /// number may vary over time in future versions (see [the
    /// `num_threads()` method for details][snt]).
    ///
    /// [snt]: struct.Configuration.html#method.num_threads
    pub fn current_num_threads(&self) -> usize {
        self.registry.num_threads()
    }

    /// If called from a Rayon worker thread in this thread-pool,
    /// returns the index of that thread; if not called from a Rayon
    /// thread, or called from a Rayon thread that belongs to a
    /// different thread-pool, returns `None`.
    ///
    /// The index for a given thread will not change over the thread's
    /// lifetime. However, multiple threads may share the same index if
    /// they are in distinct thread-pools.
    ///
    /// ### Future compatibility note
    ///
    /// Currently, every thread-pool (including the global
    /// thread-pool) has a fixed number of threads, but this may
    /// change in future Rayon versions (see [the `num_threads()` method
    /// for details][snt]). In that case, the index for a
    /// thread would not change during its lifetime, but thread
    /// indices may wind up being reused if threads are terminated and
    /// restarted.
    ///
    /// [snt]: struct.Configuration.html#method.num_threads
    pub fn current_thread_index(&self) -> Option<usize> {
        unsafe {
            let curr = WorkerThread::current();
            if curr.is_null() {
                None
            } else if (*curr).registry().id() != self.registry.id() {
                None
            } else {
                Some((*curr).index())
            }
        }
    }

    /// Spawns a task in this thread-pool contained within the static
    /// scope. See `spawn()` for more details.
    #[cfg(feature = "unstable")]
    pub fn spawn<OP>(&self, op: OP)
        where OP: FnOnce() + Send + 'static
    {
        // We assert that `self.registry` has not terminated.
        unsafe { spawn::spawn_in(op, &self.registry) }
    }

    /// Spawns an future in this thread-pool within the static
    /// scope. See `spawn_future()` for more details.
    #[cfg(feature = "unstable")]
    pub fn spawn_future<F>(&self, future: F) -> RayonFuture<F::Item, F::Error>
        where F: Future + Send + 'static
    {
        // We assert that `self.registry` has not yet terminated.
        unsafe { spawn::spawn_future_in(future, self.registry.clone()) }
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        self.registry.terminate();
    }
}

<commit_msg>allow people to call `join` and `scope` on `ThreadPool`<commit_after>use Configuration;
#[cfg(feature = "unstable")]
use future::{Future, RayonFuture};
use latch::LockLatch;
#[allow(unused_imports)]
use log::Event::*;
use job::StackJob;
use join;
use {scope, Scope};
#[cfg(feature = "unstable")]
use spawn;
use std::sync::Arc;
use std::error::Error;
use registry::{Registry, WorkerThread};

mod test;

pub struct ThreadPool {
    registry: Arc<Registry>,
}

impl ThreadPool {
    /// Constructs a new thread pool with the given configuration. If
    /// the configuration is not valid, returns a suitable `Err`
    /// result.  See `InitError` for more details.
    pub fn new(configuration: Configuration) -> Result<ThreadPool, Box<Error>> {
        let registry = try!(Registry::new(configuration));
        Ok(ThreadPool { registry: registry })
    }

    /// Returns a handle to the global thread pool. This is the pool
    /// that Rayon will use by default when you perform a `join()` or
    /// `scope()` operation, if no other thread-pool is installed. If
    /// no global thread-pool has yet been started when this function
    /// is called, then the global thread-pool will be created (with
    /// the default configuration). If you wish to configure the
    /// global thread-pool differently, then you can use [the
    /// `rayon::initialize()` function][f] to do so.
    ///
    /// [f]: fn.initialize.html
    #[cfg(feature = "unstable")]
    pub fn global() -> &'static Arc<ThreadPool> {
        lazy_static! {
            static ref DEFAULT_THREAD_POOL: Arc<ThreadPool> =
                Arc::new(ThreadPool { registry: Registry::global() });
        }

        &DEFAULT_THREAD_POOL
    }

    /// Executes `op` within the threadpool. Any attempts to use
    /// `join`, `scope`, or parallel iterators will then operate
    /// within that threadpool.
    ///
    /// # Warning: thread-local data
    ///
    /// Because `op` is executing within the Rayon thread-pool,
    /// thread-local data from the current thread will not be
    /// accessible.
    ///
    /// # Panics
    ///
    /// If `op` should panic, that panic will be propagated.
    pub fn install<OP, R>(&self, op: OP) -> R
        where OP: FnOnce() -> R + Send
    {
        unsafe {
            let job_a = StackJob::new(op, LockLatch::new());
            self.registry.inject(&[job_a.as_job_ref()]);
            job_a.latch.wait();
            job_a.into_result()
        }
    }

    /// Returns the (current) number of threads in the thread pool.
    ///
    /// ### Future compatibility note
    ///
    /// Note that unless this thread-pool was created with a
    /// configuration that specifies the number of threads, then this
    /// number may vary over time in future versions (see [the
    /// `num_threads()` method for details][snt]).
    ///
    /// [snt]: struct.Configuration.html#method.num_threads
    pub fn current_num_threads(&self) -> usize {
        self.registry.num_threads()
    }

    /// If called from a Rayon worker thread in this thread-pool,
    /// returns the index of that thread; if not called from a Rayon
    /// thread, or called from a Rayon thread that belongs to a
    /// different thread-pool, returns `None`.
    ///
    /// The index for a given thread will not change over the thread's
    /// lifetime. However, multiple threads may share the same index if
    /// they are in distinct thread-pools.
    ///
    /// ### Future compatibility note
    ///
    /// Currently, every thread-pool (including the global
    /// thread-pool) has a fixed number of threads, but this may
    /// change in future Rayon versions (see [the `num_threads()` method
    /// for details][snt]). In that case, the index for a
    /// thread would not change during its lifetime, but thread
    /// indices may wind up being reused if threads are terminated and
    /// restarted.
    ///
    /// [snt]: struct.Configuration.html#method.num_threads
    pub fn current_thread_index(&self) -> Option<usize> {
        unsafe {
            let curr = WorkerThread::current();
            if curr.is_null() {
                None
            } else if (*curr).registry().id() != self.registry.id() {
                None
            } else {
                Some((*curr).index())
            }
        }
    }

    /// Execute `oper_a` and `oper_b` in the thread-pool and return
    /// the results. Equivalent to `self.install(|| join(oper_a,
    /// oper_b))`.
    #[cfg(feature = "unstable")]
    pub fn join<A, B, RA, RB>(&self, oper_a: A, oper_b: B) -> (RA, RB)
        where A: FnOnce() -> RA + Send,
              B: FnOnce() -> RB + Send,
              RA: Send,
              RB: Send
    {
        self.install(|| join(oper_a, oper_b))
    }

    /// Execute `oper_a` and `oper_b` in the thread-pool and return
    /// the results. Equivalent to `self.install(|| scope(...))`.
    #[cfg(feature = "unstable")]
    pub fn scope<'scope, OP, R>(&self, op: OP) -> R
        where OP: for<'s> FnOnce(&'s Scope<'scope>) -> R + 'scope + Send, R: Send
    {
        self.install(|| scope(op))
    }

    /// Spawns an asynchronous task in this thread-pool. See `spawn()`
    /// for more details.
    #[cfg(feature = "unstable")]
    pub fn spawn<OP>(&self, op: OP)
        where OP: FnOnce() + Send + 'static
    {
        // We assert that `self.registry` has not terminated.
        unsafe { spawn::spawn_in(op, &self.registry) }
    }

    /// Spawns an asynchronous future in this thread-pool. See
    /// `spawn_future()` for more details.
    #[cfg(feature = "unstable")]
    pub fn spawn_future<F>(&self, future: F) -> RayonFuture<F::Item, F::Error>
        where F: Future + Send + 'static
    {
        // We assert that `self.registry` has not yet terminated.
        unsafe { spawn::spawn_future_in(future, self.registry.clone()) }
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        self.registry.terminate();
    }
}

<|endoftext|>