<commit_before>extern crate num;
extern crate nalgebra as na;
extern crate glium;
extern crate rustc_serialize;

pub use num::{
    One,
    Zero,
};

pub use na::*;

pub fn radians<N>(n: N) -> N
    where N: BaseFloat
{
    n * (N::pi() / <N as Cast<f64>>::from(180.0))
}

pub fn degrees<N>(n: N) -> N
    where N: BaseFloat
{
    n * (<N as Cast<f64>>::from(180.0) / N::pi())
}

pub trait LookAt<N> {
    fn look_at(camera: &Vec3<N>, target: &Vec3<N>, up: &Vec3<N>) -> Self;
}

impl<N> LookAt<N> for Mat4<N>
    where N: BaseFloat
{
    fn look_at(camera: &Vec3<N>, target: &Vec3<N>, up: &Vec3<N>) -> Self {
        let f = (*target - *camera).normalize();
        let s = f.cross(up).normalize();
        let u = s.cross(&f);

        let mut result = Self::one();

        unsafe {
            result.set_fast((0, 0), s.x);
            result.set_fast((1, 0), s.y);
            result.set_fast((2, 0), s.z);
            result.set_fast((0, 1), u.x);
            result.set_fast((1, 1), u.y);
            result.set_fast((2, 1), u.z);
            result.set_fast((0, 2), -f.x);
            result.set_fast((1, 2), -f.y);
            result.set_fast((2, 2), -f.z);
            result.set_fast((3, 0), -(s.dot(camera)));
            result.set_fast((3, 1), -(u.dot(camera)));
            result.set_fast((3, 2), f.dot(camera));
        }

        result
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, RustcDecodable, RustcEncodable)]
pub struct Perspective<N> {
    mat: Mat4<N>,
}

impl<N> Perspective<N>
    where N: BaseFloat
{
    pub fn new(fov: N, aspect: N, znear: N, zfar: N) -> Perspective<N> {
        let one = N::one();
        let two = N::one() + N::one();

        let tan_half_fov = (fov / two).tan();

        let mut mat = Mat4::zero();
        unsafe {
            mat.set_fast((0, 0), one / (aspect * tan_half_fov));
            mat.set_fast((1, 1), one / (tan_half_fov));
            mat.set_fast((2, 2), -(zfar + znear) / (zfar - znear));
            mat.set_fast((2, 3), -one);
            mat.set_fast((3, 2), -(two * zfar * znear) / (zfar - znear));
        }

        Perspective {
            mat: mat,
        }
    }

    pub fn as_mat<'a>(&'a self) -> &'a Mat4<N> {
        &self.mat
    }

}

impl<N> Perspective<N>
    where N: BaseFloat + Clone
{
    pub fn to_mat(&self) -> Mat4<N> {
        self.mat.clone()
    }
}

<commit_msg>add extend and truncate<commit_after>//! `gel` is an extension of sebcrozet's `nalgebra` crate, designed to facilitate OpenGL
//! mathematics.

extern crate num;
extern crate nalgebra;
extern crate glium;
extern crate rustc_serialize;

pub use num::{
    One,
    Zero,
};

pub use nalgebra::*;
/// A trait for objects able to be extended.
pub trait Extend<N> {
    type Output;

    fn extend(&self, N) -> Self::Output;
}

/// A trait for objects able to be truncated.
pub trait Truncate<N> {
    type Output;

    fn truncate(&self) -> Self::Output;
}

/// A trait for objects able to construct view matrices.
pub trait LookAt<N> {
    fn look_at(camera: &Vec3<N>, target: &Vec3<N>, up: &Vec3<N>) -> Self;
}

impl<N> Extend<N> for Vec0<N>
    where N: Copy
{
    type Output = Vec1<N>;

    fn extend(&self, elem: N) -> Self::Output {
        Vec1::new(elem)
    }
}

impl<N> Extend<N> for Vec1<N>
    where N: Copy
{
    type Output = Vec2<N>;

    fn extend(&self, elem: N) -> Self::Output {
        Vec2::new(self.x, elem)
    }
}

impl<N> Extend<N> for Vec2<N>
    where N: Copy
{
    type Output = Vec3<N>;

    fn extend(&self, elem: N) -> Self::Output {
        Vec3::new(self.x, self.y, elem)
    }
}

impl<N> Extend<N> for Vec3<N>
    where N: Copy
{
    type Output = Vec4<N>;

    fn extend(&self, elem: N) -> Self::Output {
        Vec4::new(self.x, self.y, self.z, elem)
    }
}

impl<N> Extend<N> for Vec4<N>
    where N: Copy
{
    type Output = Vec5<N>;

    fn extend(&self, elem: N) -> Self::Output {
        Vec5::new(self.x, self.y, self.z, self.w, elem)
    }
}

impl<N> Extend<N> for Vec5<N>
    where N: Copy
{
    type Output = Vec6<N>;

    fn extend(&self, elem: N) -> Self::Output {
        Vec6::new(self.x, self.y, self.z, self.w, self.a, elem)
    }
}

impl<N> Truncate<N> for Vec1<N>
    where N: Copy
{
    type Output = Vec0<N>;

    fn truncate(&self) -> Self::Output {
        Vec0::new()
    }
}

impl<N> Truncate<N> for Vec2<N>
    where N: Copy
{
    type Output = Vec1<N>;

    fn truncate(&self) -> Self::Output {
        Vec1::new(self.x)
    }
}

impl<N> Truncate<N> for Vec3<N>
    where N: Copy
{
    type Output = Vec2<N>;

    fn truncate(&self) -> Self::Output {
        Vec2::new(self.x, self.y)
    }
}

impl<N> Truncate<N> for Vec4<N>
    where N: Copy
{
    type Output = Vec3<N>;

    fn truncate(&self) -> Self::Output {
        Vec3::new(self.x, self.y, self.z)
    }
}

impl<N> Truncate<N> for Vec5<N>
    where N: Copy
{
    type Output = Vec4<N>;

    fn truncate(&self) -> Self::Output {
        Vec4::new(self.x, self.y, self.z, self.w)
    }
}

impl<N> Truncate<N> for Vec6<N>
    where N: Copy
{
    type Output = Vec5<N>;

    fn truncate(&self) -> Self::Output {
        Vec5::new(self.x, self.y, self.z, self.w, self.a)
    }
}

impl<N> Extend<N> for Pnt0<N>
    where N: Copy
{
    type Output = Pnt1<N>;

    fn extend(&self, elem: N) -> Self::Output {
        Pnt1::new(elem)
    }
}

impl<N> Extend<N> for Pnt1<N>
    where N: Copy
{
    type Output = Pnt2<N>;

    fn extend(&self, elem: N) -> Self::Output {
        Pnt2::new(self.x, elem)
    }
}

impl<N> Extend<N> for Pnt2<N>
    where N: Copy
{
    type Output = Pnt3<N>;

    fn extend(&self, elem: N) -> Self::Output {
        Pnt3::new(self.x, self.y, elem)
    }
}

impl<N> Extend<N> for Pnt3<N>
    where N: Copy
{
    type Output = Pnt4<N>;

    fn extend(&self, elem: N) -> Self::Output {
        Pnt4::new(self.x, self.y, self.z, elem)
    }
}

impl<N> Extend<N> for Pnt4<N>
    where N: Copy
{
    type Output = Pnt5<N>;

    fn extend(&self, elem: N) -> Self::Output {
        Pnt5::new(self.x, self.y, self.z, self.w, elem)
    }
}

impl<N> Extend<N> for Pnt5<N>
    where N: Copy
{
    type Output = Pnt6<N>;

    fn extend(&self, elem: N) -> Self::Output {
        Pnt6::new(self.x, self.y, self.z, self.w, self.a, elem)
    }
}

impl<N> Truncate<N> for Pnt1<N>
    where N: Copy
{
    type Output = Pnt0<N>;

    fn truncate(&self) -> Self::Output {
        Pnt0::new()
    }
}

impl<N> Truncate<N> for Pnt2<N>
    where N: Copy
{
    type Output = Pnt1<N>;

    fn truncate(&self) -> Self::Output {
        Pnt1::new(self.x)
    }
}

impl<N> Truncate<N> for Pnt3<N>
    where N: Copy
{
    type Output = Pnt2<N>;

    fn truncate(&self) -> Self::Output {
        Pnt2::new(self.x, self.y)
    }
}

impl<N> Truncate<N> for Pnt4<N>
    where N: Copy
{
    type Output = Pnt3<N>;

    fn truncate(&self) -> Self::Output {
        Pnt3::new(self.x, self.y, self.z)
    }
}

impl<N> Truncate<N> for Pnt5<N>
    where N: Copy
{
    type Output = Pnt4<N>;

    fn truncate(&self) -> Self::Output {
        Pnt4::new(self.x, self.y, self.z, self.w)
    }
}

impl<N> Truncate<N> for Pnt6<N>
    where N: Copy
{
    type Output = Pnt5<N>;

    fn truncate(&self) -> Self::Output {
        Pnt5::new(self.x, self.y, self.z, self.w, self.a)
    }
}

impl<N> LookAt<N> for Mat4<N>
    where N: BaseFloat
{
    fn look_at(camera: &Vec3<N>, target: &Vec3<N>, up: &Vec3<N>) -> Self {
        let f = (*target - *camera).normalize();
        let s = f.cross(up).normalize();
        let u = s.cross(&f);

        let mut result = Self::one();

        unsafe {
            result.set_fast((0, 0), s.x);
            result.set_fast((1, 0), s.y);
            result.set_fast((2, 0), s.z);
            result.set_fast((0, 1), u.x);
            result.set_fast((1, 1), u.y);
            result.set_fast((2, 1), u.z);
            result.set_fast((0, 2), -f.x);
            result.set_fast((1, 2), -f.y);
            result.set_fast((2, 2), -f.z);
            result.set_fast((3, 0), -(s.dot(camera)));
            result.set_fast((3, 1), -(u.dot(camera)));
            result.set_fast((3, 2), f.dot(camera));
        }

        result
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, RustcDecodable, RustcEncodable)]
pub struct Perspective<N> {
    mat: Mat4<N>,
}

impl<N> Perspective<N>
    where N: BaseFloat
{
    pub fn new(fov: N, aspect: N, znear: N, zfar: N) -> Perspective<N> {
        let one = N::one();
        let two = N::one() + N::one();

        let tan_half_fov = (fov / two).tan();

        let mut mat = Mat4::zero();
        unsafe {
            mat.set_fast((0, 0), one / (aspect * tan_half_fov));
            mat.set_fast((1, 1), one / (tan_half_fov));
            mat.set_fast((2, 2), -(zfar + znear) / (zfar - znear));
            mat.set_fast((2, 3), -one);
            mat.set_fast((3, 2), -(two * zfar * znear) / (zfar - znear));
        }

        Perspective {
            mat: mat,
        }
    }

    pub fn as_mat<'a>(&'a self) -> &'a Mat4<N> {
        &self.mat
    }

}

impl<N> Perspective<N>
    where N: BaseFloat + Clone
{
    pub fn to_mat(&self) -> Mat4<N> {
        self.mat.clone()
    }
}

pub fn radians<N>(n: N) -> N
    where N: BaseFloat
{
    n * (N::pi() / <N as Cast<f64>>::from(180.0))
}

pub fn degrees<N>(n: N) -> N
    where N: BaseFloat
{
    n * (<N as Cast<f64>>::from(180.0) / N::pi())
}

<|endoftext|>


