<commit_before>//#![warn(missing_docs)]

pub unsafe trait StableAddress: Deref {}
pub unsafe trait CloneStableAddress: StableAddress + Clone {}

pub struct OwningRef<O, T: ?Sized> {
    owner: O,
    reference: *const T,
}

pub trait Erased {}
impl<T> Erased for T {}

pub unsafe trait IntoErased {
    type Erased;
    fn into_erased(self) -> Self::Erased;
}

/////////////////////////////////////////////////////////////////////////////
// inherent API
/////////////////////////////////////////////////////////////////////////////

impl<O, T: ?Sized> OwningRef<O, T> {
    pub fn new(o: O) -> Self
        where O: StableAddress,
        O: Deref<Target = T>,
    {
        OwningRef {
            reference: &*o,
            owner: o,
        }
    }

    pub fn map<F, U: ?Sized>(self, f: F) -> OwningRef<O, U>
        where O: StableAddress,
              F: FnOnce(&T) -> &U
    {
        OwningRef {
            reference: f(&self),
            owner: self.owner,
        }
    }

    pub fn erase_owner(self) -> OwningRef<O::Erased, T>
        where O: IntoErased,
    {
        OwningRef {
            reference: self.reference,
            owner: self.owner.into_erased(),
        }
    }

    pub fn owner(&self) -> &O {
        &self.owner
    }

    pub fn into_inner(self) -> O {
        self.owner
    }
}

/////////////////////////////////////////////////////////////////////////////
// std traits
/////////////////////////////////////////////////////////////////////////////

use std::ops::Deref;
use std::convert::From;
use std::fmt::{self, Debug};
use std::marker::{Send, Sync};

impl<O, T: ?Sized> Deref for OwningRef<O, T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe {
            &*self.reference
        }
    }
}

impl<O, T: ?Sized> From<O> for OwningRef<O, T>
    where O: StableAddress, O: Deref<Target = T>,
{
    fn from(owner: O) -> Self {
        OwningRef::new(owner)
    }
}

// ^ FIXME: Is a Into impl for calling into_inner() possible as well?

impl<O, T: ?Sized> Debug for OwningRef<O, T>
    where O: Debug, T: Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "OwningRef {{ owner: {:?}, reference: {:?} }}",
               self.owner(), &**self)
    }
}

impl<O, T: ?Sized> Clone for OwningRef<O, T>
    where O: CloneStableAddress,
{
    fn clone(&self) -> Self {
        OwningRef {
            owner: self.owner.clone(),
            reference: self.reference,
        }
    }
}

unsafe impl<O: Send, T: ?Sized> Send for OwningRef<O, T> {}
unsafe impl<O: Sync, T: ?Sized> Sync for OwningRef<O, T> {}

/////////////////////////////////////////////////////////////////////////////
// std types integration and convenience type defs
/////////////////////////////////////////////////////////////////////////////

use std::boxed::Box;
use std::rc::Rc;
use std::sync::Arc;

unsafe impl<T: ?Sized> StableAddress for Box<T> {}
unsafe impl<T> StableAddress for Vec<T> {}
unsafe impl StableAddress for String {}
#[cfg(feature = "nightly")]
unsafe impl<T: ?Sized> StableAddress for Rc<T> {}
#[cfg(feature = "nightly")]
unsafe impl<T: ?Sized> StableAddress for Arc<T> {}
#[cfg(not(feature = "nightly"))]
unsafe impl<T> StableAddress for Rc<T> {}
#[cfg(not(feature = "nightly"))]
unsafe impl<T> StableAddress for Arc<T> {}

#[cfg(feature = "nightly")]
unsafe impl<T: ?Sized> CloneStableAddress for Rc<T> {}
#[cfg(feature = "nightly")]
unsafe impl<T: ?Sized> CloneStableAddress for Arc<T> {}
#[cfg(not(feature = "nightly"))]
unsafe impl<T> CloneStableAddress for Rc<T> {}
#[cfg(not(feature = "nightly"))]
unsafe impl<T> CloneStableAddress for Arc<T> {}

pub type BoxRef<T, U = T> = OwningRef<Box<T>, U>;
pub type VecRef<T, U = T> = OwningRef<Vec<T>, U>;
pub type StringRef = OwningRef<String, str>;
pub type RcRef<T, U = T> = OwningRef<Rc<T>, U>;
pub type ArcRef<T, U = T> = OwningRef<Arc<T>, U>;

unsafe impl<'a, T: 'a> IntoErased for Box<T> {
    type Erased = Box<Erased + 'a>;
    fn into_erased(self) -> Self::Erased { self }
}
unsafe impl<'a, T: 'a> IntoErased for Rc<T> {
    type Erased = Rc<Erased + 'a>;
    fn into_erased(self) -> Self::Erased { self }
}
unsafe impl<'a, T: 'a> IntoErased for Arc<T> {
    type Erased = Arc<Erased + 'a>;
    fn into_erased(self) -> Self::Erased { self }
}

pub type ErasedBoxRef<U> = OwningRef<Box<Erased>, U>;
pub type ErasedRcRef<U> = OwningRef<Rc<Erased>, U>;
pub type ErasedArcRef<U> = OwningRef<Arc<Erased>, U>;

#[cfg(test)]
mod tests {
    use super::OwningRef;
    use super::{BoxRef, VecRef, StringRef, RcRef, ArcRef};
    use super::{Erased, ErasedBoxRef};

    use std::rc::Rc;
    use std::sync::Arc;

    #[derive(Debug, PartialEq)]
    struct Example(u32, String, [u8; 3]);
    fn example() -> Example {
        Example(42, "hello world".to_string(), [1, 2, 3])
    }

    #[test]
    fn new_deref() {
        let or: OwningRef<Box<()>, ()> = OwningRef::new(Box::new(()));
        assert_eq!(&*or, &());
    }

    #[test]
    fn into() {
        let or: OwningRef<Box<()>, ()> = Box::new(()).into();
        assert_eq!(&*or, &());
    }

    #[test]
    fn map_offset_ref() {
        let or: BoxRef<Example> = Box::new(example()).into();
        let or: BoxRef<_, u32> = or.map(|x| &x.0);
        assert_eq!(&*or, &42);

        let or: BoxRef<Example> = Box::new(example()).into();
        let or: BoxRef<_, u8> = or.map(|x| &x.2[1]);
        assert_eq!(&*or, &2);
    }

    #[test]
    fn map_heap_ref() {
        let or: BoxRef<Example> = Box::new(example()).into();
        let or: BoxRef<_, str> = or.map(|x| &x.1[..5]);
        assert_eq!(&*or, "hello");
    }

    #[test]
    fn map_static_ref() {
        let or: BoxRef<()> = Box::new(()).into();
        let or: BoxRef<_, str> = or.map(|_| "hello");
        assert_eq!(&*or, "hello");
    }

    #[test]
    fn map_chained() {
        let or: BoxRef<String> = Box::new(example().1).into();
        let or: BoxRef<_, str> = or.map(|x| &x[1..5]);
        let or: BoxRef<_, str> = or.map(|x| &x[..2]);
        assert_eq!(&*or, "el");
    }

    #[test]
    fn map_chained_inference() {
        let or = BoxRef::new(Box::new(example().1))
            .map(|x| &x[..5])
            .map(|x| &x[1..3]);
        assert_eq!(&*or, "el");
    }

    #[test]
    fn owner() {
        let or: BoxRef<String> = Box::new(example().1).into();
        let or = or.map(|x| &x[..5]);
        assert_eq!(&*or, "hello");
        assert_eq!(&**or.owner(), "hello world");
    }

    #[test]
    fn into_inner() {
        let or: BoxRef<String> = Box::new(example().1).into();
        let or = or.map(|x| &x[..5]);
        assert_eq!(&*or, "hello");
        let s = *or.into_inner();
        assert_eq!(&s, "hello world");
    }

    #[test]
    fn fmt_debug() {
        let or: BoxRef<String> = Box::new(example().1).into();
        let or = or.map(|x| &x[..5]);
        let s = format!("{:?}", or);
        assert_eq!(&s, "OwningRef { owner: \"hello world\", reference: \"hello\" }");
    }

    #[test]
    fn erased_owner() {
        let o1: BoxRef<Example, str> = BoxRef::new(Box::new(example()))
            .map(|x| &x.1[..]);

        let o2: BoxRef<String, str> = BoxRef::new(Box::new(example().1))
            .map(|x| &x[..]);

        let os: Vec<ErasedBoxRef<str>> = vec![o1.erase_owner(), o2.erase_owner()];
        assert!(os.iter().all(|e| &e[..] == "hello world"));
    }

    #[test]
    fn non_static_erased_owner() {
        let foo = [413, 612];
        let bar = &foo;

        let o: BoxRef<&[i32; 2]> = Box::new(bar).into();
        let o: BoxRef<&[i32; 2], i32> = o.map(|a: &&[i32; 2]| &a[0]);
        let o: BoxRef<Erased, i32> = o.erase_owner();

        assert_eq!(*o, 413);
    }

    /////////////////////////////////////////////////////////////////////////
    // Tests of example uses cases for each supported owner type:
    /////////////////////////////////////////////////////////////////////////

    #[test]
    fn box_ref() {
        // Caching a reference to a struct field

        struct Foo {
            tag: u32,
            x: u16,
            y: u16,
            z: u16,
        }
        let foo = Foo { tag: 1, x: 100, y: 200, z: 300 };

        let or = BoxRef::new(Box::new(foo)).map(|foo| {
            match foo.tag {
                0 => &foo.x,
                1 => &foo.y,
                2 => &foo.z,
                _ => {
                    static INVALID: u16 = !0;
                    &INVALID
                }
            }
        });

        assert_eq!(*or, 200);
    }

    #[test]
    fn vec_ref() {
        // Cache a reference to an entry in a vector

        let v = VecRef::new(vec![1, 2, 3, 4, 5]).map(|v| &v[3]);
        assert_eq!(*v, 4);
    }

