<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, 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, suseconds_t, utimes};

    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>Add a cast to fix 1.5<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, suseconds_t, utimes};

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

//! A cache that holds a limited number of key-value pairs. When the
//! capacity of the cache is exceeded, the least-recently-used
//! (where "used" means a look-up or putting the pair into the cache)
//! pair is automatically removed.
//!
//! # Example
//!
//! ```
//! # extern crate "lru-cache" as lru_cache;
//! # fn main() {
//! use lru_cache::LruCache;
//!
//! let mut cache = LruCache::new(2);
//! cache.insert(1, 10);
//! cache.insert(2, 20);
//! cache.insert(3, 30);
//! assert!(cache.get(&1).is_none());
//! assert_eq!(*cache.get(&2).unwrap(), 20);
//! assert_eq!(*cache.get(&3).unwrap(), 30);
//!
//! cache.insert(2, 22);
//! assert_eq!(*cache.get(&2).unwrap(), 22);
//!
//! cache.insert(6, 60);
//! assert!(cache.get(&3).is_none());
//!
//! cache.set_capacity(1);
//! assert!(cache.get(&2).is_none());
//! # }
//! ```

extern crate "linked-hash-map" as linked_hash_map;

use std::fmt;
use std::hash::Hash;
use std::iter::{IntoIterator, Extend};

use linked_hash_map::LinkedHashMap;

// FIXME(conventions): implement iterators?
// FIXME(conventions): implement indexing?

/// An LRU Cache.
pub struct LruCache<K, V> {
    map: LinkedHashMap<K, V>,
    max_size: usize,
}

impl<K: Hash + Eq, V> LruCache<K, V> {
    /// Create an LRU Cache that holds at most `capacity` items.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate "lru-cache" as lru_cache;
    /// # fn main() {
    /// use lru_cache::LruCache;
    /// let mut cache: LruCache<i32, &str> = LruCache::new(10);
    /// # }
    /// ```
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn new(capacity: usize) -> LruCache<K, V> {
        LruCache {
            map: LinkedHashMap::new(),
            max_size: capacity,
        }
    }

    /// Inserts a key-value pair into the cache. If the key already existed, the old value is
    /// returned.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate "lru-cache" as lru_cache;
    /// # fn main() {
    /// use lru_cache::LruCache;
    /// let mut cache = LruCache::new(2);
    ///
    /// cache.insert(1, "a");
    /// cache.insert(2, "b");
    /// assert_eq!(cache.get(&1), Some(&"a"));
    /// assert_eq!(cache.get(&2), Some(&"b"));
    /// # }
    /// ```
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
        let old_val = self.map.insert(k, v);
        if self.len() > self.capacity() {
            self.remove_lru();
        }
        old_val
    }

    /// Return a value corresponding to the key in the cache.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate "lru-cache" as lru_cache;
    /// # fn main() {
    /// use lru_cache::LruCache;
    /// let mut cache = LruCache::new(2);
    ///
    /// cache.insert(1, "a");
    /// cache.insert(2, "b");
    /// cache.insert(2, "c");
    /// cache.insert(3, "d");
    ///
    /// assert_eq!(cache.get(&1), None);
    /// assert_eq!(cache.get(&2), Some(&"c"));
    /// # }
    /// ```
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn get(&mut self, k: &K) -> Option<&V> {
        self.map.get_refresh(k)
    }

    /// Remove and return a value corresponding to the key from the cache.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate "lru-cache" as lru_cache;
    /// # fn main() {
    /// use lru_cache::LruCache;
    /// let mut cache = LruCache::new(2);
    ///
    /// cache.insert(2, "a");
    ///
    /// assert_eq!(cache.remove(&1), None);
    /// assert_eq!(cache.remove(&2), Some("a"));
    /// assert_eq!(cache.remove(&2), None);
    /// assert_eq!(cache.len(), 0);
    /// # }
    /// ```
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn remove(&mut self, k: &K) -> Option<V> {
        self.map.remove(k)
    }

    /// Return the maximum number of key-value pairs the cache can hold.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate "lru-cache" as lru_cache;
    /// # fn main() {
    /// use lru_cache::LruCache;
    /// let mut cache: LruCache<i32, &str> = LruCache::new(2);
    /// assert_eq!(cache.capacity(), 2);
    /// # }
    /// ```
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn capacity(&self) -> usize {
        self.max_size
    }

    /// Change the number of key-value pairs the cache can hold. Remove
    /// least-recently-used key-value pairs if necessary.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate "lru-cache" as lru_cache;
    /// # fn main() {
    /// use lru_cache::LruCache;
    /// let mut cache = LruCache::new(2);
    ///
    /// cache.insert(1, "a");
    /// cache.insert(2, "b");
    /// cache.insert(3, "c");
    ///
    /// assert_eq!(cache.get(&1), None);
    /// assert_eq!(cache.get(&2), Some(&"b"));
    /// assert_eq!(cache.get(&3), Some(&"c"));
    ///
    /// cache.set_capacity(3);
    /// cache.insert(1, "a");
    /// cache.insert(2, "b");
    ///
    /// assert_eq!(cache.get(&1), Some(&"a"));
    /// assert_eq!(cache.get(&2), Some(&"b"));
    /// assert_eq!(cache.get(&3), Some(&"c"));
    ///
    /// cache.set_capacity(1);
    ///
    /// assert_eq!(cache.get(&1), None);
    /// assert_eq!(cache.get(&2), None);
    /// assert_eq!(cache.get(&3), Some(&"c"));
    /// # }
    /// ```
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn set_capacity(&mut self, capacity: usize) {
        for _ in capacity..self.len() {
            self.remove_lru();
        }
        self.max_size = capacity;
    }

    #[inline]
    fn remove_lru(&mut self) {
        self.map.pop_front()
    }

    /// Return the number of key-value pairs in the cache.
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn len(&self) -> usize { self.map.len() }

    /// Returns whether the cache is currently empty.
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn is_empty(&self) -> bool { self.map.is_empty() }

    /// Clear the cache of all key-value pairs.
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn clear(&mut self) { self.map.clear(); }

}

impl<K: Hash + Eq, V> Extend<(K, V)> for LruCache<K, V> {
    fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) {
        for (k, v) in iter {
            self.insert(k, v);
        }
    }
}

impl<A: fmt::Debug + Hash + Eq, B: fmt::Debug> fmt::Debug for LruCache<A, B> {
    /// Return a string that lists the key-value pairs from most-recently
    /// used to least-recently used.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{{"));

        for (i, (k, v)) in self.map.iter().rev().enumerate() {
            if i != 0 { try!(write!(f, ", ")); }
            try!(write!(f, "{:?}: {:?}", *k, *v));
        }

        write!(f, "}}")
    }
}

unsafe impl<K: Send, V: Send> Send for LruCache<K, V> {}

unsafe impl<K: Sync, V: Sync> Sync for LruCache<K, V> {}

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

    fn assert_opt_eq<V: PartialEq>(opt: Option<&V>, v: V) {
        assert!(opt.is_some());
        assert!(opt.unwrap() == &v);
    }

    #[test]
    fn test_put_and_get() {
        let mut cache = LruCache::new(2);
        cache.insert(1, 10);
        cache.insert(2, 20);
        assert_opt_eq(cache.get(&1), 10);
        assert_opt_eq(cache.get(&2), 20);
        assert_eq!(cache.len(), 2);
    }

    #[test]
    fn test_put_update() {
        let mut cache: LruCache<String, Vec<u8>> = LruCache::new(1);
        cache.insert("1".to_string(), vec![10, 10]);
        cache.insert("1".to_string(), vec![10, 19]);
        assert_opt_eq(cache.get(&"1".to_string()), vec![10, 19]);
        assert_eq!(cache.len(), 1);
    }

    #[test]
    fn test_expire_lru() {
        let mut cache: LruCache<String, String> = LruCache::new(2);
        cache.insert("foo1".to_string(), "bar1".to_string());
        cache.insert("foo2".to_string(), "bar2".to_string());
        cache.insert("foo3".to_string(), "bar3".to_string());
        assert!(cache.get(&"foo1".to_string()).is_none());
        cache.insert("foo2".to_string(), "bar2update".to_string());
        cache.insert("foo4".to_string(), "bar4".to_string());
        assert!(cache.get(&"foo3".to_string()).is_none());
    }

    #[test]
    fn test_pop() {
        let mut cache = LruCache::new(2);
        cache.insert(1, 10);
        cache.insert(2, 20);
        assert_eq!(cache.len(), 2);
        let opt1 = cache.remove(&1);
        assert!(opt1.is_some());
        assert_eq!(opt1.unwrap(), 10);
        assert!(cache.get(&1).is_none());
        assert_eq!(cache.len(), 1);
    }

    #[test]
    fn test_change_capacity() {
        let mut cache = LruCache::new(2);
        assert_eq!(cache.capacity(), 2);
        cache.insert(1, 10);
        cache.insert(2, 20);
        cache.set_capacity(1);
        assert!(cache.get(&1).is_none());
        assert_eq!(cache.capacity(), 1);
    }

    #[test]
    fn test_debug() {
        let mut cache: LruCache<i32, i32> = LruCache::new(3);
        cache.insert(1, 10);
        cache.insert(2, 20);
        cache.insert(3, 30);
        assert_eq!(format!("{:?}", cache), "{3: 30, 2: 20, 1: 10}");
        cache.insert(2, 22);
        assert_eq!(format!("{:?}", cache), "{2: 22, 3: 30, 1: 10}");
        cache.insert(6, 60);
        assert_eq!(format!("{:?}", cache), "{6: 60, 2: 22, 3: 30}");
        cache.get(&3);
        assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60, 2: 22}");
        cache.set_capacity(2);
        assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60}");
    }

    #[test]
    fn test_remove() {
        let mut cache = LruCache::new(3);
        cache.insert(1, 10);
        cache.insert(2, 20);
        cache.insert(3, 30);
        cache.insert(4, 40);
        cache.insert(5, 50);
        cache.remove(&3);
        cache.remove(&4);
        assert!(cache.get(&3).is_none());
        assert!(cache.get(&4).is_none());
        cache.insert(6, 60);
        cache.insert(7, 70);
        cache.insert(8, 80);
        assert!(cache.get(&5).is_none());
        assert_opt_eq(cache.get(&6), 60);
        assert_opt_eq(cache.get(&7), 70);
        assert_opt_eq(cache.get(&8), 80);
    }

    #[test]
    fn test_clear() {
        let mut cache = LruCache::new(2);
        cache.insert(1, 10);
        cache.insert(2, 20);
        cache.clear();
        assert!(cache.get(&1).is_none());
        assert!(cache.get(&2).is_none());
        assert_eq!(format!("{:?}", cache), "{}");
    }
}
<commit_msg>tidy docs<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A cache that holds a limited number of key-value pairs. When the
//! capacity of the cache is exceeded, the least-recently-used
//! (where "used" means a look-up or putting the pair into the cache)
//! pair is automatically removed.
//!
//! # Examples
//!
//! ```
//! # extern crate "lru-cache" as lru_cache;
//! # fn main() {
//! use lru_cache::LruCache;
//!
//! let mut cache = LruCache::new(2);
//!
//! cache.insert(1, 10);
//! cache.insert(2, 20);
//! cache.insert(3, 30);
//! assert!(cache.get(&1).is_none());
//! assert_eq!(*cache.get(&2).unwrap(), 20);
//! assert_eq!(*cache.get(&3).unwrap(), 30);
//!
//! cache.insert(2, 22);
//! assert_eq!(*cache.get(&2).unwrap(), 22);
//!
//! cache.insert(6, 60);
//! assert!(cache.get(&3).is_none());
//!
//! cache.set_capacity(1);
//! assert!(cache.get(&2).is_none());
//! # }
//! ```