<commit_before>extern crate rand;
use std::str;
use std::fmt;
use rand::Rng;

#[derive(Debug, Eq, PartialEq, PartialOrd)]
pub struct Card {
    suit:  String,
    value: String,
}

#[derive(Debug, Eq, PartialEq, PartialOrd)]
pub struct Deck {
    cards: Vec<Card>
}

impl Card {
    pub fn new(suit: String, value: String) -> Card {
        Card { suit: suit, value: value.to_string() }
    }

    pub fn new_from_str(suit: &str, value: &str) -> Card {
        Card::new(suit.to_string(), value.to_string())
    }
}

impl Ord for Card {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.value.cmp(&other.value)
    }
}

impl fmt::Display for Card {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Suit: {}, Value: {}", self.suit, self.value)
    }
}

impl Deck {
    pub fn new_from_vec(input: Vec<Card>) -> Deck {
        Deck { cards: input }
    }

    pub fn make_standard() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠"];
        let values = &["2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Queen", "King", "Ace"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    pub fn make_fifth_dimension() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠", "★"];
        let values = &["1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Princess", "Queen", "King", "Joker"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    pub fn shuffle(&mut self) {
        rand::thread_rng().shuffle(&mut self.cards);
    }
}

impl Ord for Deck {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.cards.cmp(&other.cards)
    }
}
<commit_msg>add len to deck<commit_after>extern crate rand;
use std::str;
use std::fmt;
use rand::Rng;

#[derive(Debug, Eq, PartialEq, PartialOrd)]
pub struct Card {
    suit:  String,
    value: String,
}

#[derive(Debug, Eq, PartialEq, PartialOrd)]
pub struct Deck {
    cards: Vec<Card>
}

impl Card {
    pub fn new(suit: String, value: String) -> Card {
        Card { suit: suit, value: value.to_string() }
    }

    pub fn new_from_str(suit: &str, value: &str) -> Card {
        Card::new(suit.to_string(), value.to_string())
    }
}

impl Ord for Card {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.value.cmp(&other.value)
    }
}

impl fmt::Display for Card {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Suit: {}, Value: {}", self.suit, self.value)
    }
}

impl Deck {
    pub fn new_from_vec(input: Vec<Card>) -> Deck {
        Deck { cards: input }
    }

    pub fn make_standard() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠"];
        let values = &["2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Queen", "King", "Ace"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    pub fn make_fifth_dimension() -> Deck {
        let mut result = Vec::new();
        let suits  = &["♣", "♦", "♥", "♠", "★"];
        let values = &["1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                       "Jack", "Princess", "Queen", "King", "Joker"];

        for suit in suits {
            for value in values {
                result.push(Card::new_from_str(*suit, value));
            }
        }
        return Deck::new_from_vec(result);
    }

    pub fn shuffle(&mut self) {
        rand::thread_rng().shuffle(&mut self.cards);
    }

    pub fn len(&self) {
        self.cards.len();
    }
}

impl Ord for Deck {
    fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
        self.cards.cmp(&other.cards)
    }
}
<|endoftext|>


<commit_before>//! Timestamps for files in Rust
//!
//! This library provides platform-agnostic inspection of the various timestamps
//! present in the standard `fs::Metadata` structure.
//!
//! # Installation
//!
//! Add this to you `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! filetime = "0.1"
//! ```
//!
//! # Usage
//!
//! ```no_run
//! use std::fs;
//! use filetime::FileTime;
//!
//! let metadata = fs::metadata("foo.txt").unwrap();
//!
//! let mtime = FileTime::from_last_modification_time(&metadata);
//! println!("{}", mtime);
//!
//! let atime = FileTime::from_last_access_time(&metadata);
//! assert!(mtime < atime);
//!
//! // Inspect values that can be interpreted across platforms
//! println!("{}", mtime.seconds_relative_to_1970());
//! println!("{}", mtime.nanoseconds());
//!
//! // Print the platform-specific value of seconds
//! println!("{}", mtime.seconds());
//! ```

extern crate libc;
extern crate winapi;
extern crate kernel32;

#[cfg(unix)] use std::os::unix::prelude::*;
#[cfg(windows)] use std::os::windows::prelude::*;

use std::fmt;
use std::fs;
use std::io;
use std::path::Path;

/// A helper structure to represent a timestamp for a file.
///
/// The actual value contined within is platform-specific and does not have the
/// same meaning across platforms, but comparisons and stringification can be
/// significant among the same platform.
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone)]
pub struct FileTime {
    seconds: u64,
    nanos: u32,
}

impl FileTime {
    /// Creates a new timestamp representing a 0 time.
    ///
    /// Useful for creating the base of a cmp::max chain of times.
    pub fn zero() -> FileTime {
        FileTime { seconds: 0, nanos: 0 }
    }

    /// Creates a new instance of `FileTime` with a number of seconds and
    /// nanoseconds relative to January 1, 1970.
    ///
    /// Note that this is typically the relative point that Unix time stamps are
    /// from, but on Windows the native time stamp is relative to January 1,
    /// 1601 so the return value of `seconds` from the returned `FileTime`
    /// instance may not be the same as that passed in.
    pub fn from_seconds_since_1970(seconds: u64, nanos: u32) -> FileTime {
        FileTime {
            seconds: seconds + if cfg!(windows) {11644473600} else {0},
            nanos: nanos,
        }
    }

    /// Creates a new timestamp from the last modification time listed in the
    /// specified metadata.
    ///
    /// The returned value corresponds to the `mtime` field of `stat` on Unix
    /// platforms and the `ftLastWriteTime` field on Windows platforms.
    pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime {
        #[cfg(unix)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.mtime() as u64, meta.mtime_nsec() as u32)
        }
        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.last_write_time())
        }
        imp(meta)
    }

    /// Creates a new timestamp from the last access time listed in the
    /// specified metadata.
    ///
    /// The returned value corresponds to the `atime` field of `stat` on Unix
    /// platforms and the `ftLastAccessTime` field on Windows platforms.
    pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime {
        #[cfg(unix)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.atime() as u64, meta.atime_nsec() as u32)
        }
        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.last_access_time())
        }
        imp(meta)
    }

    /// Creates a new timestamp from the creation time listed in the specified
    /// metadata.
    ///
    /// The returned value corresponds to the `birthtime` field of `stat` on
    /// Unix platforms and the `ftCreationTime` field on Windows platforms. Note
    /// that not all Unix platforms have this field available and may return
    /// `None` in some circumstances.
    pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> {
        macro_rules! birthtim {
            ($(($e:expr, $i:ident)),*) => {
                #[cfg(any($(target_os = $e),*))]
                fn imp(meta: &fs::Metadata) -> Option<FileTime> {
                    $(
                        #[cfg(target_os = $e)]
                        use std::os::$i::fs::MetadataExt;
                    )*
                    let raw = meta.as_raw_stat();
                    Some(FileTime::from_os_repr(raw.st_birthtime as u64,
                                                raw.st_birthtime_nsec as u32))
                }

                #[cfg(all(not(windows),
                          $(not(target_os = $e)),*))]
                fn imp(_meta: &fs::Metadata) -> Option<FileTime> {
                    None
                }
            }
        }

        birthtim! {
            ("bitrig", bitrig),
            ("freebsd", freebsd),
            ("ios", ios),
            ("macos", macos),
            ("openbsd", openbsd)
        }

        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> Option<FileTime> {
            Some(FileTime::from_os_repr(meta.last_access_time()))
        }
        imp(meta)
    }

    #[cfg(windows)]
    fn from_os_repr(time: u64) -> FileTime {
        // Windows write times are in 100ns intervals, so do a little math to
        // get it into the right representation.
        FileTime {
            seconds: time / (1_000_000_000 / 100),
            nanos: ((time % (1_000_000_000 / 100)) * 100) as u32,
        }
    }

    #[cfg(unix)]
    fn from_os_repr(seconds: u64, nanos: u32) -> FileTime {
        FileTime { seconds: seconds, nanos: nanos }
    }

    /// Returns the whole number of seconds represented by this timestamp.
    ///
    /// Note that this value's meaning is **platform specific**. On Unix
    /// platform time stamps are typically relative to January 1, 1970, but on
    /// Windows platforms time stamps are relative to January 1, 1601.
    pub fn seconds(&self) -> u64 { self.seconds }

    /// Returns the whole number of seconds represented by this timestamp,
    /// relative to the Unix epoch start of January 1, 1970.
    ///
    /// Note that this does not return the same value as `seconds` for Windows
    /// platforms as seconds are relative to a different date there.
    pub fn seconds_relative_to_1970(&self) -> u64 {
        self.seconds - if cfg!(windows) {11644473600} else {0}
    }

    /// Returns the nanosecond precision of this timestamp.
    ///
    /// The returned value is always less than one billion and represents a
    /// portion of a second forward from the seconds returned by the `seconds`
    /// method.
    pub fn nanoseconds(&self) -> u32 { self.nanos }
}

impl fmt::Display for FileTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}.{:09}s", self.seconds, self.nanos)
    }
}

/// Set the last access and modification times for a file on the filesystem.
///
/// This function will set the `atime` and `mtime` metadata fields for a file
/// on the local filesystem, returning any error encountered.
pub fn set_file_times<P>(p: P, atime: FileTime, mtime: FileTime)
                         -> io::Result<()> where P: AsRef<Path> {
    set_file_times_(p.as_ref(), atime, mtime)
}

#[cfg(unix)]
fn set_file_times_(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
    use std::ffi::CString;
    use libc::{timeval, time_t, c_char, c_int, suseconds_t};

    extern {
        fn utimes(name: *const c_char, times: *const timeval) -> c_int;
    }

    let times = [to_timeval(&atime), to_timeval(&mtime)];
    let p = try!(CString::new(p.as_os_str().as_bytes()));
    return unsafe {
        if utimes(p.as_ptr(), times.as_ptr()) == 0 {
            Ok(())
        } else {
            Err(io::Error::last_os_error())
        }
    };

    fn to_timeval(ft: &FileTime) -> timeval {
        timeval {
            tv_sec: ft.seconds() as time_t,
            tv_usec: (ft.nanoseconds() / 1000) as suseconds_t,
        }
    }
}

