<commit_before>#![feature(test)]

#![feature(plugin)]
#![plugin(clippy)]

extern crate test;
extern crate rand;

use rand::distributions::{IndependentSample, Range};

pub struct Settings<R>
    where R: rand::Rng
{
    pub min_pos: Vec<f32>,
    pub max_pos: Vec<f32>,

    pub cr_min: f32,
    pub cr_max: f32,
    pub cr_change_probability: f32,

    pub f_min: f32,
    pub f_max: f32,
    pub f_change_probability: f32,

    pub pop_size: usize,
    pub rng: R,
}

impl<R> Settings<R>
    where R: rand::Rng
{
    pub fn min_max_rng(min_pos: Vec<f32>, max_pos: Vec<f32>, rng: R) -> Settings<R> {
        // create settings for the algorithm
        Settings {
            min_pos: min_pos,
            max_pos: max_pos,

            cr_min: 0.0,
            cr_max: 1.0,
            cr_change_probability: 0.1,

            f_min: 0.1,
            f_max: 1.0,
            f_change_probability: 0.1,

            pop_size: 50,
            rng: rng,
        }
    }
}

impl Settings<rand::XorShiftRng> {
    pub fn new(min_pos: Vec<f32>, max_pos: Vec<f32>) -> Settings<rand::XorShiftRng> {
        Settings::min_max_rng(min_pos, max_pos, rand::weak_rng())
    }
}

#[derive(Clone,Debug)]
pub struct Individual {
    pub pos: Vec<f32>,
    // the lower, the better.
    pub cost: Option<f32>,

    // control parameters
    cr: f32,
    f: f32,
}

pub struct Population<R>
    where R: rand::Rng
{
    // TODO use a single vector for curr and best and controlparameters?
    pub curr: Vec<Individual>,
    best: Vec<Individual>,

    settings: Settings<R>,
    best_idx: Option<usize>,
    dim: usize,
    between_popsize: Range<usize>,
    between_01: Range<f32>,
    between_dim: Range<usize>,
    between_cr: Range<f32>,
    between_f: Range<f32>,
}

impl<R> Population<R>
    where R: rand::Rng
{
    // Creates a new population based on the given settings.
    pub fn new(s: Settings<R>) -> Population<R> {
        assert_eq!(s.min_pos.len(),
                   s.max_pos.len(),
                   "min_pos and max_pos need to have the same number of elements");
        assert!(s.min_pos.len() >= 1,
                "need at least one element to optimize");

        // create a vector of randomly initialized individuals for current.
        let dim = s.min_pos.len();

        // Empty individual, with no cost value (yet)
        let dummy_individual = Individual {
            pos: vec![0.0; dim],
            cost: None,
            cr: 0.0,
            f: 0.0,
        };

        // creates all the empty individuals
        let mut pop = Population {
            curr: vec![dummy_individual.clone(); s.pop_size],
            best: vec![dummy_individual; s.pop_size],
            best_idx: None,
            dim: dim,
            between_popsize: Range::new(0, s.pop_size),
            between_01: Range::new(0.0, 1.0),
            between_dim: Range::new(0, dim),
            between_cr: Range::new(s.cr_min, s.cr_max),
            between_f: Range::new(s.f_min, s.f_max),
            settings: s,
        };

        for ind in &mut pop.curr {
            // init control parameters
            ind.cr = pop.between_cr.ind_sample(&mut pop.settings.rng);
            ind.f = pop.between_f.ind_sample(&mut pop.settings.rng);

            // random range for each dimension
            for d in 0..dim {
                let between_min_max = Range::new(pop.settings.min_pos[d], pop.settings.max_pos[d]);
                ind.pos[d] = between_min_max.ind_sample(&mut pop.settings.rng);
            }
        }

        pop
    }

    fn update_best(&mut self) -> bool {
        let last_best_cost: Option<f32>;
        if let Some(last_best_idx) = self.best_idx {
            last_best_cost = self.best[last_best_idx].cost;
        } else {
            last_best_cost = None;
        }

        let mut new_best_cost = self.curr[0].cost.unwrap();
        for i in 0..self.curr.len() {
            let curr = &mut self.curr[i];
            let best = &mut self.best[i];

            // we use <= here, so that the individual moves even if the cost
            // stays the same.
            if best.cost.is_none() || curr.cost.unwrap() <= best.cost.unwrap() {
                // find global best. We use < here so that global only updates when fitness changes.
                if curr.cost.unwrap() < new_best_cost {
                    self.best_idx = Some(i);
                    new_best_cost = curr.cost.unwrap();
                }

                // replace individual's best. swap is *much* faster than clone.
                std::mem::swap(curr, best);
            }
        }

        // got a new best?
        last_best_cost.is_none() || new_best_cost < last_best_cost.unwrap()
    }

    fn update_positions(&mut self) {
        let best_idx = self.best_idx.unwrap();
        let rng = &mut self.settings.rng;
        for i in 0..self.curr.len() {
            let mut id1 = i;
            while id1 == i {
                id1 = self.between_popsize.ind_sample(rng);
            }

            let mut id2 = i;
            while id2 == i || id2 == id1 {
                id2 = self.between_popsize.ind_sample(rng);
            }

            let curr = &mut self.curr[i];
            let best = &self.best[i];

            // see "Self-Adapting Control Parameters in Differential Evolution:
            // A Comparative Study on Numerical Benchmark Problems"
            curr.cr = best.cr;
            curr.f = best.f;
            if self.between_01.ind_sample(rng) < self.settings.cr_change_probability {
                curr.cr = self.between_cr.ind_sample(rng);
            }
            if self.between_01.ind_sample(rng) < self.settings.f_change_probability {
                curr.f = self.between_f.ind_sample(rng);
            }

            let forced_mutation_dim = self.between_dim.ind_sample(rng);
            for d in 0..self.dim {
                if d == forced_mutation_dim || self.between_01.ind_sample(rng) < curr.cr {

                    curr.pos[d] = self.best[best_idx].pos[d] +
                                  curr.f * (self.best[id1].pos[d] - self.best[id2].pos[d]);
                } else {
                    curr.pos[d] = self.best[i].pos[d];
                }
            }

            // reset cost, has to be updated by the user.
            curr.cost = None;
        }
    }

    // Uses updated cost values to update positions of individuals.
    pub fn evolve(&mut self) -> Option<&Individual> {
        let found_new_best = self.update_best();
        self.update_positions();

        if found_new_best {
            Some(&self.best[self.best_idx.unwrap()])
        } else {
            None
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate rand;
    use super::*;
    use test::{black_box, Bencher};
    use rand::{XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng};
    use rand::{OsRng, weak_rng};

    fn setup<R: rand::Rng>(dim: usize, rng: R) -> Population<R> {
        let settings = Settings::min_max_rng(vec![-20.0; dim], vec![20.0; dim], rng);
        Population::new(settings)
    }

    fn dummy_fitness(individuals: &mut Vec<Individual>) {
        for ind in individuals {
            ind.cost = Some(1.234);
        }
    }

    #[bench]
    fn bench_square_fitness_opt(b: &mut Bencher) {
        let rng: XorShiftRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, rng);
        b.iter(|| {
            for ind in &mut pop.curr {
                let mut f = 0.0;
                for x in &ind.pos {
                    f += x * x;
                }
                ind.cost = Some(f);
            }
            black_box(pop.evolve());
        });
    }

    #[bench]
    fn rand_thread_rng(b: &mut Bencher) {
        let mut pop = setup(5, rand::thread_rng());
        b.iter(|| {
            dummy_fitness(&mut pop.curr);
            black_box(pop.evolve());
        });
    }

    #[bench]
    fn rand_xor_shift(b: &mut Bencher) {
        let rng: XorShiftRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, rng);
        b.iter(|| {
            dummy_fitness(&mut pop.curr);
            pop.evolve();
        });
    }

    #[bench]
    fn rand_isaac(b: &mut Bencher) {
        let rng: IsaacRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, rng);
        b.iter(|| {
            dummy_fitness(&mut pop.curr);
            pop.evolve();
        });
    }

    #[bench]
    fn rand_isaac64(b: &mut Bencher) {
        let rng: Isaac64Rng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, rng);
        b.iter(|| {
            dummy_fitness(&mut pop.curr);
            pop.evolve();
        });
    }

    #[bench]
    fn rand_std(b: &mut Bencher) {
        let rng: StdRng = StdRng::new().unwrap();
        let mut pop = setup(5, rng);
        b.iter(|| {
            dummy_fitness(&mut pop.curr);
            pop.evolve();
        });
    }

    #[bench]
    fn rand_weak_rng(b: &mut Bencher) {
        let rng = weak_rng();
        let mut pop = setup(5, rng);
        b.iter(|| {
            dummy_fitness(&mut pop.curr);
            pop.evolve();
        });
    }

}
<commit_msg>bugfix when new best was in 0<commit_after>#![feature(test)]

#![feature(plugin)]
#![plugin(clippy)]

extern crate test;
extern crate rand;

use rand::distributions::{IndependentSample, Range};

pub struct Settings<R>
    where R: rand::Rng
{
    pub min_pos: Vec<f32>,
    pub max_pos: Vec<f32>,

    pub cr_min: f32,
    pub cr_max: f32,
    pub cr_change_probability: f32,

    pub f_min: f32,
    pub f_max: f32,
    pub f_change_probability: f32,

    pub pop_size: usize,
    pub rng: R,
}

impl<R> Settings<R>
    where R: rand::Rng
{
    pub fn min_max_rng(min_pos: Vec<f32>, max_pos: Vec<f32>, rng: R) -> Settings<R> {
        // create settings for the algorithm
        Settings {
            min_pos: min_pos,
            max_pos: max_pos,

            cr_min: 0.0,
            cr_max: 1.0,
            cr_change_probability: 0.1,

            f_min: 0.1,
            f_max: 1.0,
            f_change_probability: 0.1,

            pop_size: 50,
            rng: rng,
        }
    }
}

impl Settings<rand::XorShiftRng> {
    pub fn new(min_pos: Vec<f32>, max_pos: Vec<f32>) -> Settings<rand::XorShiftRng> {
        Settings::min_max_rng(min_pos, max_pos, rand::weak_rng())
    }
}

#[derive(Clone,Debug)]
pub struct Individual {
    pub pos: Vec<f32>,
    // the lower, the better.
    pub cost: Option<f32>,

    // control parameters
    cr: f32,
    f: f32,
}

pub struct Population<R>
    where R: rand::Rng
{
    // TODO use a single vector for curr and best and controlparameters?
    pub curr: Vec<Individual>,
    best: Vec<Individual>,

    settings: Settings<R>,
    best_idx: Option<usize>,
    dim: usize,
    between_popsize: Range<usize>,
    between_01: Range<f32>,
    between_dim: Range<usize>,
    between_cr: Range<f32>,
    between_f: Range<f32>,
}