    #[test]
    fn string_ref() {
        // Caching a subslice of a String

        let s = StringRef::new("hello world".to_owned())
            .map(|s| s.split(' ').nth(1).unwrap());

        assert_eq!(&*s, "world");
    }

    #[test]
    #[cfg(feature = "nightly")]
    fn rc_ref() {
        // Creating many subslices that share ownership of the backing storage

        let rc: Rc<[i32]> = Rc::new([1, 2, 3, 4]);
        let rc: RcRef<[i32]> = rc.into();
        assert_eq!(&*rc, &[1, 2, 3, 4]);

        let rc_a: RcRef<[i32]> = rc.clone().map(|s| &s[0..2]);
        let rc_b = rc.clone().map(|s| &s[1..3]);
        let rc_c = rc.clone().map(|s| &s[2..4]);
        assert_eq!(&*rc_a, &[1, 2]);
        assert_eq!(&*rc_b, &[2, 3]);
        assert_eq!(&*rc_c, &[3, 4]);

        let rc_c_a = rc_c.clone().map(|s| &s[1]);
        assert_eq!(&*rc_c_a, &4);
    }

    #[test]
    #[cfg(feature = "nightly")]
    fn arc_ref() {
        // Calculate the sum of a atomic shared slice in parallel

        use std::thread;

        fn par_sum(rc: ArcRef<[i32]>) -> i32 {
            if rc.len() == 0 {
                return 0;
            } else if rc.len() == 1 {
                return rc[0];
            }
            let mid = rc.len() / 2;
            let left = rc.clone().map(|s| &s[..mid]);
            let right = rc.map(|s| &s[mid..]);

            let left = thread::spawn(move || par_sum(left));
            let right = thread::spawn(move || par_sum(right));

            left.join().unwrap() + right.join().unwrap()
        }

        let rc: Arc<[i32]> = Arc::new([1, 2, 3, 4]);
        let rc: ArcRef<[i32]> = rc.into();

        assert_eq!(par_sum(rc), 10);
    }

}
<commit_msg>Additional nightly-stable fix<commit_after>//#![warn(missing_docs)]

pub unsafe trait StableAddress: Deref {}
pub unsafe trait CloneStableAddress: StableAddress + Clone {}

pub struct OwningRef<O, T: ?Sized> {
    owner: O,
    reference: *const T,
}

pub trait Erased {}
impl<T> Erased for T {}

pub unsafe trait IntoErased {
    type Erased;
    fn into_erased(self) -> Self::Erased;
}

/////////////////////////////////////////////////////////////////////////////
// inherent API
/////////////////////////////////////////////////////////////////////////////

impl<O, T: ?Sized> OwningRef<O, T> {
    pub fn new(o: O) -> Self
        where O: StableAddress,
        O: Deref<Target = T>,
    {
        OwningRef {
            reference: &*o,
            owner: o,
        }
    }

    pub fn map<F, U: ?Sized>(self, f: F) -> OwningRef<O, U>
        where O: StableAddress,
              F: FnOnce(&T) -> &U
    {
        OwningRef {
            reference: f(&self),
            owner: self.owner,
        }
    }

    pub fn erase_owner(self) -> OwningRef<O::Erased, T>
        where O: IntoErased,
    {
        OwningRef {
            reference: self.reference,
            owner: self.owner.into_erased(),
        }
    }

    pub fn owner(&self) -> &O {
        &self.owner
    }

    pub fn into_inner(self) -> O {
        self.owner
    }
}

/////////////////////////////////////////////////////////////////////////////
// std traits
/////////////////////////////////////////////////////////////////////////////

use std::ops::Deref;
use std::convert::From;
use std::fmt::{self, Debug};
use std::marker::{Send, Sync};

impl<O, T: ?Sized> Deref for OwningRef<O, T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe {
            &*self.reference
        }
    }
}

impl<O, T: ?Sized> From<O> for OwningRef<O, T>
    where O: StableAddress, O: Deref<Target = T>,
{
    fn from(owner: O) -> Self {
        OwningRef::new(owner)
    }
}

// ^ FIXME: Is a Into impl for calling into_inner() possible as well?

impl<O, T: ?Sized> Debug for OwningRef<O, T>
    where O: Debug, T: Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "OwningRef {{ owner: {:?}, reference: {:?} }}",
               self.owner(), &**self)
    }
}

impl<O, T: ?Sized> Clone for OwningRef<O, T>
    where O: CloneStableAddress,
{
    fn clone(&self) -> Self {
        OwningRef {
            owner: self.owner.clone(),
            reference: self.reference,
        }
    }
}

unsafe impl<O: Send, T: ?Sized> Send for OwningRef<O, T> {}
unsafe impl<O: Sync, T: ?Sized> Sync for OwningRef<O, T> {}

/////////////////////////////////////////////////////////////////////////////
// std types integration and convenience type defs
/////////////////////////////////////////////////////////////////////////////

use std::boxed::Box;
use std::rc::Rc;
use std::sync::Arc;

unsafe impl<T: ?Sized> StableAddress for Box<T> {}
unsafe impl<T> StableAddress for Vec<T> {}
unsafe impl StableAddress for String {}
#[cfg(feature = "nightly")]
unsafe impl<T: ?Sized> StableAddress for Rc<T> {}
#[cfg(feature = "nightly")]
unsafe impl<T: ?Sized> StableAddress for Arc<T> {}
#[cfg(feature = "nightly")]
unsafe impl<T: ?Sized> CloneStableAddress for Rc<T> {}
#[cfg(feature = "nightly")]
unsafe impl<T: ?Sized> CloneStableAddress for Arc<T> {}

#[cfg(not(feature = "nightly"))]
unsafe impl<T> CloneStableAddress for Rc<T> {}
#[cfg(not(feature = "nightly"))]
unsafe impl<T> CloneStableAddress for Arc<T> {}
#[cfg(not(feature = "nightly"))]
unsafe impl<T> StableAddress for Rc<T> {}
#[cfg(not(feature = "nightly"))]
unsafe impl<T> StableAddress for Arc<T> {}

pub type BoxRef<T, U = T> = OwningRef<Box<T>, U>;
pub type VecRef<T, U = T> = OwningRef<Vec<T>, U>;
pub type StringRef = OwningRef<String, str>;
pub type RcRef<T, U = T> = OwningRef<Rc<T>, U>;
pub type ArcRef<T, U = T> = OwningRef<Arc<T>, U>;

unsafe impl<'a, T: 'a> IntoErased for Box<T> {
    type Erased = Box<Erased + 'a>;
    fn into_erased(self) -> Self::Erased { self }
}
#[cfg(feature = "nightly")]
unsafe impl<'a, T: 'a> IntoErased for Rc<T> {
    type Erased = Rc<Erased + 'a>;
    fn into_erased(self) -> Self::Erased { self }
}
#[cfg(feature = "nightly")]
unsafe impl<'a, T: 'a> IntoErased for Arc<T> {
    type Erased = Arc<Erased + 'a>;
    fn into_erased(self) -> Self::Erased { self }
}

pub type ErasedBoxRef<U> = OwningRef<Box<Erased>, U>;
pub type ErasedRcRef<U> = OwningRef<Rc<Erased>, U>;
pub type ErasedArcRef<U> = OwningRef<Arc<Erased>, U>;

#[cfg(test)]
mod tests {
    use super::OwningRef;
    use super::{BoxRef, VecRef, StringRef, RcRef, ArcRef};
    use super::{Erased, ErasedBoxRef};

    use std::rc::Rc;
    use std::sync::Arc;

    #[derive(Debug, PartialEq)]
    struct Example(u32, String, [u8; 3]);
    fn example() -> Example {
        Example(42, "hello world".to_string(), [1, 2, 3])
    }

    #[test]
    fn new_deref() {
        let or: OwningRef<Box<()>, ()> = OwningRef::new(Box::new(()));
        assert_eq!(&*or, &());
    }

    #[test]
    fn into() {
        let or: OwningRef<Box<()>, ()> = Box::new(()).into();
        assert_eq!(&*or, &());
    }

    #[test]
    fn map_offset_ref() {
        let or: BoxRef<Example> = Box::new(example()).into();
        let or: BoxRef<_, u32> = or.map(|x| &x.0);
        assert_eq!(&*or, &42);

        let or: BoxRef<Example> = Box::new(example()).into();
        let or: BoxRef<_, u8> = or.map(|x| &x.2[1]);
        assert_eq!(&*or, &2);
    }

    #[test]
    fn map_heap_ref() {
        let or: BoxRef<Example> = Box::new(example()).into();
        let or: BoxRef<_, str> = or.map(|x| &x.1[..5]);
        assert_eq!(&*or, "hello");
    }

    #[test]
    fn map_static_ref() {
        let or: BoxRef<()> = Box::new(()).into();
        let or: BoxRef<_, str> = or.map(|_| "hello");
        assert_eq!(&*or, "hello");
    }

    #[test]
    fn map_chained() {
        let or: BoxRef<String> = Box::new(example().1).into();
        let or: BoxRef<_, str> = or.map(|x| &x[1..5]);
        let or: BoxRef<_, str> = or.map(|x| &x[..2]);
        assert_eq!(&*or, "el");
    }

    #[test]
    fn map_chained_inference() {
        let or = BoxRef::new(Box::new(example().1))
            .map(|x| &x[..5])
            .map(|x| &x[1..3]);
        assert_eq!(&*or, "el");
    }

    #[test]
    fn owner() {
        let or: BoxRef<String> = Box::new(example().1).into();
        let or = or.map(|x| &x[..5]);
        assert_eq!(&*or, "hello");
        assert_eq!(&**or.owner(), "hello world");
    }

    #[test]
    fn into_inner() {
        let or: BoxRef<String> = Box::new(example().1).into();
        let or = or.map(|x| &x[..5]);
        assert_eq!(&*or, "hello");
        let s = *or.into_inner();
        assert_eq!(&s, "hello world");
    }