#[cfg(windows)]
fn set_file_times_(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
    use std::fs::OpenOptions;
    use winapi::{FILETIME, DWORD};

    let f = try!(OpenOptions::new().write(true).open(p));
    let atime = to_filetime(&atime);
    let mtime = to_filetime(&mtime);
    return unsafe {
        let ret = kernel32::SetFileTime(f.as_raw_handle() as *mut _,
                                        0 as *const _,
                                        &atime, &mtime);
        if ret != 0 {
            Ok(())
        } else {
            Err(io::Error::last_os_error())
        }
    };

    fn to_filetime(ft: &FileTime) -> FILETIME {
        let intervals = ft.seconds() * (1_000_000_000 / 100) +
                        ((ft.nanoseconds() as u64) / 100);
        FILETIME {
            dwLowDateTime: intervals as DWORD,
            dwHighDateTime: (intervals >> 32) as DWORD,
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;

    use std::fs::{self, File};
    use self::tempdir::TempDir;
    use super::{FileTime, set_file_times};

    #[test]
    fn set_file_times_test() {
        let td = TempDir::new("filetime").unwrap();
        let path = td.path().join("foo.txt");
        File::create(&path).unwrap();

        let metadata = fs::metadata(&path).unwrap();
        let mtime = FileTime::from_last_modification_time(&metadata);
        let atime = FileTime::from_last_access_time(&metadata);
        set_file_times(&path, atime, mtime).unwrap();

        let new_mtime = FileTime::from_seconds_since_1970(10_000, 0);
        set_file_times(&path, atime, new_mtime).unwrap();

        let metadata = fs::metadata(&path).unwrap();
        let mtime = FileTime::from_last_modification_time(&metadata);
        assert_eq!(mtime, new_mtime);
    }
}
<commit_msg>Derive Hash for FileTime<commit_after>//! Timestamps for files in Rust
//!
//! This library provides platform-agnostic inspection of the various timestamps
//! present in the standard `fs::Metadata` structure.
//!
//! # Installation
//!
//! Add this to you `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! filetime = "0.1"
//! ```
//!
//! # Usage
//!
//! ```no_run
//! use std::fs;
//! use filetime::FileTime;
//!
//! let metadata = fs::metadata("foo.txt").unwrap();
//!
//! let mtime = FileTime::from_last_modification_time(&metadata);
//! println!("{}", mtime);
//!
//! let atime = FileTime::from_last_access_time(&metadata);
//! assert!(mtime < atime);
//!
//! // Inspect values that can be interpreted across platforms
//! println!("{}", mtime.seconds_relative_to_1970());
//! println!("{}", mtime.nanoseconds());
//!
//! // Print the platform-specific value of seconds
//! println!("{}", mtime.seconds());
//! ```

extern crate libc;
extern crate winapi;
extern crate kernel32;

#[cfg(unix)] use std::os::unix::prelude::*;
#[cfg(windows)] use std::os::windows::prelude::*;

use std::fmt;
use std::fs;
use std::io;
use std::path::Path;

/// A helper structure to represent a timestamp for a file.
///
/// The actual value contined within is platform-specific and does not have the
/// same meaning across platforms, but comparisons and stringification can be
/// significant among the same platform.
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone, Hash)]
pub struct FileTime {
    seconds: u64,
    nanos: u32,
}

impl FileTime {
    /// Creates a new timestamp representing a 0 time.
    ///
    /// Useful for creating the base of a cmp::max chain of times.
    pub fn zero() -> FileTime {
        FileTime { seconds: 0, nanos: 0 }
    }

    /// Creates a new instance of `FileTime` with a number of seconds and
    /// nanoseconds relative to January 1, 1970.
    ///
    /// Note that this is typically the relative point that Unix time stamps are
    /// from, but on Windows the native time stamp is relative to January 1,
    /// 1601 so the return value of `seconds` from the returned `FileTime`
    /// instance may not be the same as that passed in.
    pub fn from_seconds_since_1970(seconds: u64, nanos: u32) -> FileTime {
        FileTime {
            seconds: seconds + if cfg!(windows) {11644473600} else {0},
            nanos: nanos,
        }
    }

    /// Creates a new timestamp from the last modification time listed in the
    /// specified metadata.
    ///
    /// The returned value corresponds to the `mtime` field of `stat` on Unix
    /// platforms and the `ftLastWriteTime` field on Windows platforms.
    pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime {
        #[cfg(unix)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.mtime() as u64, meta.mtime_nsec() as u32)
        }
        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.last_write_time())
        }
        imp(meta)
    }

    /// Creates a new timestamp from the last access time listed in the
    /// specified metadata.
    ///
    /// The returned value corresponds to the `atime` field of `stat` on Unix
    /// platforms and the `ftLastAccessTime` field on Windows platforms.
    pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime {
        #[cfg(unix)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.atime() as u64, meta.atime_nsec() as u32)
        }
        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.last_access_time())
        }
        imp(meta)
    }

    /// Creates a new timestamp from the creation time listed in the specified
    /// metadata.
    ///
    /// The returned value corresponds to the `birthtime` field of `stat` on
    /// Unix platforms and the `ftCreationTime` field on Windows platforms. Note
    /// that not all Unix platforms have this field available and may return
    /// `None` in some circumstances.
    pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> {
        macro_rules! birthtim {
            ($(($e:expr, $i:ident)),*) => {
                #[cfg(any($(target_os = $e),*))]
                fn imp(meta: &fs::Metadata) -> Option<FileTime> {
                    $(
                        #[cfg(target_os = $e)]
                        use std::os::$i::fs::MetadataExt;
                    )*
                    let raw = meta.as_raw_stat();
                    Some(FileTime::from_os_repr(raw.st_birthtime as u64,
                                                raw.st_birthtime_nsec as u32))
                }

                #[cfg(all(not(windows),
                          $(not(target_os = $e)),*))]
                fn imp(_meta: &fs::Metadata) -> Option<FileTime> {
                    None
                }
            }
        }

        birthtim! {
            ("bitrig", bitrig),
            ("freebsd", freebsd),
            ("ios", ios),
            ("macos", macos),
            ("openbsd", openbsd)
        }

        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> Option<FileTime> {
            Some(FileTime::from_os_repr(meta.last_access_time()))
        }
        imp(meta)
    }

    #[cfg(windows)]
    fn from_os_repr(time: u64) -> FileTime {
        // Windows write times are in 100ns intervals, so do a little math to
        // get it into the right representation.
        FileTime {
            seconds: time / (1_000_000_000 / 100),
            nanos: ((time % (1_000_000_000 / 100)) * 100) as u32,
        }
    }

    #[cfg(unix)]
    fn from_os_repr(seconds: u64, nanos: u32) -> FileTime {
        FileTime { seconds: seconds, nanos: nanos }
    }

    /// Returns the whole number of seconds represented by this timestamp.
    ///
    /// Note that this value's meaning is **platform specific**. On Unix
    /// platform time stamps are typically relative to January 1, 1970, but on
    /// Windows platforms time stamps are relative to January 1, 1601.
    pub fn seconds(&self) -> u64 { self.seconds }

    /// Returns the whole number of seconds represented by this timestamp,
    /// relative to the Unix epoch start of January 1, 1970.
    ///
    /// Note that this does not return the same value as `seconds` for Windows
    /// platforms as seconds are relative to a different date there.
    pub fn seconds_relative_to_1970(&self) -> u64 {
        self.seconds - if cfg!(windows) {11644473600} else {0}
    }

    /// Returns the nanosecond precision of this timestamp.
    ///
    /// The returned value is always less than one billion and represents a
    /// portion of a second forward from the seconds returned by the `seconds`
    /// method.
    pub fn nanoseconds(&self) -> u32 { self.nanos }
}

impl fmt::Display for FileTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}.{:09}s", self.seconds, self.nanos)
    }
}

/// Set the last access and modification times for a file on the filesystem.
///
/// This function will set the `atime` and `mtime` metadata fields for a file
/// on the local filesystem, returning any error encountered.
pub fn set_file_times<P>(p: P, atime: FileTime, mtime: FileTime)
                         -> io::Result<()> where P: AsRef<Path> {
    set_file_times_(p.as_ref(), atime, mtime)
}

#[cfg(unix)]
fn set_file_times_(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
    use std::ffi::CString;
    use libc::{timeval, time_t, c_char, c_int, suseconds_t};

    extern {
        fn utimes(name: *const c_char, times: *const timeval) -> c_int;
    }

    let times = [to_timeval(&atime), to_timeval(&mtime)];
    let p = try!(CString::new(p.as_os_str().as_bytes()));
    return unsafe {
        if utimes(p.as_ptr(), times.as_ptr()) == 0 {
            Ok(())
        } else {
            Err(io::Error::last_os_error())
        }
    };

    fn to_timeval(ft: &FileTime) -> timeval {
        timeval {
            tv_sec: ft.seconds() as time_t,
            tv_usec: (ft.nanoseconds() / 1000) as suseconds_t,
        }
    }
}