impl<R> Population<R>
    where R: rand::Rng
{
    // Creates a new population based on the given settings.
    pub fn new(s: Settings<R>) -> Population<R> {
        assert_eq!(s.min_pos.len(),
                   s.max_pos.len(),
                   "min_pos and max_pos need to have the same number of elements");
        assert!(s.min_pos.len() >= 1,
                "need at least one element to optimize");

        // create a vector of randomly initialized individuals for current.
        let dim = s.min_pos.len();

        // Empty individual, with no cost value (yet)
        let dummy_individual = Individual {
            pos: vec![0.0; dim],
            cost: None,
            cr: 0.0,
            f: 0.0,
        };

        // creates all the empty individuals
        let mut pop = Population {
            curr: vec![dummy_individual.clone(); s.pop_size],
            best: vec![dummy_individual; s.pop_size],
            best_idx: None,
            dim: dim,
            between_popsize: Range::new(0, s.pop_size),
            between_01: Range::new(0.0, 1.0),
            between_dim: Range::new(0, dim),
            between_cr: Range::new(s.cr_min, s.cr_max),
            between_f: Range::new(s.f_min, s.f_max),
            settings: s,
        };

        for ind in &mut pop.curr {
            // init control parameters
            ind.cr = pop.between_cr.ind_sample(&mut pop.settings.rng);
            ind.f = pop.between_f.ind_sample(&mut pop.settings.rng);

            // random range for each dimension
            for d in 0..dim {
                let between_min_max = Range::new(pop.settings.min_pos[d], pop.settings.max_pos[d]);
                ind.pos[d] = between_min_max.ind_sample(&mut pop.settings.rng);
            }
        }

        pop
    }

    fn update_best(&mut self) -> bool {
        let last_best_cost: Option<f32>;
        if let Some(last_best_idx) = self.best_idx {
            last_best_cost = self.best[last_best_idx].cost;
        } else {
            last_best_cost = None;
        }

        let mut new_best_cost = last_best_cost;
        for i in 0..self.curr.len() {
            let curr = &mut self.curr[i];
            let best = &mut self.best[i];

            // we use <= here, so that the individual moves even if the cost
            // stays the same.
            if best.cost.is_none() || curr.cost.unwrap() <= best.cost.unwrap() {
                // find global best. We use < here so that global only updates when fitness changes.
                if new_best_cost.is_none() || curr.cost.unwrap() < new_best_cost.unwrap() {
                    self.best_idx = Some(i);
                    new_best_cost = curr.cost;
                }

                // replace individual's best. swap is *much* faster than clone.
                std::mem::swap(curr, best);
            }
        }

        // got a new best?
        last_best_cost.is_none() || new_best_cost.unwrap() < last_best_cost.unwrap()
    }

    fn update_positions(&mut self) {
        let best_idx = self.best_idx.unwrap();
        let rng = &mut self.settings.rng;
        for i in 0..self.curr.len() {
            let mut id1 = i;
            while id1 == i {
                id1 = self.between_popsize.ind_sample(rng);
            }

            let mut id2 = i;
            while id2 == i || id2 == id1 {
                id2 = self.between_popsize.ind_sample(rng);
            }

            let curr = &mut self.curr[i];
            let best = &self.best[i];

            // see "Self-Adapting Control Parameters in Differential Evolution:
            // A Comparative Study on Numerical Benchmark Problems"
            curr.cr = best.cr;
            curr.f = best.f;
            if self.between_01.ind_sample(rng) < self.settings.cr_change_probability {
                curr.cr = self.between_cr.ind_sample(rng);
            }
            if self.between_01.ind_sample(rng) < self.settings.f_change_probability {
                curr.f = self.between_f.ind_sample(rng);
            }

            let forced_mutation_dim = self.between_dim.ind_sample(rng);
            for d in 0..self.dim {
                if d == forced_mutation_dim || self.between_01.ind_sample(rng) < curr.cr {

                    curr.pos[d] = self.best[best_idx].pos[d] +
                                  curr.f * (self.best[id1].pos[d] - self.best[id2].pos[d]);
                } else {
                    curr.pos[d] = self.best[i].pos[d];
                }
            }

            // reset cost, has to be updated by the user.
            curr.cost = None;
        }
    }

    // Uses updated cost values to update positions of individuals.
    pub fn evolve(&mut self) -> Option<&Individual> {
        let found_new_best = self.update_best();
        self.update_positions();

        if found_new_best {
            Some(&self.best[self.best_idx.unwrap()])
        } else {
            None
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate rand;
    use super::*;
    use test::{black_box, Bencher};
    use rand::{XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng};
    use rand::{OsRng, weak_rng};

    fn setup<R: rand::Rng>(dim: usize, rng: R) -> Population<R> {
        let settings = Settings::min_max_rng(vec![-20.0; dim], vec![20.0; dim], rng);
        Population::new(settings)
    }

    fn dummy_fitness(individuals: &mut Vec<Individual>) {
        for ind in individuals {
            ind.cost = Some(1.234);
        }
    }

    #[bench]
    fn bench_square_fitness_opt(b: &mut Bencher) {
        let rng: XorShiftRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, rng);
        b.iter(|| {
            for ind in &mut pop.curr {
                let mut f = 0.0;
                for x in &ind.pos {
                    f += x * x;
                }
                ind.cost = Some(f);
            }
            black_box(pop.evolve());
        });
    }

    #[bench]
    fn rand_thread_rng(b: &mut Bencher) {
        let mut pop = setup(5, rand::thread_rng());
        b.iter(|| {
            dummy_fitness(&mut pop.curr);
            black_box(pop.evolve());
        });
    }

    #[bench]
    fn rand_xor_shift(b: &mut Bencher) {
        let rng: XorShiftRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, rng);
        b.iter(|| {
            dummy_fitness(&mut pop.curr);
            pop.evolve();
        });
    }

    #[bench]
    fn rand_isaac(b: &mut Bencher) {
        let rng: IsaacRng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, rng);
        b.iter(|| {
            dummy_fitness(&mut pop.curr);
            pop.evolve();
        });
    }

    #[bench]
    fn rand_isaac64(b: &mut Bencher) {
        let rng: Isaac64Rng = OsRng::new().unwrap().gen();
        let mut pop = setup(5, rng);
        b.iter(|| {
            dummy_fitness(&mut pop.curr);
            pop.evolve();
        });
    }

    #[bench]
    fn rand_std(b: &mut Bencher) {
        let rng: StdRng = StdRng::new().unwrap();
        let mut pop = setup(5, rng);
        b.iter(|| {
            dummy_fitness(&mut pop.curr);
            pop.evolve();
        });
    }

    #[bench]
    fn rand_weak_rng(b: &mut Bencher) {
        let rng = weak_rng();
        let mut pop = setup(5, rng);
        b.iter(|| {
            dummy_fitness(&mut pop.curr);
            pop.evolve();
        });
    }

}
<|endoftext|>


<commit_before>extern crate metal_sys;
extern crate cocoa;

use cocoa::foundation::NSUInteger;

pub mod sys {
    pub use metal_sys::*;
}

pub use sys::MTLClearColor as ClearColor;
pub use sys::MTLOrigin as Origin;
pub use sys::MTLRegion as Region;
pub use sys::MTLScissorRect as ScissorRect;
pub use sys::MTLSize as Size;
pub use sys::MTLViewport as Viewport;
pub use sys::MTLDrawPrimitivesIndirectArguments as DrawPrimitivesIndirectArguments;
pub use sys::MTLDrawIndexedPrimitivesIndirectArguments as DrawIndexedPrimitivesIndirectArguments;
pub use sys::MTLDispatchThreadgroupsIndirectArguments as DispatchThreadgroupsIndirectArguments;

pub fn clear_color(red: f64, green: f64, blue: f64, alpha: f64) -> ClearColor {
    sys::MTLClearColorMake(red, green, blue, alpha)
}

pub fn origin(x: usize, y: usize, z: usize) -> Origin {
    sys::MTLOriginMake(x, y, z)
}

pub fn region_1d(x: usize, width: usize) -> Region {
    sys::MTLRegionMake1D(x as NSUInteger, width as NSUInteger)
}

pub fn region_2d(x: usize, y: usize, width: usize, height: usize) -> Region {
    sys::MTLRegionMake2D(x as NSUInteger, y as NSUInteger, width as NSUInteger, height as NSUInteger)
}

pub fn region_3d(x: usize, y: usize, z: usize, width: usize, height: usize, depth: usize) -> Region {
    sys::MTLRegionMake3D(x as NSUInteger,
                         y as NSUInteger,
                         z  as NSUInteger,
                         width as NSUInteger,
                         height as NSUInteger,
                         depth as NSUInteger)
}

 pub fn size(width: usize, height: usize, depth: usize) -> Size {
     sys::MTLSizeMake(width, height, depth)
 }
<commit_msg>Cast integral types properly in high level functions<commit_after>extern crate metal_sys;
extern crate cocoa;

use cocoa::foundation::NSUInteger;

pub mod sys {
    pub use metal_sys::*;
}

pub use sys::MTLClearColor as ClearColor;
pub use sys::MTLOrigin as Origin;
pub use sys::MTLRegion as Region;
pub use sys::MTLScissorRect as ScissorRect;
pub use sys::MTLSize as Size;
pub use sys::MTLViewport as Viewport;
pub use sys::MTLDrawPrimitivesIndirectArguments as DrawPrimitivesIndirectArguments;
pub use sys::MTLDrawIndexedPrimitivesIndirectArguments as DrawIndexedPrimitivesIndirectArguments;
pub use sys::MTLDispatchThreadgroupsIndirectArguments as DispatchThreadgroupsIndirectArguments;

pub fn clear_color(red: f64, green: f64, blue: f64, alpha: f64) -> ClearColor {
    sys::MTLClearColorMake(red, green, blue, alpha)
}

pub fn origin(x: usize, y: usize, z: usize) -> Origin {
    sys::MTLOriginMake(x as NSUInteger, y as NSUInteger, z as NSUInteger)
}

pub fn region_1d(x: usize, width: usize) -> Region {
    sys::MTLRegionMake1D(x as NSUInteger, width as NSUInteger)
}

pub fn region_2d(x: usize, y: usize, width: usize, height: usize) -> Region {
    sys::MTLRegionMake2D(x as NSUInteger, y as NSUInteger, width as NSUInteger, height as NSUInteger)
}

pub fn region_3d(x: usize, y: usize, z: usize, width: usize, height: usize, depth: usize) -> Region {
    sys::MTLRegionMake3D(x as NSUInteger,
                         y as NSUInteger,
                         z  as NSUInteger,
                         width as NSUInteger,
                         height as NSUInteger,
                         depth as NSUInteger)
}

 pub fn size(width: usize, height: usize, depth: usize) -> Size {
     sys::MTLSizeMake(width as NSUInteger, height as NSUInteger, depth as NSUInteger)
 }