extern crate "linked-hash-map" as linked_hash_map;

use std::fmt;
use std::hash::Hash;
use std::iter::{IntoIterator, Extend};

use linked_hash_map::LinkedHashMap;

// FIXME(conventions): implement iterators?
// FIXME(conventions): implement indexing?

/// An LRU cache.
pub struct LruCache<K, V> {
    map: LinkedHashMap<K, V>,
    max_size: usize,
}

impl<K: Hash + Eq, V> LruCache<K, V> {
    /// Creates an empty cache that can hold at most `capacity` items.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate "lru-cache" as lru_cache;
    /// # fn main() {
    /// use lru_cache::LruCache;
    /// let mut cache: LruCache<i32, &str> = LruCache::new(10);
    /// # }
    /// ```
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn new(capacity: usize) -> LruCache<K, V> {
        LruCache {
            map: LinkedHashMap::new(),
            max_size: capacity,
        }
    }

    /// Inserts a key-value pair into the cache. If the key already existed, the old value is
    /// returned.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate "lru-cache" as lru_cache;
    /// # fn main() {
    /// use lru_cache::LruCache;
    ///
    /// let mut cache = LruCache::new(2);
    ///
    /// cache.insert(1, "a");
    /// cache.insert(2, "b");
    /// assert_eq!(cache.get(&1), Some(&"a"));
    /// assert_eq!(cache.get(&2), Some(&"b"));
    /// # }
    /// ```
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
        let old_val = self.map.insert(k, v);
        if self.len() > self.capacity() {
            self.remove_lru();
        }
        old_val
    }

    /// Returns the value corresponding to the given key in the cache.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate "lru-cache" as lru_cache;
    /// # fn main() {
    /// use lru_cache::LruCache;
    ///
    /// let mut cache = LruCache::new(2);
    ///
    /// cache.insert(1, "a");
    /// cache.insert(2, "b");
    /// cache.insert(2, "c");
    /// cache.insert(3, "d");
    ///
    /// assert_eq!(cache.get(&1), None);
    /// assert_eq!(cache.get(&2), Some(&"c"));
    /// # }
    /// ```
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn get(&mut self, k: &K) -> Option<&V> {
        self.map.get_refresh(k)
    }

    /// Removes the given key from the cache and returns its corresponding value.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate "lru-cache" as lru_cache;
    /// # fn main() {
    /// use lru_cache::LruCache;
    ///
    /// let mut cache = LruCache::new(2);
    ///
    /// cache.insert(2, "a");
    ///
    /// assert_eq!(cache.remove(&1), None);
    /// assert_eq!(cache.remove(&2), Some("a"));
    /// assert_eq!(cache.remove(&2), None);
    /// assert_eq!(cache.len(), 0);
    /// # }
    /// ```
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn remove(&mut self, k: &K) -> Option<V> {
        self.map.remove(k)
    }

    /// Returns the maximum number of key-value pairs the cache can hold.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate "lru-cache" as lru_cache;
    /// # fn main() {
    /// use lru_cache::LruCache;
    /// let mut cache: LruCache<i32, &str> = LruCache::new(2);
    /// assert_eq!(cache.capacity(), 2);
    /// # }
    /// ```
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn capacity(&self) -> usize {
        self.max_size
    }

    /// Sets the number of key-value pairs the cache can hold. Removes
    /// least-recently-used key-value pairs if necessary.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate "lru-cache" as lru_cache;
    /// # fn main() {
    /// use lru_cache::LruCache;
    ///
    /// let mut cache = LruCache::new(2);
    ///
    /// cache.insert(1, "a");
    /// cache.insert(2, "b");
    /// cache.insert(3, "c");
    ///
    /// assert_eq!(cache.get(&1), None);
    /// assert_eq!(cache.get(&2), Some(&"b"));
    /// assert_eq!(cache.get(&3), Some(&"c"));
    ///
    /// cache.set_capacity(3);
    /// cache.insert(1, "a");
    /// cache.insert(2, "b");
    ///
    /// assert_eq!(cache.get(&1), Some(&"a"));
    /// assert_eq!(cache.get(&2), Some(&"b"));
    /// assert_eq!(cache.get(&3), Some(&"c"));
    ///
    /// cache.set_capacity(1);
    ///
    /// assert_eq!(cache.get(&1), None);
    /// assert_eq!(cache.get(&2), None);
    /// assert_eq!(cache.get(&3), Some(&"c"));
    /// # }
    /// ```
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn set_capacity(&mut self, capacity: usize) {
        for _ in capacity..self.len() {
            self.remove_lru();
        }
        self.max_size = capacity;
    }

    #[inline]
    fn remove_lru(&mut self) {
        self.map.pop_front()
    }

    /// Returns the number of key-value pairs in the cache.
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn len(&self) -> usize { self.map.len() }

    /// Returns `true` if the cache contains no key-value pairs.
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn is_empty(&self) -> bool { self.map.is_empty() }

    /// Removes all key-value pairs from the cache.
    #[unstable = "matches collection reform specification, waiting for dust to settle"]
    pub fn clear(&mut self) { self.map.clear(); }

}

impl<K: Hash + Eq, V> Extend<(K, V)> for LruCache<K, V> {
    fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) {
        for (k, v) in iter {
            self.insert(k, v);
        }
    }
}

impl<A: fmt::Debug + Hash + Eq, B: fmt::Debug> fmt::Debug for LruCache<A, B> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{{"));

        for (i, (k, v)) in self.map.iter().rev().enumerate() {
            if i != 0 { try!(write!(f, ", ")); }
            try!(write!(f, "{:?}: {:?}", *k, *v));
        }

        write!(f, "}}")
    }
}

unsafe impl<K: Send, V: Send> Send for LruCache<K, V> {}