#[cfg(windows)]
fn set_file_times_(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
    use std::fs::OpenOptions;
    use winapi::{FILETIME, DWORD};

    let f = try!(OpenOptions::new().write(true).open(p));
    let atime = to_filetime(&atime);
    let mtime = to_filetime(&mtime);
    return unsafe {
        let ret = kernel32::SetFileTime(f.as_raw_handle() as *mut _,
                                        0 as *const _,
                                        &atime, &mtime);
        if ret != 0 {
            Ok(())
        } else {
            Err(io::Error::last_os_error())
        }
    };

    fn to_filetime(ft: &FileTime) -> FILETIME {
        let intervals = ft.seconds() * (1_000_000_000 / 100) +
                        ((ft.nanoseconds() as u64) / 100);
        FILETIME {
            dwLowDateTime: intervals as DWORD,
            dwHighDateTime: (intervals >> 32) as DWORD,
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;

    use std::fs::{self, File};
    use self::tempdir::TempDir;
    use super::{FileTime, set_file_times};

    #[test]
    fn set_file_times_test() {
        let td = TempDir::new("filetime").unwrap();
        let path = td.path().join("foo.txt");
        File::create(&path).unwrap();

        let metadata = fs::metadata(&path).unwrap();
        let mtime = FileTime::from_last_modification_time(&metadata);
        let atime = FileTime::from_last_access_time(&metadata);
        set_file_times(&path, atime, mtime).unwrap();

        let new_mtime = FileTime::from_seconds_since_1970(10_000, 0);
        set_file_times(&path, atime, new_mtime).unwrap();

        let metadata = fs::metadata(&path).unwrap();
        let mtime = FileTime::from_last_modification_time(&metadata);
        assert_eq!(mtime, new_mtime);
    }
}
<|endoftext|>


<commit_before>extern crate walkdir;
extern crate regex;
extern crate url;

mod git;
mod util;
mod remote;

use std::path::{Path, PathBuf};
use walkdir::WalkDir;

pub fn command_get(projects: Vec<String>, skip_pull: bool, shallow: bool) -> i32 {
  for project in projects {
    let repo = remote::RemoteRepository::new(project.as_str());
    let dest = repo.local_path(&get_local_repos_roots()[0]);

    git::clone_or_pull(repo.url(), dest.as_path(), skip_pull, shallow);
  }
  0
}

pub fn command_list(exact: bool, fullpath: bool, unique: bool, query: Option<String>) -> i32 {
  let filter: Box<Fn(&str) -> bool> = {
    if let Some(query) = query {
      if exact {
        Box::new(move |s: &str| s == query)
      } else {
        Box::new(move |s: &str| s.contains(&query))
      }
    } else {
      Box::new(|_| true)
    }
  };

  for repo in get_local_repositories(filter) {
    if fullpath {
      let mut repo_path = PathBuf::from(repo.root);
      repo_path.push(repo.path);
      println!("{}", repo_path.display());
    } else if unique {
      let repo_name = Path::new(&repo.path)
        .file_name()
        .unwrap()
        .to_str()
        .unwrap();
      println!("{}", repo_name);
    } else {
      println!("{}", repo.path);
    }
  }

  0
}

pub fn command_root(all: bool) -> i32 {
  let roots = get_local_repos_roots();
  if all {
    for root in roots {
      println!("{}", root);
    }
  } else {
    println!("{}", roots[0]);
  }
  0
}

#[derive(Debug)]
struct Repository {
  root: String,
  path: String,
}

fn get_local_repositories(filter: Box<Fn(&str) -> bool>) -> Vec<Repository> {
  let mut dst = Vec::new();

  let roots = get_local_repos_roots();
  for root in roots {
    for entry in WalkDir::new(&root).follow_links(true).into_iter().filter_map(|e| e.ok()) {
      let path = format!("{}", entry.path().display()).replace(&format!("{}/", root), "");
      if entry.depth() == 3 {

        let entry = vec![".git", ".svn", ".hg", "_darcs"].into_iter().find(|&e| {
          let mut buf = PathBuf::from(format!("{}", entry.path().display()));
          if !filter(buf.file_name().unwrap().to_str().unwrap()) {
            return false;
          }
          buf.push(e);
          buf.exists()
        });

        if entry.is_some() {
          dst.push(Repository {
            root: root.clone(),
            path: path,
          });
        }
      }
    }
  }

  dst
}

fn get_local_repos_roots() -> Vec<String> {
  let mut local_repo_roots;

  let env_root: String = std::env::var("GHQ_ROOT").unwrap_or("".to_owned());
  if env_root == "" {
    local_repo_roots = vec![git::config("ghq.root")];
  } else {
    local_repo_roots = env_root.split(":").map(|s| s.to_owned()).collect();
  }

  if local_repo_roots.len() == 0 {
    let mut ghq_path = std::env::home_dir().unwrap();
    ghq_path.push(".ghq");
    local_repo_roots.push(format!("{}", ghq_path.display()));
  }

  assert!(local_repo_roots.len() >= 1);

  local_repo_roots
}
<commit_msg>refactor<commit_after>extern crate walkdir;
extern crate regex;
extern crate url;

mod git;
mod util;
mod remote;

use std::path::{Path, PathBuf};
use walkdir::WalkDir;

pub fn command_get(projects: Vec<String>, skip_pull: bool, shallow: bool) -> i32 {
  for project in projects {
    let repo = remote::RemoteRepository::new(project.as_str());
    let dest = repo.local_path(&get_local_repos_roots()[0]);

    git::clone_or_pull(repo.url(), dest.as_path(), skip_pull, shallow);
  }
  0
}

impl Repository {
  #[cfg(windows)]
  fn absolute_path(&self) -> String {
    let repo_path = Path::new(&self.root).join(&self.path);
    format!("{}", repo_path.display()).replace("/", "\\")
  }

  #[cfg(not(windows))]
  fn absolute_path(&self) -> String {
    let repo_path = Path::new(self.root).join(self.path);
    format!("{}", repo_path.display())
  }

  fn unique_path(&self) -> String {
    Path::new(&self.path)
      .file_name()
      .unwrap()
      .to_str()
      .unwrap()
      .to_owned()
  }
}

pub fn command_list(exact: bool, fullpath: bool, unique: bool, query: Option<String>) -> i32 {
  let filter: Box<Fn(&str) -> bool> = {
    if let Some(query) = query {
      if exact {
        Box::new(move |s: &str| s == query)
      } else {
        Box::new(move |s: &str| s.contains(&query))
      }
    } else {
      Box::new(|_| true)
    }
  };

  for repo in get_local_repositories(filter) {
    if fullpath {
      println!("{}", repo.absolute_path());
    } else if unique {
      println!("{}", repo.unique_path());
    } else {
      println!("{}", repo.path);
    }
  }

  0
}

pub fn command_root(all: bool) -> i32 {
  let roots = get_local_repos_roots();
  if all {
    for root in roots {
      println!("{}", root);
    }
  } else {
    println!("{}", roots[0]);
  }
  0
}

#[derive(Debug)]
struct Repository {
  vcs: String,
  root: String,
  path: String,
}

fn get_local_repositories(filter: Box<Fn(&str) -> bool>) -> Vec<Repository> {
  let mut dst = Vec::new();

  let roots = get_local_repos_roots();
  for root in roots {
    for entry in WalkDir::new(&root)
      .follow_links(true)
      .into_iter()
      .filter_map(|e| e.ok())
      .filter(|ref e| e.depth() == 3) {

      let path = format!("{}", entry.path().display())
        .replace(&format!("{}{}", root, std::path::MAIN_SEPARATOR), "");

      let vcs = vec![".git", ".svn", ".hg", "_darcs"]
        .into_iter()
        .find(|&e| {
          let mut buf = PathBuf::from(format!("{}", entry.path().display()));
          if !filter(buf.file_name().unwrap().to_str().unwrap()) {
            return false;
          }
          buf.push(e);
          buf.exists()
        })
        .map(|e| format!("{}", &e[1..]));

      if vcs.is_some() {
        dst.push(Repository {
          vcs: vcs.unwrap(),
          root: root.clone(),
          path: path.replace("\\", "/"),
        });
      }
    }
  }

  dst
}

fn get_local_repos_roots() -> Vec<String> {
  let mut local_repo_roots;

  let env_root: String = std::env::var("GHQ_ROOT").unwrap_or("".to_owned());
  if env_root == "" {
    local_repo_roots = vec![git::config("ghq.root")];
  } else {
    local_repo_roots = env_root.split(":").map(|s| s.to_owned()).collect();
  }

  if local_repo_roots.len() == 0 {
    let mut ghq_path = std::env::home_dir().unwrap();
    ghq_path.push(".ghq");
    local_repo_roots.push(format!("{}", ghq_path.display()));
  }

  assert!(local_repo_roots.len() >= 1);

  local_repo_roots
}
<|endoftext|>


<commit_before>extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate syn;

use proc_macro::TokenStream;

mod utils;

mod from;
mod add_like;
mod add_assign_like;
mod mul_like;
mod not_like;

macro_rules! create_derive(
    ($mod_:ident, $trait_:ident, $fn_name: ident) => {
        #[proc_macro_derive($trait_)]
        pub fn $fn_name(input: TokenStream) -> TokenStream {
            let s = input.to_string();
            let ast = syn::parse_macro_input(&s).unwrap();
            $mod_::expand(&ast, stringify!($trait_)).parse().unwrap()
        }
    }
);

create_derive!(from, From, from_derive);

create_derive!(add_like, Add, add_derive);
create_derive!(add_like, Sub, sub_derive);
create_derive!(add_like, BitAnd, bit_and_derive);
create_derive!(add_like, BitOr, bit_or_derive);
create_derive!(add_like, BitXor, bit_xor_derive);

create_derive!(mul_like, Mul, mul_derive);
create_derive!(mul_like, Div, div_derive);
create_derive!(mul_like, Rem, rem_derive);
create_derive!(mul_like, Shr, shr_derive);
create_derive!(mul_like, Shl, shl_derive);

create_derive!(not_like, Not, not_derive);
create_derive!(not_like, Neg, neg_derive);

create_derive!(add_assign_like, AddAssign,    add_assign_derive);
create_derive!(add_assign_like, SubAssign,    sub_assign_derive);
create_derive!(add_assign_like, BitAndAssign, bit_and_assign_derive);
create_derive!(add_assign_like, BitOrAssign,  bit_or_assign_derive);
create_derive!(add_assign_like, BitXorAssign, bit_xor_assign_derive);
<commit_msg>Docs: Add some introductory docs to the crate root<commit_after>//! # derive_more
//! Rust has lots of builtin traits that are implemented for its basic types, such as [`Add`], [`Not`]
//! or [`From`].
//! However, when wrapping these types inside your own structs or enums you lose the
//! implementations of these traits and are required to recreate them.
//! This is especially annoying when your own structures are very simple, such as when using the
//! commonly advised newtype pattern (e.g. `MyInt(i32)`).
//!
//! This library tries to remove these annoyances and the corresponding boilerplate code. It does
//! this by allowing you to derive lots of commonly used traits for both structs and enums.
//!
//! ## The newly derivable traits
//!
//! Obviously not all traits should be derived to the same code, because they are different
//! different traits after all. However, some of the semantics of the traits overlap a lot, so they
//! have been grouped in the following way:
//!
//! 1. `From`, only contains the [`From`].
//! 2. `Not`-like, contains [`Not`] and [`Neg`].
//! 3. `Add`-like, contains [`Add`], [`Sub`], [`BitAnd`], [`BitOr`] and [`BitXor`].
//! 4. `Mul`-like, contains [`Mul`], [`Div`], [`Rem`], [`Shr`] and [`Shl`].
//! 5. `AddAssign`-like, contains [`AddAssign`], [`SubAssign`], [`BitAndAssign`], [`BitOrAssign`]
//!    and [`BitXorAssign`].
//!
//!
//! ## Generated code
//!
//! It is important to understand what code gets generated when using one of the derives from this
//! crate. That is why the links below explain what code gets generated for a trait for each group
//! from before.
//!
//! 1. [`#[derive(From)]`](from.html)
//! 2. [`#[derive(Not)]`](not.html)
//! 3. [`#[derive(Add)]`](add.html)
//! 4. [`#[derive(Mul)]`](mul.html)
//! 5. [`#[derive(AddAssign)]`](add_assign.html)
//!
//! If you want to be sure what code is generated for your specific trait I recommend
//! using the [`cargo-expand`] utility. This will show you your code with all macros and derives
//! expanded.
//!
//! ## Installation
//!
//! This library heavily uses Macros 1.1, which is to stabilized in Rust 1.15 (the next Rust
//! release). To use it before that time you have to install the nightly or beta channel.
//!
//! After doing this, add this to `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! derive_more = "0.4.0"
//! ```
//!
//! And this to the top of your Rust file:
//!
//! ```
//! #[macro_use]
//! extern crate derive_more;
//! ```
//!
//! [`cargo-expand`]: https://github.com/dtolnay/cargo-expand
//! [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
//! [`Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html
//! [`Neg`]: https://doc.rust-lang.org/std/ops/trait.Neg.html
//! [`Add`]: https://doc.rust-lang.org/std/ops/trait.Add.html
//! [`Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
//! [`BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
//! [`BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
//! [`BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html
//! [`Mul`]: https://doc.rust-lang.org/std/ops/trait.Mul.html
//! [`Div`]: https://doc.rust-lang.org/std/ops/trait.Div.html
//! [`Rem`]: https://doc.rust-lang.org/std/ops/trait.Rem.html
//! [`Shr`]: https://doc.rust-lang.org/std/ops/trait.Shr.html
//! [`Shl`]: https://doc.rust-lang.org/std/ops/trait.Shl.html
//! [`AddAssign`]: https://doc.rust-lang.org/std/ops/trait.AddAssign.html
//! [`SubAssign`]: https://doc.rust-lang.org/std/ops/trait.SubAssign.html
//! [`BitAndAssign`]: https://doc.rust-lang.org/std/ops/trait.BitAndAssign.html
//! [`BitOrAssign`]: https://doc.rust-lang.org/std/ops/trait.BitOrAssign.html
//! [`BitXorAssign`]: https://doc.rust-lang.org/std/ops/trait.BitXorAssign.html

extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate syn;

use proc_macro::TokenStream;

mod utils;

mod from;
mod add_like;
mod add_assign_like;
mod mul_like;
mod not_like;

macro_rules! create_derive(
    ($mod_:ident, $trait_:ident, $fn_name: ident) => {
        #[proc_macro_derive($trait_)]
        #[doc(hidden)]
        pub fn $fn_name(input: TokenStream) -> TokenStream {
            let s = input.to_string();
            let ast = syn::parse_macro_input(&s).unwrap();
            $mod_::expand(&ast, stringify!($trait_)).parse().unwrap()
        }
    }
);

create_derive!(from, From, from_derive);

create_derive!(add_like, Add, add_derive);
create_derive!(add_like, Sub, sub_derive);
create_derive!(add_like, BitAnd, bit_and_derive);
create_derive!(add_like, BitOr, bit_or_derive);
create_derive!(add_like, BitXor, bit_xor_derive);

create_derive!(mul_like, Mul, mul_derive);
create_derive!(mul_like, Div, div_derive);
create_derive!(mul_like, Rem, rem_derive);
create_derive!(mul_like, Shr, shr_derive);
create_derive!(mul_like, Shl, shl_derive);

create_derive!(not_like, Not, not_derive);
create_derive!(not_like, Neg, neg_derive);

create_derive!(add_assign_like, AddAssign,    add_assign_derive);
create_derive!(add_assign_like, SubAssign,    sub_assign_derive);
create_derive!(add_assign_like, BitAndAssign, bit_and_assign_derive);
create_derive!(add_assign_like, BitOrAssign,  bit_or_assign_derive);
create_derive!(add_assign_like, BitXorAssign, bit_xor_assign_derive);
<|endoftext|>


<commit_before>mod ffi;

use std::os::raw::c_int;
use std::fmt::Display;

pub struct SoundIo {
    context: *mut ffi::Struct_SoundIo,
}
impl SoundIo {
    pub fn new() -> Self {
        SoundIo { context: unsafe { ffi::soundio_create() } }
    }

    pub fn channel_layout_builtin_count() -> i32 {
        let cnt = unsafe { ffi::soundio_channel_layout_builtin_count() };
        if cnt < 0 {
            panic!("Negative # of builtin channel layouts!")
        } else {
            cnt as i32
        }
    }

    pub fn connect(&self) -> Option<ffi::Enum_SoundIoError> {
        match unsafe { ffi::soundio_connect(self.context) } {
            ffi::Enum_SoundIoError::SoundIoErrorNone => None,
            err @ _ => Some(err),
        }
    }

    pub fn connect_backend(&self,
                           backend: ffi::Enum_SoundIoBackend)
                           -> Option<ffi::Enum_SoundIoError> {
        match unsafe { ffi::soundio_connect_backend(self.context, backend) } {
            ffi::Enum_SoundIoError::SoundIoErrorNone => None,
            err @ _ => {
                println!("{:?}", err);
                Some(err)
            }
        }
    }

    pub fn backend_count(&self) -> i32 {
        let cnt = unsafe { ffi::soundio_backend_count(self.context) } as i32;
        if cnt < 0 {
            panic!("Negative backend count!");
        } else {
            cnt
        }
    }

    pub fn get_backend(&self, idx: i32) -> Option<ffi::Enum_SoundIoBackend> {
        match unsafe { ffi::soundio_get_backend(self.context, idx) } {
            ffi::Enum_SoundIoBackend::SoundIoBackendNone => None,
            backend @ _ => Some(backend),
        }
    }

    pub fn have_backend(&self, backend: ffi::Enum_SoundIoBackend) -> bool {
        unsafe { ffi::soundio_have_backend(backend) == 1u8 }
    }

    pub fn flush_events(&self) {
        unsafe { ffi::soundio_flush_events(self.context) }
    }

    pub fn wait_events(&self) {
        unsafe { ffi::soundio_wait_events(self.context) }
    }

    pub fn wakeup(&self) {
        unsafe { ffi::soundio_wakeup(self.context) }
    }

    pub fn force_device_scan(&self) {
        unsafe { ffi::soundio_force_device_scan(self.context) }
    }

    pub fn disconnect(&self) {
        unsafe { ffi::soundio_disconnect(self.context) }
    }

    pub fn input_device_count(&self) -> Option<i32> {
        let cnt = unsafe { ffi::soundio_input_device_count(self.context) };
        if cnt < 0 {
            None
        } else {
            Some(cnt as i32)
        }
    }

    pub fn output_device_count(&self) -> Option<i32> {
        let cnt = unsafe { ffi::soundio_output_device_count(self.context) };
        if cnt < 0 {
            None
        } else {
            Some(cnt as i32)
        }
    }

    pub fn default_input_device_index(&self) -> Option<i32> {
        match unsafe { ffi::soundio_default_input_device_index(self.context) } {
            -1 => None,
            idx @ _ => Some(idx as i32),
        }
    }

    pub fn default_output_device_index(&self) -> Option<i32> {
        match unsafe { ffi::soundio_default_output_device_index(self.context) } {
            -1 => None,
            idx @ _ => Some(idx as i32),
        }
    }
}
impl Drop for SoundIo {
    fn drop(&mut self) {
        unsafe {
            self.disconnect();
            ffi::soundio_destroy(self.context)
        }
    }
}

#[derive(Debug)]
pub struct ChannelLayout {
    layout: *const ffi::Struct_SoundIoChannelLayout,
}
impl ChannelLayout {
    fn new(raw_layout: *const ffi::Struct_SoundIoChannelLayout) -> Self {
        ChannelLayout { layout: raw_layout }
    }

    pub fn get_builtin(idx: i32) -> Option<Self> {
        if 0 <= idx && idx < SoundIo::channel_layout_builtin_count() {
            Some(ChannelLayout::new(unsafe {
                ffi::soundio_channel_layout_get_builtin(idx as c_int)
            }))
        } else {
            None
        }
    }

    pub fn get_default(channel_count: i32) -> Option<Self> {
        if channel_count < 0 {
            None
        } else {
            Some(ChannelLayout::new(unsafe {
                ffi::soundio_channel_layout_get_default(channel_count as i32)
            }))
        }
    }

    pub fn find_channel(&self, channel: ffi::Enum_SoundIoChannelId) -> Option<i32> {
        match unsafe { ffi::soundio_channel_layout_find_channel(self.layout, channel) } {
            -1 => None,
            idx @ _ => Some(idx),
        }
    }

    pub fn detect_builtin(&mut self) -> bool {
        // This is a hack because of the transmute.
        unsafe {
            let mut_layout: *mut ffi::Struct_SoundIoChannelLayout =
                ::std::mem::transmute(self.layout);
            ffi::soundio_channel_layout_detect_builtin(mut_layout) == 1
        }
    }

    pub fn best_matching_channel_layout(preferred_layouts: &[ChannelLayout],
                                        available_layouts: &[ChannelLayout])
                                        -> Option<ChannelLayout> {
        // do some magic with the slices
        let raw_preferred_layouts: Vec<_> = preferred_layouts.iter()
                                                             .map(|l| unsafe { (*l.layout) })
                                                             .collect();
        let raw_available_layouts: Vec<_> = available_layouts.iter()
                                                             .map(|l| unsafe { (*l.layout) })
                                                             .collect();
        let layout_ptr = unsafe {
            ffi::soundio_best_matching_channel_layout(raw_preferred_layouts.as_ptr(),
                                                      preferred_layouts.len() as c_int,
                                                      raw_available_layouts.as_ptr(),
                                                      available_layouts.len() as c_int)
        };
        if layout_ptr.is_null() {
            None
        } else {
            Some(ChannelLayout::new(layout_ptr))
        }
    }
}
impl PartialEq for ChannelLayout {
    fn eq(&self, other: &Self) -> bool {
        unsafe { ffi::soundio_channel_layout_equal(self.layout, other.layout) == 1u8 }
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}
impl Display for ChannelLayout {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let str_ptr = unsafe { (*self.layout).name };
        write!(f, "{}", ffi::ptr_to_string(str_ptr).unwrap())
    }
}

#[test]
fn test_soundio() {
    let sio = SoundIo::new();
    assert!(sio.backend_count() > 0);
    assert!(sio.get_backend(0).is_some());
    assert!(sio.get_backend(-1).is_none());
    assert!(sio.connect().is_none());
    sio.disconnect();
    if sio.have_backend(ffi::Enum_SoundIoBackend::SoundIoBackendAlsa) {
        assert!(sio.connect_backend(ffi::Enum_SoundIoBackend::SoundIoBackendAlsa).is_none());
        sio.disconnect();
    }
    assert!(SoundIo::channel_layout_builtin_count() >= 0);
    assert!(sio.connect().is_none());
    sio.flush_events();
    assert!(sio.output_device_count().unwrap() > 0);
    assert!(sio.input_device_count().unwrap() > 0);
}

#[test]
fn test_channel_layout() {
    let cnt = SoundIo::channel_layout_builtin_count();
    assert!(cnt > 0);
    assert!(ChannelLayout::get_builtin(-1).is_none());
    assert_eq!(ChannelLayout::get_builtin(0), ChannelLayout::get_builtin(0));
    let mut layout = ChannelLayout::get_default(2).unwrap();
    assert!(layout.detect_builtin());
    assert!(layout.find_channel(ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft).is_some());
    assert!(layout.find_channel(ffi::Enum_SoundIoChannelId::SoundIoChannelIdLfe2).is_none());
    assert!(cnt > 2);
    let preferred = [ChannelLayout::get_builtin(0).unwrap(),
                     ChannelLayout::get_builtin(1).unwrap()];
    let available = [ChannelLayout::get_builtin(1).unwrap(),
                     ChannelLayout::get_builtin(2).unwrap()];
    let best_match = ChannelLayout::best_matching_channel_layout(&preferred, &available);
    assert_eq!(ChannelLayout::get_builtin(1).unwrap(), best_match.unwrap());

}

#[test]
fn test_enums() {
    assert_eq!("(no error)",
               format!("{}", ffi::Enum_SoundIoError::SoundIoErrorNone));
    assert_eq!("ALSA",
               format!("{}", ffi::Enum_SoundIoBackend::SoundIoBackendAlsa));
    assert_eq!("Front Left",
               format!("{}", ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft));
    assert_eq!(ffi::Enum_SoundIoChannelId::from("Front Left".to_string()),
               ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft);
    assert!(ffi::Enum_SoundIoChannelId::from("SomeInvalidBoredom".to_string()) !=
            ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft);
    assert_eq!("unsigned 8-bit",
               format!("{}", ffi::Enum_SoundIoFormat::SoundIoFormatU8));
    assert_eq!(1,
               ffi::Enum_SoundIoFormat::SoundIoFormatU8.get_bytes_per_sample());
    assert_eq!(4,
               ffi::Enum_SoundIoFormat::SoundIoFormatU32LE.get_bytes_per_sample());
}
<commit_msg>Implement `Device`<commit_after>mod ffi;

use std::os::raw::c_int;
use std::fmt::Display;

pub struct SoundIo {
    context: *mut ffi::Struct_SoundIo,
}
impl SoundIo {
    pub fn new() -> Self {
        SoundIo { context: unsafe { ffi::soundio_create() } }
    }

    pub fn channel_layout_builtin_count() -> i32 {
        let cnt = unsafe { ffi::soundio_channel_layout_builtin_count() };
        if cnt < 0 {
            panic!("Negative # of builtin channel layouts!")
        } else {
            cnt as i32
        }
    }

    pub fn connect(&self) -> Option<ffi::Enum_SoundIoError> {
        match unsafe { ffi::soundio_connect(self.context) } {
            ffi::Enum_SoundIoError::SoundIoErrorNone => None,
            err @ _ => Some(err),
        }
    }

    pub fn connect_backend(&self,
                           backend: ffi::Enum_SoundIoBackend)
                           -> Option<ffi::Enum_SoundIoError> {
        match unsafe { ffi::soundio_connect_backend(self.context, backend) } {
            ffi::Enum_SoundIoError::SoundIoErrorNone => None,
            err @ _ => {
                println!("{:?}", err);
                Some(err)
            }
        }
    }

    pub fn backend_count(&self) -> i32 {
        let cnt = unsafe { ffi::soundio_backend_count(self.context) } as i32;
        if cnt < 0 {
            panic!("Negative backend count!");
        } else {
            cnt
        }
    }

    pub fn get_backend(&self, idx: i32) -> Option<ffi::Enum_SoundIoBackend> {
        match unsafe { ffi::soundio_get_backend(self.context, idx) } {
            ffi::Enum_SoundIoBackend::SoundIoBackendNone => None,
            backend @ _ => Some(backend),
        }
    }

    pub fn have_backend(&self, backend: ffi::Enum_SoundIoBackend) -> bool {
        unsafe { ffi::soundio_have_backend(backend) == 1u8 }
    }

    pub fn flush_events(&self) {
        unsafe { ffi::soundio_flush_events(self.context) }
    }

    pub fn wait_events(&self) {
        unsafe { ffi::soundio_wait_events(self.context) }
    }

    pub fn wakeup(&self) {
        unsafe { ffi::soundio_wakeup(self.context) }
    }

    pub fn force_device_scan(&self) {
        unsafe { ffi::soundio_force_device_scan(self.context) }
    }

    pub fn disconnect(&self) {
        unsafe { ffi::soundio_disconnect(self.context) }
    }

    pub fn input_device_count(&self) -> Option<i32> {
        let cnt = unsafe { ffi::soundio_input_device_count(self.context) };
        if cnt < 0 {
            None
        } else {
            Some(cnt as i32)
        }
    }

    pub fn output_device_count(&self) -> Option<i32> {
        let cnt = unsafe { ffi::soundio_output_device_count(self.context) };
        if cnt < 0 {
            None
        } else {
            Some(cnt as i32)
        }
    }

    pub fn default_input_device_index(&self) -> Option<i32> {
        match unsafe { ffi::soundio_default_input_device_index(self.context) } {
            -1 => None,
            idx @ _ => Some(idx as i32),
        }
    }

    pub fn default_output_device_index(&self) -> Option<i32> {
        match unsafe { ffi::soundio_default_output_device_index(self.context) } {
            -1 => None,
            idx @ _ => Some(idx as i32),
        }
    }
}
impl Drop for SoundIo {
    fn drop(&mut self) {
        unsafe {
            self.disconnect();
            ffi::soundio_destroy(self.context)
        }
    }
}

#[derive(Debug)]
pub struct ChannelLayout {
    layout: *const ffi::Struct_SoundIoChannelLayout,
}
impl ChannelLayout {
    fn new(raw_layout: *const ffi::Struct_SoundIoChannelLayout) -> Self {
        ChannelLayout { layout: raw_layout }
    }

    pub fn get_builtin(idx: i32) -> Option<Self> {
        if 0 <= idx && idx < SoundIo::channel_layout_builtin_count() {
            Some(ChannelLayout::new(unsafe {
                ffi::soundio_channel_layout_get_builtin(idx as c_int)
            }))
        } else {
            None
        }
    }

    pub fn get_default(channel_count: i32) -> Option<Self> {
        if channel_count < 0 {
            None
        } else {
            Some(ChannelLayout::new(unsafe {
                ffi::soundio_channel_layout_get_default(channel_count as i32)
            }))
        }
    }

    pub fn find_channel(&self, channel: ffi::Enum_SoundIoChannelId) -> Option<i32> {
        match unsafe { ffi::soundio_channel_layout_find_channel(self.layout, channel) } {
            -1 => None,
            idx @ _ => Some(idx),
        }
    }

    pub fn detect_builtin(&mut self) -> bool {
        // This is a hack because of the transmute.
        unsafe {
            let mut_layout: *mut ffi::Struct_SoundIoChannelLayout =
                ::std::mem::transmute(self.layout);
            ffi::soundio_channel_layout_detect_builtin(mut_layout) == 1
        }
    }

    pub fn best_matching_channel_layout(preferred_layouts: &[ChannelLayout],
                                        available_layouts: &[ChannelLayout])
                                        -> Option<ChannelLayout> {
        // do some magic with the slices
        let raw_preferred_layouts: Vec<_> = preferred_layouts.iter()
                                                             .map(|l| unsafe { (*l.layout) })
                                                             .collect();
        let raw_available_layouts: Vec<_> = available_layouts.iter()
                                                             .map(|l| unsafe { (*l.layout) })
                                                             .collect();
        let layout_ptr = unsafe {
            ffi::soundio_best_matching_channel_layout(raw_preferred_layouts.as_ptr(),
                                                      preferred_layouts.len() as c_int,
                                                      raw_available_layouts.as_ptr(),
                                                      available_layouts.len() as c_int)
        };
        if layout_ptr.is_null() {
            None
        } else {
            Some(ChannelLayout::new(layout_ptr))
        }
    }
}
impl PartialEq for ChannelLayout {
    fn eq(&self, other: &Self) -> bool {
        unsafe { ffi::soundio_channel_layout_equal(self.layout, other.layout) == 1u8 }
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}
impl Display for ChannelLayout {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let str_ptr = unsafe { (*self.layout).name };
        write!(f, "{}", ffi::ptr_to_string(str_ptr).unwrap())
    }
}

#[derive(Debug)]
pub struct Device {
    device: *mut ffi::Struct_SoundIoDevice,
}
impl Device {
    pub fn new(dev_ptr: *mut ffi::Struct_SoundIoDevice) -> Self {
        Device { device: dev_ptr }
    }

    // ref is a keyword
    fn inc_ref(&self) {
        unsafe { ffi::soundio_device_ref(self.device) }
    }

    fn dec_ref(&self) {
        unsafe { ffi::soundio_device_unref(self.device) }
    }

    pub fn sort_channel_layouts(&self) {
        unsafe { ffi::soundio_device_sort_channel_layouts(self.device) }
    }

    pub fn supports_format(&self, format: ffi::Enum_SoundIoFormat) -> bool {
        unsafe { ffi::soundio_device_supports_format(self.device, format) == 1u8 }
    }

    pub fn supports_layout(&self, layout: &ChannelLayout) -> bool {
        unsafe { ffi::soundio_device_supports_layout(self.device, layout.layout) == 1u8 }
    }

    pub fn supports_sample_rate(&self, sample_rate: i32) -> bool {
        unsafe {
            ffi::soundio_device_supports_sample_rate(self.device, sample_rate as c_int) == 1u8
        }
    }

    pub fn nearest_sample_rate(&self, sample_rate: i32) -> i32 {
        unsafe { ffi::soundio_device_nearest_sample_rate(self.device, sample_rate) as i32 }
    }
}
impl Display for Device {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let str_ptr = unsafe { (*self.device).name };
        write!(f, "{}", ffi::ptr_to_string(str_ptr).unwrap())
    }
}
impl Drop for Device {
    fn drop(&mut self) {
        self.dec_ref()
    }
}
impl PartialEq for Device {
    fn eq(&self, other: &Self) -> bool {
        unsafe { ffi::soundio_device_equal(self.device, other.device) == 1u8 }
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

#[test]
fn test_soundio() {
    let sio = SoundIo::new();
    assert!(sio.backend_count() > 0);
    assert!(sio.get_backend(0).is_some());
    assert!(sio.get_backend(-1).is_none());
    assert!(sio.connect().is_none());
    sio.disconnect();
    if sio.have_backend(ffi::Enum_SoundIoBackend::SoundIoBackendAlsa) {
        assert!(sio.connect_backend(ffi::Enum_SoundIoBackend::SoundIoBackendAlsa).is_none());
        sio.disconnect();
    }
    assert!(SoundIo::channel_layout_builtin_count() >= 0);
    assert!(sio.connect().is_none());
    sio.flush_events();
    assert!(sio.output_device_count().unwrap() > 0);
    assert!(sio.input_device_count().unwrap() > 0);
}

#[test]
fn test_channel_layout() {
    let cnt = SoundIo::channel_layout_builtin_count();
    assert!(cnt > 0);
    assert!(ChannelLayout::get_builtin(-1).is_none());
    assert_eq!(ChannelLayout::get_builtin(0), ChannelLayout::get_builtin(0));
    let mut layout = ChannelLayout::get_default(2).unwrap();
    assert!(layout.detect_builtin());
    assert!(layout.find_channel(ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft).is_some());
    assert!(layout.find_channel(ffi::Enum_SoundIoChannelId::SoundIoChannelIdLfe2).is_none());
    assert!(cnt > 2);
    let preferred = [ChannelLayout::get_builtin(0).unwrap(),
                     ChannelLayout::get_builtin(1).unwrap()];
    let available = [ChannelLayout::get_builtin(1).unwrap(),
                     ChannelLayout::get_builtin(2).unwrap()];
    let best_match = ChannelLayout::best_matching_channel_layout(&preferred, &available);
    assert_eq!(ChannelLayout::get_builtin(1).unwrap(), best_match.unwrap());

}

#[test]
fn test_enums() {
    assert_eq!("(no error)",
               format!("{}", ffi::Enum_SoundIoError::SoundIoErrorNone));
    assert_eq!("ALSA",
               format!("{}", ffi::Enum_SoundIoBackend::SoundIoBackendAlsa));
    assert_eq!("Front Left",
               format!("{}", ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft));
    assert_eq!(ffi::Enum_SoundIoChannelId::from("Front Left".to_string()),
               ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft);
    assert!(ffi::Enum_SoundIoChannelId::from("SomeInvalidBoredom".to_string()) !=
            ffi::Enum_SoundIoChannelId::SoundIoChannelIdFrontLeft);
    assert_eq!("unsigned 8-bit",
               format!("{}", ffi::Enum_SoundIoFormat::SoundIoFormatU8));
    assert_eq!(1,
               ffi::Enum_SoundIoFormat::SoundIoFormatU8.get_bytes_per_sample());
    assert_eq!(4,
               ffi::Enum_SoundIoFormat::SoundIoFormatU32LE.get_bytes_per_sample());
}

#[test]
fn test_device() {
    let sio = SoundIo::new();
    assert!(sio.connect().is_none());
    sio.flush_events();
    let in_dev_idx = sio.default_input_device_index().unwrap();
    let out_dev_idx = sio.default_output_device_index().unwrap();
    let in_dev = sio.get_input_device(in_dev_idx).unwrap();
    let out_dev = sio.get_output_device(out_dev_idx).unwrap();
    println!("{}", in_dev);
    println!("{}", out_dev);
    assert!(in_dev != out_dev);
    assert_eq!(in_dev, in_dev);
    out_dev.sort_channel_layouts();
    let stereo_layout = ChannelLayout::get_default(2).unwrap();
    assert!(in_dev.supports_format(ffi::Enum_SoundIoFormat::SoundIoFormatFloat32LE));
    assert!(out_dev.supports_format(ffi::Enum_SoundIoFormat::SoundIoFormatFloat32LE));
    assert!(in_dev.supports_layout(&stereo_layout));
    assert!(out_dev.supports_layout(&stereo_layout));
    assert!(in_dev.supports_sample_rate(48_000));
    assert!(out_dev.supports_sample_rate(48_000));
    assert!(in_dev.nearest_sample_rate(1) > 0);
    assert!(out_dev.nearest_sample_rate(1) > 0);
}
<|endoftext|>


<commit_before>#[cfg(feature="either")]
pub extern crate either;

use std::rc::Rc;
use std::cell::RefCell;
use std::borrow::Cow;
use std::ptr;

mod types;
use types::{Callbacks, Untyped, SumType2};

mod helpers;
use helpers::{rc_and_weak, with_weak};

#[cfg(feature="either")]
use either::Either;

/// A source of values that feeds the streams connected to it
#[derive(Clone)]
pub struct Sink<T: Clone>
{
    cbs: Rc<RefCell<Callbacks<T>>>,
}

impl<T: Clone> Sink<T>
{
    /// Creates a new sink
    pub fn new() -> Self
    {
        Sink{ cbs: Rc::new(RefCell::new(Callbacks::new())) }
    }

    /// Creates a Stream that receives the objects sent through this sink
    pub fn stream(&self) -> Stream<T>
    {
        Stream{ cbs: self.cbs.clone(), source: None }
    }

    /// Send a value into the sink
    pub fn send(&self, val: T)
    {
        self.cbs.borrow_mut().call(val)
    }

    /// Sends values from an Iterator into the sink
    pub fn feed(&self, iter: I)
        where I: IntoIterator<Item=T>
    {
        let mut cbs = self.cbs.borrow_mut();
        for val in iter
        {
            cbs.call(val)
        }
    }
}

/// A stream of discrete events sent over time
#[derive(Clone)]
pub struct Stream<T: Clone>
{
    cbs: Rc<RefCell<Callbacks<T>>>,
    source: Option<Rc<Untyped>>,  // strong reference to a parent Stream
}

impl<T: Clone + 'static> Stream<T>
{
    /// Maps this stream into another stream using the provided function
    pub fn map<F, R>(&self, f: F) -> Stream<R>
        where F: Fn(Cow<T>) -> R + 'static,
        R: Clone + 'static
    {
        self.filter_map(move |arg| Some(f(arg)))
    }

    /// Creates a new Stream that only contains the values where the predicate is true
    pub fn filter<F>(&self, pred: F) -> Self
        where F: Fn(&T) -> bool + 'static
    {
        let (new_cbs, weak) = rc_and_weak(Callbacks::new());
        self.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak, |cb| if pred(&arg) { cb.borrow_mut().call_cow(arg) })
        });
        Stream{ cbs: new_cbs, source: Some(Rc::new(self.clone())) }
    }

    /// Filter and map a stream simultaneously
    pub fn filter_map<F, R>(&self, f: F) -> Stream<R>
        where F: Fn(Cow<T>) -> Option<R> + 'static,
        R: Clone + 'static
    {
        let (new_cbs, weak) = rc_and_weak(Callbacks::new());
        self.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak, |cb| if let Some(val) = f(arg) { cb.borrow_mut().call(val) })
        });
        Stream{ cbs: new_cbs, source: Some(Rc::new(self.clone())) }
    }

    /// Creates a new stream that fires with the events from both streams
    pub fn merge(&self, other: &Stream<T>) -> Self
    {
        let (new_cbs, weak1) = rc_and_weak(Callbacks::new());
        let weak2 = weak1.clone();
        self.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak1, |cb| cb.borrow_mut().call_cow(arg))
        });
        other.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak2, |cb| cb.borrow_mut().call_cow(arg))
        });
        Stream{ cbs: new_cbs, source: Some(Rc::new((self.clone(), other.clone()))) }
    }

    /// Merges two streams of different types
    #[cfg(feature="either")]
    pub fn merge_with(&self, other: &Stream, f: F) -> Stream<R>
        where F: Fn(Either<Cow<T>, Cow>) -> R + 'static,
        U: Clone + 'static, R: Clone + 'static
    {
        let (new_cbs, weak1) = rc_and_weak(Callbacks::new());
        let weak2 = weak1.clone();
        let f1 = Rc::new(f);
        let f2 = f1.clone();
        self.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak1, |cb| cb.borrow_mut().call(f1(Either::Left(arg))))
        });
        other.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak2, |cb| cb.borrow_mut().call(f2(Either::Right(arg))))
        });
        Stream{ cbs: new_cbs, source: Some(Rc::new((self.clone(), other.clone()))) }
    }

    /// Read the values without modifying them
    pub fn inspect<F>(self, f: F) -> Self
        where F: Fn(Cow<T>) + 'static
    {
        self.cbs.borrow_mut().push(move |arg| { f(arg); true });
        self
    }

    /// Creates a Signal that holds the last value sent to this Stream
    pub fn hold(&self, initial: T) -> Signal<T>
    {
        self.hold_if(initial, |_| true)
    }

    /// Holds the last value in this stream where the predicate is true
    pub fn hold_if<F>(&self, initial: T, pred: F) -> Signal<T>
        where F: Fn(&T) -> bool + 'static
    {
        let (storage, weak) = rc_and_weak(initial);
        self.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak, |st| if pred(&arg) { *st.borrow_mut() = arg.into_owned() })
        });
        Signal{
            val: SigVal::Shared(storage),
            source: Some(Rc::new(self.clone()))
        }
    }

    /// Accumulates the values sent over this stream
    pub fn fold(&self, initial: A, f: F) -> Signal
        where F: Fn(A, Cow<T>) -> A + 'static,
        A: Clone + 'static
    {
        let (storage, weak) = rc_and_weak(initial);
        self.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak, |st| unsafe {
                let acc = &mut *st.borrow_mut();
                let old = ptr::read(acc);
                let new = f(old, arg);
                ptr::write(acc, new);
            })
        });
        Signal{
            val: SigVal::Shared(storage),
            source: Some(Rc::new(self.clone()))
        }
    }
}