    #[test]
    fn fmt_debug() {
        let or: BoxRef<String> = Box::new(example().1).into();
        let or = or.map(|x| &x[..5]);
        let s = format!("{:?}", or);
        assert_eq!(&s, "OwningRef { owner: \"hello world\", reference: \"hello\" }");
    }

    #[test]
    fn erased_owner() {
        let o1: BoxRef<Example, str> = BoxRef::new(Box::new(example()))
            .map(|x| &x.1[..]);

        let o2: BoxRef<String, str> = BoxRef::new(Box::new(example().1))
            .map(|x| &x[..]);

        let os: Vec<ErasedBoxRef<str>> = vec![o1.erase_owner(), o2.erase_owner()];
        assert!(os.iter().all(|e| &e[..] == "hello world"));
    }

    #[test]
    fn non_static_erased_owner() {
        let foo = [413, 612];
        let bar = &foo;

        let o: BoxRef<&[i32; 2]> = Box::new(bar).into();
        let o: BoxRef<&[i32; 2], i32> = o.map(|a: &&[i32; 2]| &a[0]);
        let o: BoxRef<Erased, i32> = o.erase_owner();

        assert_eq!(*o, 413);
    }

    /////////////////////////////////////////////////////////////////////////
    // Tests of example uses cases for each supported owner type:
    /////////////////////////////////////////////////////////////////////////

    #[test]
    fn box_ref() {
        // Caching a reference to a struct field

        struct Foo {
            tag: u32,
            x: u16,
            y: u16,
            z: u16,
        }
        let foo = Foo { tag: 1, x: 100, y: 200, z: 300 };

        let or = BoxRef::new(Box::new(foo)).map(|foo| {
            match foo.tag {
                0 => &foo.x,
                1 => &foo.y,
                2 => &foo.z,
                _ => {
                    static INVALID: u16 = !0;
                    &INVALID
                }
            }
        });

        assert_eq!(*or, 200);
    }

    #[test]
    fn vec_ref() {
        // Cache a reference to an entry in a vector

        let v = VecRef::new(vec![1, 2, 3, 4, 5]).map(|v| &v[3]);
        assert_eq!(*v, 4);
    }

    #[test]
    fn string_ref() {
        // Caching a subslice of a String

        let s = StringRef::new("hello world".to_owned())
            .map(|s| s.split(' ').nth(1).unwrap());

        assert_eq!(&*s, "world");
    }

    #[test]
    #[cfg(feature = "nightly")]
    fn rc_ref() {
        // Creating many subslices that share ownership of the backing storage

        let rc: Rc<[i32]> = Rc::new([1, 2, 3, 4]);
        let rc: RcRef<[i32]> = rc.into();
        assert_eq!(&*rc, &[1, 2, 3, 4]);

        let rc_a: RcRef<[i32]> = rc.clone().map(|s| &s[0..2]);
        let rc_b = rc.clone().map(|s| &s[1..3]);
        let rc_c = rc.clone().map(|s| &s[2..4]);
        assert_eq!(&*rc_a, &[1, 2]);
        assert_eq!(&*rc_b, &[2, 3]);
        assert_eq!(&*rc_c, &[3, 4]);

        let rc_c_a = rc_c.clone().map(|s| &s[1]);
        assert_eq!(&*rc_c_a, &4);
    }

    #[test]
    #[cfg(feature = "nightly")]
    fn arc_ref() {
        // Calculate the sum of a atomic shared slice in parallel

        use std::thread;

        fn par_sum(rc: ArcRef<[i32]>) -> i32 {
            if rc.len() == 0 {
                return 0;
            } else if rc.len() == 1 {
                return rc[0];
            }
            let mid = rc.len() / 2;
            let left = rc.clone().map(|s| &s[..mid]);
            let right = rc.map(|s| &s[mid..]);

            let left = thread::spawn(move || par_sum(left));
            let right = thread::spawn(move || par_sum(right));

            left.join().unwrap() + right.join().unwrap()
        }

        let rc: Arc<[i32]> = Arc::new([1, 2, 3, 4]);
        let rc: ArcRef<[i32]> = rc.into();

        assert_eq!(par_sum(rc), 10);
    }

}
<|endoftext|>


<commit_before>#![crate_name = "piston"]
#![deny(missing_docs)]
#![warn(dead_code)]

//! A modular game engine written in Rust.
//!
//! This is the core library of the Piston Game engine.
//! The `Piston` core library reexports the core modules.
//!
//! If you are looking for a convenient window wrapper,
//! see [piston_window](https://github.com/pistondevelopers/piston_window).
//!
//! For examples, see [piston-examples](https://github.com/pistondevelopers/piston-examples).
//!
//! For more information and an overview, see [Piston's README in the core repository](https://github.com/pistondevelopers/piston).
//!
//! ### About Piston as a Game Engine
//!
//! Piston is a modular game engine with a minimal core abstraction.
//! The core connects input events, window and event loop.
//!
//! Piston is designed for optimal modularity,
//! making it optional to even use the core modules in many cases.
//! The goal is to have as little abstraction as possible,
//! while making larger libraries as independent as possible.
//! The motivation is to encourage diversity and experimentation with various abstractions,
//! without getting tied up to a fixed set of platforms, abstractions or vendors.
//! You can combine Piston with any other library in Rust's ecosystem.
//! This design has worked very well so far.
//!
//! For example (a few libraries, there are many more):
//!
//! - [Image](https://github.com/pistondevelopers/image) library is standalone
//! from both the core and the 2D graphics library,
//! only connected through the 2D graphics backends.
//! - [Piston's 2D graphics](https://github.com/pistondevelopers/graphics) is optional and can be used without a window backend.
//! The window backend can be used without a 2D graphics backend, and so on.
//! - For image processing, see [Imageproc](https://github.com/pistondevelopers/imageproc).
//! - [Dyon](https://github.com/pistondevelopers/dyon) is a Rusty dynamically typed scripting language,
//! using a lifetime checker without garbage collection.
//!
//! For more information and an overview, see [Piston's README in the core repository](https://github.com/pistondevelopers/piston).
//!
//! When writing a library, please depend directly on the core module needed.
//! This makes it less likely that the library will break.
//!
//! When writing an application, it is acceptable to use the `Piston` core.
//! To use it you usually need a window backend:
//!
//! - [pistoncore-glutin_window](https://github.com/pistondevelopers/glutin_window)
//! - [pistoncore-sdl2_window](https://github.com/pistondevelopers/sdl2_window)
//! - [pistoncore-glfw_window](https://github.com/pistondevelopers/glfw_window)
//!
//! There are a [few other window backends as well](https://crates.io/search?q=piston%20window).
//!
//! Plus a 2D graphics backend (optional):
//!
//! - [piston2d-opengl_graphics](https://github.com/pistondevelopers/opengl_graphics)
//! - [piston2d-gfx_graphics](https://github.com/pistondevelopers/gfx_graphics)
//! - [piston2d-glium_graphics](https://github.com/pistondevelopers/glium_graphics)
//!
//! There are a [few other graphics backends as well](https://crates.io/search?q=piston%20graphics).
//!
//! You will find examples of how to get started in each 2D graphics backend repository.
//!
//! ### About Piston as a Project
//!
//! The Piston project is a huge collaboration across many projects,
//! mainly focused on maintenance of libraries and research.
//! Since this has been going on since 2014, there is too much out there
//! to summarize here, but rougly the project is organized into two open source organizations:
//!
//! - [PistonDevelopers](https://github.com/pistondevelopers/) - everything game engine related
//! - [AdvancedResearch](https://github.com/advancedresearch/) - everything advanced math related
//!
//! In addition we collaborate across organizations with other projects, mainly:
//!
//! - [Gfx-rs](https://github.com/gfx-rs/) - everything 3D graphics related
//! - [RustAudio](https://github.com/rustaudio) - everything audio related
//!
//! In addition there are many other projects and organizations.
//!
//! For more information and an overview, see [Piston's README in the core repository](https://github.com/pistondevelopers/piston).

// Reexported crates.
pub extern crate input;
pub extern crate event_loop;
pub extern crate window;
<commit_msg>Improved docs at top level<commit_after>#![crate_name = "piston"]
#![deny(missing_docs)]
#![warn(dead_code)]