<|endoftext|>


<commit_before>// Copyright (c) 2016 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#![cfg_attr(feature="nightly", feature(
    specialization, // for impl FromPyObject<'s> for Vec<...> (#31844)
))]
#![allow(
    unused_imports, // because some imports are only necessary with python 2.x or 3.x
    clippy::missing_safety_doc,
    clippy::manual_strip,
    clippy::match_like_matches_macro
)]
#![warn(
    // TODO: We need to fix this
    macro_expanded_macro_exports_accessed_by_absolute_paths,
)]

//! Rust bindings to the Python interpreter.
//!
//! # Ownership and Lifetimes
//! In Python, all objects are implicitly reference counted.
//! In rust, we will use the `PyObject` type to represent a reference to a Python object.
//!
//! The method `clone_ref()` (from trait `PyClone`) can be used to create additional
//! references to the same Python object.
//!
//! Because all Python objects potentially have multiple owners, the
//! concept of Rust mutability does not apply to Python objects.
//! As a result, this API will allow mutating Python objects even if they are not stored
//! in a mutable Rust variable.
//!
//! The Python interpreter uses a global interpreter lock (GIL)
//! to ensure thread-safety.
//! This API uses a zero-sized `struct Python<'p>` as a token to indicate
//! that a function can assume that the GIL is held.
//!
//! You obtain a `Python` instance by acquiring the GIL,
//! and have to pass it into all operations that call into the Python runtime.
//!
//! # Python 2.7
//! The library will use the python3 bindings by default. To use the python2 bindings
//! you must specific the `python27` feature explicitly in your `Cargo.toml`.
//!
//! ```ignore
//! [dependencies.cpython]
//! version = "*"
//! default-features = false
//! features = ["python27-sys"]
//! ```
//!
//! # Error Handling
//! The vast majority of operations in this library will return `PyResult<...>`.
//! This is an alias for the type `Result<..., PyErr>`.
//!
//! A `PyErr` represents a Python exception. Errors within the rust-cpython library are
//! also exposed as Python exceptions.
//!
//! # Example
//! ```
//! use cpython::{Python, PyDict, PyResult};
//!
//! fn main() {
//!     let gil = Python::acquire_gil();
//!     hello(gil.python()).unwrap();
//! }
//!
//! fn hello(py: Python) -> PyResult<()> {
//!     let sys = py.import("sys")?;
//!     let version: String = sys.get(py, "version")?.extract(py)?;
//!
//!     let locals = PyDict::new(py);
//!     locals.set_item(py, "os", py.import("os")?)?;
//!     let user: String = py.eval("os.getenv('USER') or os.getenv('USERNAME')", None, Some(&locals))?.extract(py)?;
//!
//!     println!("Hello {}, I'm Python {}", user, version);
//!     Ok(())
//! }
//! ```

use std::{mem, ptr};

#[cfg(feature = "python27-sys")]
pub(crate) use python27_sys as ffi;

#[cfg(feature = "python3-sys")]
pub(crate) use python3_sys as ffi;

pub use ffi::Py_ssize_t;

pub use crate::conversion::{FromPyObject, RefFromPyObject, ToPyObject};
pub use crate::err::{PyErr, PyResult};
pub use crate::objectprotocol::ObjectProtocol;
pub use crate::objects::*;
pub use crate::py_class::CompareOp;
pub use crate::python::{
    PyClone, PyDrop, Python, PythonObject, PythonObjectDowncastError,
    PythonObjectWithCheckedDowncast, PythonObjectWithTypeObject,
};
pub use crate::pythonrun::{prepare_freethreaded_python, GILGuard, GILProtected};
pub use crate::sharedref::{
    PyLeakedRef, PyLeakedRefMut, PySharedRef, PySharedRefCell, UnsafePyLeaked,
};

#[cfg(feature = "python27-sys")]
#[allow(non_camel_case_types)]
pub type Py_hash_t = libc::c_long;

#[cfg(feature = "python3-sys")]
#[allow(non_camel_case_types)]
pub type Py_hash_t = ffi::Py_hash_t;

/// Constructs a `&'static CStr` literal.
macro_rules! cstr(
    ($s: tt) => (
        // TODO: verify that $s is a string literal without nuls
        unsafe {
            std::ffi::CStr::from_ptr(concat!($s, "\0").as_ptr() as *const _)
        }
    );
);

// AST coercion macros (https://danielkeep.github.io/tlborm/book/blk-ast-coercion.html)
#[macro_export]
#[doc(hidden)]
macro_rules! py_coerce_expr {
    ($s:expr) => {
        $s
    };
}
#[macro_export]
#[doc(hidden)]
macro_rules! py_coerce_item {
    ($s:item) => {
        $s
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! py_replace_expr {
    ($_t:tt $sub:expr) => {
        $sub
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! py_impl_to_py_object_for_python_object {
    ($T: ty) => {
        /// Identity conversion: allows using existing `PyObject` instances where
        /// `T: ToPyObject` is expected.
        impl $crate::ToPyObject for $T {
            type ObjectType = $T;

            #[inline]
            fn to_py_object(&self, py: $crate::Python) -> $T {
                $crate::PyClone::clone_ref(self, py)
            }

            #[inline]
            fn into_py_object(self, _py: $crate::Python) -> $T {
                self
            }

            #[inline]
            fn with_borrowed_ptr<F, R>(&self, _py: $crate::Python, f: F) -> R
            where
                F: FnOnce(*mut $crate::_detail::ffi::PyObject) -> R,
            {
                f($crate::PythonObject::as_object(self).as_ptr())
            }
        }
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! py_impl_from_py_object_for_python_object {
    ($T:ty) => {
        impl<'s> $crate::FromPyObject<'s> for $T {
            #[inline]
            fn extract(py: $crate::Python, obj: &'s $crate::PyObject) -> $crate::PyResult<$T> {
                use $crate::PyClone;
                Ok(obj.clone_ref(py).cast_into::<$T>(py)?)
            }
        }

        impl<'s> $crate::FromPyObject<'s> for &'s $T {
            #[inline]
            fn extract(py: $crate::Python, obj: &'s $crate::PyObject) -> $crate::PyResult<&'s $T> {
                Ok(obj.cast_as::<$T>(py)?)
            }
        }
    };
}

pub mod argparse;
pub mod buffer;
mod conversion;
mod err;
mod function;
mod objects;
mod python;
mod pythonrun;
//pub mod rustobject;
#[macro_use]
pub mod py_class;
mod sharedref;
mod objectprotocol;

#[cfg(feature = "serde-convert")]
pub mod serde;

/// Private re-exports for macros. Do not use.
#[doc(hidden)]
pub mod _detail {
    pub mod ffi {
        pub use crate::ffi::*;
    }
    pub mod libc {
        pub use libc::{c_char, c_int, c_void};
    }
    pub use crate::err::{from_owned_ptr_or_panic, result_from_owned_ptr};
    pub use crate::function::{
        handle_callback, py_fn_impl, AbortOnDrop, PyObjectCallbackConverter,
        PythonObjectCallbackConverter,
    };
    pub use paste;
}

/// Expands to an `extern "C"` function that allows Python to load
/// the rust code as a Python extension module.
///
/// Macro syntax: `py_module_initializer!($name, |$py, $m| $body)`
///
/// 1. `name`: The module name as a Rust identifier.
/// 2. A lambda of type `Fn(Python, &PyModule) -> PyResult<()>`.
///    This function will be called when the module is imported, and is responsible
///    for adding the module's members.
///
/// For backwards compatibilty with older versions of rust-cpython,
/// two additional name identifiers (for py2 and py3 initializer names)
/// can be provided, but they will be ignored.
///
/// # Example
/// ```
/// use cpython::{Python, PyResult, PyObject, py_module_initializer, py_fn};
///
/// py_module_initializer!(hello, |py, m| {
///     m.add(py, "__doc__", "Module documentation string")?;
///     m.add(py, "run", py_fn!(py, run()))?;
///     Ok(())
/// });
///
/// fn run(py: Python) -> PyResult<PyObject> {
///     println!("Rust says: Hello Python!");
///     Ok(py.None())
/// }
/// # fn main() {}
/// ```
///
/// In your `Cargo.toml`, use the `extension-module` feature for the `cpython` dependency:
/// ```cargo
/// [dependencies.cpython]
/// version = "*"
/// features = ["extension-module"]
/// ```
/// The full example project can be found at:
///   https://github.com/dgrunwald/rust-cpython/tree/master/extensions/hello
///
/// Rust will compile the code into a file named `libhello.so`, but we have to
/// rename the file in order to use it with Python:
///
/// ```bash
/// cp ./target/debug/libhello.so ./hello.so
/// ```
/// (Note: on Mac OS you will have to rename `libhello.dynlib` to `libhello.so`)
///
/// The extension module can then be imported into Python:
///
/// ```python
/// >>> import hello
/// >>> hello.run()
/// Rust says: Hello Python!
/// ```
///
#[macro_export]
#[cfg(feature = "python27-sys")]
macro_rules! py_module_initializer {
    ($name: ident, $( $_py2: ident, $_py3: ident, )? |$py_id: ident, $m_id: ident| $body: tt) => {
        $crate::_detail::paste::item! {
            #[no_mangle]
            #[allow(non_snake_case)]
            pub unsafe extern "C" fn [< init $name >]() {
                // Nest init function so that $body isn't in unsafe context
                fn init($py_id: $crate::Python, $m_id: &$crate::PyModule) -> $crate::PyResult<()> {
                    $body
                }
                let name = concat!(stringify!($name), "\0").as_ptr() as *const _;
                $crate::py_module_initializer_impl(name, init)
            }
        }
    };
}

#[doc(hidden)]
#[cfg(feature = "python27-sys")]
pub unsafe fn py_module_initializer_impl(
    name: *const libc::c_char,
    init: fn(Python, &PyModule) -> PyResult<()>,
) {
    let guard = function::AbortOnDrop("py_module_initializer");
    let py = Python::assume_gil_acquired();
    ffi::PyEval_InitThreads();
    let module = ffi::Py_InitModule(name, ptr::null_mut());
    if module.is_null() {
        mem::forget(guard);
        return;
    }

    let module = match PyObject::from_borrowed_ptr(py, module).cast_into::<PyModule>(py) {
        Ok(m) => m,
        Err(e) => {
            PyErr::from(e).restore(py);
            mem::forget(guard);
            return;
        }
    };
    let ret = match init(py, &module) {
        Ok(()) => (),
        Err(e) => e.restore(py),
    };
    mem::forget(guard);
    ret
}

#[macro_export]
#[cfg(feature = "python3-sys")]
macro_rules! py_module_initializer {
    ($name: ident, $( $_py2: ident, $_py3: ident, )? |$py_id: ident, $m_id: ident| $body: tt) => {
        $crate::_detail::paste::item! {
            #[no_mangle]
            #[allow(non_snake_case)]
            pub unsafe extern "C" fn [< PyInit_ $name >]() -> *mut $crate::_detail::ffi::PyObject {
                // Nest init function so that $body isn't in unsafe context
                fn init($py_id: $crate::Python, $m_id: &$crate::PyModule) -> $crate::PyResult<()> {
                    $body
                }
                static mut MODULE_DEF: $crate::_detail::ffi::PyModuleDef =
                    $crate::_detail::ffi::PyModuleDef_INIT;
                // We can't convert &'static str to *const c_char within a static initializer,
                // so we'll do it here in the module initialization:
                MODULE_DEF.m_name = concat!(stringify!($name), "\0").as_ptr() as *const _;
                $crate::py_module_initializer_impl(&mut MODULE_DEF, init)
            }
        }
    };
}

#[doc(hidden)]
#[cfg(feature = "python3-sys")]
pub unsafe fn py_module_initializer_impl(
    def: *mut ffi::PyModuleDef,
    init: fn(Python, &PyModule) -> PyResult<()>,
) -> *mut ffi::PyObject {
    let guard = function::AbortOnDrop("py_module_initializer");
    let py = Python::assume_gil_acquired();
    ffi::PyEval_InitThreads();
    let module = ffi::PyModule_Create(def);
    if module.is_null() {
        mem::forget(guard);
        return module;
    }

    let module = match PyObject::from_owned_ptr(py, module).cast_into::<PyModule>(py) {
        Ok(m) => m,
        Err(e) => {
            PyErr::from(e).restore(py);
            mem::forget(guard);
            return ptr::null_mut();
        }
    };
    let ret = match init(py, &module) {
        Ok(()) => module.into_object().steal_ptr(),
        Err(e) => {
            e.restore(py);
            ptr::null_mut()
        }
    };
    mem::forget(guard);
    ret
}

// Strip 'r#' prefix from stringified raw identifiers.
#[macro_export]
#[doc(hidden)]
macro_rules! strip_raw {
    ($s:expr) => {{
        let s = $s;
        if s.starts_with("r#") {
            &s[2..]
        } else {
            s
        }
    }};
}
<commit_msg>Re-export NumberProtocol from crate-root<commit_after>// Copyright (c) 2016 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#![cfg_attr(feature="nightly", feature(
    specialization, // for impl FromPyObject<'s> for Vec<...> (#31844)
))]
#![allow(
    unused_imports, // because some imports are only necessary with python 2.x or 3.x
    clippy::missing_safety_doc,
    clippy::manual_strip,
    clippy::match_like_matches_macro
)]
#![warn(
    // TODO: We need to fix this
    macro_expanded_macro_exports_accessed_by_absolute_paths,
)]