impl<T: Clone + 'static> Stream<Option<T>>
{
    /// Filters a stream of `Option`s, returning the unwrapped `Some` values
    pub fn filter_some(&self) -> Stream<T>
    {
        self.filter_map(|opt| opt.into_owned())
    }
}

impl<T: SumType2 + Clone + 'static> Stream<T>
    where T::Type1: Clone + 'static, T::Type2: Clone + 'static
{
    /// Splits a two element sum type stream into two streams with the unwrapped values
    pub fn split(&self) -> (Stream<T::Type1>, Stream<T::Type2>)
    {
        let (cbs_1, weak_1) = rc_and_weak(Callbacks::new());
        let (cbs_2, weak_2) = rc_and_weak(Callbacks::new());
        self.cbs.borrow_mut().push(move |result| {
            match (result.is_type1(), weak_1.upgrade(), weak_2.upgrade()) {
                (true, Some(cb), _) => { cb.borrow_mut().call(result.into_owned().into_type1().unwrap()); true },
                (false, _, Some(cb)) => { cb.borrow_mut().call(result.into_owned().into_type2().unwrap()); true },
                (_, None, None) => return false,  // both output steams dropped, drop this callback
                _ => true,  // sent to a dropped stream, but the other is still alive. keep this callback
            }
        });
        let source_rc = Rc::new(self.clone());
        let stream_1 = Stream{ cbs: cbs_1, source: Some(source_rc.clone()) };
        let stream_2 = Stream{ cbs: cbs_2, source: Some(source_rc) };
        (stream_1, stream_2)
    }
}