//! A modular game engine written in Rust.
//!
//! This is the core library of the Piston Game engine.
//! The `Piston` core library reexports the core modules.
//!
//! If you are looking for a convenient window wrapper,
//! see [piston_window](https://github.com/pistondevelopers/piston_window).
//!
//! For examples, see [piston-examples](https://github.com/pistondevelopers/piston-examples).
//!
//! For more information and an overview, see [Piston's README in the core repository](https://github.com/pistondevelopers/piston).
//!
//! ### Design
//!
//! The Piston core is a thin and modular abstraction for user input, window and event loop.
//! This functionality is separated into 3 core modules.
//!
//! The core modules are intended to be used directly by generic libraries.
//! By depending directly on core modules, it is easier to maintain the ecosystem.
//!
//! This library is intended to be used in application code.
//! When you write application code, it is common to separate reusable code,
//! which depends on various abstractions, from platform specific code.
//! The reusable code that you write for applications might use the Piston core.
//!
//! The default programming pattern in Piston is Model-View-Controller:
//!
//! - A controller handles events and manipulates a model
//! - A view renders a model on the screen
//!
//! For more information about this pattern, see [Model-View-Controller (Wikipedia)](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller).
//!
//! The most important traits in Piston are the following:
//!
//! - [GenericEvent](input::GenericEvent) (allows handling of events for controllers)
//! - [Window](window::Window) (allows polling of events)
//!
//! ### Link to documentation for core modules
//!
//! - [pistoncore-input](https://docs.rs/pistoncore-input)
//!   (User input and event handling)
//! - [pistoncore-window](https://docs.rs/pistoncore-window)
//!   (Window abstraction)
//! - [pistoncore-event_loop](https://docs.rs/pistoncore-event_loop)
//!   (Event loop)
//!
//! ### About Piston as a Game Engine
//!
//! Piston is a modular game engine with a minimal core abstraction.
//! The core connects input events, window and event loop.
//!
//! Piston is designed for optimal modularity,
//! making it optional to even use the core modules in many cases.
//! The goal is to have as little abstraction as possible,
//! while making larger libraries as independent as possible.
//! The motivation is to encourage diversity and experimentation with various abstractions,
//! without getting tied up to a fixed set of platforms, abstractions or vendors.
//! You can combine Piston with any other library in Rust's ecosystem.
//! This design has worked very well so far.
//!
//! For example (a few libraries, there are many more):
//!
//! - [Image](https://github.com/pistondevelopers/image) library is standalone
//! from both the core and the 2D graphics library,
//! only connected through the 2D graphics backends.
//! - [Piston's 2D graphics](https://github.com/pistondevelopers/graphics) is optional and can be used without a window backend.
//! The window backend can be used without a 2D graphics backend, and so on.
//! - For image processing, see [Imageproc](https://github.com/pistondevelopers/imageproc).
//! - [Dyon](https://github.com/pistondevelopers/dyon) is a Rusty dynamically typed scripting language,
//! using a lifetime checker without garbage collection.
//!
//! For more information and an overview, see [Piston's README in the core repository](https://github.com/pistondevelopers/piston).
//!
//! When writing a library, please depend directly on the core module needed.
//! This makes it less likely that the library will break.
//!
//! When writing an application, it is acceptable to use the `Piston` core.
//! To use it you usually need a window backend:
//!
//! - [pistoncore-glutin_window](https://github.com/pistondevelopers/glutin_window)
//! - [pistoncore-sdl2_window](https://github.com/pistondevelopers/sdl2_window)
//! - [pistoncore-glfw_window](https://github.com/pistondevelopers/glfw_window)
//!
//! There are a [few other window backends as well](https://crates.io/search?q=piston%20window).
//!
//! Plus a 2D graphics backend (optional):
//!
//! - [piston2d-opengl_graphics](https://github.com/pistondevelopers/opengl_graphics)
//! - [piston2d-gfx_graphics](https://github.com/pistondevelopers/gfx_graphics)
//! - [piston2d-glium_graphics](https://github.com/pistondevelopers/glium_graphics)
//!
//! There are a [few other graphics backends as well](https://crates.io/search?q=piston%20graphics).
//!
//! You will find examples of how to get started in each 2D graphics backend repository.
//!
//! ### About Piston as a Project
//!
//! The Piston project is a huge collaboration across many projects,
//! mainly focused on maintenance of libraries and research.
//! Since this has been going on since 2014, there is too much out there
//! to summarize here, but rougly the project is organized into two open source organizations:
//!
//! - [PistonDevelopers](https://github.com/pistondevelopers/) - everything game engine related
//! - [AdvancedResearch](https://github.com/advancedresearch/) - everything advanced math related
//!
//! In addition we collaborate across organizations with other projects, mainly:
//!
//! - [Gfx-rs](https://github.com/gfx-rs/) - everything 3D graphics related
//! - [RustAudio](https://github.com/rustaudio) - everything audio related
//!
//! In addition there are many other projects and organizations.
//!
//! For more information and an overview, see [Piston's README in the core repository](https://github.com/pistondevelopers/piston).

// Reexported crates.
pub extern crate input;
pub extern crate event_loop;
pub extern crate window;

pub use input::*;
pub use event_loop::*;
pub use window::*;
<|endoftext|>


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

extern crate ansi_term;
extern crate base64;
#[cfg(target_os = "linux")]
extern crate caps;
extern crate crypto as rust_crypto;
#[cfg(windows)]
extern crate ctrlc;

#[macro_use]
extern crate log;

#[macro_use]
extern crate serde_derive;

#[cfg(not(windows))]
extern crate users as linux_users;

#[cfg(windows)]
extern crate habitat_win_users;
#[cfg(windows)]
extern crate widestring;
#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate windows_acl;

pub use self::error::{Error, Result};

pub mod binlink;
pub mod channel;
pub mod config;
pub mod crypto;
pub mod env;
pub mod error;
pub mod event;
pub mod fs;
pub mod os;
pub mod output;
pub mod package;
pub mod service;
pub mod url;
pub mod util;

use std::env::VarError;
use std::ffi::OsStr;
use std::fmt;
use std::path::PathBuf;

pub use crate::os::filesystem;
pub use crate::os::users;

pub const AUTH_TOKEN_ENVVAR: &str = "HAB_AUTH_TOKEN";

lazy_static::lazy_static! {
    pub static ref PROGRAM_NAME: String = {
        let arg0 = std::env::args().next().map(PathBuf::from);
        arg0.as_ref()
            .and_then(|p| p.file_stem())
            .and_then(|p| p.to_str())
            .unwrap()
            .to_string()
    };
}

/// A Builder channel
#[derive(Clone, Debug, PartialEq)]
pub struct ChannelIdent(String);

impl ChannelIdent {
    const LEGACY_ENVVAR: &'static str = "HAB_DEPOT_CHANNEL";
    pub const BLDR_ENVVAR: &'static str = "HAB_BLDR_CHANNEL";
    const UNSTABLE: &'static str = "unstable";
    const STABLE: &'static str = "stable";

    pub fn from_env_var(key: impl AsRef<OsStr>) -> std::result::Result<Self, VarError> {
        crate::env::var(key).map(ChannelIdent)
    }

    pub fn as_str(&self) -> &str {
        self.0.as_str()
    }

    pub fn stable() -> Self {
        Self::from(Self::STABLE)
    }

    pub fn unstable() -> Self {
        Self::from(Self::UNSTABLE)
    }

    fn legacy_default() -> Self {
        ChannelIdent(
            env::var(Self::LEGACY_ENVVAR)
                .ok()
                .and_then(|c| Some(c.to_string()))
                .unwrap_or_else(|| Self::STABLE.to_string()),
        )
    }
}

impl From<&str> for ChannelIdent {
    fn from(s: &str) -> Self {
        ChannelIdent(s.to_string())
    }
}

impl From<String> for ChannelIdent {
    fn from(s: String) -> Self {
        ChannelIdent(s)
    }
}

impl fmt::Display for ChannelIdent {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl Default for ChannelIdent {
    fn default() -> Self {
        match env::var(ChannelIdent::BLDR_ENVVAR) {
            Ok(value) => ChannelIdent(value.to_string()),
            Err(_) => ChannelIdent::legacy_default(),
        }
    }
}
<commit_msg>Derive necessary traits for ChannelIdent: Deserialize, Serialize, Eq, Hash<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate ansi_term;
extern crate base64;
#[cfg(target_os = "linux")]
extern crate caps;
extern crate crypto as rust_crypto;
#[cfg(windows)]
extern crate ctrlc;

#[macro_use]
extern crate log;

#[macro_use]
extern crate serde_derive;

#[cfg(not(windows))]
extern crate users as linux_users;

#[cfg(windows)]
extern crate habitat_win_users;
#[cfg(windows)]
extern crate widestring;
#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate windows_acl;

pub use self::error::{Error, Result};

pub mod binlink;
pub mod channel;
pub mod config;
pub mod crypto;
pub mod env;
pub mod error;
pub mod event;
pub mod fs;
pub mod os;
pub mod output;
pub mod package;
pub mod service;
pub mod url;
pub mod util;

use std::env::VarError;
use std::ffi::OsStr;
use std::fmt;
use std::path::PathBuf;

pub use crate::os::filesystem;
pub use crate::os::users;

pub const AUTH_TOKEN_ENVVAR: &str = "HAB_AUTH_TOKEN";

lazy_static::lazy_static! {
    pub static ref PROGRAM_NAME: String = {
        let arg0 = std::env::args().next().map(PathBuf::from);
        arg0.as_ref()
            .and_then(|p| p.file_stem())
            .and_then(|p| p.to_str())
            .unwrap()
            .to_string()
    };
}

/// A Builder channel
#[derive(Deserialize, Serialize, Clone, Debug, Eq, Hash, PartialEq)]
pub struct ChannelIdent(String);

impl ChannelIdent {
    const LEGACY_ENVVAR: &'static str = "HAB_DEPOT_CHANNEL";
    pub const BLDR_ENVVAR: &'static str = "HAB_BLDR_CHANNEL";
    const UNSTABLE: &'static str = "unstable";
    const STABLE: &'static str = "stable";

    pub fn from_env_var(key: impl AsRef<OsStr>) -> std::result::Result<Self, VarError> {
        crate::env::var(key).map(ChannelIdent)
    }

    pub fn as_str(&self) -> &str {
        self.0.as_str()
    }

    pub fn stable() -> Self {
        Self::from(Self::STABLE)
    }

    pub fn unstable() -> Self {
        Self::from(Self::UNSTABLE)
    }