//! Rust bindings to the Python interpreter.
//!
//! # Ownership and Lifetimes
//! In Python, all objects are implicitly reference counted.
//! In rust, we will use the `PyObject` type to represent a reference to a Python object.
//!
//! The method `clone_ref()` (from trait `PyClone`) can be used to create additional
//! references to the same Python object.
//!
//! Because all Python objects potentially have multiple owners, the
//! concept of Rust mutability does not apply to Python objects.
//! As a result, this API will allow mutating Python objects even if they are not stored
//! in a mutable Rust variable.
//!
//! The Python interpreter uses a global interpreter lock (GIL)
//! to ensure thread-safety.
//! This API uses a zero-sized `struct Python<'p>` as a token to indicate
//! that a function can assume that the GIL is held.
//!
//! You obtain a `Python` instance by acquiring the GIL,
//! and have to pass it into all operations that call into the Python runtime.
//!
//! # Python 2.7
//! The library will use the python3 bindings by default. To use the python2 bindings
//! you must specific the `python27` feature explicitly in your `Cargo.toml`.
//!
//! ```ignore
//! [dependencies.cpython]
//! version = "*"
//! default-features = false
//! features = ["python27-sys"]
//! ```
//!
//! # Error Handling
//! The vast majority of operations in this library will return `PyResult<...>`.
//! This is an alias for the type `Result<..., PyErr>`.
//!
//! A `PyErr` represents a Python exception. Errors within the rust-cpython library are
//! also exposed as Python exceptions.
//!
//! # Example
//! ```
//! use cpython::{Python, PyDict, PyResult};
//!
//! fn main() {
//!     let gil = Python::acquire_gil();
//!     hello(gil.python()).unwrap();
//! }
//!
//! fn hello(py: Python) -> PyResult<()> {
//!     let sys = py.import("sys")?;
//!     let version: String = sys.get(py, "version")?.extract(py)?;
//!
//!     let locals = PyDict::new(py);
//!     locals.set_item(py, "os", py.import("os")?)?;
//!     let user: String = py.eval("os.getenv('USER') or os.getenv('USERNAME')", None, Some(&locals))?.extract(py)?;
//!
//!     println!("Hello {}, I'm Python {}", user, version);
//!     Ok(())
//! }
//! ```

use std::{mem, ptr};

#[cfg(feature = "python27-sys")]
pub(crate) use python27_sys as ffi;

#[cfg(feature = "python3-sys")]
pub(crate) use python3_sys as ffi;

pub use ffi::Py_ssize_t;

pub use crate::conversion::{FromPyObject, RefFromPyObject, ToPyObject};
pub use crate::err::{PyErr, PyResult};
pub use crate::objectprotocol::{ObjectProtocol, NumberProtocol};
pub use crate::objects::*;
pub use crate::py_class::CompareOp;
pub use crate::python::{
    PyClone, PyDrop, Python, PythonObject, PythonObjectDowncastError,
    PythonObjectWithCheckedDowncast, PythonObjectWithTypeObject,
};
pub use crate::pythonrun::{prepare_freethreaded_python, GILGuard, GILProtected};
pub use crate::sharedref::{
    PyLeakedRef, PyLeakedRefMut, PySharedRef, PySharedRefCell, UnsafePyLeaked,
};

#[cfg(feature = "python27-sys")]
#[allow(non_camel_case_types)]
pub type Py_hash_t = libc::c_long;

#[cfg(feature = "python3-sys")]
#[allow(non_camel_case_types)]
pub type Py_hash_t = ffi::Py_hash_t;

/// Constructs a `&'static CStr` literal.
macro_rules! cstr(
    ($s: tt) => (
        // TODO: verify that $s is a string literal without nuls
        unsafe {
            std::ffi::CStr::from_ptr(concat!($s, "\0").as_ptr() as *const _)
        }
    );
);