impl<T: Clone + 'static> Stream<Stream<T>>
{
    /// Listens to the events from the last stream sent to a nested stream
    pub fn switch(&self) -> Stream<T>
    {
        let (new_cbs, weak) = rc_and_weak(Callbacks::new());
        let mut storage = Rc::new(());
        self.cbs.borrow_mut().push(move |stream| {
            // check if the ouput stream is still alive
            if weak.upgrade().is_none() { return false }
            let cbs_w = weak.clone();
            // this represents the connection between this stream and the output
            let lifetime = Rc::new(());
            let lifetime_w = Rc::downgrade(&lifetime);
            // drop the previous Rc so it unlinks from the output stream
            storage = lifetime;
            // redirect the inner stream to the output stream
            stream.cbs.borrow_mut().push(move |arg| {
                lifetime_w.upgrade() // check if we're still linked to this stream
                    .and_then(|_| cbs_w.upgrade()) // check if output stream still alive
                    .map(|cb| cb.borrow_mut().call_cow(arg))
                    .is_some()
            });
            true
        });
        Stream{ cbs: new_cbs, source: Some(Rc::new(self.clone())) }
    }
}

#[derive(Clone)]
enum SigVal<T>
{
    Constant(Rc<T>),
    Shared(Rc<RefCell<T>>),
    Dynamic(Rc<Fn() -> T>),
    Nested(Rc<Fn() -> Signal<T>>),
}