unsafe impl<K: Sync, V: Sync> Sync for LruCache<K, V> {}

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

    fn assert_opt_eq<V: PartialEq>(opt: Option<&V>, v: V) {
        assert!(opt.is_some());
        assert!(opt.unwrap() == &v);
    }

    #[test]
    fn test_put_and_get() {
        let mut cache = LruCache::new(2);
        cache.insert(1, 10);
        cache.insert(2, 20);
        assert_opt_eq(cache.get(&1), 10);
        assert_opt_eq(cache.get(&2), 20);
        assert_eq!(cache.len(), 2);
    }

    #[test]
    fn test_put_update() {
        let mut cache: LruCache<String, Vec<u8>> = LruCache::new(1);
        cache.insert("1".to_string(), vec![10, 10]);
        cache.insert("1".to_string(), vec![10, 19]);
        assert_opt_eq(cache.get(&"1".to_string()), vec![10, 19]);
        assert_eq!(cache.len(), 1);
    }

    #[test]
    fn test_expire_lru() {
        let mut cache: LruCache<String, String> = LruCache::new(2);
        cache.insert("foo1".to_string(), "bar1".to_string());
        cache.insert("foo2".to_string(), "bar2".to_string());
        cache.insert("foo3".to_string(), "bar3".to_string());
        assert!(cache.get(&"foo1".to_string()).is_none());
        cache.insert("foo2".to_string(), "bar2update".to_string());
        cache.insert("foo4".to_string(), "bar4".to_string());
        assert!(cache.get(&"foo3".to_string()).is_none());
    }

    #[test]
    fn test_pop() {
        let mut cache = LruCache::new(2);
        cache.insert(1, 10);
        cache.insert(2, 20);
        assert_eq!(cache.len(), 2);
        let opt1 = cache.remove(&1);
        assert!(opt1.is_some());
        assert_eq!(opt1.unwrap(), 10);
        assert!(cache.get(&1).is_none());
        assert_eq!(cache.len(), 1);
    }

    #[test]
    fn test_change_capacity() {
        let mut cache = LruCache::new(2);
        assert_eq!(cache.capacity(), 2);
        cache.insert(1, 10);
        cache.insert(2, 20);
        cache.set_capacity(1);
        assert!(cache.get(&1).is_none());
        assert_eq!(cache.capacity(), 1);
    }

    #[test]
    fn test_debug() {
        let mut cache: LruCache<i32, i32> = LruCache::new(3);
        cache.insert(1, 10);
        cache.insert(2, 20);
        cache.insert(3, 30);
        assert_eq!(format!("{:?}", cache), "{3: 30, 2: 20, 1: 10}");
        cache.insert(2, 22);
        assert_eq!(format!("{:?}", cache), "{2: 22, 3: 30, 1: 10}");
        cache.insert(6, 60);
        assert_eq!(format!("{:?}", cache), "{6: 60, 2: 22, 3: 30}");
        cache.get(&3);
        assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60, 2: 22}");
        cache.set_capacity(2);
        assert_eq!(format!("{:?}", cache), "{3: 30, 6: 60}");
    }

    #[test]
    fn test_remove() {
        let mut cache = LruCache::new(3);
        cache.insert(1, 10);
        cache.insert(2, 20);
        cache.insert(3, 30);
        cache.insert(4, 40);
        cache.insert(5, 50);
        cache.remove(&3);
        cache.remove(&4);
        assert!(cache.get(&3).is_none());
        assert!(cache.get(&4).is_none());
        cache.insert(6, 60);
        cache.insert(7, 70);
        cache.insert(8, 80);
        assert!(cache.get(&5).is_none());
        assert_opt_eq(cache.get(&6), 60);
        assert_opt_eq(cache.get(&7), 70);
        assert_opt_eq(cache.get(&8), 80);
    }

    #[test]
    fn test_clear() {
        let mut cache = LruCache::new(2);
        cache.insert(1, 10);
        cache.insert(2, 20);
        cache.clear();
        assert!(cache.get(&1).is_none());
        assert!(cache.get(&2).is_none());
        assert_eq!(format!("{:?}", cache), "{}");
    }
}
<|endoftext|>


<commit_before>#![feature(plugin_registrar, box_syntax, rustc_private)]
#[macro_use] extern crate rustc;
extern crate syntax;

use rustc::lint::{LintPass, LintArray, Context};
use syntax::attr::contains_name;
use syntax::ast;
use rustc::middle::const_eval::eval_const_expr;
use rustc::middle::const_eval::const_val::*;
use rustc::plugin::registry::Registry;

declare_lint!(STATIC_ASSERT, Deny,
              "check compile-time information");

struct StaticAssertPass;

impl LintPass for StaticAssertPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(STATIC_ASSERT)
    }

    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
        if !contains_name(&it.attrs, "static_assert_") {
            return;
        }
        let evaluated = match it.node {
            ast::ItemConst(_, ref expr) => eval_const_expr(&cx.tcx, expr),
            _ => return,
        };
        match evaluated {
            const_bool(true) => return,
            // FIXME: https://github.com/rust-lang/rust/issues/25307
            const_int(i) if i == 1 => return,
            const_uint(_) => cx.sess().span_err(it.span, "static assertion on uint"),
            const_float(_) => cx.sess().span_err(it.span, "static assertion on float"),
            const_str(_) => cx.sess().span_err(it.span, "static assertion on str"),
            const_binary(_) => cx.sess().span_err(it.span, "static assertion on binary"),
            Struct(_) => cx.sess().span_err(it.span, "static assertion on struct"),
            Tuple(_) => cx.sess().span_err(it.span, "static assertion on tuple"),
            _ => {}
        }
        cx.span_lint(STATIC_ASSERT, it.span, "static assertion failed");
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_lint_pass(box StaticAssertPass); // as LintPassObject
}

#[macro_export]
macro_rules! static_assert(
    ($e:expr) => {
        #[static_assert_]
        #[allow(dead_code)]
        const COND: bool = $e;
    }
);
<commit_msg>rustup<commit_after>#![feature(plugin_registrar, box_syntax, rustc_private)]
#[macro_use] extern crate rustc;
extern crate rustc_plugin;
extern crate rustc_front;
extern crate syntax;

use rustc::lint::{LintPass, LateLintPass, LintArray, LateContext, LintContext};
use syntax::attr::contains_name;
use rustc::middle::const_eval::eval_const_expr;
use rustc::middle::const_eval::ConstVal::*;
use rustc_plugin::registry::Registry;
use rustc_front::hir;

declare_lint!(STATIC_ASSERT, Deny,
              "check compile-time information");

struct StaticAssertPass;

impl LintPass for StaticAssertPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(STATIC_ASSERT)
    }
}

impl LateLintPass for StaticAssertPass {
    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
        if !contains_name(&it.attrs, "static_assert_") {
            return;
        }
        let evaluated = if let hir::ItemConst(_, ref expr) = it.node {
            eval_const_expr(&cx.tcx, expr)
        } else {
            return
        };
        match evaluated {
            Bool(true) => {},
            Bool(false) => cx.span_lint(STATIC_ASSERT, it.span, "static assertion failed"),
            // FIXME: https://github.com/rust-lang/rust/issues/25307
            Int(i) if i == 1 => {},
            _ => cx.sess().span_err(it.span, &format!("static assertion on {:?}", evaluated)),
        }
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_late_lint_pass(box StaticAssertPass); // as LintPassObject
}

#[macro_export]
macro_rules! static_assert(
    ($e:expr) => {
        #[static_assert_]
        #[allow(dead_code)]
        const COND: bool = $e;
    }
);
<|endoftext|>


<commit_before>/*!
nphysics
========
**nphysics** is a 2 and 3-dimensional physics engine for games and animations.
It uses [ncollide](http://ncollide.org) for collision detection, and
[nalgebra](http://nalgebra.org) for vector/matrix math. 2D and 3D
implementations both share the same code!

Examples are available in the `examples2d` and `examples3d` directories. There
is also a short (outdated) [demonstration video](http://youtu.be/CANjXZ5rocI).
An on-line version of this documentation is available
[here](http://nphysics.org). Feel free to ask for help and discuss features on
the official [user forum](http://users.nphysics.org).

## Why another physics engine?
There are a lot of physics engine out there.
However having a physics engine written in Rust is much more fun than
writing bindings and has several advantages:

- it shows that Rust is suitable for soft real-time applications
- it shows how well Rust behaves with highly generic code
- it shows that there is no need to write two separate engine for 2D and 3D:
  genericity wrt the dimension is possible (modulo low level arithmetic
  specializations for each dimension).
- in a not-that-near future, C++ will die of ugliness. Then, people will
  search for a physics engine and **nphysics** will be there, proudly
  exhibiting its _Rusty_ sexyness.

## Compilation
You will need the latest release of the [Rust compiler](http://www.rust-lang.org)
and the official package manager: [Cargo](https://github.com/rust-lang/cargo).

If you want to use the 2D version of `nphysics`, add the crate named
`nphysics2d` to your dependencies:

```ignore
[dependencies]
nphysics2d = "0.8"
```

For the 3D version, add the crate named `nphysics3d`:

```ignore
[dependencies]
nphysics3d = "0.8"
```

Use `make examples` to build the demos and execute `./your_favorite_example_here --help`
to see all the cool stuffs you can do.

## Features
- Static and dynamic rigid bodies.
- Common convex primitives: cone, box, ball, cylinder.
- Concave geometries build from convex primitives (aka. compound geometries).
- Stable stacking.
- Island based sleeping (objects deactivation).
- Ray casting.
- Swept sphere based continuous collision detection.
- Ball-in-socket joint.
- FixedJoint joint.
- Sensors.

## What is missing?
**nphysics** is a very young library and needs to learn a lot of things to
become a grown up. Many missing features are because of missing features on
**ncollide**. Features missing from **nphysics** itself include:

- efficient signaling system
- more joints, joint limits, joint motors and breakable joints.
- soft-bodies (see https://github.com/natal/roft for a draft)
- parallel pipeline
- GPU-based pipeline

## Dependencies
All dependencies are automatically cloned with a recursive clone.
The libraries needed to compile the physics engine are:

* [ncollide](http://ncollide.org): the collision detection library.
* [nalgebra](http://nalgebra.org): the linear algebra library.

The libraries needed to compile the examples are:

*/
#![deny(non_camel_case_types)]
#![deny(unused_parens)]
#![deny(non_upper_case_globals)]
#![deny(unused_qualifications)]
#![deny(missing_docs)]
#![deny(unused_results)]
#![warn(non_camel_case_types)]
#![allow(missing_copy_implementations)]
#![doc(html_root_url = "http://nphysics.org/rustdoc/")]

#[macro_use]
extern crate approx;
#[macro_use]
extern crate downcast;

extern crate alga;
extern crate nalgebra as na;
#[cfg(feature = "dim2")]
extern crate ncollide2d as ncollide;
#[cfg(feature = "dim3")]
extern crate ncollide3d as ncollide;
extern crate num_traits as num;
extern crate slab;

/*
 * The two following crates are pulled-in for
 * measuring time.
 */
#[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))]
extern crate time;