// AST coercion macros (https://danielkeep.github.io/tlborm/book/blk-ast-coercion.html)
#[macro_export]
#[doc(hidden)]
macro_rules! py_coerce_expr {
    ($s:expr) => {
        $s
    };
}
#[macro_export]
#[doc(hidden)]
macro_rules! py_coerce_item {
    ($s:item) => {
        $s
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! py_replace_expr {
    ($_t:tt $sub:expr) => {
        $sub
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! py_impl_to_py_object_for_python_object {
    ($T: ty) => {
        /// Identity conversion: allows using existing `PyObject` instances where
        /// `T: ToPyObject` is expected.
        impl $crate::ToPyObject for $T {
            type ObjectType = $T;

            #[inline]
            fn to_py_object(&self, py: $crate::Python) -> $T {
                $crate::PyClone::clone_ref(self, py)
            }

            #[inline]
            fn into_py_object(self, _py: $crate::Python) -> $T {
                self
            }

            #[inline]
            fn with_borrowed_ptr<F, R>(&self, _py: $crate::Python, f: F) -> R
            where
                F: FnOnce(*mut $crate::_detail::ffi::PyObject) -> R,
            {
                f($crate::PythonObject::as_object(self).as_ptr())
            }
        }
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! py_impl_from_py_object_for_python_object {
    ($T:ty) => {
        impl<'s> $crate::FromPyObject<'s> for $T {
            #[inline]
            fn extract(py: $crate::Python, obj: &'s $crate::PyObject) -> $crate::PyResult<$T> {
                use $crate::PyClone;
                Ok(obj.clone_ref(py).cast_into::<$T>(py)?)
            }
        }

        impl<'s> $crate::FromPyObject<'s> for &'s $T {
            #[inline]
            fn extract(py: $crate::Python, obj: &'s $crate::PyObject) -> $crate::PyResult<&'s $T> {
                Ok(obj.cast_as::<$T>(py)?)
            }
        }
    };
}

pub mod argparse;
pub mod buffer;
mod conversion;
mod err;
mod function;
mod objects;
mod python;
mod pythonrun;
//pub mod rustobject;
#[macro_use]
pub mod py_class;
mod sharedref;
mod objectprotocol;

#[cfg(feature = "serde-convert")]
pub mod serde;

/// Private re-exports for macros. Do not use.
#[doc(hidden)]
pub mod _detail {
    pub mod ffi {
        pub use crate::ffi::*;
    }
    pub mod libc {
        pub use libc::{c_char, c_int, c_void};
    }
    pub use crate::err::{from_owned_ptr_or_panic, result_from_owned_ptr};
    pub use crate::function::{
        handle_callback, py_fn_impl, AbortOnDrop, PyObjectCallbackConverter,
        PythonObjectCallbackConverter,
    };
    pub use paste;
}

/// Expands to an `extern "C"` function that allows Python to load
/// the rust code as a Python extension module.
///
/// Macro syntax: `py_module_initializer!($name, |$py, $m| $body)`
///
/// 1. `name`: The module name as a Rust identifier.
/// 2. A lambda of type `Fn(Python, &PyModule) -> PyResult<()>`.
///    This function will be called when the module is imported, and is responsible
///    for adding the module's members.
///
/// For backwards compatibilty with older versions of rust-cpython,
/// two additional name identifiers (for py2 and py3 initializer names)
/// can be provided, but they will be ignored.
///
/// # Example
/// ```
/// use cpython::{Python, PyResult, PyObject, py_module_initializer, py_fn};
///
/// py_module_initializer!(hello, |py, m| {
///     m.add(py, "__doc__", "Module documentation string")?;
///     m.add(py, "run", py_fn!(py, run()))?;
///     Ok(())
/// });
///
/// fn run(py: Python) -> PyResult<PyObject> {
///     println!("Rust says: Hello Python!");
///     Ok(py.None())
/// }
/// # fn main() {}
/// ```
///
/// In your `Cargo.toml`, use the `extension-module` feature for the `cpython` dependency:
/// ```cargo
/// [dependencies.cpython]
/// version = "*"
/// features = ["extension-module"]
/// ```
/// The full example project can be found at:
///   https://github.com/dgrunwald/rust-cpython/tree/master/extensions/hello
///
/// Rust will compile the code into a file named `libhello.so`, but we have to
/// rename the file in order to use it with Python:
///
/// ```bash
/// cp ./target/debug/libhello.so ./hello.so
/// ```
/// (Note: on Mac OS you will have to rename `libhello.dynlib` to `libhello.so`)
///
/// The extension module can then be imported into Python:
///
/// ```python
/// >>> import hello
/// >>> hello.run()
/// Rust says: Hello Python!
/// ```
///
#[macro_export]
#[cfg(feature = "python27-sys")]
macro_rules! py_module_initializer {
    ($name: ident, $( $_py2: ident, $_py3: ident, )? |$py_id: ident, $m_id: ident| $body: tt) => {
        $crate::_detail::paste::item! {
            #[no_mangle]
            #[allow(non_snake_case)]
            pub unsafe extern "C" fn [< init $name >]() {
                // Nest init function so that $body isn't in unsafe context
                fn init($py_id: $crate::Python, $m_id: &$crate::PyModule) -> $crate::PyResult<()> {
                    $body
                }
                let name = concat!(stringify!($name), "\0").as_ptr() as *const _;
                $crate::py_module_initializer_impl(name, init)
            }
        }
    };
}

#[doc(hidden)]
#[cfg(feature = "python27-sys")]
pub unsafe fn py_module_initializer_impl(
    name: *const libc::c_char,
    init: fn(Python, &PyModule) -> PyResult<()>,
) {
    let guard = function::AbortOnDrop("py_module_initializer");
    let py = Python::assume_gil_acquired();
    ffi::PyEval_InitThreads();
    let module = ffi::Py_InitModule(name, ptr::null_mut());
    if module.is_null() {
        mem::forget(guard);
        return;
    }

    let module = match PyObject::from_borrowed_ptr(py, module).cast_into::<PyModule>(py) {
        Ok(m) => m,
        Err(e) => {
            PyErr::from(e).restore(py);
            mem::forget(guard);
            return;
        }
    };
    let ret = match init(py, &module) {
        Ok(()) => (),
        Err(e) => e.restore(py),
    };
    mem::forget(guard);
    ret
}

#[macro_export]
#[cfg(feature = "python3-sys")]
macro_rules! py_module_initializer {
    ($name: ident, $( $_py2: ident, $_py3: ident, )? |$py_id: ident, $m_id: ident| $body: tt) => {
        $crate::_detail::paste::item! {
            #[no_mangle]
            #[allow(non_snake_case)]
            pub unsafe extern "C" fn [< PyInit_ $name >]() -> *mut $crate::_detail::ffi::PyObject {
                // Nest init function so that $body isn't in unsafe context
                fn init($py_id: $crate::Python, $m_id: &$crate::PyModule) -> $crate::PyResult<()> {
                    $body
                }
                static mut MODULE_DEF: $crate::_detail::ffi::PyModuleDef =
                    $crate::_detail::ffi::PyModuleDef_INIT;
                // We can't convert &'static str to *const c_char within a static initializer,
                // so we'll do it here in the module initialization:
                MODULE_DEF.m_name = concat!(stringify!($name), "\0").as_ptr() as *const _;
                $crate::py_module_initializer_impl(&mut MODULE_DEF, init)
            }
        }
    };
}

#[doc(hidden)]
#[cfg(feature = "python3-sys")]
pub unsafe fn py_module_initializer_impl(
    def: *mut ffi::PyModuleDef,
    init: fn(Python, &PyModule) -> PyResult<()>,
) -> *mut ffi::PyObject {
    let guard = function::AbortOnDrop("py_module_initializer");
    let py = Python::assume_gil_acquired();
    ffi::PyEval_InitThreads();
    let module = ffi::PyModule_Create(def);
    if module.is_null() {
        mem::forget(guard);
        return module;
    }

    let module = match PyObject::from_owned_ptr(py, module).cast_into::<PyModule>(py) {
        Ok(m) => m,
        Err(e) => {
            PyErr::from(e).restore(py);
            mem::forget(guard);
            return ptr::null_mut();
        }
    };
    let ret = match init(py, &module) {
        Ok(()) => module.into_object().steal_ptr(),
        Err(e) => {
            e.restore(py);
            ptr::null_mut()
        }
    };
    mem::forget(guard);
    ret
}

// Strip 'r#' prefix from stringified raw identifiers.
#[macro_export]
#[doc(hidden)]
macro_rules! strip_raw {
    ($s:expr) => {{
        let s = $s;
        if s.starts_with("r#") {
            &s[2..]
        } else {
            s
        }
    }};
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! Meta parsing and encoding for data oriented design

extern crate read_token;
extern crate range;

pub use whitespace::{ Whitespace, WHITESPACE };
pub use parse_error_handler::{ ParseErrorHandler, ParseStdErr };
pub use parse_error::ParseError;
pub use ty::Type;
pub use token::Token;
pub use select::Select;
pub use parameter::Parameter;
pub use optional::Optional;
pub use until_any_or_whitespace::UntilAnyOrWhitespace;
pub use text::Text;
pub use number::Number;
pub use rule::Rule;

mod parse_error;
mod parse_error_handler;
mod ty;
mod token;
mod whitespace;
mod select;
mod parameter;
mod optional;
mod until_any_or_whitespace;
mod text;
mod number;
mod rule;

/// Implemented by meta readers.
///
/// A meta reader contains an internal state that corresponds to a virtual
/// tree structure. The meta parser communicates with the meta reader such
/// that parsing is interrupted if any error happens.
pub trait MetaReader {
    /// The state that points to a location in the parsed structure.
    type State: Clone;

    /// Starts parsing a node.
    fn start_node(&mut self, name: &str, state: &Self::State) ->
        Result<Self::State, ParseError>;
    /// Ends parsing a node.
    fn end_node(&mut self, state: &Self::State) ->
        Result<Self::State, ParseError>;
    /// Sets a bool property of the node.
    fn set_as_bool(&mut self, name: &str, val: bool, state: &Self::State) ->
        Result<Self::State, ParseError>;
    /// Sets a string property of the node.
    fn set_as_string(&mut self, name: &str, val: String, state: &Self::State) ->
        Result<Self::State, ParseError>;
    /// Sets a f64 property of the node.
    fn set_as_f64(&mut self, name: &str, val: f64, state: &Self::State) ->
        Result<Self::State, ParseError>;
}

/// Implemented by meta writers.
pub trait MetaWriter {
    /// Starts encoding a node.
    fn start_node(&mut self, name: &str);
    /// Ends encoding a node.
    fn end_node(&mut self, name: &str);
    /// Get bool property.
    fn get_as_bool(&mut self, name: &str) -> Option<bool>;
    /// Get str property.
    fn get_as_str<F, U>(&mut self, name: &str, f: F) -> Option<U>
        where F: FnOnce(&str) -> U;
    /// Get f64 property.
    fn get_as_f64(&mut self, name: &str) -> Option<f64>;
}

#[inline(always)]
fn update<'a>(range: range::Range, chars: &mut &'a [char], offset: &mut usize) {
    let next_offset = range.next_offset();
    *chars = &chars[next_offset - *offset..];
    *offset = next_offset;
}
<commit_msg>Added `CommandState`<commit_after>#![deny(missing_docs)]

//! Meta parsing and encoding for data oriented design

extern crate read_token;
extern crate range;

pub use whitespace::{ Whitespace, WHITESPACE };
pub use parse_error_handler::{ ParseErrorHandler, ParseStdErr };
pub use parse_error::ParseError;
pub use ty::Type;
pub use token::Token;
pub use select::Select;
pub use parameter::Parameter;
pub use optional::Optional;
pub use until_any_or_whitespace::UntilAnyOrWhitespace;
pub use text::Text;
pub use number::Number;
pub use rule::Rule;

mod parse_error;
mod parse_error_handler;
mod ty;
mod token;
mod whitespace;
mod select;
mod parameter;
mod optional;
mod until_any_or_whitespace;
mod text;
mod number;
mod rule;

/// Implemented by meta readers.
///
/// A meta reader contains an internal state that corresponds to a virtual
/// tree structure. The meta parser communicates with the meta reader such
/// that parsing is interrupted if any error happens.
pub trait MetaReader {
    /// The state that points to a location in the parsed structure.
    type State: Clone;

    /// Starts parsing a node.
    fn start_node(&mut self, name: &str, state: &Self::State) ->
        Result<Self::State, ParseError>;
    /// Ends parsing a node.
    fn end_node(&mut self, state: &Self::State) ->
        Result<Self::State, ParseError>;
    /// Sets a bool property of the node.
    fn set_as_bool(&mut self, name: &str, val: bool, state: &Self::State) ->
        Result<Self::State, ParseError>;
    /// Sets a string property of the node.
    fn set_as_string(&mut self, name: &str, val: String, state: &Self::State) ->
        Result<Self::State, ParseError>;
    /// Sets a f64 property of the node.
    fn set_as_f64(&mut self, name: &str, val: f64, state: &Self::State) ->
        Result<Self::State, ParseError>;
}

/// Implemented by meta writers.
pub trait MetaWriter {
    /// Starts encoding a node.
    fn start_node(&mut self, name: &str);
    /// Ends encoding a node.
    fn end_node(&mut self, name: &str);
    /// Get bool property.
    fn get_as_bool(&mut self, name: &str) -> Option<bool>;
    /// Get str property.
    fn get_as_str<F, U>(&mut self, name: &str, f: F) -> Option<U>
        where F: FnOnce(&str) -> U;
    /// Get f64 property.
    fn get_as_f64(&mut self, name: &str) -> Option<f64>;
}

#[inline(always)]
fn update<'a>(range: range::Range, chars: &mut &'a [char], offset: &mut usize) {
    let next_offset = range.next_offset();
    *chars = &chars[next_offset - *offset..];
    *offset = next_offset;
}

/// Used by meta readers to handle or forward a state.
/// This makes it easier to write generic meta readers wrapping a sub reader.
pub enum CommandState<T, U> {
    /// Handle state.
    Handle(T),
    /// Forward command to sub meta reader.
    Forward(U),
}

<|endoftext|>


<commit_before>// Copyright 2014 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.

//! Abstraction of a thread pool for basic parallelism.

#![feature(unsafe_destructor)]

use std::mem;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread::{self, JoinGuard};

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Thunk<'a> = Box<FnBox + Send + 'a>;

struct Sentinel<'a> {
    jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
    active: bool
}

impl<'a> Sentinel<'a> {
    fn new(jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>) -> Sentinel<'a> {
        Sentinel {
            jobs: jobs,
            active: true
        }
    }

    // Cancel and destroy this sentinel.
    fn cancel(mut self) {
        self.active = false;
    }
}

#[unsafe_destructor]
impl<'a> Drop for Sentinel<'a> {
    fn drop(&mut self) {
        if self.active {
            spawn_in_pool(self.jobs.clone())
        }
    }
}

/// A thread pool used to execute functions in parallel.
///
/// Spawns `n` worker threads and replenishes the pool if any worker threads
/// panic.
///
/// # Example
///
/// ```rust
/// use threadpool::ThreadPool;
/// use std::sync::mpsc::channel;
///
/// let pool = ThreadPool::new(4);
///
/// let (tx, rx) = channel();
/// for i in 0..8 {
///     let tx = tx.clone();
///     pool.execute(move|| {
///         tx.send(i).unwrap();
///     });
/// }
///
/// assert_eq!(rx.iter().take(8).fold(0, |a, b| a + b), 28);
/// ```
pub struct ThreadPool {
    // How the threadpool communicates with subthreads.
    //
    // This is the only such Sender, so when it is dropped all subthreads will
    // quit.
    jobs: Sender<Thunk<'static>>
}

impl ThreadPool {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: usize) -> ThreadPool {
        assert!(threads >= 1);

        let (tx, rx) = channel::<Thunk<'static>>();
        let rx = Arc::new(Mutex::new(rx));

        // Threadpool threads
        for _ in 0..threads {
            spawn_in_pool(rx.clone());
        }

        ThreadPool { jobs: tx }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F : FnOnce() + Send + 'static
    {
        self.jobs.send(Box::new(move || job())).unwrap();
    }
}

fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk<'static>>>>) {
    thread::spawn(move || {
        // Will spawn a new thread on panic unless it is cancelled.
        let sentinel = Sentinel::new(&jobs);

        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The Threadpool was dropped.
                Err(..) => break
            }
        }

        sentinel.cancel();
    });
}