impl<T> SigVal<T>
{
    fn from_fn<F>(f: F) -> Self
        where F: Fn() -> T + 'static
    {
        SigVal::Dynamic(Rc::new(f))
    }
}

// Represents a continuous value that changes over time
#[derive(Clone)]
pub struct Signal<T>
{
    val: SigVal<T>,
    source: Option<Rc<Untyped>>,
}

impl<T: Clone> Signal<T>
{
    /// Creates a signal with a constant value
    pub fn constant(val: U) -> Self
        where U: Into<Rc<T>>
    {
        Signal{ val: SigVal::Constant(val.into()), source: None }
    }

    /// Creates a signal that samples it's values from a function
    pub fn from_fn<F>(f: F) -> Self
        where F: Fn() -> T + 'static
    {
        Signal{ val: SigVal::from_fn(f), source: None }
    }

    /// Sample by value.
    /// This clones the content of the signal
    pub fn sample(&self) -> T
    {
        match self.val
        {
            SigVal::Constant(ref v) => (**v).clone(),
            SigVal::Shared(ref s) => s.borrow().clone(),
            SigVal::Dynamic(ref f) => f(),
            SigVal::Nested(ref sig) => sig().sample(),
        }
    }

    /// Sample by reference.
    /// This is meant to be the most efficient way when cloning is undesirable,
    /// but it requires a callback to prevent outliving the RefCell borrow
    pub fn sample_with<F, R>(&self, cb: F) -> R
        where F: FnOnce(Cow<T>) -> R
    {
        match self.val
        {
            SigVal::Constant(ref v) => cb(Cow::Borrowed(v)),
            SigVal::Shared(ref s) => cb(Cow::Borrowed(&s.borrow())),
            SigVal::Dynamic(ref f) => cb(Cow::Owned(f())),
            SigVal::Nested(ref sig) => sig().sample_with(cb),
        }
    }

    /// Maps a signal with the provided function
    pub fn map<F, R>(&self, f: F) -> Signal<R>
        where F: Fn(Cow<T>) -> R + 'static,
        R: Clone, T: 'static
    {
        let this = self.clone();
        Signal{
            val: SigVal::from_fn(move || this.sample_with(|val| f(val))),
            source: None
        }
    }

    /// Takes a snapshot of the Signal every time the trigger signal fires
    pub fn snapshot<S, F, R>(&self, trigger: &Stream<S>, f: F) -> Stream<R>
        where F: Fn(Cow<T>, Cow<S>) -> R + 'static,
        S: Clone + 'static, R: Clone + 'static, T: 'static
    {
        let this = self.clone();
        trigger.map(move |b| this.sample_with(|a| f(a, b)))
    }
}

impl <T: Clone + 'static> Signal<Signal<T>>
{
    /// Creates a new signal that samples the inner value of a nested signal
    pub fn switch(&self) -> Signal<T>
    {
        let this = self.clone();
        Signal{
            val: SigVal::Nested(Rc::new(move || this.sample())),
            source: None
        }
    }
}

impl<T: Clone, U: Into<Rc<T>>> From for Signal<T>
{
    fn from(val: U) -> Self
    {
        Signal::constant(val)
    }
}
<commit_msg>added Stream::channel<commit_after>#[cfg(feature="either")]
pub extern crate either;

use std::rc::Rc;
use std::cell::RefCell;
use std::borrow::Cow;
use std::ptr;
use std::sync::mpsc;

mod types;
use types::{Callbacks, Untyped, SumType2};

mod helpers;
use helpers::{rc_and_weak, with_weak};

#[cfg(feature="either")]
use either::Either;

/// A source of values that feeds the streams connected to it
#[derive(Clone)]
pub struct Sink<T: Clone>
{
    cbs: Rc<RefCell<Callbacks<T>>>,
}