#[cfg(all(
  any(target_arch = "wasm32", target_arch = "asmjs"),
  feature = "stdweb",
))]
#[macro_use]
extern crate stdweb;

#[cfg(all(
  any(target_arch = "wasm32", target_arch = "asmjs"),
  feature = "use-wasm-bindgen",
))]
extern crate wasm_bindgen;

//#[cfg(test)]
//extern crate test;

pub mod algebra;
pub mod counters;
pub mod detection;
pub mod force_generator;
pub mod joint;
pub mod object;
pub mod solver;
pub mod utils;
pub mod volumetric;
pub mod world;
// mod tests;

/// Compilation flags dependent aliases for mathematical types.
#[cfg(feature = "dim3")]
pub mod math {
  use algebra::{Force3, Inertia3, Velocity3};
  use na::{
    Dynamic, Isometry3, Matrix3, Matrix6, MatrixMN, MatrixSlice6xX, MatrixSliceMut6xX, Point3,
    Translation3, UnitQuaternion, Vector3, Vector6, U3, U6,
  };

  /// The maximum number of possible rotations and translations of a rigid body.
  pub const SPATIAL_DIM: usize = 6;
  /// The maximum number of possible rotations of a rigid body.
  pub const ANGULAR_DIM: usize = 3;
  /// The maximum number of possible translations of a rigid body.
  pub const DIM: usize = 3;

  /// The dimension of the ambiant space.
  pub type Dim = U3;

  /// The dimension of a spatial vector.
  pub type SpatialDim = U6;

  /// The dimension of the rotations.
  pub type AngularDim = U3;

  /// The point type.
  pub type Point<N> = Point3<N>;

  /// The angular vector type.
  pub type AngularVector<N> = Vector3<N>;

  /// The vector type.
  pub type Vector<N> = Vector3<N>;

  /// The vector type with dimension `SpatialDim × 1`.
  pub type SpatialVector<N> = Vector6<N>;

  /// The orientation type.
  pub type Orientation<N> = Vector3<N>;

  /// The transformation matrix type.
  pub type Isometry<N> = Isometry3<N>;

  /// The rotation matrix type.
  pub type Rotation<N> = UnitQuaternion<N>;

  /// The translation type.
  pub type Translation<N> = Translation3<N>;

  /// The velocity type combining the linear velocity and the angular velocity.
  pub type Velocity<N> = Velocity3<N>;

  /// The force type combining a linear force and a torque.
  pub type Force<N> = Force3<N>;

  /// The inertia tensor type.
  pub type AngularInertia<N> = Matrix3<N>;

  /// The inertia type.
  pub type Inertia<N> = Inertia3<N>;

  /// The inertia matrix type.
  pub type InertiaMatrix<N> = Matrix6<N>;

  /// Square matrix with dimension `SpatialDim × SpatialDim`.
  pub type SpatialMatrix<N> = Matrix6<N>;

  /// The type of a constraint jacobian in twist coordinates.
  pub type Jacobian<N> = MatrixMN<N, U6, Dynamic>;

  /// The type of a slice of the constraint jacobian in twist coordinates.
  pub type JacobianSlice<'a, N> = MatrixSlice6xX<'a, N>;

  /// The type of a mutable slice of the constraint jacobian in twist coordinates.
  pub type JacobianSliceMut<'a, N> = MatrixSliceMut6xX<'a, N>;
}

/// Compilation flags dependent aliases for mathematical types.
#[cfg(feature = "dim2")]
pub mod math {
  use algebra::{Force2, Inertia2, Velocity2};
  use na::{
    Dynamic, Isometry2, Matrix1, Matrix3, MatrixMN, MatrixSlice3xX, MatrixSliceMut3xX, Point2,
    Translation2, UnitComplex, Vector1, Vector2, Vector3, U1, U2, U3,
  };

  /// The maximum number of possible rotations and translations of a rigid body.
  pub const SPATIAL_DIM: usize = 3;
  /// The maximum number of possible rotations of a rigid body.
  pub const ANGULAR_DIM: usize = 1;
  /// The maximum number of possible translations of a rigid body.
  pub const DIM: usize = 2;

  /// The dimension of the ambiant space.
  pub type Dim = U2;

  /// The dimension of the rotation.
  pub type AngularDim = U1;

  /// The dimension of a spatial vector.
  pub type SpatialDim = U3;

  /// The point type.
  pub type Point<N> = Point2<N>;

  /// The vector type with dimension `SpatialDim × 1`.
  pub type SpatialVector<N> = Vector3<N>;

  /// The angular vector type.
  pub type AngularVector<N> = Vector1<N>;

  /// The vector type.
  pub type Vector<N> = Vector2<N>;

  /// The orientation type.
  pub type Orientation<N> = Vector1<N>;

  /// The transformation matrix type.
  pub type Isometry<N> = Isometry2<N>;

  /// The rotation matrix type.
  pub type Rotation<N> = UnitComplex<N>;

  /// The translation type.
  pub type Translation<N> = Translation2<N>;

  /// The velocity type combining the linear velocity and the angular velocity.
  pub type Velocity<N> = Velocity2<N>;

  /// The force type combining a linear force and a torque.
  pub type Force<N> = Force2<N>;

  /// The inertia tensor type.
  pub type AngularInertia<N> = Matrix1<N>;

  /// The inertia type.
  pub type Inertia<N> = Inertia2<N>;

  /// The inertia matrix type.
  pub type InertiaMatrix<N> = Matrix3<N>;

  /// Square matrix with dimension `SpatialDim × SpatialDim`.
  pub type SpatialMatrix<N> = Matrix3<N>;

  /// The type of a constraint jacobian in twist coordinates.
  pub type Jacobian<N> = MatrixMN<N, U3, Dynamic>;

  /// The type of a slice of the constraint jacobian in twist coordinates.
  pub type JacobianSlice<'a, N> = MatrixSlice3xX<'a, N>;

  /// The type of a mutable slice of the constraint jacobian in twist coordinates.
  pub type JacobianSliceMut<'a, N> = MatrixSliceMut3xX<'a, N>;
}
<commit_msg>increment version number in lib docs<commit_after>/*!
nphysics
========
**nphysics** is a 2 and 3-dimensional physics engine for games and animations.
It uses [ncollide](http://ncollide.org) for collision detection, and
[nalgebra](http://nalgebra.org) for vector/matrix math. 2D and 3D
implementations both share the same code!

Examples are available in the `examples2d` and `examples3d` directories. There
is also a short (outdated) [demonstration video](http://youtu.be/CANjXZ5rocI).
An on-line version of this documentation is available
[here](http://nphysics.org). Feel free to ask for help and discuss features on
the official [user forum](http://users.nphysics.org).

## Why another physics engine?
There are a lot of physics engine out there.
However having a physics engine written in Rust is much more fun than
writing bindings and has several advantages:

- it shows that Rust is suitable for soft real-time applications
- it shows how well Rust behaves with highly generic code
- it shows that there is no need to write two separate engine for 2D and 3D:
  genericity wrt the dimension is possible (modulo low level arithmetic
  specializations for each dimension).
- in a not-that-near future, C++ will die of ugliness. Then, people will
  search for a physics engine and **nphysics** will be there, proudly
  exhibiting its _Rusty_ sexyness.

## Compilation
You will need the latest release of the [Rust compiler](http://www.rust-lang.org)
and the official package manager: [Cargo](https://github.com/rust-lang/cargo).

If you want to use the 2D version of `nphysics`, add the crate named
`nphysics2d` to your dependencies:

```ignore
[dependencies]
nphysics2d = "0.9"
```

For the 3D version, add the crate named `nphysics3d`:

```ignore
[dependencies]
nphysics3d = "0.9"
```

Use `make examples` to build the demos and execute `./your_favorite_example_here --help`
to see all the cool stuffs you can do.

## Features
- Static and dynamic rigid bodies.
- Common convex primitives: cone, box, ball, cylinder.
- Concave geometries build from convex primitives (aka. compound geometries).
- Stable stacking.
- Island based sleeping (objects deactivation).
- Ray casting.
- Swept sphere based continuous collision detection.
- Ball-in-socket joint.
- FixedJoint joint.
- Sensors.

## What is missing?
**nphysics** is a very young library and needs to learn a lot of things to
become a grown up. Many missing features are because of missing features on
**ncollide**. Features missing from **nphysics** itself include:

- efficient signaling system
- more joints, joint limits, joint motors and breakable joints.
- soft-bodies (see https://github.com/natal/roft for a draft)
- parallel pipeline
- GPU-based pipeline

## Dependencies
All dependencies are automatically cloned with a recursive clone.
The libraries needed to compile the physics engine are:

* [ncollide](http://ncollide.org): the collision detection library.
* [nalgebra](http://nalgebra.org): the linear algebra library.

The libraries needed to compile the examples are:

*/
#![deny(non_camel_case_types)]
#![deny(unused_parens)]
#![deny(non_upper_case_globals)]
#![deny(unused_qualifications)]
#![deny(missing_docs)]
#![deny(unused_results)]
#![warn(non_camel_case_types)]
#![allow(missing_copy_implementations)]
#![doc(html_root_url = "http://nphysics.org/rustdoc/")]

#[macro_use]
extern crate approx;
#[macro_use]
extern crate downcast;

extern crate alga;
extern crate nalgebra as na;
#[cfg(feature = "dim2")]
extern crate ncollide2d as ncollide;
#[cfg(feature = "dim3")]
extern crate ncollide3d as ncollide;
extern crate num_traits as num;
extern crate slab;