/// A scoped thread pool used to execute functions in parallel.
///
/// `ScopedPool` is different from `ThreadPool` in that:
///
/// * When dropped, it propagates panics that occur in the worker threads.
/// * It doesn't require the `'static` bound on the functions that are executed.
/// * Worker threads are joined when the `ScopedPool` is dropped.
///
/// # Example
///
/// ```rust
/// use threadpool::ScopedPool;
///
/// let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
///
/// // We need an extra scope to shorten the lifetime of the pool
/// {
///     let pool = ScopedPool::new(4);
///     for x in &mut numbers[..] {
///         pool.execute(move|| {
///             *x += 1;
///         });
///     }
/// }
///
/// assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
/// ```
pub struct ScopedPool<'pool> {
    sender: Option<Sender<Thunk<'pool>>>,
    _guards: Vec<JoinGuard<'pool, ()>>
}

impl<'pool> ScopedPool<'pool> {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: u32) -> ScopedPool<'pool> {
        assert!(threads >= 1);

        let (sender, receiver) = channel();
        let receiver = Arc::new(Mutex::new(receiver));

        let mut guards = Vec::with_capacity(threads as usize);
        for _ in 0..threads {
            guards.push(spawn_scoped_in_pool(receiver.clone()));
        }

        ScopedPool { sender: Some(sender), _guards: guards }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F: FnOnce() + Send + 'pool
    {
        self.sender.as_ref().unwrap().send(Box::new(job)).unwrap();
    }
}

#[unsafe_destructor]
impl<'a> Drop for ScopedPool<'a> {
    fn drop(&mut self) {
        // We need to ensure that the sender is dropped before the JoinGuards
        // Otherwise the threads will be joined and wait forever in the loop
        mem::replace(&mut self.sender, None);
    }
}

fn spawn_scoped_in_pool<'a>(jobs: Arc<Mutex<Receiver<Thunk<'a>>>>) -> JoinGuard<'a, ()>
{
    thread::scoped(move || {
        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The pool was dropped.
                Err(..) => break
            }
        }
    })
}

#[cfg(test)]
mod test {
    use super::ThreadPool;
    use std::sync::mpsc::channel;
    use std::sync::{Arc, Barrier};

    const TEST_TASKS: usize = 4;

    #[test]
    fn test_works() {
        let pool = ThreadPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    #[should_panic]
    fn test_zero_tasks_panic() {
        ThreadPool::new(0);
    }

    #[test]
    fn test_recovery_from_subtask_panic() {
        let pool = ThreadPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }

        // Ensure new threads were spawned to compensate.
        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() {

        let pool = ThreadPool::new(TEST_TASKS);
        let waiter = Arc::new(Barrier::new(TEST_TASKS + 1));

        // Panic all the existing threads in a bit.
        for _ in 0..TEST_TASKS {
            let waiter = waiter.clone();
            pool.execute(move|| {
                waiter.wait();
                panic!();
            });
        }

        drop(pool);

        // Kick off the failure.
        waiter.wait();
    }
}

#[cfg(test)]
mod test_scoped {
    use super::ScopedPool;
    use std::sync::mpsc::channel;

    const TEST_TASKS: u32 = 4;

    #[test]
    fn test_works_1() {
        let pool = ScopedPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS as usize).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_works_2() {
        let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        {
            let pool = ScopedPool::new(TEST_TASKS);
            for x in numbers.iter_mut() {
                pool.execute(move || {
                    *x += 1;
                });
            }
        }
        assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
    }

    #[test]
    #[should_panic]
    fn test_zero_tasks_panic() {
        ScopedPool::new(0);
    }

    #[test]
    #[should_panic]
    fn test_panic_propagation() {
        let pool = ScopedPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }
    }
}
<commit_msg>Remove the unsafe_destructor feature<commit_after>// Copyright 2014 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.

//! Abstraction of a thread pool for basic parallelism.

use std::mem;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread::{self, JoinGuard};

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Thunk<'a> = Box<FnBox + Send + 'a>;

struct Sentinel<'a> {
    jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
    active: bool
}

impl<'a> Sentinel<'a> {
    fn new(jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>) -> Sentinel<'a> {
        Sentinel {
            jobs: jobs,
            active: true
        }
    }

    // Cancel and destroy this sentinel.
    fn cancel(mut self) {
        self.active = false;
    }
}

impl<'a> Drop for Sentinel<'a> {
    fn drop(&mut self) {
        if self.active {
            spawn_in_pool(self.jobs.clone())
        }
    }
}

/// A thread pool used to execute functions in parallel.
///
/// Spawns `n` worker threads and replenishes the pool if any worker threads
/// panic.
///
/// # Example
///
/// ```rust
/// use threadpool::ThreadPool;
/// use std::sync::mpsc::channel;
///
/// let pool = ThreadPool::new(4);
///
/// let (tx, rx) = channel();
/// for i in 0..8 {
///     let tx = tx.clone();
///     pool.execute(move|| {
///         tx.send(i).unwrap();
///     });
/// }
///
/// assert_eq!(rx.iter().take(8).fold(0, |a, b| a + b), 28);
/// ```
pub struct ThreadPool {
    // How the threadpool communicates with subthreads.
    //
    // This is the only such Sender, so when it is dropped all subthreads will
    // quit.
    jobs: Sender<Thunk<'static>>
}

impl ThreadPool {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: usize) -> ThreadPool {
        assert!(threads >= 1);

        let (tx, rx) = channel::<Thunk<'static>>();
        let rx = Arc::new(Mutex::new(rx));

        // Threadpool threads
        for _ in 0..threads {
            spawn_in_pool(rx.clone());
        }

        ThreadPool { jobs: tx }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F : FnOnce() + Send + 'static
    {
        self.jobs.send(Box::new(move || job())).unwrap();
    }
}

fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk<'static>>>>) {
    thread::spawn(move || {
        // Will spawn a new thread on panic unless it is cancelled.
        let sentinel = Sentinel::new(&jobs);

        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The Threadpool was dropped.
                Err(..) => break
            }
        }

        sentinel.cancel();
    });
}

/// A scoped thread pool used to execute functions in parallel.
///
/// `ScopedPool` is different from `ThreadPool` in that:
///
/// * When dropped, it propagates panics that occur in the worker threads.
/// * It doesn't require the `'static` bound on the functions that are executed.
/// * Worker threads are joined when the `ScopedPool` is dropped.
///
/// # Example
///
/// ```rust
/// use threadpool::ScopedPool;
///
/// let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
///
/// // We need an extra scope to shorten the lifetime of the pool
/// {
///     let pool = ScopedPool::new(4);
///     for x in &mut numbers[..] {
///         pool.execute(move|| {
///             *x += 1;
///         });
///     }
/// }
///
/// assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
/// ```
pub struct ScopedPool<'pool> {
    sender: Option<Sender<Thunk<'pool>>>,
    _guards: Vec<JoinGuard<'pool, ()>>
}

impl<'pool> ScopedPool<'pool> {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: u32) -> ScopedPool<'pool> {
        assert!(threads >= 1);

        let (sender, receiver) = channel();
        let receiver = Arc::new(Mutex::new(receiver));

        let mut guards = Vec::with_capacity(threads as usize);
        for _ in 0..threads {
            guards.push(spawn_scoped_in_pool(receiver.clone()));
        }

        ScopedPool { sender: Some(sender), _guards: guards }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F: FnOnce() + Send + 'pool
    {
        self.sender.as_ref().unwrap().send(Box::new(job)).unwrap();
    }
}

impl<'a> Drop for ScopedPool<'a> {
    fn drop(&mut self) {
        // We need to ensure that the sender is dropped before the JoinGuards
        // Otherwise the threads will be joined and wait forever in the loop
        mem::replace(&mut self.sender, None);
    }
}

fn spawn_scoped_in_pool<'a>(jobs: Arc<Mutex<Receiver<Thunk<'a>>>>) -> JoinGuard<'a, ()>
{
    thread::scoped(move || {
        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The pool was dropped.
                Err(..) => break
            }
        }
    })
}

#[cfg(test)]
mod test {
    use super::ThreadPool;
    use std::sync::mpsc::channel;
    use std::sync::{Arc, Barrier};

    const TEST_TASKS: usize = 4;

    #[test]
    fn test_works() {
        let pool = ThreadPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    #[should_panic]
    fn test_zero_tasks_panic() {
        ThreadPool::new(0);
    }

    #[test]
    fn test_recovery_from_subtask_panic() {
        let pool = ThreadPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }

        // Ensure new threads were spawned to compensate.
        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() {

        let pool = ThreadPool::new(TEST_TASKS);
        let waiter = Arc::new(Barrier::new(TEST_TASKS + 1));

        // Panic all the existing threads in a bit.
        for _ in 0..TEST_TASKS {
            let waiter = waiter.clone();
            pool.execute(move|| {
                waiter.wait();
                panic!();
            });
        }

        drop(pool);

        // Kick off the failure.
        waiter.wait();
    }
}

#[cfg(test)]
mod test_scoped {
    use super::ScopedPool;
    use std::sync::mpsc::channel;

    const TEST_TASKS: u32 = 4;

    #[test]
    fn test_works_1() {
        let pool = ScopedPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS as usize).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_works_2() {
        let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        {
            let pool = ScopedPool::new(TEST_TASKS);
            for x in numbers.iter_mut() {
                pool.execute(move || {
                    *x += 1;
                });
            }
        }
        assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
    }

    #[test]
    #[should_panic]
    fn test_zero_tasks_panic() {
        ScopedPool::new(0);
    }