    fn legacy_default() -> Self {
        ChannelIdent(
            env::var(Self::LEGACY_ENVVAR)
                .ok()
                .and_then(|c| Some(c.to_string()))
                .unwrap_or_else(|| Self::STABLE.to_string()),
        )
    }
}

impl From<&str> for ChannelIdent {
    fn from(s: &str) -> Self {
        ChannelIdent(s.to_string())
    }
}

impl From<String> for ChannelIdent {
    fn from(s: String) -> Self {
        ChannelIdent(s)
    }
}

impl fmt::Display for ChannelIdent {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl Default for ChannelIdent {
    fn default() -> Self {
        match env::var(ChannelIdent::BLDR_ENVVAR) {
            Ok(value) => ChannelIdent(value.to_string()),
            Err(_) => ChannelIdent::legacy_default(),
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Write};

pub use position::Position;
use bounds::Bounds;

pub mod position;
mod bounds;

pub trait Shape {
    fn bounds(&self) -> Bounds;
    fn write_eps(&self, wr: &mut Write) -> io::Result<()>;
}

pub struct SetRGB(pub f32, pub f32, pub f32);
pub struct Point(pub Position, pub f32);
pub struct Points(pub Vec<Position>, pub f32);
pub struct Line(pub Position, pub Position);
pub struct Lines(pub Vec<(Position, Position)>);

impl Shape for SetRGB {
    fn bounds(&self) -> Bounds {
        Bounds::new()
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        writeln!(wr, "{:.2} {:.2} {:.2} setrgbcolor", self.0, self.1, self.2)
    }
}

impl Shape for Point {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        b.add_position(self.0);
        b
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        writeln!(wr,
                 "newpath {} {} {} 0 360 arc fill",
                 self.0.x,
                 self.0.y,
                 self.1)
    }
}

impl Shape for Points {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        for &pos in &self.0 {
            b.add_position(pos);
        }
        b
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        try!(writeln!(wr,
                      "/p {{
2 dict begin
/y exch def
/x exch def
gsave
newpath x y {} 0 360 \
                       arc fill
grestore
end
}} def",
                      self.1));
        for pos in &self.0 {
            try!(writeln!(wr, "{:.4} {:.4} p", pos.x, pos.y));
        }

        Ok(())
    }
}

impl Shape for Lines {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        for &(p1, p2) in &self.0 {
            b.add_position(p1);
            b.add_position(p2);
        }
        b
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        try!(writeln!(wr,
                      "/l {{
2 dict begin
/y2 exch def
/x2 exch def
/y1 exch def
/x1 exch def
\
                       gsave
newpath x1 y1 moveto x2 y2 lineto stroke
grestore
end
}} def"));
        for &(p1, p2) in &self.0 {
            try!(writeln!(wr, "{:.4} {:.4} {:.4} {:.4} l", p1.x, p1.y, p2.x, p2.y));
        }

        Ok(())
    }
}

impl Shape for Line {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        b.add_position(self.0);
        b.add_position(self.1);
        b
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        writeln!(wr,
                 "newpath {} {} moveto {} {} lineto stroke",
                 self.0.x,
                 self.0.y,
                 self.1.x,
                 self.1.y)
    }
}

pub struct EpsDocument {
    shapes: Vec<Box<Shape>>,
}

impl EpsDocument {
    pub fn new() -> EpsDocument {
        EpsDocument { shapes: Vec::new() }
    }

    pub fn add_shape(&mut self, shape: Box<Shape>) {
        self.shapes.push(shape);
    }

    /// Write as Embedded Postscript (EPS)
    pub fn write_eps(&self, wr: &mut Write, min_width: f32, min_height: f32) -> io::Result<()> {
        // Determine extend of canvas
        let mut bounds = Bounds::new();

        for shape in &self.shapes {
            bounds.extend(shape.bounds());
        }

        let width = bounds.width().max(min_width);
        let height = bounds.height().max(min_height);
        let border_percent = 0.1;

        let scale = 1.0 + 2.0 * border_percent;

        try!(writeln!(wr,
                      r#"%%!PS-Adobe-3.0 EPSF-3.0
%%Creator: https://github.com/mneumann/eps-writer-rs
%%DocumentData: Clean7Bit
%%Origin: 0 0
%%BoundingBox: {} {} {} {}
%%LanguageLevel: 2
%%Pages: 1
%%Page: 1 1
"#,
                      bounds.min_x() - border_percent * width,
                      bounds.min_y() - border_percent * height,
                      bounds.max_x() + border_percent * width,
                      bounds.max_y() + border_percent * height));

        // use a stroke width of 0.1% of the width or height of the canvas
        let stroke_width = scale * width.max(height) / 1000.0;
        try!(writeln!(wr, r#"{} setlinewidth"#, stroke_width));

        for shape in &self.shapes {
            try!(shape.write_eps(wr));
        }

        writeln!(wr, "%%EOF")
    }
}
<commit_msg>Add HiResBoundingBox<commit_after>use std::io::{self, Write};

pub use position::Position;
use bounds::Bounds;

pub mod position;
mod bounds;

pub trait Shape {
    fn bounds(&self) -> Bounds;
    fn write_eps(&self, wr: &mut Write) -> io::Result<()>;
}

pub struct SetRGB(pub f32, pub f32, pub f32);
pub struct Point(pub Position, pub f32);
pub struct Points(pub Vec<Position>, pub f32);
pub struct Line(pub Position, pub Position);
pub struct Lines(pub Vec<(Position, Position)>);

impl Shape for SetRGB {
    fn bounds(&self) -> Bounds {
        Bounds::new()
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        writeln!(wr, "{:.2} {:.2} {:.2} setrgbcolor", self.0, self.1, self.2)
    }
}

impl Shape for Point {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        b.add_position(self.0);
        b
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        writeln!(wr,
                 "newpath {} {} {} 0 360 arc fill",
                 self.0.x,
                 self.0.y,
                 self.1)
    }
}

impl Shape for Points {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        for &pos in &self.0 {
            b.add_position(pos);
        }
        b
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        try!(writeln!(wr,
                      "/p {{
2 dict begin
/y exch def
/x exch def
gsave
newpath x y {} 0 360 \
                       arc fill
grestore
end
}} def",
                      self.1));
        for pos in &self.0 {
            try!(writeln!(wr, "{:.4} {:.4} p", pos.x, pos.y));
        }

        Ok(())
    }
}

impl Shape for Lines {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        for &(p1, p2) in &self.0 {
            b.add_position(p1);
            b.add_position(p2);
        }
        b
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        try!(writeln!(wr,
                      "/l {{
2 dict begin
/y2 exch def
/x2 exch def
/y1 exch def
/x1 exch def
\
                       gsave
newpath x1 y1 moveto x2 y2 lineto stroke
grestore
end
}} def"));
        for &(p1, p2) in &self.0 {
            try!(writeln!(wr, "{:.4} {:.4} {:.4} {:.4} l", p1.x, p1.y, p2.x, p2.y));
        }

        Ok(())
    }
}

impl Shape for Line {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        b.add_position(self.0);
        b.add_position(self.1);
        b
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        writeln!(wr,
                 "newpath {} {} moveto {} {} lineto stroke",
                 self.0.x,
                 self.0.y,
                 self.1.x,
                 self.1.y)
    }
}

pub struct EpsDocument {
    shapes: Vec<Box<Shape>>,
}

impl EpsDocument {
    pub fn new() -> EpsDocument {
        EpsDocument { shapes: Vec::new() }
    }

    pub fn add_shape(&mut self, shape: Box<Shape>) {
        self.shapes.push(shape);
    }