/*
 * The two following crates are pulled-in for
 * measuring time.
 */
#[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))]
extern crate time;

#[cfg(all(
  any(target_arch = "wasm32", target_arch = "asmjs"),
  feature = "stdweb",
))]
#[macro_use]
extern crate stdweb;

#[cfg(all(
  any(target_arch = "wasm32", target_arch = "asmjs"),
  feature = "use-wasm-bindgen",
))]
extern crate wasm_bindgen;

//#[cfg(test)]
//extern crate test;

pub mod algebra;
pub mod counters;
pub mod detection;
pub mod force_generator;
pub mod joint;
pub mod object;
pub mod solver;
pub mod utils;
pub mod volumetric;
pub mod world;
// mod tests;

/// Compilation flags dependent aliases for mathematical types.
#[cfg(feature = "dim3")]
pub mod math {
  use algebra::{Force3, Inertia3, Velocity3};
  use na::{
    Dynamic, Isometry3, Matrix3, Matrix6, MatrixMN, MatrixSlice6xX, MatrixSliceMut6xX, Point3,
    Translation3, UnitQuaternion, Vector3, Vector6, U3, U6,
  };

  /// The maximum number of possible rotations and translations of a rigid body.
  pub const SPATIAL_DIM: usize = 6;
  /// The maximum number of possible rotations of a rigid body.
  pub const ANGULAR_DIM: usize = 3;
  /// The maximum number of possible translations of a rigid body.
  pub const DIM: usize = 3;

  /// The dimension of the ambiant space.
  pub type Dim = U3;

  /// The dimension of a spatial vector.
  pub type SpatialDim = U6;

  /// The dimension of the rotations.
  pub type AngularDim = U3;

  /// The point type.
  pub type Point<N> = Point3<N>;

  /// The angular vector type.
  pub type AngularVector<N> = Vector3<N>;

  /// The vector type.
  pub type Vector<N> = Vector3<N>;

  /// The vector type with dimension `SpatialDim × 1`.
  pub type SpatialVector<N> = Vector6<N>;

  /// The orientation type.
  pub type Orientation<N> = Vector3<N>;

  /// The transformation matrix type.
  pub type Isometry<N> = Isometry3<N>;

  /// The rotation matrix type.
  pub type Rotation<N> = UnitQuaternion<N>;

  /// The translation type.
  pub type Translation<N> = Translation3<N>;

  /// The velocity type combining the linear velocity and the angular velocity.
  pub type Velocity<N> = Velocity3<N>;

  /// The force type combining a linear force and a torque.
  pub type Force<N> = Force3<N>;

  /// The inertia tensor type.
  pub type AngularInertia<N> = Matrix3<N>;

  /// The inertia type.
  pub type Inertia<N> = Inertia3<N>;

  /// The inertia matrix type.
  pub type InertiaMatrix<N> = Matrix6<N>;

  /// Square matrix with dimension `SpatialDim × SpatialDim`.
  pub type SpatialMatrix<N> = Matrix6<N>;

  /// The type of a constraint jacobian in twist coordinates.
  pub type Jacobian<N> = MatrixMN<N, U6, Dynamic>;

  /// The type of a slice of the constraint jacobian in twist coordinates.
  pub type JacobianSlice<'a, N> = MatrixSlice6xX<'a, N>;

  /// The type of a mutable slice of the constraint jacobian in twist coordinates.
  pub type JacobianSliceMut<'a, N> = MatrixSliceMut6xX<'a, N>;
}

/// Compilation flags dependent aliases for mathematical types.
#[cfg(feature = "dim2")]
pub mod math {
  use algebra::{Force2, Inertia2, Velocity2};
  use na::{
    Dynamic, Isometry2, Matrix1, Matrix3, MatrixMN, MatrixSlice3xX, MatrixSliceMut3xX, Point2,
    Translation2, UnitComplex, Vector1, Vector2, Vector3, U1, U2, U3,
  };

  /// The maximum number of possible rotations and translations of a rigid body.
  pub const SPATIAL_DIM: usize = 3;
  /// The maximum number of possible rotations of a rigid body.
  pub const ANGULAR_DIM: usize = 1;
  /// The maximum number of possible translations of a rigid body.
  pub const DIM: usize = 2;

  /// The dimension of the ambiant space.
  pub type Dim = U2;

  /// The dimension of the rotation.
  pub type AngularDim = U1;

  /// The dimension of a spatial vector.
  pub type SpatialDim = U3;

  /// The point type.
  pub type Point<N> = Point2<N>;

  /// The vector type with dimension `SpatialDim × 1`.
  pub type SpatialVector<N> = Vector3<N>;

  /// The angular vector type.
  pub type AngularVector<N> = Vector1<N>;

  /// The vector type.
  pub type Vector<N> = Vector2<N>;

  /// The orientation type.
  pub type Orientation<N> = Vector1<N>;

  /// The transformation matrix type.
  pub type Isometry<N> = Isometry2<N>;

  /// The rotation matrix type.
  pub type Rotation<N> = UnitComplex<N>;

  /// The translation type.
  pub type Translation<N> = Translation2<N>;

  /// The velocity type combining the linear velocity and the angular velocity.
  pub type Velocity<N> = Velocity2<N>;

  /// The force type combining a linear force and a torque.
  pub type Force<N> = Force2<N>;

  /// The inertia tensor type.
  pub type AngularInertia<N> = Matrix1<N>;

  /// The inertia type.
  pub type Inertia<N> = Inertia2<N>;

  /// The inertia matrix type.
  pub type InertiaMatrix<N> = Matrix3<N>;

  /// Square matrix with dimension `SpatialDim × SpatialDim`.
  pub type SpatialMatrix<N> = Matrix3<N>;

  /// The type of a constraint jacobian in twist coordinates.
  pub type Jacobian<N> = MatrixMN<N, U3, Dynamic>;

  /// The type of a slice of the constraint jacobian in twist coordinates.
  pub type JacobianSlice<'a, N> = MatrixSlice3xX<'a, N>;

  /// The type of a mutable slice of the constraint jacobian in twist coordinates.
  pub type JacobianSliceMut<'a, N> = MatrixSliceMut3xX<'a, N>;
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate mopa;
extern crate pulse;
extern crate threadpool;
extern crate fnv;

use std::any::TypeId;
use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
use mopa::Any;
use pulse::{Pulse, Signal};
use threadpool::ThreadPool;

pub use storage::{Storage, StorageBase, VecStorage, HashMapStorage};

mod storage;

/// Index generation. When a new entity is placed at the old index,
/// it bumps the generation by 1. This allows to avoid using components
/// from the entities that were deleted.
/// G<=0 - the entity of generation G is dead
/// G >0 - the entity of generation G is alive
pub type Generation = i32;
/// Index type is arbitrary. It doesn't show up in any interfaces.
/// Keeping it 32bit allows for a single 64bit word per entity.
pub type Index = u32;
/// Entity type, as seen by the user.
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct Entity(Index, Generation);

impl Entity {
    #[cfg(test)]
    /// Create a new entity (externally from ECS)
    pub fn new(index: u32, gen: i32) -> Entity {
        Entity(index, gen)
    }

    /// Get the index of the entity.
    pub fn get_id(&self) -> usize { self.0 as usize }
    /// Get the generation of the entity.
    pub fn get_gen(&self) -> Generation { self.1 }
}

/// A custom entity iterator. Needed because the world doesn't really store
/// entities directly, but rather has just a vector of Index -> Generation.
pub struct EntityIter<'a> {
    guard: RwLockReadGuard<'a, Vec<Generation>>,
    index: usize,
}

impl<'a> Iterator for EntityIter<'a> {
    type Item = Entity;
    fn next(&mut self) -> Option<Entity> {
        loop {
            match self.guard.get(self.index) {
                Some(&gen) if gen > 0 => {
                    let ent = Entity(self.index as Index, gen);
                    self.index += 1;
                    return Some(ent)
                },
                Some(_) => self.index += 1, // continue
                None => return None,
            }
        }
    }
}

/// Abstract component type. Doesn't have to be Copy or even Clone.
pub trait Component: Any + Sized {
    type Storage: Storage<Self> + Any + Send + Sync;
}

trait StorageLock: Any + Send + Sync {
    fn del_slice(&self, &[Entity]);
}

mopafy!(StorageLock);

impl<S: StorageBase + Any + Send + Sync> StorageLock for RwLock<S> {
    fn del_slice(&self, entities: &[Entity]) {
        let mut guard = self.write().unwrap();
        for &e in entities.iter() {
            guard.del(e);
        }
    }
}

/// The world struct contains all the data, which is entities and their components.
/// The methods are supposed to be valid for any context they are available in.
pub struct World {
    generations: RwLock<Vec<Generation>>,
    components: HashMap<TypeId, Box<StorageLock>>,
}

impl World {
    /// Create a new empty world.
    pub fn new() -> World {
        World {
            generations: RwLock::new(Vec::new()),
            components: HashMap::new(),
        }
    }
    /// Register a new component type.
    pub fn register<T: Component>(&mut self) {
        let any = RwLock::new(T::Storage::new());
        self.components.insert(TypeId::of::<T>(), Box::new(any));
    }
    /// Unregister a component type.
    pub fn unregister<T: Component>(&mut self) -> Option<T::Storage> {
        self.components.remove(&TypeId::of::<T>()).map(|boxed|
            match boxed.downcast::<RwLock<T::Storage>>() {
                Ok(b) => (*b).into_inner().unwrap(),
                Err(_) => panic!("Unable to downcast the storage type"),
            }
        )
    }
    fn lock<T: Component>(&self) -> &RwLock<T::Storage> {
        let boxed = self.components.get(&TypeId::of::<T>()).unwrap();
        boxed.downcast_ref().unwrap()
    }
    /// Lock a component for reading.
    pub fn read<'a, T: Component>(&'a self) -> RwLockReadGuard<'a, T::Storage> {
        self.lock::<T>().read().unwrap()
    }
    /// Lock a component for writing.
    pub fn write<'a, T: Component>(&'a self) -> RwLockWriteGuard<'a, T::Storage> {
        self.lock::<T>().write().unwrap()
    }
    /// Return the entity iterator.
    pub fn entities<'a>(&'a self) -> EntityIter<'a> {
        EntityIter {
            guard: self.generations.read().unwrap(),
            index: 0,
        }
    }
}