    #[test]
    #[should_panic]
    fn test_panic_propagation() {
        let pool = ScopedPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }
    }
}
<|endoftext|>


<commit_before>//! ### rust-mysql-simple
//! Mysql client library implemented in rust nightly.
//!
//! #### Install
//! Just include another `[dependencies.*]` section into your Cargo.toml:
//!
//! ```toml
//! [dependencies.mysql]
//! git = "https://github.com/blackbeam/rust-mysql-simple"
//! ```
//!
//! rust-mysql-simple offer support of SSL via `ssl` cargo feature which is enabled by default. If you have no plans to use SSL, then you should disable that feature to not to depend on rust-openssl:
//!
//! ```toml
//! [dependencies.mysql]
//! git = "https://github.com/blackbeam/rust-mysql-simple"
//! default-features = false
//! ```
//!
//! #### Use
//! You should start by creating [`MyOpts`](conn/struct.MyOpts.html) struct.
//!
//! Then you can create [`MyPool`](conn/pool/struct.MyPool.html) which should be
//! enough to work with mysql server.
#![crate_name="mysql"]
#![crate_type="rlib"]
#![crate_type="dylib"]

#![feature(unsafe_destructor)]
#![feature(plugin)]
#![feature(io)]
#![feature(core)]
#![feature(ip)]
#![feature(tcp)]
#![feature(collections)]
#![feature(std_misc)]
#![feature(convert)]
#![cfg_attr(test, feature(test))]

#![plugin(regex_macros)]

#[cfg(test)]
extern crate test;

extern crate core;
extern crate time;
#[cfg(feature = "openssl")]
extern crate openssl;
extern crate regex;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bitflags;
extern crate byteorder;
extern crate unix_socket;

mod scramble;
pub mod consts;
pub mod error;
mod packet;
mod io;
pub mod value;
pub mod conn;
<commit_msg>Add slice_patterns feature<commit_after>//! ### rust-mysql-simple
//! Mysql client library implemented in rust nightly.
//!
//! #### Install
//! Just include another `[dependencies.*]` section into your Cargo.toml:
//!
//! ```toml
//! [dependencies.mysql]
//! git = "https://github.com/blackbeam/rust-mysql-simple"
//! ```
//!
//! rust-mysql-simple offer support of SSL via `ssl` cargo feature which is enabled by default. If you have no plans to use SSL, then you should disable that feature to not to depend on rust-openssl:
//!
//! ```toml
//! [dependencies.mysql]
//! git = "https://github.com/blackbeam/rust-mysql-simple"
//! default-features = false
//! ```
//!
//! #### Use
//! You should start by creating [`MyOpts`](conn/struct.MyOpts.html) struct.
//!
//! Then you can create [`MyPool`](conn/pool/struct.MyPool.html) which should be
//! enough to work with mysql server.
#![crate_name="mysql"]
#![crate_type="rlib"]
#![crate_type="dylib"]

#![feature(unsafe_destructor)]
#![feature(plugin)]
#![feature(io)]
#![feature(core)]
#![feature(ip)]
#![feature(tcp)]
#![feature(collections)]
#![feature(std_misc)]
#![feature(convert)]
#![feature(slice_patterns)]
#![cfg_attr(test, feature(test))]

#![plugin(regex_macros)]

#[cfg(test)]
extern crate test;

extern crate core;
extern crate time;
#[cfg(feature = "openssl")]
extern crate openssl;
extern crate regex;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bitflags;
extern crate byteorder;
extern crate unix_socket;

mod scramble;
pub mod consts;
pub mod error;
mod packet;
mod io;
pub mod value;
pub mod conn;
<|endoftext|>


<commit_before>#![allow(unused_imports, dead_code, unused_variables)]

#[cfg(feature = "pkg-config")]
extern crate pkg_config;
#[cfg(feature = "bindgen")]
extern crate bindgen;
#[cfg(feature="bundled")]
extern crate cmake;
#[cfg(feature="bundled")]
extern crate tar;
#[cfg(feature="bundled")]
extern crate flate2;
#[cfg(feature="bundled")]
extern crate reqwest;

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

// corresponds to the headers that we have in sdl2-sys/SDL2-{version}
const SDL2_HEADERS_BUNDLED_VERSION: &str = "2.0.6";

// means the lastest stable version that can be downloaded from SDL2's source
const LASTEST_SDL2_VERSION: &str = "2.0.5";

#[cfg(feature="bundled")]
fn download_to<T: io::Write>(url: &str, mut dest: T) {
    use io::BufRead;

    let resp = reqwest::get(url).expect(&format!("Failed to GET resource: {:?}", url));
    let size = resp.headers()
        .get::<reqwest::header::ContentLength>()
        .map(|ct_len| **ct_len)
        .unwrap_or(0);
    if !resp.status().is_success() { panic!("Download request failed with status: {:?}", resp.status()) }
    if size == 0 { panic!("Size of content was returned was 0") }

    let mut src = io::BufReader::new(resp);
    loop {
        let n = {
            let mut buf = src.fill_buf().unwrap();
            dest.write_all(&mut buf).unwrap();
            buf.len()
        };
        if n == 0 { break; }
        src.consume(n);
    }
}

#[cfg(feature="bundled")]
fn main() {
    let target = env::var("TARGET").expect("Cargo build scripts always have TARGET");
    let host = env::var("HOST").expect("Cargo build scripts always have HOST");
    let target_os = get_os_from_triple(target.as_str()).unwrap();

    prepare_bindings(&target, &host);

    let sdl2_archive_name = format!("SDL2-{}.tar.gz", LASTEST_SDL2_VERSION);
    let sdl2_archive_url = format!("http://libsdl.org/release/{}", sdl2_archive_name);

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

    let sdl2_archive_path = Path::new(&out_dir).join(sdl2_archive_name);
    let sdl2_build_path = Path::new(&out_dir).join(format!("SDL2-{}", LASTEST_SDL2_VERSION));
    if !sdl2_archive_path.exists() {
        let sdl2_archive = fs::File::create(&sdl2_archive_path).unwrap();
        download_to(&sdl2_archive_url, &sdl2_archive);
    }
    let reader = flate2::read::GzDecoder::new(
        fs::File::open(&sdl2_archive_path).unwrap()
    ).unwrap();
    let mut ar = tar::Archive::new(reader);
    ar.unpack(&out_dir).unwrap();

    let install_path = cmake::Config::new(sdl2_build_path)
        .define("SDL_SHARED", "OFF")
        .define("SDL_STATIC", "ON")
        .build();

    println!("cargo:rustc-link-search={}", install_path.join("lib").display());
    println!("cargo:rustc-link-lib=static=SDL2main");
    println!("cargo:rustc-link-lib=static=SDL2");

    // Also linked to any required libraries for each supported platform
    if target_os == "windows-msvc" {
        println!("cargo:rustc-link-lib=user32");
        println!("cargo:rustc-link-lib=gdi32");
        println!("cargo:rustc-link-lib=winmm");
        println!("cargo:rustc-link-lib=imm32");
        println!("cargo:rustc-link-lib=ole32");
        println!("cargo:rustc-link-lib=oleaut32");
        println!("cargo:rustc-link-lib=version");
        println!("cargo:rustc-link-lib=uuid");
        println!("cargo:rustc-link-lib=dinput8");
        println!("cargo:rustc-link-lib=dxguid");
    } else {
        // TODO: Add other platform linker options here.
    }
}

#[cfg(not(feature="bundled"))]
fn main() {
    let target = env::var("TARGET").expect("Cargo build scripts always have TARGET");
    let host = env::var("HOST").expect("Cargo build scripts always have HOST");
    let target_os = get_os_from_triple(target.as_str()).unwrap();

    prepare_bindings(&target, &host);

    if target_os == "ios" {
        println!("cargo:rustc-flags=-l framework=AVFoundation");
        println!("cargo:rustc-flags=-l framework=AudioToolbox");
        println!("cargo:rustc-flags=-l framework=CoreAudio");
        println!("cargo:rustc-flags=-l framework=CoreGraphics");
        println!("cargo:rustc-flags=-l framework=CoreMotion");
        println!("cargo:rustc-flags=-l framework=Foundation");
        println!("cargo:rustc-flags=-l framework=GameController");
        println!("cargo:rustc-flags=-l framework=OpenGLES");
        println!("cargo:rustc-flags=-l framework=QuartzCore");
        println!("cargo:rustc-flags=-l framework=UIKit");
    }
}

#[cfg(not(feature="pkg-config"))]
#[cfg(not(feature="bundled"))]
fn build_pkgconfig() -> bool {
    false
}

#[cfg(feature="pkg-config")]
fn build_pkgconfig() -> bool {
    pkg_config::probe_library("sdl2").is_ok()
}

#[cfg(not(feature = "bindgen"))]
fn prepare_bindings(target: &str, host: &str) {
    add_explicit_linker_flags(get_os_from_triple(target).unwrap());
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    let crate_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
    fs::copy(crate_path.join("pregenerated_bindings.rs"), out_path.join("bindings.rs"))
        .expect("Couldn't find pregenerated bindings!");
}

#[cfg(feature = "bindgen")]
fn prepare_bindings(target: &str, host: &str) {
    let mut bindings = bindgen::Builder::default();

    // Set correct target triple when cross-compiling
    if target != host {
        bindings = bindings.clang_arg("-target");
        bindings = bindings.clang_arg(target.clone());
    }

    if let Ok(include_path) = env::var("SDL2_INCLUDE_PATH") {
        bindings = bindings.clang_arg(String::from("-I") + &include_path);
        add_explicit_linker_flags(get_os_from_triple(target).unwrap());
    } else if build_pkgconfig() {
        #[cfg(feature = "pkg-config")]
        for path in &pkg_config::find_library("sdl2").unwrap().include_paths {
            bindings = bindings.clang_arg(String::from("-I") +
                                          &path.clone().into_os_string().into_string().unwrap());
        }
    } else {
        let mut include_path: PathBuf = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
        include_path.push(String::from("SDL2-") + SDL2_BUNDLED_VERSION);
        include_path.push("include");
        bindings = bindings.clang_arg(String::from("-I") +
                                      &include_path.into_os_string().into_string().unwrap());
        // SDL2 hasn't a default configuration for Linux
        if get_os_from_triple(target).unwrap() == "linux" {
            bindings = bindings.clang_arg("-DSDL_VIDEO_DRIVER_X11");
            bindings = bindings.clang_arg("-DSDL_VIDEO_DRIVER_WAYLAND");
        }
        add_explicit_linker_flags(get_os_from_triple(target).unwrap());
    }

    let bindings = bindings
        .header("wrapper.h")
        .hide_type("_")
        .hide_type("FP_NAN")
        .hide_type("FP_INFINITE")
        .hide_type("FP_ZERO")
        .hide_type("FP_SUBNORMAL")
        .hide_type("FP_NORMAL") // Until https://github.com/rust-lang-nursery/rust-bindgen/issues/687 gets fixed
        .hide_type("max_align_t") // Until https://github.com/rust-lang-nursery/rust-bindgen/issues/550 gets fixed
        .generate()
        .expect("Unable to generate bindings!");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());

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