    /// Write as Embedded Postscript (EPS)
    pub fn write_eps(&self, wr: &mut Write, min_width: f32, min_height: f32) -> io::Result<()> {
        // Determine extend of canvas
        let mut bounds = Bounds::new();

        for shape in &self.shapes {
            bounds.extend(shape.bounds());
        }

        let width = bounds.width().max(min_width);
        let height = bounds.height().max(min_height);
        let border_percent = 0.1;

        let scale = 1.0 + 2.0 * border_percent;

        try!(writeln!(wr,
                      r#"%%!PS-Adobe-3.0 EPSF-3.0
%%Creator: https://github.com/mneumann/eps-writer-rs
%%DocumentData: Clean7Bit
%%Origin: 0 0
%%BoundingBox: {} {} {} {}
%%HiResBoundingBox: {} {} {} {}
%%LanguageLevel: 2
%%Pages: 1
%%Page: 1 1
"#,
                      (bounds.min_x() - border_percent * width) as isize,
                      (bounds.min_y() - border_percent * height) as isize,
                      (bounds.max_x() + border_percent * width) as isize,
                      (bounds.max_y() + border_percent * height) as isize,

                      bounds.min_x() - border_percent * width,
                      bounds.min_y() - border_percent * height,
                      bounds.max_x() + border_percent * width,
                      bounds.max_y() + border_percent * height));

        // use a stroke width of 0.1% of the width or height of the canvas
        let stroke_width = scale * width.max(height) / 1000.0;
        try!(writeln!(wr, r#"{} setlinewidth"#, stroke_width));

        for shape in &self.shapes {
            try!(shape.write_eps(wr));
        }

        writeln!(wr, "%%EOF")
    }
}
<|endoftext|>


<commit_before>extern crate libloading;

pub use libloading::{Library, Symbol};

#[macro_export]
macro_rules! ffi_dispatch(
    ($feature: expr, $handle: ident, $func: ident, $($arg: expr),*) => (
        {
            #[cfg(feature = $feature)]
            let ret = ($handle.$func)($($arg),*);
            #[cfg(not(feature = $feature))]
            let ret = $func($($arg),*);

            ret
        }
    );
);

#[macro_export]
macro_rules! ffi_dispatch_static(
    ($feature: expr, $handle: ident, $name: ident) => (
        {
            #[cfg(feature = $feature)]
            let ret = $handle.$name;
            #[cfg(not(feature = $feature))]
            let ret = &$name;

            ret
        }
    );
);

#[macro_export]
macro_rules! link_external_library(
    ($link: expr,
        $(statics: $($sname: ident: $stype: ty),+,)|*
        $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|*
        $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|*
    ) => (
        #[link(name = $link)]
        extern "C" {
            $($(
                pub static $sname: $stype;
            )+)*
            $($(
                pub fn $fname($(_: $farg),*) -> $fret;
            )+)*
            $($(
                pub fn $vname($(_: $vargs),+ , ...) -> $vret;
            )+)*
        }
    );
);

pub enum DlError {
    NotFound,
    MissingSymbol(&'static str)
}

#[macro_export]
macro_rules! dlopen_external_library(
    (__struct, $structname: ident,
        $(statics: $($sname: ident: $stype: ty),+,)|*
        $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|*
        $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|*
    ) => (
        pub struct $structname {
            __lib: $crate::Library,
            $($(
                pub $sname: $crate::Symbol<'static, &'static $stype>,
            )+)*
            $($(
                pub $fname: $crate::Symbol<'static, unsafe extern "C" fn($($farg),*) -> $fret>,
            )+)*
            $($(
                pub $vname: $crate::Symbol<'static, unsafe extern "C" fn($($vargs),+ , ...) -> $vret>,
            )+)*
        }
    );
    (__impl, $structname: ident,
        $(statics: $($sname: ident: $stype: ty),+,)|*
        $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|*
        $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|*
    ) => (
    impl $structname {
        pub fn open(name: &str) -> Result<$structname, $crate::DlError> {
            // we use it to ensure the 'static lifetime
            use std::mem::transmute;
            let lib = match $crate::Library::new(name) {
                Ok(l) => l,
                Err(_) => return Err($crate::DlError::NotFound)
            };
            unsafe {
                let s = $structname {
                    $($($sname: {
                        let s_name = concat!(stringify!($sname), "\0");
                        transmute(match lib.get::<&'static $stype>(s_name.as_bytes()) {
                            Ok(s) => s,
                            Err(_) => return Err($crate::DlError::MissingSymbol(s_name))
                        })
                    },
                    )+)*
                    $($($fname: {
                        let s_name = concat!(stringify!($fname), "\0");
                        transmute(match lib.get::<unsafe extern "C" fn($($farg),*) -> $fret>(s_name.as_bytes()) {
                            Ok(s) => s,
                            Err(_) => return Err($crate::DlError::MissingSymbol(s_name))
                        })
                    },
                    )+)*
                    $($($vname: {
                        let s_name = concat!(stringify!($vname), "\0");
                        transmute(match lib.get::<unsafe extern "C" fn($($vargs),+ , ...) -> $vret>(s_name.as_bytes()) {
                            Ok(s) => s,
                            Err(_) => return Err($crate::DlError::MissingSymbol(s_name))
                        })
                    },
                    )+)*
                    __lib: lib
                };
                Ok(s)
            }
        }
    }
    );
    ($structname: ident,
        $(statics: $($sname: ident: $stype: ty),+,)|*
        $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|*
        $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|*
    ) => (
        dlopen_external_library!(__struct,
            $structname, $(statics: $($sname: $stype),+,)|*
            $(functions: $(fn $fname($($farg),*) -> $fret),+,)|*
            $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|*
        );
        dlopen_external_library!(__impl,
            $structname, $(statics: $($sname: $stype),+,)|*
            $(functions: $(fn $fname($($farg),*) -> $fret),+,)|*
            $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|*
        );
        unsafe impl Sync for $structname { }
    );
);

#[macro_export]
macro_rules! external_library(
    ($feature: expr, $structname: ident, $link: expr,
        $(statics: $($sname: ident: $stype: ty),+,)|*
        $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|*
        $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|*
    ) => (
        #[cfg(feature = $feature)]
        dlopen_external_library!(
            $structname, $(statics: $($sname: $stype),+,)|*
            $(functions: $(fn $fname($($farg),*) -> $fret),+,)|*
            $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|*
        );

        #[cfg(not(feature = $feature))]
        link_external_library!(
            $link, $(statics: $($sname: $stype),+,)|*
            $(functions: $(fn $fname($($farg),*) -> $fret),+,)|*
            $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|*
        );
    );
);
<commit_msg>Use full path in recursive macros<commit_after>extern crate libloading;

pub use libloading::{Library, Symbol};

#[macro_export]
macro_rules! ffi_dispatch(
    ($feature: expr, $handle: ident, $func: ident, $($arg: expr),*) => (
        {
            #[cfg(feature = $feature)]
            let ret = ($handle.$func)($($arg),*);
            #[cfg(not(feature = $feature))]
            let ret = $func($($arg),*);

            ret
        }
    );
);

#[macro_export]
macro_rules! ffi_dispatch_static(
    ($feature: expr, $handle: ident, $name: ident) => (
        {
            #[cfg(feature = $feature)]
            let ret = $handle.$name;
            #[cfg(not(feature = $feature))]
            let ret = &$name;

            ret
        }
    );
);

#[macro_export]
macro_rules! link_external_library(
    ($link: expr,
        $(statics: $($sname: ident: $stype: ty),+,)|*
        $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|*
        $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|*
    ) => (
        #[link(name = $link)]
        extern "C" {
            $($(
                pub static $sname: $stype;
            )+)*
            $($(
                pub fn $fname($(_: $farg),*) -> $fret;
            )+)*
            $($(
                pub fn $vname($(_: $vargs),+ , ...) -> $vret;
            )+)*
        }
    );
);

pub enum DlError {
    NotFound,
    MissingSymbol(&'static str)
}

#[macro_export]
macro_rules! dlopen_external_library(
    (__struct, $structname: ident,
        $(statics: $($sname: ident: $stype: ty),+,)|*
        $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|*
        $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|*
    ) => (
        pub struct $structname {
            __lib: $crate::Library,
            $($(
                pub $sname: $crate::Symbol<'static, &'static $stype>,
            )+)*
            $($(
                pub $fname: $crate::Symbol<'static, unsafe extern "C" fn($($farg),*) -> $fret>,
            )+)*
            $($(
                pub $vname: $crate::Symbol<'static, unsafe extern "C" fn($($vargs),+ , ...) -> $vret>,
            )+)*
        }
    );
    (__impl, $structname: ident,
        $(statics: $($sname: ident: $stype: ty),+,)|*
        $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|*
        $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|*
    ) => (
    impl $structname {
        pub fn open(name: &str) -> Result<$structname, $crate::DlError> {
            // we use it to ensure the 'static lifetime
            use std::mem::transmute;
            let lib = match $crate::Library::new(name) {
                Ok(l) => l,
                Err(_) => return Err($crate::DlError::NotFound)
            };
            unsafe {
                let s = $structname {
                    $($($sname: {
                        let s_name = concat!(stringify!($sname), "\0");
                        transmute(match lib.get::<&'static $stype>(s_name.as_bytes()) {
                            Ok(s) => s,
                            Err(_) => return Err($crate::DlError::MissingSymbol(s_name))
                        })
                    },
                    )+)*
                    $($($fname: {
                        let s_name = concat!(stringify!($fname), "\0");
                        transmute(match lib.get::<unsafe extern "C" fn($($farg),*) -> $fret>(s_name.as_bytes()) {
                            Ok(s) => s,
                            Err(_) => return Err($crate::DlError::MissingSymbol(s_name))
                        })
                    },
                    )+)*
                    $($($vname: {
                        let s_name = concat!(stringify!($vname), "\0");
                        transmute(match lib.get::<unsafe extern "C" fn($($vargs),+ , ...) -> $vret>(s_name.as_bytes()) {
                            Ok(s) => s,
                            Err(_) => return Err($crate::DlError::MissingSymbol(s_name))
                        })
                    },
                    )+)*
                    __lib: lib
                };
                Ok(s)
            }
        }
    }
    );
    ($structname: ident,
        $(statics: $($sname: ident: $stype: ty),+,)|*
        $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|*
        $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|*
    ) => (
        $crate::dlopen_external_library!(__struct,
            $structname, $(statics: $($sname: $stype),+,)|*
            $(functions: $(fn $fname($($farg),*) -> $fret),+,)|*
            $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|*
        );
        $crate::dlopen_external_library!(__impl,
            $structname, $(statics: $($sname: $stype),+,)|*
            $(functions: $(fn $fname($($farg),*) -> $fret),+,)|*
            $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|*
        );
        unsafe impl Sync for $structname { }
    );
);

#[macro_export]
macro_rules! external_library(
    ($feature: expr, $structname: ident, $link: expr,
        $(statics: $($sname: ident: $stype: ty),+,)|*
        $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|*
        $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|*
    ) => (
        #[cfg(feature = $feature)]
        $crate::dlopen_external_library!(
            $structname, $(statics: $($sname: $stype),+,)|*
            $(functions: $(fn $fname($($farg),*) -> $fret),+,)|*
            $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|*
        );

        #[cfg(not(feature = $feature))]
        $crate::link_external_library!(
            $link, $(statics: $($sname: $stype),+,)|*
            $(functions: $(fn $fname($($farg),*) -> $fret),+,)|*
            $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|*
        );
    );
);
<|endoftext|>


<commit_before>#![cfg_attr(all(feature="nightly", test), feature(test))]
#![cfg_attr(feature="nightly", feature(const_fn))]

#[macro_use]
#[cfg(test)]
extern crate lazy_static;

use std::thread::{self, JoinHandle};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::sync::{Arc, Mutex, Barrier};
use std::cell::RefCell;
use std::marker::PhantomData;

enum Message {
    NewJob(Thunk<'static>),
    Join,
}

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>;

impl Drop for PoolCache {
    fn drop(&mut self) {
        ::std::mem::replace(&mut self.job_sender, None);
    }
}

pub struct PoolCache {
    threads: Vec<JoinHandle<()>>,
    job_sender: Option<Sender<Message>>,
    join_barrier: Arc<(Mutex<Receiver<Message>>, Barrier)>,
}

impl PoolCache {
    pub fn new(n: u32) -> PoolCache {
        assert!(n >= 1);

        let (job_sender, job_receiver) = channel();
        let job_receiver = Arc::new((Mutex::new(job_receiver),
                                     Barrier::new(n as usize + 1)));

        let mut threads = Vec::with_capacity(n as usize);
        for _ in 0..n {
            let job_receiver = job_receiver.clone();
            threads.push(thread::spawn(move || {
                loop {
                    let message = {
                        // Only lock jobs for the time it takes
                        // to get a job, not run it.
                        let lock = job_receiver.0.lock().unwrap();
                        lock.recv()
                    };

                    match message {
                        Ok(Message::NewJob(job)) => {
                            job.call_box();
                        }
                        Ok(Message::Join) => {
                            job_receiver.1.wait();
                        }
                        // The pool was dropped.
                        Err(..) => break
                    }
                }
            }));
        }

        PoolCache {
            threads: threads,
            job_sender: Some(job_sender),
            join_barrier: job_receiver,
        }

        // spawn n threads, put them in waiting mode
    }

    pub fn scope<'pool, 'scope, F, R>(&'pool mut self, f: F) -> R
        where F: FnOnce(&Scope<'pool, 'scope>) -> R
    {
        let mut scope = Scope {
            pool: self,
            dtors: RefCell::new(None),
            _marker: PhantomData,
        };
        let ret = f(&scope);
        scope.drop_all();
        ret
    }

    pub fn thread_count(&self) -> u32 {
        self.threads.len() as u32
    }
}

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

pub struct Scope<'pool, 'scope> {
    pool: &'pool mut PoolCache,
    dtors: RefCell<Option<DtorChain<'scope>>>,
    _marker: PhantomData<&'scope mut ()>,
}

struct DtorChain<'a> {
    dtor: Box<FnBox + 'a>,
    next: Option<Box<DtorChain<'a>>>
}

impl<'pool, 'scope> Scope<'pool, 'scope> {
    // This method is carefully written in a transactional style, so
    // that it can be called directly and, if any dtor panics, can be
    // resumed in the unwinding this causes. By initially running the
    // method outside of any destructor, we avoid any leakage problems
    // due to #14875.
    fn drop_all(&mut self) {
        loop {
            // use a separate scope to ensure that the RefCell borrow
            // is relinquished before running `dtor`
            let dtor = {
                let mut dtors = self.dtors.borrow_mut();
                if let Some(mut node) = dtors.take() {
                    *dtors = node.next.take().map(|b| *b);
                    node.dtor
                } else {
                    break
                }
            };
            dtor.call_box()
        }

        for _ in 0..self.pool.threads.len() {
            self.pool.job_sender.as_ref().unwrap().send(Message::Join).unwrap();
        }

        self.pool.join_barrier.1.wait();
    }

    fn defer<F>(&self, f: F) where F: FnOnce() + 'scope {
        let mut dtors = self.dtors.borrow_mut();
        *dtors = Some(DtorChain {
            dtor: Box::new(f),
            next: dtors.take().map(Box::new)
        });
    }

    pub fn execute<F>(&self, f: F)
        where F: FnOnce() + Send + 'scope
    {
        let b = unsafe {
            ::std::mem::transmute::<Thunk<'scope>, Thunk<'static>>(Box::new(f))
        };
        self.pool.job_sender.as_ref().unwrap().send(Message::NewJob(b)).unwrap();
        self.defer(move || {

        });
    }
}

impl<'pool, 'scope> Drop for Scope<'pool, 'scope> {
    fn drop(&mut self) {
        self.drop_all()
    }
}

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

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

    #[test]
    fn example() {
        // Create a threadpool holding 4 threads
        let mut pool = PoolCache::new(4);

        let mut vec = vec![0, 1, 2, 3, 4, 5, 6, 7];

        // Use the threads as scoped threads that can
        // reference anything outside this closure
        pool.scope(|scoped| {

            // Create references to each element in the vector ...
            for e in &mut vec {
                // ... and add 1 to it in a seperate thread
                scoped.execute(move || {
                    *e += 1;
                });
            }
        });

        assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7, 8]);
    }

    #[test]
    fn smoketest() {
        let mut pool = PoolCache::new(4);

        for i in 1..7 {
            let mut vec = vec![0, 1, 2, 3, 4];
            pool.scope(|s| {
                for e in vec.iter_mut() {
                    s.execute(move || {
                        *e += i;
                    });
                }
            });

            let mut vec2 = vec![0, 1, 2, 3, 4];
            for e in vec2.iter_mut() {
                *e += i;
            }

            assert_eq!(vec, vec2);
        }
    }
}