/// World argument for a system closure.
pub struct WorldArg(Arc<World>, RefCell<Option<Pulse>>);

impl WorldArg {
    /// Borrows the world, allowing the system lock some components and get the entity
    /// iterator. Has to be called only once. Fires a pulse at the end.
    pub fn fetch<'a, U, F>(&'a self, f: F) -> U
        where F: FnOnce(&'a World) -> U
    {
        let pulse = self.1.borrow_mut().take().expect("fetch may only be called once.");
        let u = f(&self.0);
        pulse.pulse();
        u
    }
}

/// Helper builder for entities.
pub struct EntityBuilder<'a>(Entity, &'a World);

impl<'a> EntityBuilder<'a> {
    /// Add a component value to the new entity.
    pub fn with<T: Component>(self, value: T) -> EntityBuilder<'a> {
        self.1.write::<T>().insert(self.0, value);
        self
    }
    /// Finish entity construction.
    pub fn build(self) -> Entity {
        self.0
    }
}

pub struct Scheduler {
    world: Arc<World>,
    threads: ThreadPool,
    first_free: Index,
}

fn find_free<'a>(mut gens: RwLockWriteGuard<'a, Vec<Generation>>, base: usize) -> Index {
    match gens[base..].iter().position(|g| *g <= 0) {
        Some(pos) => (base + pos) as Index,
        None => {
            gens.push(0);
            (gens.len() - 1) as Index
        },
    }
}

impl Scheduler {
    pub fn new(world: World, num_threads: usize) -> Scheduler {
        let ff = find_free(world.generations.write().unwrap(), 0);
        Scheduler {
            world: Arc::new(world),
            threads: ThreadPool::new(num_threads),
            first_free: ff,
        }
    }
    pub fn get_world(&self) -> &World {
        //println!("{:?}", &*self.world.generations.read().unwrap());
        &self.world
    }
    pub fn run<F>(&mut self, functor: F) where
        F: 'static + Send + FnOnce(WorldArg)
    {
        let (signal, pulse) = Signal::new();
        let world = self.world.clone();
        self.threads.execute(|| {
            let warg = WorldArg(world, RefCell::new(Some(pulse)));
            functor(warg);
        });
        signal.wait().unwrap();
    }
    pub fn add_entity<'a>(&'a mut self) -> EntityBuilder<'a> {
        let mut gens = self.world.generations.write().unwrap();
        let ent = {
            let gen = &mut gens[self.first_free as usize];
            assert!(*gen <= 0);
            *gen = 1 - *gen;
            Entity(self.first_free, *gen)
        };
        self.first_free = find_free(gens, (self.first_free + 1) as usize);
        EntityBuilder(ent, &self.world)
    }
    pub fn del_entity(&mut self, entity: Entity) {
        for boxed in self.world.components.values() {
            boxed.del_slice(&[entity]);
        }
        let mut gens = self.world.generations.write().unwrap();
        let mut gen = &mut gens[entity.get_id() as usize];
        assert!(*gen > 0);
        *gen *= -1;
    }
    pub fn wait(&self) {
        while self.threads.active_count() > 0 {} //TODO
    }
}

macro_rules! impl_run {
    ($name:ident [$( $write:ident ),*] [$( $read:ident ),*]) => (impl Scheduler {
        #[allow(non_snake_case, unused_mut)]
        pub fn $name<
            $($write:Component,)* $($read:Component,)*
            F: 'static + Send + FnMut( $(&mut $write,)* $(&$read,)* )
        >(&mut self, functor: F) {
            self.run(|warg| {
                let mut fun = functor;
                let ($(mut $write,)* $($read,)* entities) = warg.fetch(|w|
                    ($(w.write::<$write>(),)*
                     $(w.read::<$read>(),)*
                       w.entities())
                );
                for ent in entities {
                    if let ( $( Some($write), )* $( Some($read), )* ) =
                        ( $( $write.get_mut(ent), )* $( $read.get(ent), )* ) {
                        fun( $($write,)* $($read,)* );
                    }
                }
            });
        }
    })
}

impl_run!( run0w1r [] [R0] );
impl_run!( run0w2r [] [R0, R1] );
impl_run!( run1w0r [W0] [] );
impl_run!( run1w1r [W0] [R0] );
impl_run!( run1w2r [W0] [R0, R1] );
impl_run!( run1w3r [W0] [R0, R1, R2] );
impl_run!( run1w4r [W0] [R0, R1, R2, R3] );
impl_run!( run1w5r [W0] [R0, R1, R2, R3, R4] );
impl_run!( run1w6r [W0] [R0, R1, R2, R3, R4, R5] );
impl_run!( run1w7r [W0] [R0, R1, R2, R3, R5, R6, R7] );
impl_run!( run2w0r [W0, W1] [] );
impl_run!( run2w1r [W0, W1] [R0] );
impl_run!( run2w2r [W0, W1] [R0, R1] );
<commit_msg>Introduced Appendix with next Entity instead of next_free index<commit_after>#[macro_use]
extern crate mopa;
extern crate pulse;
extern crate threadpool;
extern crate fnv;

use std::any::TypeId;
use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
use mopa::Any;
use pulse::{Pulse, Signal};
use threadpool::ThreadPool;

pub use storage::{Storage, StorageBase, VecStorage, HashMapStorage};

mod storage;

/// Index generation. When a new entity is placed at the old index,
/// it bumps the generation by 1. This allows to avoid using components
/// from the entities that were deleted.
/// G<=0 - the entity of generation G is dead
/// G >0 - the entity of generation G is alive
pub type Generation = i32;
/// Index type is arbitrary. It doesn't show up in any interfaces.
/// Keeping it 32bit allows for a single 64bit word per entity.
pub type Index = u32;
/// Entity type, as seen by the user.
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
pub struct Entity(Index, Generation);

impl Entity {
    #[cfg(test)]
    /// Create a new entity (externally from ECS)
    pub fn new(index: u32, gen: i32) -> Entity {
        Entity(index, gen)
    }

    /// Get the index of the entity.
    pub fn get_id(&self) -> usize { self.0 as usize }
    /// Get the generation of the entity.
    pub fn get_gen(&self) -> Generation { self.1 }
}

/// A custom entity iterator. Needed because the world doesn't really store
/// entities directly, but rather has just a vector of Index -> Generation.
pub struct EntityIter<'a> {
    guard: RwLockReadGuard<'a, Vec<Generation>>,
    index: usize,
}

impl<'a> Iterator for EntityIter<'a> {
    type Item = Entity;
    fn next(&mut self) -> Option<Entity> {
        loop {
            match self.guard.get(self.index) {
                Some(&gen) if gen > 0 => {
                    let ent = Entity(self.index as Index, gen);
                    self.index += 1;
                    return Some(ent)
                },
                Some(_) => self.index += 1, // continue
                None => return None,
            }
        }
    }
}

/// Abstract component type. Doesn't have to be Copy or even Clone.
pub trait Component: Any + Sized {
    type Storage: Storage<Self> + Any + Send + Sync;
}

trait StorageLock: Any + Send + Sync {
    fn del_slice(&self, &[Entity]);
}

mopafy!(StorageLock);

impl<S: StorageBase + Any + Send + Sync> StorageLock for RwLock<S> {
    fn del_slice(&self, entities: &[Entity]) {
        let mut guard = self.write().unwrap();
        for &e in entities.iter() {
            guard.del(e);
        }
    }
}

/// The world struct contains all the data, which is entities and their components.
/// The methods are supposed to be valid for any context they are available in.
pub struct World {
    generations: RwLock<Vec<Generation>>,
    components: HashMap<TypeId, Box<StorageLock>>,
}

impl World {
    /// Create a new empty world.
    pub fn new() -> World {
        World {
            generations: RwLock::new(Vec::new()),
            components: HashMap::new(),
        }
    }
    /// Register a new component type.
    pub fn register<T: Component>(&mut self) {
        let any = RwLock::new(T::Storage::new());
        self.components.insert(TypeId::of::<T>(), Box::new(any));
    }
    /// Unregister a component type.
    pub fn unregister<T: Component>(&mut self) -> Option<T::Storage> {
        self.components.remove(&TypeId::of::<T>()).map(|boxed|
            match boxed.downcast::<RwLock<T::Storage>>() {
                Ok(b) => (*b).into_inner().unwrap(),
                Err(_) => panic!("Unable to downcast the storage type"),
            }
        )
    }
    fn lock<T: Component>(&self) -> &RwLock<T::Storage> {
        let boxed = self.components.get(&TypeId::of::<T>()).unwrap();
        boxed.downcast_ref().unwrap()
    }
    /// Lock a component for reading.
    pub fn read<'a, T: Component>(&'a self) -> RwLockReadGuard<'a, T::Storage> {
        self.lock::<T>().read().unwrap()
    }
    /// Lock a component for writing.
    pub fn write<'a, T: Component>(&'a self) -> RwLockWriteGuard<'a, T::Storage> {
        self.lock::<T>().write().unwrap()
    }
    /// Return the entity iterator.
    pub fn entities<'a>(&'a self) -> EntityIter<'a> {
        EntityIter {
            guard: self.generations.read().unwrap(),
            index: 0,
        }
    }
    fn find_next(&self, base: usize) -> Entity {
        let gens = self.generations.read().unwrap();
        match gens.iter().enumerate().skip(base).find(|&(_, g)| *g <= 0) {
            Some((id, gen)) => Entity(id as Index, 1 - gen),
            None => Entity(gens.len() as Index, 1),
        }
    }
}