fn get_os_from_triple(triple: &str) -> Option<&str>
{
    triple.split("-").nth(2)
}

fn add_explicit_linker_flags(target_os: &str) {
    if cfg!(feature = "use_mac_framework") && target_os == "darwin" {
        println!("cargo:rustc-flags=-l framework=SDL2");
    } else {
        println!("cargo:rustc-flags=-l SDL2");
    }
}
<commit_msg>On linux SDL2 requires libsndio<commit_after>#![allow(unused_imports, dead_code, unused_variables)]

#[cfg(feature = "pkg-config")]
extern crate pkg_config;
#[cfg(feature = "bindgen")]
extern crate bindgen;
#[cfg(feature="bundled")]
extern crate cmake;
#[cfg(feature="bundled")]
extern crate tar;
#[cfg(feature="bundled")]
extern crate flate2;
#[cfg(feature="bundled")]
extern crate reqwest;

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

// corresponds to the headers that we have in sdl2-sys/SDL2-{version}
const SDL2_HEADERS_BUNDLED_VERSION: &str = "2.0.6";

// means the lastest stable version that can be downloaded from SDL2's source
const LASTEST_SDL2_VERSION: &str = "2.0.5";

#[cfg(feature="bundled")]
fn download_to<T: io::Write>(url: &str, mut dest: T) {
    use io::BufRead;

    let resp = reqwest::get(url).expect(&format!("Failed to GET resource: {:?}", url));
    let size = resp.headers()
        .get::<reqwest::header::ContentLength>()
        .map(|ct_len| **ct_len)
        .unwrap_or(0);
    if !resp.status().is_success() { panic!("Download request failed with status: {:?}", resp.status()) }
    if size == 0 { panic!("Size of content was returned was 0") }

    let mut src = io::BufReader::new(resp);
    loop {
        let n = {
            let mut buf = src.fill_buf().unwrap();
            dest.write_all(&mut buf).unwrap();
            buf.len()
        };
        if n == 0 { break; }
        src.consume(n);
    }
}

#[cfg(feature="bundled")]
fn main() {
    let target = env::var("TARGET").expect("Cargo build scripts always have TARGET");
    let host = env::var("HOST").expect("Cargo build scripts always have HOST");
    let target_os = get_os_from_triple(target.as_str()).unwrap();

    prepare_bindings(&target, &host);

    let sdl2_archive_name = format!("SDL2-{}.tar.gz", LASTEST_SDL2_VERSION);
    let sdl2_archive_url = format!("http://libsdl.org/release/{}", sdl2_archive_name);

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

    let sdl2_archive_path = Path::new(&out_dir).join(sdl2_archive_name);
    let sdl2_build_path = Path::new(&out_dir).join(format!("SDL2-{}", LASTEST_SDL2_VERSION));
    if !sdl2_archive_path.exists() {
        let sdl2_archive = fs::File::create(&sdl2_archive_path).unwrap();
        download_to(&sdl2_archive_url, &sdl2_archive);
    }
    let reader = flate2::read::GzDecoder::new(
        fs::File::open(&sdl2_archive_path).unwrap()
    ).unwrap();
    let mut ar = tar::Archive::new(reader);
    ar.unpack(&out_dir).unwrap();

    let install_path = cmake::Config::new(sdl2_build_path)
        .define("SDL_SHARED", "OFF")
        .define("SDL_STATIC", "ON")
        .build();

    println!("cargo:rustc-link-search={}", install_path.join("lib").display());
    println!("cargo:rustc-link-lib=static=SDL2main");
    println!("cargo:rustc-link-lib=static=SDL2");

    // Also linked to any required libraries for each supported platform
    if target_os == "windows-msvc" {
        println!("cargo:rustc-link-lib=user32");
        println!("cargo:rustc-link-lib=gdi32");
        println!("cargo:rustc-link-lib=winmm");
        println!("cargo:rustc-link-lib=imm32");
        println!("cargo:rustc-link-lib=ole32");
        println!("cargo:rustc-link-lib=oleaut32");
        println!("cargo:rustc-link-lib=version");
        println!("cargo:rustc-link-lib=uuid");
        println!("cargo:rustc-link-lib=dinput8");
        println!("cargo:rustc-link-lib=dxguid");
    } else if target_os.contains("linux") {
        println!("cargo:rustc-link-lib=sndio");
    } else {
        // TODO: Add other platform linker options here.
    }
}

#[cfg(not(feature="bundled"))]
fn main() {
    let target = env::var("TARGET").expect("Cargo build scripts always have TARGET");
    let host = env::var("HOST").expect("Cargo build scripts always have HOST");
    let target_os = get_os_from_triple(target.as_str()).unwrap();

    prepare_bindings(&target, &host);

    if target_os == "ios" {
        println!("cargo:rustc-flags=-l framework=AVFoundation");
        println!("cargo:rustc-flags=-l framework=AudioToolbox");
        println!("cargo:rustc-flags=-l framework=CoreAudio");
        println!("cargo:rustc-flags=-l framework=CoreGraphics");
        println!("cargo:rustc-flags=-l framework=CoreMotion");
        println!("cargo:rustc-flags=-l framework=Foundation");
        println!("cargo:rustc-flags=-l framework=GameController");
        println!("cargo:rustc-flags=-l framework=OpenGLES");
        println!("cargo:rustc-flags=-l framework=QuartzCore");
        println!("cargo:rustc-flags=-l framework=UIKit");
    }
}

#[cfg(not(feature="pkg-config"))]
#[cfg(not(feature="bundled"))]
fn build_pkgconfig() -> bool {
    false
}

#[cfg(feature="pkg-config")]
fn build_pkgconfig() -> bool {
    pkg_config::probe_library("sdl2").is_ok()
}

#[cfg(not(feature = "bindgen"))]
fn prepare_bindings(target: &str, host: &str) {
    add_explicit_linker_flags(get_os_from_triple(target).unwrap());
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    let crate_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
    fs::copy(crate_path.join("pregenerated_bindings.rs"), out_path.join("bindings.rs"))
        .expect("Couldn't find pregenerated bindings!");
}

#[cfg(feature = "bindgen")]
fn prepare_bindings(target: &str, host: &str) {
    let mut bindings = bindgen::Builder::default();

    // Set correct target triple when cross-compiling
    if target != host {
        bindings = bindings.clang_arg("-target");
        bindings = bindings.clang_arg(target.clone());
    }

    if let Ok(include_path) = env::var("SDL2_INCLUDE_PATH") {
        bindings = bindings.clang_arg(String::from("-I") + &include_path);
        add_explicit_linker_flags(get_os_from_triple(target).unwrap());
    } else if build_pkgconfig() {
        #[cfg(feature = "pkg-config")]
        for path in &pkg_config::find_library("sdl2").unwrap().include_paths {
            bindings = bindings.clang_arg(String::from("-I") +
                                          &path.clone().into_os_string().into_string().unwrap());
        }
    } else {
        let mut include_path: PathBuf = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
        include_path.push(String::from("SDL2-") + SDL2_BUNDLED_VERSION);
        include_path.push("include");
        bindings = bindings.clang_arg(String::from("-I") +
                                      &include_path.into_os_string().into_string().unwrap());
        // SDL2 hasn't a default configuration for Linux
        if get_os_from_triple(target).unwrap() == "linux" {
            bindings = bindings.clang_arg("-DSDL_VIDEO_DRIVER_X11");
            bindings = bindings.clang_arg("-DSDL_VIDEO_DRIVER_WAYLAND");
        }
        add_explicit_linker_flags(get_os_from_triple(target).unwrap());
    }

    let bindings = bindings
        .header("wrapper.h")
        .hide_type("_")
        .hide_type("FP_NAN")
        .hide_type("FP_INFINITE")
        .hide_type("FP_ZERO")
        .hide_type("FP_SUBNORMAL")
        .hide_type("FP_NORMAL") // Until https://github.com/rust-lang-nursery/rust-bindgen/issues/687 gets fixed
        .hide_type("max_align_t") // Until https://github.com/rust-lang-nursery/rust-bindgen/issues/550 gets fixed
        .generate()
        .expect("Unable to generate bindings!");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());

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

fn get_os_from_triple(triple: &str) -> Option<&str>
{
    triple.split("-").nth(2)
}

fn add_explicit_linker_flags(target_os: &str) {
    if cfg!(feature = "use_mac_framework") && target_os == "darwin" {
        println!("cargo:rustc-flags=-l framework=SDL2");
    } else {
        println!("cargo:rustc-flags=-l SDL2");
    }
}
<|endoftext|>


<commit_before>extern crate html2text;
extern crate termion;
use std::io::{self, Write};
use std::fmt::Display;
use html2text::render::text_renderer::{RichAnnotation};

fn to_style(tag: &Vec<RichAnnotation>) -> String {
    let mut style = String::new();

    for ann in tag {
        match *ann {
            RichAnnotation::Default => (),
            RichAnnotation::Link(_) => {
                style.push_str(&format!("{}", termion::style::Underline));
            },
            RichAnnotation::Image => {
                style.push_str(&format!("{}", termion::color::Fg(termion::color::LightBlue)));
            },
        }
    }
    style
}

fn main() {
    let stdin = io::stdin();

    let annotated = html2text::from_read_rich(&mut stdin.lock(), 80);
    for line in annotated {
        for (s, tag) in line.iter() {
            let style = to_style(tag);
            write!(io::stdout(), "{}{}{}", style, s, termion::style::Reset);
        }
        write!(io::stdout(), "\n");
    }
}<commit_msg>Use the real terminal size in html2term. Fix a few warnings.<commit_after>extern crate html2text;
extern crate termion;
use std::io::{self, Write};
use html2text::render::text_renderer::{RichAnnotation};

fn to_style(tag: &Vec<RichAnnotation>) -> String {
    let mut style = String::new();

    for ann in tag {
        match *ann {
            RichAnnotation::Default => (),
            RichAnnotation::Link(_) => {
                style.push_str(&format!("{}", termion::style::Underline));
            },
            RichAnnotation::Image => {
                style.push_str(&format!("{}", termion::color::Fg(termion::color::LightBlue)));
            },
        }
    }
    style
}

fn main() {
    let stdin = io::stdin();

    let (width, _) = termion::terminal_size().unwrap();

    let annotated = html2text::from_read_rich(&mut stdin.lock(), width as usize);
    for line in annotated {
        for (s, tag) in line.iter() {
            let style = to_style(tag);
            write!(io::stdout(), "{}{}{}", style, s, termion::style::Reset).unwrap();
        }
        write!(io::stdout(), "\n").unwrap();
    }
}<|endoftext|>