#[cfg(all(test, feature="nightly"))]
mod benches {
    extern crate test;

    use self::test::{Bencher, black_box};
    use super::PoolCache;
    use std::sync::Mutex;

    // const MS_SLEEP_PER_OP: u32 = 1;

    lazy_static! {
        static ref POOL_1: Mutex<PoolCache> = Mutex::new(PoolCache::new(1));
        static ref POOL_2: Mutex<PoolCache> = Mutex::new(PoolCache::new(2));
        static ref POOL_3: Mutex<PoolCache> = Mutex::new(PoolCache::new(3));
        static ref POOL_4: Mutex<PoolCache> = Mutex::new(PoolCache::new(4));
        static ref POOL_5: Mutex<PoolCache> = Mutex::new(PoolCache::new(5));
        static ref POOL_8: Mutex<PoolCache> = Mutex::new(PoolCache::new(8));
    }

    fn fib(n: u64) -> u64 {
        let mut prev_prev: u64 = 1;
        let mut prev = 1;
        let mut current = 1;
        for _ in 2..(n+1) {
            current = prev_prev.wrapping_add(prev);
            prev_prev = prev;
            prev = current;
        }
        current
    }

    fn threads_interleaved_n(pool: &mut PoolCache)  {
        let size = 1024; // 1kiB

        let mut data = vec![1u8; size];
        pool.scope(|s| {
            for e in data.iter_mut() {
                s.execute(move || {
                    *e += fib(black_box(1000 * (*e as u64))) as u8;
                    //thread::sleep_ms(MS_SLEEP_PER_OP);
                });
            }
        });
    }