/// World argument for a system closure.
pub struct WorldArg(Arc<World>, RefCell<Option<Pulse>>);

impl WorldArg {
    /// Borrows the world, allowing the system lock some components and get the entity
    /// iterator. Has to be called only once. Fires a pulse at the end.
    pub fn fetch<'a, U, F>(&'a self, f: F) -> U
        where F: FnOnce(&'a World) -> U
    {
        let pulse = self.1.borrow_mut().take().expect("fetch may only be called once.");
        let u = f(&self.0);
        pulse.pulse();
        u
    }
}

/// Helper builder for entities.
pub struct EntityBuilder<'a>(Entity, &'a World);

impl<'a> EntityBuilder<'a> {
    /// Add a component value to the new entity.
    pub fn with<T: Component>(self, value: T) -> EntityBuilder<'a> {
        self.1.write::<T>().insert(self.0, value);
        self
    }
    /// Finish entity construction.
    pub fn build(self) -> Entity {
        self.0
    }
}

struct Appendix {
    next: Entity,
    queue: Vec<Entity>,
}

pub struct Scheduler {
    world: Arc<World>,
    threads: ThreadPool,
    appendix: RwLock<Appendix>,
}

impl Scheduler {
    pub fn new(world: World, num_threads: usize) -> Scheduler {
        let next = Appendix {
            next: world.find_next(0),
            queue: Vec::new(),
        };
        Scheduler {
            world: Arc::new(world),
            threads: ThreadPool::new(num_threads),
            appendix: RwLock::new(next),
        }
    }
    pub fn get_world(&self) -> &World {
        //println!("{:?}", &*self.world.generations.read().unwrap());
        &self.world
    }
    pub fn run<F>(&mut self, functor: F) where
        F: 'static + Send + FnOnce(WorldArg)
    {
        let (signal, pulse) = Signal::new();
        let world = self.world.clone();
        self.threads.execute(|| {
            let warg = WorldArg(world, RefCell::new(Some(pulse)));
            functor(warg);
        });
        signal.wait().unwrap();
    }
    pub fn add_entity<'a>(&'a mut self) -> EntityBuilder<'a> {
        let mut appendix = self.appendix.write().unwrap();
        let ent = appendix.next;
        assert!(ent.get_gen() > 0);
        if ent.get_gen() == 1 {
            let mut gens = self.world.generations.write().unwrap();
            assert!(gens.len() == ent.get_id());
            gens.push(ent.get_gen());
        }
        appendix.next = self.world.find_next(ent.get_id() + 1);
        EntityBuilder(ent, &self.world)
    }
    pub fn del_entity(&mut self, entity: Entity) {
        for boxed in self.world.components.values() {
            boxed.del_slice(&[entity]);
        }
        let mut gens = self.world.generations.write().unwrap();
        let mut gen = &mut gens[entity.get_id() as usize];
        assert!(*gen > 0);
        let mut appendix = self.appendix.write().unwrap();
        if entity.get_id() < appendix.next.get_id() {
            appendix.next = Entity(entity.0, *gen+1);
        }
        *gen *= -1;
    }
    pub fn wait(&self) {
        while self.threads.active_count() > 0 {} //TODO
    }
}

macro_rules! impl_run {
    ($name:ident [$( $write:ident ),*] [$( $read:ident ),*]) => (impl Scheduler {
        #[allow(non_snake_case, unused_mut)]
        pub fn $name<
            $($write:Component,)* $($read:Component,)*
            F: 'static + Send + FnMut( $(&mut $write,)* $(&$read,)* )
        >(&mut self, functor: F) {
            self.run(|warg| {
                let mut fun = functor;
                let ($(mut $write,)* $($read,)* entities) = warg.fetch(|w|
                    ($(w.write::<$write>(),)*
                     $(w.read::<$read>(),)*
                       w.entities())
                );
                for ent in entities {
                    if let ( $( Some($write), )* $( Some($read), )* ) =
                        ( $( $write.get_mut(ent), )* $( $read.get(ent), )* ) {
                        fun( $($write,)* $($read,)* );
                    }
                }
            });
        }
    })
}

impl_run!( run0w1r [] [R0] );
impl_run!( run0w2r [] [R0, R1] );
impl_run!( run1w0r [W0] [] );
impl_run!( run1w1r [W0] [R0] );
impl_run!( run1w2r [W0] [R0, R1] );
impl_run!( run1w3r [W0] [R0, R1, R2] );
impl_run!( run1w4r [W0] [R0, R1, R2, R3] );
impl_run!( run1w5r [W0] [R0, R1, R2, R3, R4] );
impl_run!( run1w6r [W0] [R0, R1, R2, R3, R4, R5] );
impl_run!( run1w7r [W0] [R0, R1, R2, R3, R5, R6, R7] );
impl_run!( run2w0r [W0, W1] [] );
impl_run!( run2w1r [W0, W1] [R0] );
impl_run!( run2w2r [W0, W1] [R0, R1] );
<|endoftext|>


<commit_before>/// We use this numerical type for all calculations.
pub type Num = f32;

/// Represents the state of a neuron.
#[derive(Copy, Clone)]
pub struct State {
    /// membrane potential of neuron (in mV)
    v: Num,

    /// recovery variable
    u: Num
}

impl State {
    pub fn new() -> State {
        State {
            v: -70.0,
            u: -14.0
        }
    }
    pub fn potential(&self) -> Num {
        self.v
    }
}

/// The neuron configuration parameters.
pub struct Config {
    /// Rate of recovery.
    a: Num,

    /// Sensitivity of recovery variable `u` to the membrane potential `v`.
    b: Num,

    /// After-spike reset value of membrane potential `v`.
    c: Num,

    /// After-spike reset of recovery variable `u`.
    d: Num
}

impl Config {
    /// Generates an excitatory neuron configuration according to Izhikevich's paper [reentry]
    /// where `r` is a random variable uniformly distributed in [0, 1].
    pub fn excitatory(r: Num) -> Config {
        debug_assert!(r >= 0.0 && r <= 1.0);

        let r2 = r*r;
        Config {
            a: 0.02,
            b: 0.2,
            c: -65.0 + 15.0 * r2,
            d: 8.0 - 6.0 * r2
        }
    }

    pub fn inhibitory(r: Num) -> Config {
        debug_assert!(r >= 0.0 && r <= 1.0);

        Config {
            a: 0.02 + 0.08 * r,
            b: 0.25 - 0.05 * r,
            c: -65.0,
            d: 2.0
        }
    }

    /// Regular spiking (RS) cell configuration.
    pub fn regular_spiking() -> Config {
        Config::excitatory(0.0)
    }

    /// Chattering (CH) cell configuration.
    pub fn chattering() -> Config {
        Config::excitatory(1.0)
    }
}

#[inline(always)]
fn dv(u: Num, v: Num, i_syn: Num) -> Num {
    0.04 * (v*v) + 5.0 * v + 140.0 - u - i_syn
}

#[inline(always)]
fn du(u: Num, v: Num, a: Num, b: Num) -> Num {
    a * (b*v - u)
}

impl State {
    /// Calculate the new state after `dt` ms.
    #[inline(always)]
    pub fn step(self, dt: Num, i_syn: Num, config: &Config) -> State {
        if self.v >= 30.0 {
            State {
                v: config.c,
                u: self.u + config.d
            }
        }
        else {
            State {
                v: self.v + dt*dv(self.u, self.v, i_syn),
                u: self.u + dt*du(self.u, self.v, config.a, config.b)
            }
        }
    }
}
<commit_msg>Reverse if<commit_after>/// We use this numerical type for all calculations.
pub type Num = f32;

/// Represents the state of a neuron.
#[derive(Copy, Clone)]
pub struct State {
    /// membrane potential of neuron (in mV)
    v: Num,

    /// recovery variable
    u: Num
}

impl State {
    pub fn new() -> State {
        State {
            v: -70.0,
            u: -14.0
        }
    }
    pub fn potential(&self) -> Num {
        self.v
    }
}

/// The neuron configuration parameters.
pub struct Config {
    /// Rate of recovery.
    a: Num,

    /// Sensitivity of recovery variable `u` to the membrane potential `v`.
    b: Num,

    /// After-spike reset value of membrane potential `v`.
    c: Num,

    /// After-spike reset of recovery variable `u`.
    d: Num
}

impl Config {
    /// Generates an excitatory neuron configuration according to Izhikevich's paper [reentry]
    /// where `r` is a random variable uniformly distributed in [0, 1].
    pub fn excitatory(r: Num) -> Config {
        debug_assert!(r >= 0.0 && r <= 1.0);

        let r2 = r*r;
        Config {
            a: 0.02,
            b: 0.2,
            c: -65.0 + 15.0 * r2,
            d: 8.0 - 6.0 * r2
        }
    }