impl<T: Clone> Sink<T>
{
    /// Creates a new sink
    pub fn new() -> Self
    {
        Sink{ cbs: Rc::new(RefCell::new(Callbacks::new())) }
    }

    /// Creates a Stream that receives the objects sent through this sink
    pub fn stream(&self) -> Stream<T>
    {
        Stream{ cbs: self.cbs.clone(), source: None }
    }

    /// Send a value into the sink
    pub fn send(&self, val: T)
    {
        self.cbs.borrow_mut().call(val)
    }

    /// Sends values from an Iterator into the sink
    pub fn feed(&self, iter: I)
        where I: IntoIterator<Item=T>
    {
        let mut cbs = self.cbs.borrow_mut();
        for val in iter
        {
            cbs.call(val)
        }
    }
}

/// A stream of discrete events sent over time
#[derive(Clone)]
pub struct Stream<T: Clone>
{
    cbs: Rc<RefCell<Callbacks<T>>>,
    source: Option<Rc<Untyped>>,  // strong reference to a parent Stream
}

impl<T: Clone + 'static> Stream<T>
{
    /// Maps this stream into another stream using the provided function
    pub fn map<F, R>(&self, f: F) -> Stream<R>
        where F: Fn(Cow<T>) -> R + 'static,
        R: Clone + 'static
    {
        self.filter_map(move |arg| Some(f(arg)))
    }

    /// Creates a new Stream that only contains the values where the predicate is true
    pub fn filter<F>(&self, pred: F) -> Self
        where F: Fn(&T) -> bool + 'static
    {
        let (new_cbs, weak) = rc_and_weak(Callbacks::new());
        self.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak, |cb| if pred(&arg) { cb.borrow_mut().call_cow(arg) })
        });
        Stream{ cbs: new_cbs, source: Some(Rc::new(self.clone())) }
    }

    /// Filter and map a stream simultaneously
    pub fn filter_map<F, R>(&self, f: F) -> Stream<R>
        where F: Fn(Cow<T>) -> Option<R> + 'static,
        R: Clone + 'static
    {
        let (new_cbs, weak) = rc_and_weak(Callbacks::new());
        self.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak, |cb| if let Some(val) = f(arg) { cb.borrow_mut().call(val) })
        });
        Stream{ cbs: new_cbs, source: Some(Rc::new(self.clone())) }
    }

    /// Creates a new stream that fires with the events from both streams
    pub fn merge(&self, other: &Stream<T>) -> Self
    {
        let (new_cbs, weak1) = rc_and_weak(Callbacks::new());
        let weak2 = weak1.clone();
        self.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak1, |cb| cb.borrow_mut().call_cow(arg))
        });
        other.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak2, |cb| cb.borrow_mut().call_cow(arg))
        });
        Stream{ cbs: new_cbs, source: Some(Rc::new((self.clone(), other.clone()))) }
    }

    /// Merges two streams of different types
    #[cfg(feature="either")]
    pub fn merge_with(&self, other: &Stream, f: F) -> Stream<R>
        where F: Fn(Either<Cow<T>, Cow>) -> R + 'static,
        U: Clone + 'static, R: Clone + 'static
    {
        let (new_cbs, weak1) = rc_and_weak(Callbacks::new());
        let weak2 = weak1.clone();
        let f1 = Rc::new(f);
        let f2 = f1.clone();
        self.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak1, |cb| cb.borrow_mut().call(f1(Either::Left(arg))))
        });
        other.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak2, |cb| cb.borrow_mut().call(f2(Either::Right(arg))))
        });
        Stream{ cbs: new_cbs, source: Some(Rc::new((self.clone(), other.clone()))) }
    }

    /// Read the values without modifying them
    pub fn inspect<F>(self, f: F) -> Self
        where F: Fn(Cow<T>) + 'static
    {
        self.cbs.borrow_mut().push(move |arg| { f(arg); true });
        self
    }

    /// Creates a channel and sends the stream events through it
    pub fn channel(&self) -> mpsc::Receiver<T>
    {
        let (tx, rx) = mpsc::channel();
        self.cbs.borrow_mut().push(move |arg| {
            tx.send(arg.into_owned()).is_ok()
        });
        rx
    }

    /// Creates a Signal that holds the last value sent to this Stream
    pub fn hold(&self, initial: T) -> Signal<T>
    {
        self.hold_if(initial, |_| true)
    }

    /// Holds the last value in this stream where the predicate is true
    pub fn hold_if<F>(&self, initial: T, pred: F) -> Signal<T>
        where F: Fn(&T) -> bool + 'static
    {
        let (storage, weak) = rc_and_weak(initial);
        self.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak, |st| if pred(&arg) { *st.borrow_mut() = arg.into_owned() })
        });
        Signal{
            val: SigVal::Shared(storage),
            source: Some(Rc::new(self.clone()))
        }
    }

    /// Accumulates the values sent over this stream
    pub fn fold(&self, initial: A, f: F) -> Signal
        where F: Fn(A, Cow<T>) -> A + 'static,
        A: Clone + 'static
    {
        let (storage, weak) = rc_and_weak(initial);
        self.cbs.borrow_mut().push(move |arg| {
            with_weak(&weak, |st| unsafe {
                let acc = &mut *st.borrow_mut();
                let old = ptr::read(acc);
                let new = f(old, arg);
                ptr::write(acc, new);
            })
        });
        Signal{
            val: SigVal::Shared(storage),
            source: Some(Rc::new(self.clone()))
        }
    }
}

impl<T: Clone + 'static> Stream<Option<T>>
{
    /// Filters a stream of `Option`s, returning the unwrapped `Some` values
    pub fn filter_some(&self) -> Stream<T>
    {
        self.filter_map(|opt| opt.into_owned())
    }
}

impl<T: SumType2 + Clone + 'static> Stream<T>
    where T::Type1: Clone + 'static, T::Type2: Clone + 'static
{
    /// Splits a two element sum type stream into two streams with the unwrapped values
    pub fn split(&self) -> (Stream<T::Type1>, Stream<T::Type2>)
    {
        let (cbs_1, weak_1) = rc_and_weak(Callbacks::new());
        let (cbs_2, weak_2) = rc_and_weak(Callbacks::new());
        self.cbs.borrow_mut().push(move |result| {
            match (result.is_type1(), weak_1.upgrade(), weak_2.upgrade()) {
                (true, Some(cb), _) => { cb.borrow_mut().call(result.into_owned().into_type1().unwrap()); true },
                (false, _, Some(cb)) => { cb.borrow_mut().call(result.into_owned().into_type2().unwrap()); true },
                (_, None, None) => return false,  // both output steams dropped, drop this callback
                _ => true,  // sent to a dropped stream, but the other is still alive. keep this callback
            }
        });
        let source_rc = Rc::new(self.clone());
        let stream_1 = Stream{ cbs: cbs_1, source: Some(source_rc.clone()) };
        let stream_2 = Stream{ cbs: cbs_2, source: Some(source_rc) };
        (stream_1, stream_2)
    }
}

impl<T: Clone + 'static> Stream<Stream<T>>
{
    /// Listens to the events from the last stream sent to a nested stream
    pub fn switch(&self) -> Stream<T>
    {
        let (new_cbs, weak) = rc_and_weak(Callbacks::new());
        let mut storage = Rc::new(());
        self.cbs.borrow_mut().push(move |stream| {
            // check if the ouput stream is still alive
            if weak.upgrade().is_none() { return false }
            let cbs_w = weak.clone();
            // this represents the connection between this stream and the output
            let lifetime = Rc::new(());
            let lifetime_w = Rc::downgrade(&lifetime);
            // drop the previous Rc so it unlinks from the output stream
            storage = lifetime;
            // redirect the inner stream to the output stream
            stream.cbs.borrow_mut().push(move |arg| {
                lifetime_w.upgrade() // check if we're still linked to this stream
                    .and_then(|_| cbs_w.upgrade()) // check if output stream still alive
                    .map(|cb| cb.borrow_mut().call_cow(arg))
                    .is_some()
            });
            true
        });
        Stream{ cbs: new_cbs, source: Some(Rc::new(self.clone())) }
    }
}

#[derive(Clone)]
enum SigVal<T>
{
    Constant(Rc<T>),
    Shared(Rc<RefCell<T>>),
    Dynamic(Rc<Fn() -> T>),
    Nested(Rc<Fn() -> Signal<T>>),
}

impl<T> SigVal<T>
{
    fn from_fn<F>(f: F) -> Self
        where F: Fn() -> T + 'static
    {
        SigVal::Dynamic(Rc::new(f))
    }
}

// Represents a continuous value that changes over time
#[derive(Clone)]
pub struct Signal<T>
{
    val: SigVal<T>,
    source: Option<Rc<Untyped>>,
}

impl<T: Clone> Signal<T>
{
    /// Creates a signal with a constant value
    pub fn constant(val: U) -> Self
        where U: Into<Rc<T>>
    {
        Signal{ val: SigVal::Constant(val.into()), source: None }
    }

    /// Creates a signal that samples it's values from a function
    pub fn from_fn<F>(f: F) -> Self
        where F: Fn() -> T + 'static
    {
        Signal{ val: SigVal::from_fn(f), source: None }
    }

    /// Sample by value.
    /// This clones the content of the signal
    pub fn sample(&self) -> T
    {
        match self.val
        {
            SigVal::Constant(ref v) => (**v).clone(),
            SigVal::Shared(ref s) => s.borrow().clone(),
            SigVal::Dynamic(ref f) => f(),
            SigVal::Nested(ref sig) => sig().sample(),
        }
    }

    /// Sample by reference.
    /// This is meant to be the most efficient way when cloning is undesirable,
    /// but it requires a callback to prevent outliving the RefCell borrow
    pub fn sample_with<F, R>(&self, cb: F) -> R
        where F: FnOnce(Cow<T>) -> R
    {
        match self.val
        {
            SigVal::Constant(ref v) => cb(Cow::Borrowed(v)),
            SigVal::Shared(ref s) => cb(Cow::Borrowed(&s.borrow())),
            SigVal::Dynamic(ref f) => cb(Cow::Owned(f())),
            SigVal::Nested(ref sig) => sig().sample_with(cb),
        }
    }

    /// Maps a signal with the provided function
    pub fn map<F, R>(&self, f: F) -> Signal<R>
        where F: Fn(Cow<T>) -> R + 'static,
        R: Clone, T: 'static
    {
        let this = self.clone();
        Signal{
            val: SigVal::from_fn(move || this.sample_with(|val| f(val))),
            source: None
        }
    }

    /// Takes a snapshot of the Signal every time the trigger signal fires
    pub fn snapshot<S, F, R>(&self, trigger: &Stream<S>, f: F) -> Stream<R>
        where F: Fn(Cow<T>, Cow<S>) -> R + 'static,
        S: Clone + 'static, R: Clone + 'static, T: 'static
    {
        let this = self.clone();
        trigger.map(move |b| this.sample_with(|a| f(a, b)))
    }
}

impl <T: Clone + 'static> Signal<Signal<T>>
{
    /// Creates a new signal that samples the inner value of a nested signal
    pub fn switch(&self) -> Signal<T>
    {
        let this = self.clone();
        Signal{
            val: SigVal::Nested(Rc::new(move || this.sample())),
            source: None
        }
    }
}

impl<T: Clone, U: Into<Rc<T>>> From for Signal<T>
{
    fn from(val: U) -> Self
    {
        Signal::constant(val)
    }
}
<|endoftext|>