    #[bench]
    fn threads_interleaved_1(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_1.lock().unwrap()))
    }

    #[bench]
    fn threads_interleaved_2(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_2.lock().unwrap()))
    }

    #[bench]
    fn threads_interleaved_4(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_4.lock().unwrap()))
    }

    #[bench]
    fn threads_interleaved_8(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_8.lock().unwrap()))
    }

    fn threads_chunked_n(pool: &mut PoolCache) {
        let size = 1024 * 1024 * 100 / 4; // 100MiB

        let n = pool.thread_count();
        let mut data = vec![0u32; size];
        pool.scope(|s| {
            let l = (data.len() - 1) / n as usize + 1;
            for es in data.chunks_mut(l) {
                s.execute(move || {
                    if es.len() > 1 {
                        es[0] = 1;
                        es[1] = 1;
                        for i in 2..es.len() {
                            // Fibonnaci gets big fast,
                            // so just wrap around all the time
                            es[i] = es[i-1].wrapping_add(es[i-2]);
                        }
                    }
                    //thread::sleep_ms(MS_SLEEP_PER_OP);
                });
            }
        });
    }

    #[bench]
    fn threads_chunked_1(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_1.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_2(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_2.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_3(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_3.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_4(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_4.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_5(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_5.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_8(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_8.lock().unwrap()))
    }
}
<commit_msg>Remove dead code<commit_after>#![cfg_attr(all(feature="nightly", test), feature(test))]
#![cfg_attr(feature="nightly", feature(const_fn))]

#[macro_use]
#[cfg(test)]
extern crate lazy_static;

use std::thread::{self, JoinHandle};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::sync::{Arc, Mutex, Barrier};
use std::marker::PhantomData;

enum Message {
    NewJob(Thunk<'static>),
    Join,
}

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>;

impl Drop for PoolCache {
    fn drop(&mut self) {
        ::std::mem::replace(&mut self.job_sender, None);
    }
}

pub struct PoolCache {
    threads: Vec<JoinHandle<()>>,
    job_sender: Option<Sender<Message>>,
    join_barrier: Arc<(Mutex<Receiver<Message>>, Barrier)>,
}

impl PoolCache {
    pub fn new(n: u32) -> PoolCache {
        assert!(n >= 1);

        let (job_sender, job_receiver) = channel();
        let job_receiver = Arc::new((Mutex::new(job_receiver),
                                     Barrier::new(n as usize + 1)));

        let mut threads = Vec::with_capacity(n as usize);

        // spawn n threads, put them in waiting mode
        for _ in 0..n {
            let job_receiver = job_receiver.clone();
            threads.push(thread::spawn(move || {
                loop {
                    let message = {
                        // Only lock jobs for the time it takes
                        // to get a job, not run it.
                        let lock = job_receiver.0.lock().unwrap();
                        lock.recv()
                    };

                    match message {
                        Ok(Message::NewJob(job)) => {
                            job.call_box();
                        }
                        Ok(Message::Join) => {
                            job_receiver.1.wait();
                        }
                        // The pool was dropped.
                        Err(..) => break
                    }
                }
            }));
        }

        PoolCache {
            threads: threads,
            job_sender: Some(job_sender),
            join_barrier: job_receiver,
        }
    }

    pub fn scope<'pool, 'scope, F, R>(&'pool mut self, f: F) -> R
        where F: FnOnce(&Scope<'pool, 'scope>) -> R
    {
        let scope = Scope {
            pool: self,
            _marker: PhantomData,
        };
        f(&scope)
    }

    pub fn thread_count(&self) -> u32 {
        self.threads.len() as u32
    }
}

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

pub struct Scope<'pool, 'scope> {
    pool: &'pool mut PoolCache,
    _marker: PhantomData<&'scope mut ()>,
}

impl<'pool, 'scope> Scope<'pool, 'scope> {
    pub fn execute<F>(&self, f: F)
        where F: FnOnce() + Send + 'scope
    {
        let b = unsafe {
            ::std::mem::transmute::<Thunk<'scope>, Thunk<'static>>(Box::new(f))
        };
        self.pool.job_sender.as_ref().unwrap().send(Message::NewJob(b)).unwrap();
    }
}

impl<'pool, 'scope> Drop for Scope<'pool, 'scope> {
    fn drop(&mut self) {
        for _ in 0..self.pool.threads.len() {
            self.pool.job_sender.as_ref().unwrap().send(Message::Join).unwrap();
        }

        self.pool.join_barrier.1.wait();
    }
}

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

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

    #[test]
    fn example() {
        // Create a threadpool holding 4 threads
        let mut pool = PoolCache::new(4);

        let mut vec = vec![0, 1, 2, 3, 4, 5, 6, 7];

        // Use the threads as scoped threads that can
        // reference anything outside this closure
        pool.scope(|scoped| {

            // Create references to each element in the vector ...
            for e in &mut vec {
                // ... and add 1 to it in a seperate thread
                scoped.execute(move || {
                    *e += 1;
                });
            }
        });

        assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7, 8]);
    }

    #[test]
    fn smoketest() {
        let mut pool = PoolCache::new(4);

        for i in 1..7 {
            let mut vec = vec![0, 1, 2, 3, 4];
            pool.scope(|s| {
                for e in vec.iter_mut() {
                    s.execute(move || {
                        *e += i;
                    });
                }
            });

            let mut vec2 = vec![0, 1, 2, 3, 4];
            for e in vec2.iter_mut() {
                *e += i;
            }

            assert_eq!(vec, vec2);
        }
    }

    #[test]
    #[should_panic]
    fn panicking() {
        let mut pool = PoolCache::new(4);
        pool.scope(|scoped| {
            scoped.execute(move || {
                panic!()
            });
        });
    }
}

#[cfg(all(test, feature="nightly"))]
mod benches {
    extern crate test;

    use self::test::{Bencher, black_box};
    use super::PoolCache;
    use std::sync::Mutex;

    // const MS_SLEEP_PER_OP: u32 = 1;

    lazy_static! {
        static ref POOL_1: Mutex<PoolCache> = Mutex::new(PoolCache::new(1));
        static ref POOL_2: Mutex<PoolCache> = Mutex::new(PoolCache::new(2));
        static ref POOL_3: Mutex<PoolCache> = Mutex::new(PoolCache::new(3));
        static ref POOL_4: Mutex<PoolCache> = Mutex::new(PoolCache::new(4));
        static ref POOL_5: Mutex<PoolCache> = Mutex::new(PoolCache::new(5));
        static ref POOL_8: Mutex<PoolCache> = Mutex::new(PoolCache::new(8));
    }

    fn fib(n: u64) -> u64 {
        let mut prev_prev: u64 = 1;
        let mut prev = 1;
        let mut current = 1;
        for _ in 2..(n+1) {
            current = prev_prev.wrapping_add(prev);
            prev_prev = prev;
            prev = current;
        }
        current
    }

    fn threads_interleaved_n(pool: &mut PoolCache)  {
        let size = 1024; // 1kiB

        let mut data = vec![1u8; size];
        pool.scope(|s| {
            for e in data.iter_mut() {
                s.execute(move || {
                    *e += fib(black_box(1000 * (*e as u64))) as u8;
                    //thread::sleep_ms(MS_SLEEP_PER_OP);
                });
            }
        });
    }

    #[bench]
    fn threads_interleaved_1(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_1.lock().unwrap()))
    }

    #[bench]
    fn threads_interleaved_2(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_2.lock().unwrap()))
    }

    #[bench]
    fn threads_interleaved_4(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_4.lock().unwrap()))
    }

    #[bench]
    fn threads_interleaved_8(b: &mut Bencher) {
        b.iter(|| threads_interleaved_n(&mut POOL_8.lock().unwrap()))
    }

    fn threads_chunked_n(pool: &mut PoolCache) {
        let size = 1024 * 1024 * 100 / 4; // 100MiB

        let n = pool.thread_count();
        let mut data = vec![0u32; size];
        pool.scope(|s| {
            let l = (data.len() - 1) / n as usize + 1;
            for es in data.chunks_mut(l) {
                s.execute(move || {
                    if es.len() > 1 {
                        es[0] = 1;
                        es[1] = 1;
                        for i in 2..es.len() {
                            // Fibonnaci gets big fast,
                            // so just wrap around all the time
                            es[i] = es[i-1].wrapping_add(es[i-2]);
                        }
                    }
                    //thread::sleep_ms(MS_SLEEP_PER_OP);
                });
            }
        });
    }

    #[bench]
    fn threads_chunked_1(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_1.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_2(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_2.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_3(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_3.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_4(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_4.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_5(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_5.lock().unwrap()))
    }

    #[bench]
    fn threads_chunked_8(b: &mut Bencher) {
        b.iter(|| threads_chunked_n(&mut POOL_8.lock().unwrap()))
    }
}
<|endoftext|>


<commit_before>use primitives::{PrimitiveIterator, U4};

use std::fs::File;
use std::io::{Error as IoError, Read};

pub mod primitives;

pub type ParserResult<T> = Result<T, ParserError>;

#[derive(Debug)]
pub enum ParserError {
    Io(IoError),
}

impl From<IoError> for ParserError {
    fn from(error: IoError) -> ParserError {
        ParserError::Io(error)
    }
}

#[derive(Debug)]
pub struct ClassFile {
    pub magic: U4,
}

impl ClassFile {
    pub fn from(file: File) -> ParserResult<ClassFile> {
        let mut bytes = file.bytes();

        let magic = try!(bytes.next_u4());

        Ok(ClassFile { magic: magic })
    }
}

#[cfg(test)]
mod tests {

    extern crate spectral;

    use self::spectral::prelude::*;

    use super::ClassFile;

    use std::fs::File;
    use std::path::PathBuf;

    const MANIFEST_DIR: &'static str = env!("CARGO_MANIFEST_DIR");

    #[test]
    fn can_successfully_parse_magic() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.magic).is_equal_to(&0xCAFEBABE);
    }

    fn open_test_resource(resource_path: &str) -> File {
        let mut file_path = PathBuf::from(MANIFEST_DIR);
        file_path.push("test-resources/");
        file_path.push(resource_path);

        File::open(file_path).unwrap()
    }

}
<commit_msg>Can now parse out the major and minor version from the ClassFile<commit_after>use primitives::{PrimitiveIterator, U2, U4};

use std::fs::File;
use std::io::{Error as IoError, Read};

pub mod primitives;

pub type ParserResult<T> = Result<T, ParserError>;

#[derive(Debug)]
pub enum ParserError {
    Io(IoError),
}

impl From<IoError> for ParserError {
    fn from(error: IoError) -> ParserError {
        ParserError::Io(error)
    }
}

#[derive(Debug)]
pub struct ClassFile {
    pub magic: U4,
    pub minor_version: U2,
    pub major_version: U2,
}

impl ClassFile {
    pub fn from(file: File) -> ParserResult<ClassFile> {
        let mut bytes = file.bytes();

        let magic = try!(bytes.next_u4());
        let minor_version = try!(bytes.next_u2());
        let major_version = try!(bytes.next_u2());

        Ok(ClassFile {
            magic: magic,
            minor_version: minor_version,
            major_version: major_version,
        })
    }
}

#[cfg(test)]
mod tests {

    extern crate spectral;

    use self::spectral::prelude::*;

    use super::ClassFile;

    use std::fs::File;
    use std::path::PathBuf;

    const MANIFEST_DIR: &'static str = env!("CARGO_MANIFEST_DIR");

    #[test]
    fn can_successfully_parse_magic() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.magic).is_equal_to(&0xCAFEBABE);
    }

    #[test]
    fn can_successfully_parse_version() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.minor_version).is_equal_to(&0);
        assert_that(&classfile.major_version).is_equal_to(&52);
    }

    fn open_test_resource(resource_path: &str) -> File {
        let mut file_path = PathBuf::from(MANIFEST_DIR);
        file_path.push("test-resources/");
        file_path.push(resource_path);

        File::open(file_path).unwrap()
    }

}
<|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"]
#![comment="Mysql client library writen in rust"]
#![license="MIT"]
#![crate_type="rlib"]
#![crate_type="dylib"]

#![feature(unsafe_destructor)]
#![feature(phase)]
#![feature(if_let)]
#![feature(slicing_syntax)]

#![allow(dead_code)]
#![feature(macro_rules)]

#[cfg(test)]
extern crate test;
extern crate core;
extern crate time;
#[cfg(feature = "openssl")]
extern crate openssl;
extern crate regex;
#[phase(plugin)]
extern crate regex_macros;

#[phase(plugin)]
extern crate lazy_static;

mod scramble;
pub mod consts;
pub mod error;
mod packet;
mod io;
pub mod value;
pub mod conn;
<commit_msg>Remove unused attributes<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(phase)]
#![feature(if_let)]
#![feature(slicing_syntax)]

#![allow(dead_code)]
#![feature(macro_rules)]

#[cfg(test)]
extern crate test;
extern crate core;
extern crate time;
#[cfg(feature = "openssl")]
extern crate openssl;
extern crate regex;
#[phase(plugin)]
extern crate regex_macros;

#[phase(plugin)]
extern crate lazy_static;

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


<commit_before>//! A simple, thread-safe IRC library.
#![crate_name = "irc"]
#![crate_type = "lib"]
#![unstable]
#![warn(missing_docs)]

#![feature(collections, core, io, path, slicing_syntax)]
#[cfg(feature = "ctcp")] extern crate time;
#[cfg(feature = "encode")] extern crate encoding;
extern crate "rustc-serialize" as rustc_serialize;
#[cfg(feature = "ssl")] extern crate openssl;

pub mod client;
pub mod server;
<commit_msg>Updated for Rust master.<commit_after>//! A simple, thread-safe IRC library.
#![crate_name = "irc"]
#![crate_type = "lib"]
#![unstable]
#![warn(missing_docs)]

#![feature(collections, core, io, path)]
#[cfg(feature = "ctcp")] extern crate time;
#[cfg(feature = "encode")] extern crate encoding;
extern crate "rustc-serialize" as rustc_serialize;
#[cfg(feature = "ssl")] extern crate openssl;

pub mod client;
pub mod server;
<|endoftext|>