    pub fn inhibitory(r: Num) -> Config {
        debug_assert!(r >= 0.0 && r <= 1.0);

        Config {
            a: 0.02 + 0.08 * r,
            b: 0.25 - 0.05 * r,
            c: -65.0,
            d: 2.0
        }
    }

    /// Regular spiking (RS) cell configuration.
    pub fn regular_spiking() -> Config {
        Config::excitatory(0.0)
    }

    /// Chattering (CH) cell configuration.
    pub fn chattering() -> Config {
        Config::excitatory(1.0)
    }
}

#[inline(always)]
fn dv(u: Num, v: Num, i_syn: Num) -> Num {
    0.04 * (v*v) + 5.0 * v + 140.0 - u - i_syn
}

#[inline(always)]
fn du(u: Num, v: Num, a: Num, b: Num) -> Num {
    a * (b*v - u)
}

impl State {
    /// Calculate the new state after `dt` ms.
    #[inline(always)]
    pub fn step(self, dt: Num, i_syn: Num, config: &Config) -> State {
        if self.v < 30.0 {
            State {
                v: self.v + dt*dv(self.u, self.v, i_syn),
                u: self.u + dt*du(self.u, self.v, config.a, config.b)
            }
        }
        else {
            State {
                v: config.c,
                u: self.u + config.d
            }
        }
    }
}
<|endoftext|>


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

extern crate hyper;
#[cfg(feature = "with-native-tls")]
extern crate hyper_native_tls;
#[cfg(feature = "with-openssl")]
extern crate hyper_openssl;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde_qs;

mod client;
mod error;
mod resources;
mod params;

pub use client::Client;
pub use error::{Error, ErrorCode, ErrorType, RequestError};
pub use params::{List, Metadata, Timestamp};
pub use resources::*;
<commit_msg>Add lib fix<commit_after>// Copyright 2017 Rapidity Networks, Inc.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate hyper;
#[cfg(feature = "with-native-tls")]
extern crate hyper_native_tls;
#[cfg(feature = "with-openssl")]
extern crate hyper_openssl;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde_qs;

mod client;
mod error;
mod resources;
mod params;

pub use client::{Client, Params};
pub use error::{Error, ErrorCode, ErrorType, RequestError};
pub use params::{List, Metadata, Timestamp};
pub use resources::*;
<|endoftext|>


<commit_before>#![feature(type_ascription)]

// TODO core of this crate
// macro_rules! hado {
//     ($v:ident <- $expr:expr;) => {
//         $crate::Monad::bind()
//     }
// }

trait Monad<O> {
    type Inner;
    fn bind<F>(t: Self, f: F) -> O where F: Fn(Self::Inner) -> O ;
    fn ret(Self::Inner) -> Self;
}

impl<T, O> Monad<Option<O>> for Option<T> {
    type Inner = T;
    fn bind<F>(t: Option<T>, f: F) -> Option<O>
        where F: Fn(T) -> Option<O> {
        match t {
            Some(t) => f(t),
            None => None,
        }
    }
    fn ret(inner: T) -> Self {
        Some(inner)
    }
}

impl<T, O, E> Monad<Result<O, E>> for Result<T, E> {
    type Inner = T;
    fn bind<F>(t: Result<T, E>, f: F) -> Result<O, E>
        where F: Fn(T) -> Result<O, E> {
        match t {
            Ok(t) => f(t),
            Err(e) => Err(e),
        }
    }
    fn ret(inner: T) -> Self {
        Ok(inner)
    }
}

impl<T, O> Monad<Vec<O>> for Vec<T> {
    type Inner = T;
    fn bind<F>(t: Self, f: F) -> Vec<O>
        where F: Fn(T) -> Vec<O> {
        let mut acc: Vec<O> = Vec::new();
        for v in t {
            acc.append(&mut f(v))
        }
        acc
    }
    fn ret(inner: T) -> Vec<T> {
        vec![inner]
    }
}

#[cfg(test)]
mod tests {
    use super::Monad;
    #[test] fn option_monad() {
        assert_eq!(
            Some(0),
            Monad::bind(Some(1), |x| Some(x*0))
        );
        assert_eq!(
            None,
            Monad::bind(None, |x: u32| Some(x*0))
        );
    }
    #[test] fn result_monad() {
        assert_eq!(
            Ok(0),
            Monad::<Result<u32, &'static str>>::bind(Ok(1), |x: u32| Ok(x*0))
        );
        assert_eq!(
            Err("failed"),
            Monad::bind(Err("failed"), |x: u32| Ok(x*0))
        );
    }
    #[test] fn list_monad() {
        assert_eq!(
            Vec::new(): Vec<u32>,
            Monad::<Vec<u32>>::bind(Vec::new(), |_: u32| vec![0, 0])
        );
        assert_eq!(
            vec![0, 0, 0, 0]: Vec<u32>,
            Monad::<Vec<u32>>::bind(vec![0, 0], |_: u32| vec![0, 0])
        );
        assert_eq!(
            vec![0, 0, 1, 1, 2, 2]: Vec<u32>,
            Monad::<Vec<u32>>::bind(vec![0, 1, 2], |x: u32| vec![x, x])
        );
    }
}
<commit_msg>Can't believe this actually works<commit_after>#![feature(type_ascription)]

// TODO core of this crate
macro_rules! hado {
    (ret ( $ty:ty ) $expr:expr) => {
        $crate::Monad::< $ty >::ret($expr)
    };
    (ret $expr:expr) => {
        $crate::Monad::ret($expr)
    };
    (ign <- $expr:expr; $($rest:tt)*) => {
        $crate::Monad::bind($expr, |_| hado!($($rest)*))
    };
    ($ident:ident <- $expr:expr; $($rest:tt)*) => {
        $crate::Monad::bind($expr, |$ident| hado!($($rest)*))
    };
    ($stmt:stmt; $($rest:tt)*) => {
        { $stmt ; hado!($($rest)*) }
    };
    ($expr:expr) => {
        $expr
    }
}

trait Monad<O> {
    type Inner;
    fn bind<F>(t: Self, f: F) -> O where F: Fn(Self::Inner) -> O ;
    fn ret(Self::Inner) -> Self;
}

impl<T, O> Monad<Option<O>> for Option<T> {
    type Inner = T;
    fn bind<F>(t: Option<T>, f: F) -> Option<O>
        where F: Fn(T) -> Option<O> {
        match t {
            Some(t) => f(t),
            None => None,
        }
    }
    fn ret(inner: T) -> Self {
        Some(inner)
    }
}

impl<T, O, E> Monad<Result<O, E>> for Result<T, E> {
    type Inner = T;
    fn bind<F>(t: Result<T, E>, f: F) -> Result<O, E>
        where F: Fn(T) -> Result<O, E> {
        match t {
            Ok(t) => f(t),
            Err(e) => Err(e),
        }
    }
    fn ret(inner: T) -> Self {
        Ok(inner)
    }
}

impl<T, O> Monad<Vec<O>> for Vec<T> {
    type Inner = T;
    fn bind<F>(t: Self, f: F) -> Vec<O>
        where F: Fn(T) -> Vec<O> {
        let mut acc: Vec<O> = Vec::new();
        for v in t {
            acc.append(&mut f(v))
        }
        acc
    }
    fn ret(inner: T) -> Vec<T> {
        vec![inner]
    }
}

#[cfg(test)]
mod tests {
    use super::Monad;
    #[test] fn hado() {
        assert_eq!(
            Some(3),
            hado!(
                x <- Some(1);
                y <- Some(2);
                Some(x + y)
            )
        );

        assert_eq!(
            Some(3),
            hado!(
                x <- Some(1);
                println!("yey");
                y <- Some(2);
                Some(x + y)
            )
        );

        assert_eq!(
            vec![0, 0, 1, 1, 2, 2]: Vec<u32>,
            hado!(
                a <- vec![0, 1, 2];
                b <- vec![a, a];
                ret(Vec<u32>) b
            )
        );
        assert_eq!(
            hado!(
                a <- vec![0, 1, 2];
                b <- vec![a, a];
                ret(Vec<u32>) b
            ),
            hado!(
                a <- vec![0, 1, 2];
                vec![a, a]
            )
        );
        assert_eq!(
            hado!(
                ign <- vec![0, 1, 2];
                let b = 7;
                ret(Vec<u32>) b
            ),
            hado!(
                ign <- vec![0, 1, 2];
                vec![7]
            )
        );
    }
    #[test] fn option_monad() {
        assert_eq!(
            Some(0),
            Monad::bind(Some(1), |x| Some(x*0))
        );
        assert_eq!(
            None,
            Monad::bind(None, |x: u32| Some(x*0))
        );
    }
    #[test] fn result_monad() {
        assert_eq!(
            Ok(0),
            Monad::<Result<u32, &'static str>>::bind(Ok(1), |x: u32| Ok(x*0))
        );
        assert_eq!(
            Err("failed"),
            Monad::bind(Err("failed"), |x: u32| Ok(x*0))
        );
    }
    #[test] fn list_monad() {
        assert_eq!(
            Vec::new(): Vec<u32>,
            Monad::<Vec<u32>>::bind(Vec::new(), |_: u32| vec![0, 0])
        );
        assert_eq!(
            vec![0, 0, 0, 0]: Vec<u32>,
            Monad::<Vec<u32>>::bind(vec![0, 0], |_: u32| vec![0, 0])
        );
        assert_eq!(
            vec![0, 0, 1, 1, 2, 2]: Vec<u32>,
            Monad::<Vec<u32>>::bind(vec![0, 1, 2], |x: u32| vec![x, x])
        );
    }
}
<|endoftext|>