<commit_before>//! # Examples
//!
//! ```
//! use objpool::PoolBuilder;
//! use std::thread;
//!
//! let pool = PoolBuilder::new(|| 0).max_items(5).finalize();
//! let mut handles = Vec::new();
//! for _ in 0..10 {
//!     let pool = pool.clone();
//!     handles.push(thread::spawn(move || {
//!         for _ in 0..1000 {
//!             *pool.get() += 1;
//!         }
//!     }));
//! }
//!
//! for handle in handles {
//!     handle.join().unwrap();
//! }
//! assert_eq!(*pool.get() + *pool.get() + *pool.get() + *pool.get() + *pool.get(), 10000);
//! ```

use std::error::Error;
use std::fmt::{self, Debug, Display, Formatter};
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Condvar, Mutex, Weak};
use std::time::{Duration, SystemTime};

pub struct Pool<T, F> where F: Fn() -> T {
    create: F,
    items: Mutex<Items<T>>,
    item_available: Condvar,
    weak_self: Weak<Pool<T, F>>,
}

impl<T, F> Pool<T, F> where F: Fn() -> T {
    pub fn new(create: F) -> Arc<Pool<T, F>> {
        Pool::new_impl(create, None)
    }

    fn new_impl(create: F, max_items: Option<usize>) -> Arc<Pool<T, F>> {
        let pool = Arc::new(Pool {
            create: create,
            items: Mutex::new(Items {
                available: Vec::new(),
                count: 0,
                max: max_items,
            }),
            item_available: Condvar::new(),
            weak_self: Weak::new(),
        });
        unsafe {
            let ptr = &pool.weak_self as *const Weak<Pool<T, F>> as *mut Weak<Pool<T, F>>;
            *ptr = Arc::downgrade(&pool);
        }
        pool
    }

    pub fn get(&self) -> Item<T, F> {
        self.get_impl(None).unwrap()
    }

    pub fn get_timeout(&self, duration: Duration) -> Result<Item<T, F>, TimeoutError> {
        self.get_impl(Some(duration))
    }

    fn get_impl(&self, duration: Option<Duration>) -> Result<Item<T, F>, TimeoutError> {
        let mut items = self.items.lock().unwrap();
        let item = match items.available.pop() {
            Some(item) => item,
            None => {
                if items.count < items.max.unwrap_or(std::usize::MAX) {
                    items.count += 1;
                    drop(items);
                    (self.create)()
                } else {
                    let start = SystemTime::now();
                    while items.available.is_empty() {
                        items = match duration {
                            Some(duration) => {
                                let elapsed = match start.elapsed() {
                                    Ok(elapsed) => elapsed,
                                    Err(_) => Duration::from_secs(0),
                                };
                                if elapsed >= duration {
                                    return Err(TimeoutError);
                                }
                                let (items, wait_result) =
                                    self.item_available.wait_timeout(items, duration - elapsed).unwrap();
                                if wait_result.timed_out() {
                                    return Err(TimeoutError);
                                }
                                items
                            },
                            None => self.item_available.wait(items).unwrap(),
                        }
                    }
                    items.available.pop().unwrap()
                }
            }
        };
        Ok(Item {
            item: Some(item),
            pool: self.weak_self.upgrade().unwrap(),
        })
    }

    fn put(&self, item: T) {
        self.items.lock().unwrap().available.push(item);
        self.item_available.notify_one();
    }
}

impl<T, F> Debug for Pool<T, F> where F: Fn() -> T {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Pool")
            .field("items", &*self.items.lock().unwrap())
            .finish()
    }
}

pub struct PoolBuilder<T, F> where F: Fn() -> T {
    create: F,
    max_items: Option<usize>,
}

impl<T, F> PoolBuilder<T, F> where F: Fn() -> T {
    pub fn new(create: F) -> PoolBuilder<T, F> {
        PoolBuilder { create: create, max_items: None }
    }

    pub fn max_items(mut self, max_items: usize) -> PoolBuilder<T, F> {
        self.max_items = Some(max_items);
        self
    }

    pub fn finalize(self) -> Arc<Pool<T, F>> {
        Pool::new_impl(self.create, self.max_items)
    }
}

struct Items<T> {
    available: Vec<T>,
    count: usize,
    max: Option<usize>,
}

impl<T> Debug for Items<T> {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Items")
            .field("available", &self.available.len())
            .field("count", &self.count)
            .field("max", &self.max)
            .finish()
    }
}

pub struct Item<T, F> where F: Fn() -> T {
    item: Option<T>,
    pool: Arc<Pool<T, F>>,
}

impl<T, F> Debug for Item<T, F> where T: Debug, F: Fn() -> T {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Item")
            .field("item", &self.item)
            .finish()
    }
}

impl<T, F> Deref for Item<T, F> where F: Fn() -> T {
    type Target = T;

    fn deref(&self) -> &T {
        self.item.as_ref().unwrap()
    }
}

impl<T, F> DerefMut for Item<T, F> where F: Fn() -> T {
    fn deref_mut(&mut self) -> &mut T {
        self.item.as_mut().unwrap()
    }
}

impl<T, F> Drop for Item<T, F> where F: Fn() -> T {
    fn drop(&mut self) {
        self.pool.put(self.item.take().unwrap());
    }
}

#[derive(Debug, Eq, PartialEq)]
pub struct TimeoutError;

impl Display for TimeoutError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.write_str("wait timed out")
    }
}

impl Error for TimeoutError {
    fn description(&self) -> &str {
        "wait timed out"
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error;
    use std::time::{Duration, SystemTime};
    use std::thread;
    use super::*;

    trait AsMillis {
        fn as_millis(&self) -> u64;
    }

    impl AsMillis for Duration {
        fn as_millis(&self) -> u64 {
            self.as_secs() * 1000 + self.subsec_nanos() as u64 / 1000000
        }
    }

    #[test]
    fn pool_builder() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let _x = pool.get();
        assert_eq!(pool.get_timeout(Duration::from_secs(0)).err(), Some(TimeoutError));
    }

    #[test]
    fn pool_get() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let x = pool.get();
        let start = SystemTime::now();
        let handle = thread::spawn(move || {
            let _ = pool.get();
        });
        thread::sleep(Duration::from_millis(100));
        drop(x);
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_get_mut() {
        let pool = Pool::new(|| 0);
        *pool.get() = 4;
        assert_eq!(*pool.get(), 4);
    }

    #[test]
    fn pool_get_timeout_ok() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let x = pool.get();
        let start = SystemTime::now();
        let handle = thread::spawn(move || {
            let _ = pool.get_timeout(Duration::from_secs(1)).unwrap();
        });
        thread::sleep(Duration::from_millis(100));
        drop(x);
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_get_timeout_err() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let _x = pool.get();
        let start = SystemTime::now();
        let handle = {
            let pool = pool.clone();
            thread::spawn(move || {
                assert_eq!(pool.get_timeout(Duration::from_millis(100)).err(), Some(TimeoutError));
            })
        };
        while start.elapsed().unwrap().as_millis() < 100 {
            pool.item_available.notify_one();
        }
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_debug() {
        let pool = PoolBuilder::new(|| 0).max_items(5).finalize();
        assert_eq!(format!("{:?}", pool),
            "Pool { items: Items { available: 0, count: 0, max: Some(5) } }");
        let x = pool.get();
        let _y = pool.get();
        let _z = pool.get();
        drop(x);
        assert_eq!(format!("{:?}", pool),
            "Pool { items: Items { available: 1, count: 3, max: Some(5) } }");
    }

    #[test]
    fn item_debug() {
        let pool = Pool::new(|| 0);
        let x = pool.get();
        assert_eq!(format!("{:?}", x), "Item { item: Some(0) }");
    }

    #[test]
    fn timeout_error() {
        assert_eq!(format!("{}", TimeoutError), "wait timed out");
        assert_eq!(TimeoutError.description(), "wait timed out");
    }
}
<commit_msg>simply get implementation<commit_after>//! # Examples
//!
//! ```
//! use objpool::PoolBuilder;
//! use std::thread;
//!
//! let pool = PoolBuilder::new(|| 0).max_items(5).finalize();
//! let mut handles = Vec::new();
//! for _ in 0..10 {
//!     let pool = pool.clone();
//!     handles.push(thread::spawn(move || {
//!         for _ in 0..1000 {
//!             *pool.get() += 1;
//!         }
//!     }));
//! }
//!
//! for handle in handles {
//!     handle.join().unwrap();
//! }
//! assert_eq!(*pool.get() + *pool.get() + *pool.get() + *pool.get() + *pool.get(), 10000);
//! ```

use std::error::Error;
use std::fmt::{self, Debug, Display, Formatter};
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Condvar, Mutex, Weak};
use std::time::{Duration, SystemTime};

pub struct Pool<T, F> where F: Fn() -> T {
    create: F,
    items: Mutex<Items<T>>,
    item_available: Condvar,
    weak_self: Weak<Pool<T, F>>,
}

impl<T, F> Pool<T, F> where F: Fn() -> T {
    pub fn new(create: F) -> Arc<Pool<T, F>> {
        Pool::new_impl(create, None)
    }

    fn new_impl(create: F, max_items: Option<usize>) -> Arc<Pool<T, F>> {
        let pool = Arc::new(Pool {
            create: create,
            items: Mutex::new(Items {
                available: Vec::new(),
                count: 0,
                max: max_items,
            }),
            item_available: Condvar::new(),
            weak_self: Weak::new(),
        });
        unsafe {
            let ptr = &pool.weak_self as *const Weak<Pool<T, F>> as *mut Weak<Pool<T, F>>;
            *ptr = Arc::downgrade(&pool);
        }
        pool
    }

    pub fn get(&self) -> Item<T, F> {
        self.get_impl(None).unwrap()
    }

    pub fn get_timeout(&self, duration: Duration) -> Result<Item<T, F>, TimeoutError> {
        self.get_impl(Some(duration))
    }

    fn get_impl(&self, duration: Option<Duration>) -> Result<Item<T, F>, TimeoutError> {
        let mut items = self.items.lock().unwrap();

        if let Some(item) = items.available.pop() {
            return Ok(self.wrap(item));
        }

        if items.count < items.max.unwrap_or(std::usize::MAX) {
            items.count += 1;
            drop(items);
            return Ok(self.wrap((self.create)()));
        }

        if duration.is_some() {
            let duration = duration.unwrap();
            let start = SystemTime::now();
            while items.available.is_empty() {
                let elapsed = start.elapsed().unwrap_or(Duration::from_secs(0));
                if elapsed >= duration {
                    return Err(TimeoutError);
                }
                items = self.item_available.wait_timeout(items, duration - elapsed).unwrap().0;
            }
        } else {
            while items.available.is_empty() {
                items = self.item_available.wait(items).unwrap();
            }
        }

        Ok(self.wrap(items.available.pop().unwrap()))
    }

    fn wrap(&self, item: T) -> Item<T, F> {
        Item {
            item: Some(item),
            pool: self.weak_self.upgrade().unwrap(),
        }
    }

    fn put(&self, item: T) {
        self.items.lock().unwrap().available.push(item);
        self.item_available.notify_one();
    }
}

impl<T, F> Debug for Pool<T, F> where F: Fn() -> T {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Pool")
            .field("items", &*self.items.lock().unwrap())
            .finish()
    }
}

pub struct PoolBuilder<T, F> where F: Fn() -> T {
    create: F,
    max_items: Option<usize>,
}

impl<T, F> PoolBuilder<T, F> where F: Fn() -> T {
    pub fn new(create: F) -> PoolBuilder<T, F> {
        PoolBuilder { create: create, max_items: None }
    }

    pub fn max_items(mut self, max_items: usize) -> PoolBuilder<T, F> {
        self.max_items = Some(max_items);
        self
    }

    pub fn finalize(self) -> Arc<Pool<T, F>> {
        Pool::new_impl(self.create, self.max_items)
    }
}

struct Items<T> {
    available: Vec<T>,
    count: usize,
    max: Option<usize>,
}

impl<T> Debug for Items<T> {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Items")
            .field("available", &self.available.len())
            .field("count", &self.count)
            .field("max", &self.max)
            .finish()
    }
}

pub struct Item<T, F> where F: Fn() -> T {
    item: Option<T>,
    pool: Arc<Pool<T, F>>,
}

impl<T, F> Debug for Item<T, F> where T: Debug, F: Fn() -> T {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.debug_struct("Item")
            .field("item", &self.item)
            .finish()
    }
}

impl<T, F> Deref for Item<T, F> where F: Fn() -> T {
    type Target = T;

    fn deref(&self) -> &T {
        self.item.as_ref().unwrap()
    }
}

impl<T, F> DerefMut for Item<T, F> where F: Fn() -> T {
    fn deref_mut(&mut self) -> &mut T {
        self.item.as_mut().unwrap()
    }
}

impl<T, F> Drop for Item<T, F> where F: Fn() -> T {
    fn drop(&mut self) {
        self.pool.put(self.item.take().unwrap());
    }
}

#[derive(Debug, Eq, PartialEq)]
pub struct TimeoutError;

impl Display for TimeoutError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.write_str("wait timed out")
    }
}

impl Error for TimeoutError {
    fn description(&self) -> &str {
        "wait timed out"
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error;
    use std::time::{Duration, SystemTime};
    use std::thread;
    use super::*;

    trait AsMillis {
        fn as_millis(&self) -> u64;
    }

    impl AsMillis for Duration {
        fn as_millis(&self) -> u64 {
            self.as_secs() * 1000 + self.subsec_nanos() as u64 / 1000000
        }
    }

    #[test]
    fn pool_builder() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let _x = pool.get();
        assert_eq!(pool.get_timeout(Duration::from_secs(0)).err(), Some(TimeoutError));
    }

    #[test]
    fn pool_get() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let x = pool.get();
        let start = SystemTime::now();
        let handle = thread::spawn(move || {
            let _ = pool.get();
        });
        thread::sleep(Duration::from_millis(100));
        drop(x);
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_get_mut() {
        let pool = Pool::new(|| 0);
        *pool.get() = 4;
        assert_eq!(*pool.get(), 4);
    }

    #[test]
    fn pool_get_timeout_ok() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let x = pool.get();
        let start = SystemTime::now();
        let handle = thread::spawn(move || {
            let _ = pool.get_timeout(Duration::from_secs(1)).unwrap();
        });
        thread::sleep(Duration::from_millis(100));
        drop(x);
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_get_timeout_err() {
        let pool = PoolBuilder::new(|| 0).max_items(1).finalize();
        let _x = pool.get();
        let start = SystemTime::now();
        let handle = {
            let pool = pool.clone();
            thread::spawn(move || {
                assert_eq!(pool.get_timeout(Duration::from_millis(100)).err(), Some(TimeoutError));
            })
        };
        while start.elapsed().unwrap().as_millis() < 100 {
            pool.item_available.notify_one();
        }
        handle.join().unwrap();
        let elapsed_ms = start.elapsed().unwrap().as_millis();
        assert!(elapsed_ms >= 50 && elapsed_ms < 150);
    }

    #[test]
    fn pool_debug() {
        let pool = PoolBuilder::new(|| 0).max_items(5).finalize();
        assert_eq!(format!("{:?}", pool),
            "Pool { items: Items { available: 0, count: 0, max: Some(5) } }");
        let x = pool.get();
        let _y = pool.get();
        let _z = pool.get();
        drop(x);
        assert_eq!(format!("{:?}", pool),
            "Pool { items: Items { available: 1, count: 3, max: Some(5) } }");
    }

    #[test]
    fn item_debug() {
        let pool = Pool::new(|| 0);
        let x = pool.get();
        assert_eq!(format!("{:?}", x), "Item { item: Some(0) }");
    }

    #[test]
    fn timeout_error() {
        assert_eq!(format!("{}", TimeoutError), "wait timed out");
        assert_eq!(TimeoutError.description(), "wait timed out");
    }
}
<|endoftext|>


<commit_before>//! A safe wrapper for the [`c-ares`](http://c-ares.haxx.se) library.
//!
//! This crate is a fairly faithful wrapper of `c-ares`; which is to say that
//! it preserves some of the complication of using the underlying library:
//!
//! -  Direct usage of this crate requires you to pay attention to `c-ares` as
//!    it tells you which file descriptors it cares about, and to poll for
//!    activity on those file descriptors.
//!
//! -  This likely requires you to have an event loop or similar with which to
//!    integrate.
//!
//! -  If that sounds a bit too much like hard work, you should probably prefer
//!    the [`c-ares-resolver`](https://crates.io/crates/c-ares-resolver) crate,
//!    which takes care of all that stuff and presents a much simpler API.
//!
//! Still here?  Usage of this crate is as follows:
//!
//! -  Create a `Channel`.
//!
//! -  Make queries on the `Channel`.  Queries all take callbacks, which will
//!    be called when the query completes.
//!
//! -  Have `c-ares` tell you what file descriptors to listen on for read and /
//!    or write events.  You can do this either by providing a callback, which
//!    is called whenever the set of interesting file descriptors changes, or
//!    by querying the `Channel` directly with `get_sock()`.
//!
//! -  Do as `c-ares` asks.  That is, listen for the events that it requests,
//!    on the file descriptors that it cares about.
//!
//! -  When a file descriptor becomes readable or writable, call `process_fd()`
//!    on the `Channel` to tell `c-ares` what has happened.
//!
//! -  If you have queries pending and don't see events happening, you still
//!    need to call `process_fd()` at some point anyway - to give `c-ares` an
//!    opportunity to process any requests that have timed out.
//!
//! Complete examples showing how to use the library can be found
//! [here](https://github.com/dimbleby/rust-c-ares/tree/master/examples).
#![deny(missing_docs)]
#[macro_use] extern crate bitflags;
extern crate c_ares_sys;
extern crate c_types;
extern crate itertools;

mod a;
mod aaaa;
mod channel;
mod cname;
mod error;
pub mod flags;
mod host;
mod hostent;
mod mx;
mod nameinfo;
mod naptr;
pub mod ni_flags;
mod ns;
mod ptr;
mod query;
mod srv;
mod types;
mod txt;
mod soa;
mod utils;

#[cfg(test)]
mod tests;

// Re-export types from other crates that are on our interface.
pub use c_types::fd_set;

// Re-export public interfaces.
pub use a::{
    AResult,
    AResults,
    AResultsIter,
};
pub use aaaa::{
    AAAAResult,
    AAAAResults,
    AAAAResultsIter,
};
pub use channel::{
    Channel,
    GetSock,
    GetSockIter,
    Options,
};
pub use cname::CNameResults;
pub use error::Error;
pub use host::HostResults;
pub use hostent::{
    HostAddressResultsIter,
    HostAliasResultsIter,
};
pub use mx::{
    MXResult,
    MXResults,
    MXResultsIter,
};
pub use nameinfo::NameInfoResult;
pub use naptr::{
    NAPTRResult,
    NAPTRResults,
    NAPTRResultsIter,
};
pub use ns::NSResults;
pub use ptr::PTRResults;
pub use soa::SOAResult;
pub use srv::{
    SRVResult,
    SRVResults,
    SRVResultsIter,
};
pub use txt::{
    TXTResult,
    TXTResults,
    TXTResultsIter,
};
pub use types::{
    AddressFamily,
    Socket,
    SOCKET_BAD,
};
<commit_msg>docs formatting<commit_after>//! A safe wrapper for the [`c-ares`](http://c-ares.haxx.se) library.
//!
//! This crate is a fairly faithful wrapper of `c-ares`; which is to say that
//! it preserves some of the complication of using the underlying library:
//!
//! -  Direct usage of this crate requires you to pay attention to `c-ares` as
//!    it tells you which file descriptors it cares about, and to poll for
//!    activity on those file descriptors.
//!
//! -  This likely requires you to have an event loop or similar with which to
//!    integrate.
//!
//! If that sounds a bit too much like hard work, you should probably prefer
//! the [`c-ares-resolver`](https://crates.io/crates/c-ares-resolver) crate,
//! which takes care of all that stuff for you and presents a much simpler API.
//!
//! Still here?  Usage of this crate is as follows:
//!
//! -  Create a `Channel`.
//!
//! -  Make queries on the `Channel`.  Queries all take callbacks, which will
//!    be called when the query completes.
//!
//! -  Have `c-ares` tell you what file descriptors to listen on for read and /
//!    or write events.  You can do this either by providing a callback, which
//!    is called whenever the set of interesting file descriptors changes, or
//!    by querying the `Channel` directly with `get_sock()`.
//!
//! -  Do as `c-ares` asks.  That is, listen for the events that it requests,
//!    on the file descriptors that it cares about.
//!
//! -  When a file descriptor becomes readable or writable, call `process_fd()`
//!    on the `Channel` to tell `c-ares` what has happened.
//!
//! -  If you have queries pending and don't see events happening, you still
//!    need to call `process_fd()` at some point anyway - to give `c-ares` an
//!    opportunity to process any requests that have timed out.
//!
//! Complete examples showing how to use the library can be found
//! [here](https://github.com/dimbleby/rust-c-ares/tree/master/examples).
#![deny(missing_docs)]
#[macro_use] extern crate bitflags;
extern crate c_ares_sys;
extern crate c_types;
extern crate itertools;

mod a;
mod aaaa;
mod channel;
mod cname;
mod error;
pub mod flags;
mod host;
mod hostent;
mod mx;
mod nameinfo;
mod naptr;
pub mod ni_flags;
mod ns;
mod ptr;
mod query;
mod srv;
mod types;
mod txt;
mod soa;
mod utils;

#[cfg(test)]
mod tests;

// Re-export types from other crates that are on our interface.
pub use c_types::fd_set;

// Re-export public interfaces.
pub use a::{
    AResult,
    AResults,
    AResultsIter,
};
pub use aaaa::{
    AAAAResult,
    AAAAResults,
    AAAAResultsIter,
};
pub use channel::{
    Channel,
    GetSock,
    GetSockIter,
    Options,
};
pub use cname::CNameResults;
pub use error::Error;
pub use host::HostResults;
pub use hostent::{
    HostAddressResultsIter,
    HostAliasResultsIter,
};
pub use mx::{
    MXResult,
    MXResults,
    MXResultsIter,
};
pub use nameinfo::NameInfoResult;
pub use naptr::{
    NAPTRResult,
    NAPTRResults,
    NAPTRResultsIter,
};
pub use ns::NSResults;
pub use ptr::PTRResults;
pub use soa::SOAResult;
pub use srv::{
    SRVResult,
    SRVResults,
    SRVResultsIter,
};
pub use txt::{
    TXTResult,
    TXTResults,
    TXTResultsIter,
};
pub use types::{
    AddressFamily,
    Socket,
    SOCKET_BAD,
};
<|endoftext|>


<commit_before>#![feature(advanced_slice_patterns, slice_patterns)]
#![recursion_limit = "1024"]
#[macro_use]

extern crate error_chain;
extern crate git2;

pub mod author;
pub mod config;
pub mod errors;
pub mod git;

use std::collections::HashMap;
use std::env;
use std::process::Command;

use author::{Author, AuthorParser};
use config::Config;
use errors::*;

const NAMESPACE: &'static str = "git-together";

fn namespaced(name: &str) -> String {
    format!("{}.{}", NAMESPACE, name)
}

pub struct GitTogether<C> {
    config: C,
    author_parser: AuthorParser,
}

impl GitTogether<git::Config> {
    pub fn new() -> Result<Self> {
        let repo = git::Repo::new();
        if let Ok(ref repo) = repo {
            let _ = repo.auto_include(&format!(".{}", NAMESPACE));
        }

        let config = match repo {
                Ok(ref repo) => repo.config(),
                Err(e) => Err(e),
            }.or_else(|_| git::Config::new())?;
        let domain = config.get(&namespaced("domain")).ok();
        let author_parser = AuthorParser { domain: domain };

        Ok(GitTogether {
            config: config,
            author_parser: author_parser,
        })
    }
}

impl<C: config::Config> GitTogether<C> {
    pub fn set_active(&mut self, inits: &[&str]) -> Result<Vec<Author>> {
        let authors = self.get_authors(inits)?;
        self.config.set(&namespaced("active"), &inits.join("+"))?;
        Ok(authors)
    }

    pub fn all_authors(&self) -> Result<HashMap<String, Author>> {
        let mut authors = HashMap::new();
        let raw = self.config.get_all(&namespaced("authors."))?;
        for (name, value) in raw {
            let initials = name.split('.').last().ok_or("")?;
            let author = self.parse_author(initials, &value)?;
            authors.insert(initials.into(), author);
        }
        Ok(authors)
    }

    pub fn signoff<'a>(&self, cmd: &'a mut Command) -> Result<&'a mut Command> {
        let active = self.config.get(&namespaced("active"))?;
        let inits: Vec<_> = active.split('+').collect();
        let authors = self.get_authors(&inits)?;

        let (author, committer) = match *authors.as_slice() {
            [] => {
                return Err("".into());
            }
            [ref solo] => (solo, solo),
            [ref author, ref committer, _..] => (author, committer),
        };

        let cmd = cmd.env("GIT_AUTHOR_NAME", author.name.clone())
            .env("GIT_AUTHOR_EMAIL", author.email.clone())
            .env("GIT_COMMITTER_NAME", committer.name.clone())
            .env("GIT_COMMITTER_EMAIL", committer.email.clone());

        let no_signoff = env::var("GIT_TOGETHER_NO_SIGNOFF").is_ok();
        let cmd = if !no_signoff && author != committer {
            cmd.arg("--signoff")
        } else {
            cmd
        };

        Ok(cmd)
    }

    fn get_active(&self) -> Result<Vec<String>> {
        self.config
            .get(&namespaced("active"))
            .map(|active| active.split('+').map(|s| s.into()).collect())
    }

    pub fn rotate_active(&mut self) -> Result<()> {
        self.get_active().and_then(|active| {
            let mut inits: Vec<_> = active.iter().map(String::as_ref).collect();
            if !inits.is_empty() {
                let author = inits.remove(0);
                inits.push(author);
            }
            self.set_active(&inits[..]).map(|_| ())
        })
    }

    fn get_authors(&self, inits: &[&str]) -> Result<Vec<Author>> {
        inits.iter()
            .map(|&initials| self.get_author(initials))
            .collect()
    }

    fn get_author(&self, initials: &str) -> Result<Author> {
        self.config
            .get(&namespaced(&format!("authors.{}", initials)))
            .chain_err(|| format!("author not found for '{}'", initials))
            .and_then(|raw| self.parse_author(initials, &raw))
    }

    fn parse_author(&self, initials: &str, raw: &str) -> Result<Author> {
        self.author_parser
            .parse(raw)
            .chain_err(|| {
                format!("invalid author for '{}': '{}'", initials, raw)
            })
    }
}

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

    use std::collections::HashMap;

    use author::{Author, AuthorParser};
    use config::Config;

    #[test]
    fn get_authors() {
        let config = MockConfig::new(&[("authors.jh", ""),
                                       ("authors.nn", "Naomi Nagata"),
                                       ("authors.ab", "Amos Burton; aburton"),
                                       ("authors.ak", "Alex Kamal; akamal"),
                                       ("authors.ca", "Chrisjen Avasarala;"),
                                       ("authors.bd",
                                        "Bobbie Draper; bdraper@mars.mil"),
                                       ("authors.jm",
                                        "Joe Miller; jmiller@starhelix.com")]);
        let author_parser =
            AuthorParser { domain: Some("rocinante.com".into()) };
        let gt = GitTogether {
            config: config,
            author_parser: author_parser,
        };

        assert!(gt.get_authors(&["jh"]).is_err());
        assert!(gt.get_authors(&["nn"]).is_err());
        assert!(gt.get_authors(&["ca"]).is_err());
        assert!(gt.get_authors(&["jh", "bd"]).is_err());

        assert_eq!(gt.get_authors(&["ab", "ak"]).unwrap(),
                   vec![Author {
                            name: "Amos Burton".into(),
                            email: "aburton@rocinante.com".into(),
                        },
                        Author {
                            name: "Alex Kamal".into(),
                            email: "akamal@rocinante.com".into(),
                        }]);
        assert_eq!(gt.get_authors(&["ab", "bd", "jm"]).unwrap(),
                   vec![Author {
                            name: "Amos Burton".into(),
                            email: "aburton@rocinante.com".into(),
                        },
                        Author {
                            name: "Bobbie Draper".into(),
                            email: "bdraper@mars.mil".into(),
                        },
                        Author {
                            name: "Joe Miller".into(),
                            email: "jmiller@starhelix.com".into(),
                        }]);
    }

    #[test]
    fn set_active() {
        let config =
            MockConfig::new(&[("authors.jh", "James Holden; jholden"),
                              ("authors.nn", "Naomi Nagata; nnagata")]);
        let author_parser =
            AuthorParser { domain: Some("rocinante.com".into()) };
        let mut gt = GitTogether {
            config: config,
            author_parser: author_parser,
        };

        gt.set_active(&["jh"]).unwrap();
        assert_eq!(gt.get_active().unwrap(), vec!["jh"]);

        gt.set_active(&["jh", "nn"]).unwrap();
        assert_eq!(gt.get_active().unwrap(), vec!["jh", "nn"]);
    }

    #[test]
    fn rotate_active() {
        let config =
            MockConfig::new(&[("active", "jh+nn"),
                              ("authors.jh", "James Holden; jholden"),
                              ("authors.nn", "Naomi Nagata; nnagata")]);
        let author_parser =
            AuthorParser { domain: Some("rocinante.com".into()) };
        let mut gt = GitTogether {
            config: config,
            author_parser: author_parser,
        };

        gt.rotate_active().unwrap();
        assert_eq!(gt.get_active().unwrap(), vec!["nn", "jh"]);
    }

    #[test]
    fn all_authors() {
        let config = MockConfig::new(&[("active", "jh+nn"),
                                       ("authors.ab", "Amos Burton; aburton"),
                                       ("authors.bd",
                                        "Bobbie Draper; bdraper@mars.mil"),
                                       ("authors.jm",
                                        "Joe Miller; jmiller@starhelix.com")]);
        let author_parser =
            AuthorParser { domain: Some("rocinante.com".into()) };
        let gt = GitTogether {
            config: config,
            author_parser: author_parser,
        };

        let all_authors = gt.all_authors().unwrap();
        assert_eq!(all_authors.len(), 3);
        assert_eq!(all_authors["ab"],
                   Author {
                       name: "Amos Burton".into(),
                       email: "aburton@rocinante.com".into(),
                   });
        assert_eq!(all_authors["bd"],
                   Author {
                       name: "Bobbie Draper".into(),
                       email: "bdraper@mars.mil".into(),
                   });
        assert_eq!(all_authors["jm"],
                   Author {
                       name: "Joe Miller".into(),
                       email: "jmiller@starhelix.com".into(),
                   });
    }

    struct MockConfig {
        data: HashMap<String, String>,
    }

    impl MockConfig {
        fn new(data: &[(&str, &str)]) -> MockConfig {
            MockConfig {
                data: data.iter()
                    .map(|&(k, v)| (namespaced(k), v.into()))
                    .collect(),
            }
        }
    }

    impl Config for MockConfig {
        fn get(&self, name: &str) -> Result<String> {
            self.data
                .get(name.into())
                .cloned()
                .ok_or(format!("name not found: '{}'", name).into())
        }

        fn get_all(&self, glob: &str) -> Result<HashMap<String, String>> {
            Ok(self.data
                .iter()
                .filter(|&(name, _)| name.contains(glob))
                .map(|(name, value)| (name.clone(), value.clone()))
                .collect())
        }

        fn add(&mut self, _: &str, _: &str) -> Result<()> {
            unimplemented!();
        }

        fn set(&mut self, name: &str, value: &str) -> Result<()> {
            self.data.insert(name.into(), value.into());
            Ok(())
        }
    }
}
<commit_msg>clean up getting a config from a repo<commit_after>#![feature(advanced_slice_patterns, slice_patterns)]
#![recursion_limit = "1024"]
#[macro_use]

extern crate error_chain;
extern crate git2;

pub mod author;
pub mod config;
pub mod errors;
pub mod git;

use std::collections::HashMap;
use std::env;
use std::process::Command;

use author::{Author, AuthorParser};
use config::Config;
use errors::*;

const NAMESPACE: &'static str = "git-together";

fn namespaced(name: &str) -> String {
    format!("{}.{}", NAMESPACE, name)
}

pub struct GitTogether<C> {
    config: C,
    author_parser: AuthorParser,
}

impl GitTogether<git::Config> {
    pub fn new() -> Result<Self> {
        let repo = git::Repo::new();
        if let Ok(ref repo) = repo {
            let _ = repo.auto_include(&format!(".{}", NAMESPACE));
        }

        let config = repo.and_then(|r| r.config()).or_else(|_| git::Config::new())?;
        let domain = config.get(&namespaced("domain")).ok();
        let author_parser = AuthorParser { domain: domain };

        Ok(GitTogether {
            config: config,
            author_parser: author_parser,
        })
    }
}

impl<C: config::Config> GitTogether<C> {
    pub fn set_active(&mut self, inits: &[&str]) -> Result<Vec<Author>> {
        let authors = self.get_authors(inits)?;
        self.config.set(&namespaced("active"), &inits.join("+"))?;
        Ok(authors)
    }

    pub fn all_authors(&self) -> Result<HashMap<String, Author>> {
        let mut authors = HashMap::new();
        let raw = self.config.get_all(&namespaced("authors."))?;
        for (name, value) in raw {
            let initials = name.split('.').last().ok_or("")?;
            let author = self.parse_author(initials, &value)?;
            authors.insert(initials.into(), author);
        }
        Ok(authors)
    }

    pub fn signoff<'a>(&self, cmd: &'a mut Command) -> Result<&'a mut Command> {
        let active = self.config.get(&namespaced("active"))?;
        let inits: Vec<_> = active.split('+').collect();
        let authors = self.get_authors(&inits)?;

        let (author, committer) = match *authors.as_slice() {
            [] => {
                return Err("".into());
            }
            [ref solo] => (solo, solo),
            [ref author, ref committer, _..] => (author, committer),
        };

        let cmd = cmd.env("GIT_AUTHOR_NAME", author.name.clone())
            .env("GIT_AUTHOR_EMAIL", author.email.clone())
            .env("GIT_COMMITTER_NAME", committer.name.clone())
            .env("GIT_COMMITTER_EMAIL", committer.email.clone());

        let no_signoff = env::var("GIT_TOGETHER_NO_SIGNOFF").is_ok();
        let cmd = if !no_signoff && author != committer {
            cmd.arg("--signoff")
        } else {
            cmd
        };

        Ok(cmd)
    }

    fn get_active(&self) -> Result<Vec<String>> {
        self.config
            .get(&namespaced("active"))
            .map(|active| active.split('+').map(|s| s.into()).collect())
    }

    pub fn rotate_active(&mut self) -> Result<()> {
        self.get_active().and_then(|active| {
            let mut inits: Vec<_> = active.iter().map(String::as_ref).collect();
            if !inits.is_empty() {
                let author = inits.remove(0);
                inits.push(author);
            }
            self.set_active(&inits[..]).map(|_| ())
        })
    }

    fn get_authors(&self, inits: &[&str]) -> Result<Vec<Author>> {
        inits.iter()
            .map(|&initials| self.get_author(initials))
            .collect()
    }

    fn get_author(&self, initials: &str) -> Result<Author> {
        self.config
            .get(&namespaced(&format!("authors.{}", initials)))
            .chain_err(|| format!("author not found for '{}'", initials))
            .and_then(|raw| self.parse_author(initials, &raw))
    }

    fn parse_author(&self, initials: &str, raw: &str) -> Result<Author> {
        self.author_parser
            .parse(raw)
            .chain_err(|| {
                format!("invalid author for '{}': '{}'", initials, raw)
            })
    }
}

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

    use std::collections::HashMap;

    use author::{Author, AuthorParser};
    use config::Config;

    #[test]
    fn get_authors() {
        let config = MockConfig::new(&[("authors.jh", ""),
                                       ("authors.nn", "Naomi Nagata"),
                                       ("authors.ab", "Amos Burton; aburton"),
                                       ("authors.ak", "Alex Kamal; akamal"),
                                       ("authors.ca", "Chrisjen Avasarala;"),
                                       ("authors.bd",
                                        "Bobbie Draper; bdraper@mars.mil"),
                                       ("authors.jm",
                                        "Joe Miller; jmiller@starhelix.com")]);
        let author_parser =
            AuthorParser { domain: Some("rocinante.com".into()) };
        let gt = GitTogether {
            config: config,
            author_parser: author_parser,
        };

        assert!(gt.get_authors(&["jh"]).is_err());
        assert!(gt.get_authors(&["nn"]).is_err());
        assert!(gt.get_authors(&["ca"]).is_err());
        assert!(gt.get_authors(&["jh", "bd"]).is_err());

        assert_eq!(gt.get_authors(&["ab", "ak"]).unwrap(),
                   vec![Author {
                            name: "Amos Burton".into(),
                            email: "aburton@rocinante.com".into(),
                        },
                        Author {
                            name: "Alex Kamal".into(),
                            email: "akamal@rocinante.com".into(),
                        }]);
        assert_eq!(gt.get_authors(&["ab", "bd", "jm"]).unwrap(),
                   vec![Author {
                            name: "Amos Burton".into(),
                            email: "aburton@rocinante.com".into(),
                        },
                        Author {
                            name: "Bobbie Draper".into(),
                            email: "bdraper@mars.mil".into(),
                        },
                        Author {
                            name: "Joe Miller".into(),
                            email: "jmiller@starhelix.com".into(),
                        }]);
    }

    #[test]
    fn set_active() {
        let config =
            MockConfig::new(&[("authors.jh", "James Holden; jholden"),
                              ("authors.nn", "Naomi Nagata; nnagata")]);
        let author_parser =
            AuthorParser { domain: Some("rocinante.com".into()) };
        let mut gt = GitTogether {
            config: config,
            author_parser: author_parser,
        };

        gt.set_active(&["jh"]).unwrap();
        assert_eq!(gt.get_active().unwrap(), vec!["jh"]);

        gt.set_active(&["jh", "nn"]).unwrap();
        assert_eq!(gt.get_active().unwrap(), vec!["jh", "nn"]);
    }

    #[test]
    fn rotate_active() {
        let config =
            MockConfig::new(&[("active", "jh+nn"),
                              ("authors.jh", "James Holden; jholden"),
                              ("authors.nn", "Naomi Nagata; nnagata")]);
        let author_parser =
            AuthorParser { domain: Some("rocinante.com".into()) };
        let mut gt = GitTogether {
            config: config,
            author_parser: author_parser,
        };

        gt.rotate_active().unwrap();
        assert_eq!(gt.get_active().unwrap(), vec!["nn", "jh"]);
    }

    #[test]
    fn all_authors() {
        let config = MockConfig::new(&[("active", "jh+nn"),
                                       ("authors.ab", "Amos Burton; aburton"),
                                       ("authors.bd",
                                        "Bobbie Draper; bdraper@mars.mil"),
                                       ("authors.jm",
                                        "Joe Miller; jmiller@starhelix.com")]);
        let author_parser =
            AuthorParser { domain: Some("rocinante.com".into()) };
        let gt = GitTogether {
            config: config,
            author_parser: author_parser,
        };

        let all_authors = gt.all_authors().unwrap();
        assert_eq!(all_authors.len(), 3);
        assert_eq!(all_authors["ab"],
                   Author {
                       name: "Amos Burton".into(),
                       email: "aburton@rocinante.com".into(),
                   });
        assert_eq!(all_authors["bd"],
                   Author {
                       name: "Bobbie Draper".into(),
                       email: "bdraper@mars.mil".into(),
                   });
        assert_eq!(all_authors["jm"],
                   Author {
                       name: "Joe Miller".into(),
                       email: "jmiller@starhelix.com".into(),
                   });
    }

    struct MockConfig {
        data: HashMap<String, String>,
    }

    impl MockConfig {
        fn new(data: &[(&str, &str)]) -> MockConfig {
            MockConfig {
                data: data.iter()
                    .map(|&(k, v)| (namespaced(k), v.into()))
                    .collect(),
            }
        }
    }

    impl Config for MockConfig {
        fn get(&self, name: &str) -> Result<String> {
            self.data
                .get(name.into())
                .cloned()
                .ok_or(format!("name not found: '{}'", name).into())
        }

        fn get_all(&self, glob: &str) -> Result<HashMap<String, String>> {
            Ok(self.data
                .iter()
                .filter(|&(name, _)| name.contains(glob))
                .map(|(name, value)| (name.clone(), value.clone()))
                .collect())
        }

        fn add(&mut self, _: &str, _: &str) -> Result<()> {
            unimplemented!();
        }

        fn set(&mut self, name: &str, value: &str) -> Result<()> {
            self.data.insert(name.into(), value.into());
            Ok(())
        }
    }
}
<|endoftext|>


<commit_before>mod geometry;
mod material;
mod math;
mod renderable;

pub use self::geometry::*;
pub use self::material::Material;
pub use self::math::*;

use self::renderable::{Hit, Renderable};

extern crate rand;
use rand::Rng;

use std::f64::consts::PI;

fn intersect<'a>(scene: &'a [Sphere], ray: &Ray) -> Option<Hit<'a>> {
    let mut hit_dist = std::f64::INFINITY;
    let mut hit_obj : Option<&Sphere> = None;
    for sph in scene {
        if let Some(dist) = sph.intersect(&ray) {
            if dist < hit_dist {
                hit_dist = dist;
                hit_obj = Some(&sph);
            }
        }
    }

    match hit_obj {
        None => { None },
        Some(obj) => {
            Some(obj.get_hit(&ray, hit_dist))
        }
    }
}

pub fn radiance<R: Rng>(scene: &[Sphere], ray: &Ray, depth: i32, rng: &mut R) -> Vec3d {
    intersect(&scene, &ray).map_or(Vec3d::zero(), |hit| {
        let n1 = if hit.normal.dot(ray.direction) < 0.0 { hit.normal } else { hit.normal.neg() };
        let mut colour = hit.colour;
        let max_reflectance = colour.max_component();
        let depth = depth + 1;
        if depth > 5 {
            let rand = rng.gen::<f64>();
            if rand < max_reflectance && depth < 500 { // Rust's stack blows up ~600 on my machine
               colour = colour * (1.0 / max_reflectance);
            } else {
                return hit.emission;
            }
        }
        match *hit.material {
            Material::Diffuse => {
                // Get a random polar coordinate.
                let r1 = rng.gen::<f64>() * 2.0 * PI;
                let r2 = rng.gen::<f64>();
                let r2s = r2.sqrt();
                // Create a coordinate system u,v,w local to the point, where the w is the normal
                // pointing out of the sphere and the u and v are orthonormal to w.
                let w = n1;
                // Pick an arbitrary non-zero preferred axis for u
                let u = if n1.x.abs() > 0.1 { Vec3d::new(0.0, 1.0, 0.0) } else { Vec3d::new(1.0, 0.0, 0.0) }.cross(w);
                let v = w.cross(u);
                // construct the new direction
                let new_dir = u * r1.cos() * r2s + v * r1.sin() * r2s + w * (1.0 - r2).sqrt();
                colour = colour * radiance(scene, &Ray::new(hit.pos, new_dir.normalized()), depth, rng);
            },
            Material::Specular => {
                let reflection = ray.direction - hit.normal * 2.0 * hit.normal.dot(ray.direction);
                let reflected_ray = Ray::new(hit.pos, reflection);
                colour = colour * radiance(scene, &reflected_ray, depth, rng);
            },
            Material::Refractive => {
                let reflection = ray.direction - hit.normal * 2.0 * hit.normal.dot(ray.direction);
                let reflected_ray = Ray::new(hit.pos, reflection);
                let into = hit.normal.dot(n1) > 0.0;
                let nc = 1.0;
                let nt = 1.5;
                let nnt = if into { nc/nt } else { nt/nc };
                let ddn = ray.direction.dot(n1);
                let cos2t = 1.0 - nnt * nnt * (1.0 - ddn * ddn);
                if cos2t < 0.0 {
                    // Total internal reflection
                    colour = colour * radiance(scene, &reflected_ray, depth, rng);
                } else {
                    let tbd = ddn * nnt + cos2t.sqrt();
                    let tbd = if into { tbd } else { -tbd };
                    let tdir = (ray.direction * nnt - hit.normal * tbd).normalized();
                    let transmitted_ray = Ray::new(hit.pos, tdir);
                    let a = nt - nc;
                    let b = nt + nc;
                    let r0 = (a * a) / (b * b);
                    let c = 1.0 - if into { -ddn } else { tdir.dot(hit.normal) };
                    let re = r0 + (1.0 - r0) * c * c * c * c * c;
                    let tr = 1.0 - re;
                    let p = 0.25 + 0.5 * re;
                    let rp = re / p;
                    let tp = tr / (1.0 - p);
                    colour = colour * if depth > 2 {
                        if rng.gen::<f64>() < p {
                            radiance(scene, &reflected_ray, depth, rng) * rp
                        } else {
                            radiance(scene, &transmitted_ray, depth, rng) * tp
                        }
                    } else {
                        radiance(scene, &reflected_ray, depth, rng) * re +
                            radiance(scene, &transmitted_ray, depth, rng) * tr
                    }
                }
            }
        }
        hit.emission + colour
    })
}

pub fn random_samp<T: Rng>(rng: &mut T) -> f64 {
    let r = 2.0 * rng.gen::<f64>();
    if r < 1.0 { r.sqrt() - 1.0 } else { 1.0 - (2.0 - r).sqrt() }
}

pub fn to_int(v: f64) -> u8 {
    let ch = (v.powf(1.0/2.2) * 255.0 + 0.5) as i64;
    if ch < 0 { 0 } else if ch > 255 { 255 } else { ch as u8 }
}
<commit_msg>Use u8 literals<commit_after>mod geometry;
mod material;
mod math;
mod renderable;

pub use self::geometry::*;
pub use self::material::Material;
pub use self::math::*;

use self::renderable::{Hit, Renderable};

extern crate rand;
use rand::Rng;

use std::f64::consts::PI;

fn intersect<'a>(scene: &'a [Sphere], ray: &Ray) -> Option<Hit<'a>> {
    let mut hit_dist = std::f64::INFINITY;
    let mut hit_obj : Option<&Sphere> = None;
    for sph in scene {
        if let Some(dist) = sph.intersect(&ray) {
            if dist < hit_dist {
                hit_dist = dist;
                hit_obj = Some(&sph);
            }
        }
    }

    match hit_obj {
        None => { None },
        Some(obj) => {
            Some(obj.get_hit(&ray, hit_dist))
        }
    }
}

pub fn radiance<R: Rng>(scene: &[Sphere], ray: &Ray, depth: i32, rng: &mut R) -> Vec3d {
    intersect(&scene, &ray).map_or(Vec3d::zero(), |hit| {
        let n1 = if hit.normal.dot(ray.direction) < 0.0 { hit.normal } else { hit.normal.neg() };
        let mut colour = hit.colour;
        let max_reflectance = colour.max_component();
        let depth = depth + 1;
        if depth > 5 {
            let rand = rng.gen::<f64>();
            if rand < max_reflectance && depth < 500 { // Rust's stack blows up ~600 on my machine
               colour = colour * (1.0 / max_reflectance);
            } else {
                return hit.emission;
            }
        }
        match *hit.material {
            Material::Diffuse => {
                // Get a random polar coordinate.
                let r1 = rng.gen::<f64>() * 2.0 * PI;
                let r2 = rng.gen::<f64>();
                let r2s = r2.sqrt();
                // Create a coordinate system u,v,w local to the point, where the w is the normal
                // pointing out of the sphere and the u and v are orthonormal to w.
                let w = n1;
                // Pick an arbitrary non-zero preferred axis for u
                let u = if n1.x.abs() > 0.1 { Vec3d::new(0.0, 1.0, 0.0) } else { Vec3d::new(1.0, 0.0, 0.0) }.cross(w);
                let v = w.cross(u);
                // construct the new direction
                let new_dir = u * r1.cos() * r2s + v * r1.sin() * r2s + w * (1.0 - r2).sqrt();
                colour = colour * radiance(scene, &Ray::new(hit.pos, new_dir.normalized()), depth, rng);
            },
            Material::Specular => {
                let reflection = ray.direction - hit.normal * 2.0 * hit.normal.dot(ray.direction);
                let reflected_ray = Ray::new(hit.pos, reflection);
                colour = colour * radiance(scene, &reflected_ray, depth, rng);
            },
            Material::Refractive => {
                let reflection = ray.direction - hit.normal * 2.0 * hit.normal.dot(ray.direction);
                let reflected_ray = Ray::new(hit.pos, reflection);
                let into = hit.normal.dot(n1) > 0.0;
                let nc = 1.0;
                let nt = 1.5;
                let nnt = if into { nc/nt } else { nt/nc };
                let ddn = ray.direction.dot(n1);
                let cos2t = 1.0 - nnt * nnt * (1.0 - ddn * ddn);
                if cos2t < 0.0 {
                    // Total internal reflection
                    colour = colour * radiance(scene, &reflected_ray, depth, rng);
                } else {
                    let tbd = ddn * nnt + cos2t.sqrt();
                    let tbd = if into { tbd } else { -tbd };
                    let tdir = (ray.direction * nnt - hit.normal * tbd).normalized();
                    let transmitted_ray = Ray::new(hit.pos, tdir);
                    let a = nt - nc;
                    let b = nt + nc;
                    let r0 = (a * a) / (b * b);
                    let c = 1.0 - if into { -ddn } else { tdir.dot(hit.normal) };
                    let re = r0 + (1.0 - r0) * c * c * c * c * c;
                    let tr = 1.0 - re;
                    let p = 0.25 + 0.5 * re;
                    let rp = re / p;
                    let tp = tr / (1.0 - p);
                    colour = colour * if depth > 2 {
                        if rng.gen::<f64>() < p {
                            radiance(scene, &reflected_ray, depth, rng) * rp
                        } else {
                            radiance(scene, &transmitted_ray, depth, rng) * tp
                        }
                    } else {
                        radiance(scene, &reflected_ray, depth, rng) * re +
                            radiance(scene, &transmitted_ray, depth, rng) * tr
                    }
                }
            }
        }
        hit.emission + colour
    })
}

pub fn random_samp<T: Rng>(rng: &mut T) -> f64 {
    let r = 2.0 * rng.gen::<f64>();
    if r < 1.0 { r.sqrt() - 1.0 } else { 1.0 - (2.0 - r).sqrt() }
}

pub fn to_int(v: f64) -> u8 {
    let ch = (v.powf(1.0/2.2) * 255.0 + 0.5) as i64;
    if ch < 0 { 0u8 } else if ch > 255 { 255u8 } else { ch as u8 }
}
<|endoftext|>


<commit_before>//! Manipulations and data types that represent polynomial.

#![warn(bad_style)]
#![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate num;

use std::{cmp, fmt};
use std::ops::{Add, Mul, Neg, Sub};
use num::{Zero, One};

/// Polynomial expression
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Polynomial<T> {
    data: Vec<T>,
}

impl<T: Zero> Polynomial<T> {
    /// Creates new `Polynomial`.
    ///
    /// ```rust
    /// use polynomial::Polynomial;
    /// let poly = Polynomial::new(vec![1, 2, 3]);
    /// assert_eq!("1+2*x+3*x^2", poly.pretty("x"));
    /// ```
    #[inline]
    pub fn new(mut data: Vec<T>) -> Polynomial<T> {
        while let Some(true) = data.last().map(|x| x.is_zero()) {
            let _ = data.pop();
        }
        Polynomial { data: data }
    }
}

impl<T: Zero + One + Clone> Polynomial<T> {
    /// Evaluates the polynomial value.
    ///
    /// ```rust
    /// use polynomial::Polynomial;
    /// let poly = Polynomial::new(vec![1, 2, 3]);
    /// assert_eq!(1, poly.eval(0));
    /// assert_eq!(6, poly.eval(1));
    /// assert_eq!(17, poly.eval(2));
    /// ```
    #[inline]
    pub fn eval(&self, x: T) -> T {
        let mut sum: T = Zero::zero();
        let mut x_n: T = One::one();
        for n in self.data.iter() {
            sum = sum + n.clone() * x_n.clone();
            x_n = x_n * x.clone();
        }
        sum
    }
}

impl<T> Polynomial<T> {
    /// Gets the slice of internal data.
    #[inline]
    pub fn data(&self) -> &[T] {
        &self.data
    }
}

impl<T> Polynomial<T>
    where T: Zero + One + Eq + Neg<Output = T> + Ord + fmt::Display + Clone
{
    /// Pretty prints the polynomial.
    pub fn pretty(&self, x: &str) -> String {
        if self.is_zero() {
            return "0".to_string();
        }

        let one = One::one();
        let mut s = Vec::new();
        for (i, n) in self.data.iter().enumerate() {
            // output n*x^i / -n*x^i
            if n.is_zero() {
                continue;
            }

            let term = if i.is_zero() {
                n.to_string()
            } else if i == 1 {
                if (*n) == one {
                    x.to_string()
                } else if (*n) == -one.clone() {
                    format!("-{}", x)
                } else {
                    format!("{}*{}", n.to_string(), x)
                }
            } else {
                if (*n) == one {
                    format!("{}^{}", x, i)
                } else if (*n) == -one.clone() {
                    format!("-{}^{}", x, i)
                } else {
                    format!("{}*{}^{}", n.to_string(), x, i)
                }
            };

            if s.len() > 0 && (*n) > Zero::zero() {
                s.push("+".to_string());
            }
            s.push(term);
        }

        s.concat()
    }
}

impl<'a, T> Neg for Polynomial<T>
    where T: Neg + Zero + Clone, <T as Neg>::Output: Zero
{
    type Output = Polynomial<<T as Neg>::Output>;

    #[inline]
    fn neg(self) -> Polynomial<<T as Neg>::Output> {
        -&self
    }
}

impl<'a, T> Neg for &'a Polynomial<T>
    where T: Neg + Zero + Clone, <T as Neg>::Output: Zero
{
    type Output = Polynomial<<T as Neg>::Output>;

    #[inline]
    fn neg(self) -> Polynomial<<T as Neg>::Output> {
        Polynomial::new(self.data.iter().map(|x| -x.clone()).collect())
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs> $imp<Polynomial<Rhs>> for Polynomial<Lhs>
            where Lhs: Zero + $imp<Rhs> + Clone, Rhs: Zero + Clone,
                  <Lhs as $imp<Rhs>>::Output: Zero
        {
            type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<Polynomial<Rhs>> for &'a Polynomial<Lhs>
            where Lhs: Zero + $imp<Rhs> + Clone, Rhs: Zero + Clone,
                  <Lhs as $imp<Rhs>>::Output: Zero
        {
            type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<&'a Polynomial<Rhs>> for Polynomial<Lhs>
            where Lhs: Zero + $imp<Rhs> + Clone, Rhs: Zero + Clone,
                  <Lhs as $imp<Rhs>>::Output: Zero
        {
            type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs> Add<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
    where Lhs: Zero + Add<Rhs> + Clone, Rhs: Zero + Clone,
          <Lhs as Add<Rhs>>::Output: Zero
{
    type Output = Polynomial<<Lhs as Add<Rhs>>::Output>;

    fn add(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Add<Rhs>>::Output> {
        let max_len = cmp::max(self.data.len(), other.data.len());
        let min_len = cmp::min(self.data.len(), other.data.len());

        let mut sum = Vec::with_capacity(max_len);
        for i in 0..min_len {
            sum.push(self.data[i].clone() + other.data[i].clone());
        }

        if self.data.len() <= other.data.len() {
            for i in min_len..max_len {
                sum.push(num::zero::<Lhs>() + other.data[i].clone());
            }
        } else {
            for i in min_len..max_len {
                sum.push(self.data[i].clone() + num::zero::<Rhs>());
            }
        }

        Polynomial::new(sum)
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs> Sub<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
    where Lhs: Zero + Sub<Rhs> + Clone, Rhs: Zero + Clone,
          <Lhs as Sub<Rhs>>::Output: Zero
{
    type Output = Polynomial<<Lhs as Sub<Rhs>>::Output>;

    fn sub(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Sub<Rhs>>::Output> {
        let min_len = cmp::min(self.data.len(), other.data.len());
        let max_len = cmp::max(self.data.len(), other.data.len());

        let mut sub = Vec::with_capacity(max_len);
        for i in 0..min_len {
            sub.push(self.data[i].clone() - other.data[i].clone());
        }
        if self.data.len() <= other.data.len() {
            for i in min_len..max_len {
                sub.push(num::zero::<Lhs>() - other.data[i].clone())
            }
        } else {
            for i in min_len..max_len {
                sub.push(self.data[i].clone() - num::zero::<Rhs>())
            }
        }
        Polynomial::new(sub)
    }
}

forward_all_binop!(impl Mul, mul);

impl<'a, 'b, Lhs, Rhs> Mul<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
    where Lhs: Zero + Mul<Rhs> + Clone, Rhs: Zero + Clone,
          <Lhs as Mul<Rhs>>::Output: Zero
{
    type Output = Polynomial<<Lhs as Mul<Rhs>>::Output>;

    fn mul(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Mul<Rhs>>::Output> {
        if self.is_zero() || other.is_zero() {
            return Polynomial::new(vec![]);
        }

        let slen = self.data.len();
        let olen = other.data.len();
        let prod = (0..slen + olen - 1)
                       .map(|i| {
                           let mut p = num::zero::<<Lhs as Mul<Rhs>>::Output>();
                           let kstart = cmp::max(olen, i + 1) - olen;
                           let kend = cmp::min(slen, i + 1);
                           for k in kstart..kend {
                               p = p + self.data[k].clone() * other.data[i - k].clone();
                           }
                           p
                       })
                       .collect();
        Polynomial::new(prod)
    }
}

impl<T: Zero + Clone> Zero for Polynomial<T> {
    #[inline]
    fn zero() -> Polynomial<T> {
        Polynomial { data: vec![] }
    }
    #[inline]
    fn is_zero(&self) -> bool {
        self.data.is_empty()
    }
}

impl<T: Zero + One + Clone> One for Polynomial<T> {
    #[inline]
    fn one() -> Polynomial<T> {
        Polynomial { data: vec![One::one()] }
    }
}

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

    #[test]
    fn new() {
        fn check(dst: Vec<i32>, src: Vec<i32>) {
            assert_eq!(dst, Polynomial::new(src).data);
        }
        check(vec![1, 2, 3], vec![1, 2, 3]);
        check(vec![1, 2, 3], vec![1, 2, 3, 0, 0]);
        check(vec![], vec![0, 0, 0]);
    }

    #[test]
    fn neg_add_sub() {
        fn check(a: &[i32], b: &[i32], c: &[i32]) {
            fn check_eq(a: &Polynomial<i32>, b: &Polynomial<i32>) {
                assert_eq!(*a, *b);
                assert_eq!(-a, -b);
            }
            fn check_add(sum: &Polynomial<i32>, a: &Polynomial<i32>, b: &Polynomial<i32>) {
                check_eq(sum, &(a + b));
                check_eq(sum, &(b + a));
            }
            fn check_sub(sum: &Polynomial<i32>, a: &Polynomial<i32>, b: &Polynomial<i32>) {
                check_eq(a, &(sum - b));
                check_eq(b, &(sum - a));
            }

            let a = &Polynomial::new(a.to_vec());
            let b = &Polynomial::new(b.to_vec());
            let c = &Polynomial::new(c.to_vec());
            check_add(c, a, b);
            check_add(&(-c), &(-a), &(-b));
            check_sub(c, a, b);
            check_sub(&(-c), &(-a), &(-b));
        }
        check(&[], &[], &[]);
        check(&[], &[1], &[1]);
        check(&[1], &[1], &[2]);
        check(&[1, 0, 1], &[1], &[2, 0, 1]);
        check(&[1, 0, -1], &[-1, 0, 1], &[]);
    }

    #[test]
    fn mul() {
        fn check(a: &[i32], b: &[i32], c: &[i32]) {
            let a = Polynomial::new(a.to_vec());
            let b = Polynomial::new(b.to_vec());
            let c = Polynomial::new(c.to_vec());
            assert_eq!(c, &a * &b);
            assert_eq!(c, &b * &a);
        }
        check(&[], &[], &[]);
        check(&[0, 0], &[], &[]);
        check(&[0, 0], &[1], &[]);
        check(&[1, 0], &[1], &[1]);
        check(&[1, 0, 1], &[1], &[1, 0, 1]);
        check(&[1, 1], &[1, 1], &[1, 2, 1]);
        check(&[1, 1], &[1, 0, 1], &[1, 1, 1, 1]);
        check(&[0, 0, 1], &[0, 0, 1], &[0, 0, 0, 0, 1]);
    }

    #[test]
    fn eval() {
        fn check<F: Fn(i32) -> i32>(pol: &[i32], f: F) {
            for n in -10..10 {
                assert_eq!(f(n), Polynomial::new(pol.to_vec()).eval(n));
            }
        }
        check(&[], |_x| 0);
        check(&[1], |_x| 1);
        check(&[1, 1], |x| x + 1);
        check(&[0, 1], |x| x);
        check(&[10, -10, 10], |x| 10 * x * x - 10 * x + 10);
    }

    #[test]
    fn pretty() {
        fn check(slice: &[i32], s: &str) {
            assert_eq!(s.to_string(), Polynomial::new(slice.to_vec()).pretty("x"));
        }
        check(&[0], "0");
        check(&[1], "1");
        check(&[1, 1], "1+x");
        check(&[1, 1, 1], "1+x+x^2");
        check(&[2, 2, 2], "2+2*x+2*x^2");
        check(&[0, 0, 0, 1], "x^3");
        check(&[0, 0, 0, -1], "-x^3");
        check(&[-1, 0, 0, -1], "-1-x^3");
        check(&[-1, 1, 0, -1], "-1+x-x^3");
        check(&[-1, 1, -1, -1], "-1+x-x^2-x^3");
    }
}
<commit_msg>Run rustfmt<commit_after>//! Manipulations and data types that represent polynomial.

#![warn(bad_style)]
#![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate num;

use std::{cmp, fmt};
use std::ops::{Add, Mul, Neg, Sub};
use num::{Zero, One};

/// Polynomial expression
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct Polynomial<T> {
    data: Vec<T>,
}

impl<T: Zero> Polynomial<T> {
    /// Creates new `Polynomial`.
    ///
    /// ```rust
    /// use polynomial::Polynomial;
    /// let poly = Polynomial::new(vec![1, 2, 3]);
    /// assert_eq!("1+2*x+3*x^2", poly.pretty("x"));
    /// ```
    #[inline]
    pub fn new(mut data: Vec<T>) -> Polynomial<T> {
        while let Some(true) = data.last().map(|x| x.is_zero()) {
            let _ = data.pop();
        }
        Polynomial { data: data }
    }
}

impl<T: Zero + One + Clone> Polynomial<T> {
    /// Evaluates the polynomial value.
    ///
    /// ```rust
    /// use polynomial::Polynomial;
    /// let poly = Polynomial::new(vec![1, 2, 3]);
    /// assert_eq!(1, poly.eval(0));
    /// assert_eq!(6, poly.eval(1));
    /// assert_eq!(17, poly.eval(2));
    /// ```
    #[inline]
    pub fn eval(&self, x: T) -> T {
        let mut sum: T = Zero::zero();
        let mut x_n: T = One::one();
        for n in self.data.iter() {
            sum = sum + n.clone() * x_n.clone();
            x_n = x_n * x.clone();
        }
        sum
    }
}

impl<T> Polynomial<T> {
    /// Gets the slice of internal data.
    #[inline]
    pub fn data(&self) -> &[T] {
        &self.data
    }
}

impl<T> Polynomial<T>
    where T: Zero + One + Eq + Neg<Output = T> + Ord + fmt::Display + Clone
{
    /// Pretty prints the polynomial.
    pub fn pretty(&self, x: &str) -> String {
        if self.is_zero() {
            return "0".to_string();
        }

        let one = One::one();
        let mut s = Vec::new();
        for (i, n) in self.data.iter().enumerate() {
            // output n*x^i / -n*x^i
            if n.is_zero() {
                continue;
            }

            let term = if i.is_zero() {
                n.to_string()
            } else if i == 1 {
                if (*n) == one {
                    x.to_string()
                } else if (*n) == -one.clone() {
                    format!("-{}", x)
                } else {
                    format!("{}*{}", n.to_string(), x)
                }
            } else {
                if (*n) == one {
                    format!("{}^{}", x, i)
                } else if (*n) == -one.clone() {
                    format!("-{}^{}", x, i)
                } else {
                    format!("{}*{}^{}", n.to_string(), x, i)
                }
            };

            if s.len() > 0 && (*n) > Zero::zero() {
                s.push("+".to_string());
            }
            s.push(term);
        }

        s.concat()
    }
}

impl<'a, T> Neg for Polynomial<T>
    where T: Neg + Zero + Clone,
          <T as Neg>::Output: Zero
{
    type Output = Polynomial<<T as Neg>::Output>;

    #[inline]
    fn neg(self) -> Polynomial<<T as Neg>::Output> {
        -&self
    }
}

impl<'a, T> Neg for &'a Polynomial<T>
    where T: Neg + Zero + Clone,
          <T as Neg>::Output: Zero
{
    type Output = Polynomial<<T as Neg>::Output>;

    #[inline]
    fn neg(self) -> Polynomial<<T as Neg>::Output> {
        Polynomial::new(self.data.iter().map(|x| -x.clone()).collect())
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs> $imp<Polynomial<Rhs>> for Polynomial<Lhs>
            where Lhs: Zero + $imp<Rhs> + Clone, Rhs: Zero + Clone,
                  <Lhs as $imp<Rhs>>::Output: Zero
        {
            type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<Polynomial<Rhs>> for &'a Polynomial<Lhs>
            where Lhs: Zero + $imp<Rhs> + Clone, Rhs: Zero + Clone,
                  <Lhs as $imp<Rhs>>::Output: Zero
        {
            type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<&'a Polynomial<Rhs>> for Polynomial<Lhs>
            where Lhs: Zero + $imp<Rhs> + Clone, Rhs: Zero + Clone,
                  <Lhs as $imp<Rhs>>::Output: Zero
        {
            type Output = Polynomial<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs> Add<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
    where Lhs: Zero + Add<Rhs> + Clone,
          Rhs: Zero + Clone,
          <Lhs as Add<Rhs>>::Output: Zero
{
    type Output = Polynomial<<Lhs as Add<Rhs>>::Output>;

    fn add(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Add<Rhs>>::Output> {
        let max_len = cmp::max(self.data.len(), other.data.len());
        let min_len = cmp::min(self.data.len(), other.data.len());

        let mut sum = Vec::with_capacity(max_len);
        for i in 0..min_len {
            sum.push(self.data[i].clone() + other.data[i].clone());
        }

        if self.data.len() <= other.data.len() {
            for i in min_len..max_len {
                sum.push(num::zero::<Lhs>() + other.data[i].clone());
            }
        } else {
            for i in min_len..max_len {
                sum.push(self.data[i].clone() + num::zero::<Rhs>());
            }
        }

        Polynomial::new(sum)
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs> Sub<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
    where Lhs: Zero + Sub<Rhs> + Clone,
          Rhs: Zero + Clone,
          <Lhs as Sub<Rhs>>::Output: Zero
{
    type Output = Polynomial<<Lhs as Sub<Rhs>>::Output>;

    fn sub(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Sub<Rhs>>::Output> {
        let min_len = cmp::min(self.data.len(), other.data.len());
        let max_len = cmp::max(self.data.len(), other.data.len());

        let mut sub = Vec::with_capacity(max_len);
        for i in 0..min_len {
            sub.push(self.data[i].clone() - other.data[i].clone());
        }
        if self.data.len() <= other.data.len() {
            for i in min_len..max_len {
                sub.push(num::zero::<Lhs>() - other.data[i].clone())
            }
        } else {
            for i in min_len..max_len {
                sub.push(self.data[i].clone() - num::zero::<Rhs>())
            }
        }
        Polynomial::new(sub)
    }
}

forward_all_binop!(impl Mul, mul);

impl<'a, 'b, Lhs, Rhs> Mul<&'b Polynomial<Rhs>> for &'a Polynomial<Lhs>
    where Lhs: Zero + Mul<Rhs> + Clone,
          Rhs: Zero + Clone,
          <Lhs as Mul<Rhs>>::Output: Zero
{
    type Output = Polynomial<<Lhs as Mul<Rhs>>::Output>;

    fn mul(self, other: &Polynomial<Rhs>) -> Polynomial<<Lhs as Mul<Rhs>>::Output> {
        if self.is_zero() || other.is_zero() {
            return Polynomial::new(vec![]);
        }

        let slen = self.data.len();
        let olen = other.data.len();
        let prod = (0..slen + olen - 1)
            .map(|i| {
                let mut p = num::zero::<<Lhs as Mul<Rhs>>::Output>();
                let kstart = cmp::max(olen, i + 1) - olen;
                let kend = cmp::min(slen, i + 1);
                for k in kstart..kend {
                    p = p + self.data[k].clone() * other.data[i - k].clone();
                }
                p
            })
            .collect();
        Polynomial::new(prod)
    }
}

impl<T: Zero + Clone> Zero for Polynomial<T> {
    #[inline]
    fn zero() -> Polynomial<T> {
        Polynomial { data: vec![] }
    }
    #[inline]
    fn is_zero(&self) -> bool {
        self.data.is_empty()
    }
}

impl<T: Zero + One + Clone> One for Polynomial<T> {
    #[inline]
    fn one() -> Polynomial<T> {
        Polynomial { data: vec![One::one()] }
    }
}

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

    #[test]
    fn new() {
        fn check(dst: Vec<i32>, src: Vec<i32>) {
            assert_eq!(dst, Polynomial::new(src).data);
        }
        check(vec![1, 2, 3], vec![1, 2, 3]);
        check(vec![1, 2, 3], vec![1, 2, 3, 0, 0]);
        check(vec![], vec![0, 0, 0]);
    }

    #[test]
    fn neg_add_sub() {
        fn check(a: &[i32], b: &[i32], c: &[i32]) {
            fn check_eq(a: &Polynomial<i32>, b: &Polynomial<i32>) {
                assert_eq!(*a, *b);
                assert_eq!(-a, -b);
            }
            fn check_add(sum: &Polynomial<i32>, a: &Polynomial<i32>, b: &Polynomial<i32>) {
                check_eq(sum, &(a + b));
                check_eq(sum, &(b + a));
            }
            fn check_sub(sum: &Polynomial<i32>, a: &Polynomial<i32>, b: &Polynomial<i32>) {
                check_eq(a, &(sum - b));
                check_eq(b, &(sum - a));
            }

            let a = &Polynomial::new(a.to_vec());
            let b = &Polynomial::new(b.to_vec());
            let c = &Polynomial::new(c.to_vec());
            check_add(c, a, b);
            check_add(&(-c), &(-a), &(-b));
            check_sub(c, a, b);
            check_sub(&(-c), &(-a), &(-b));
        }
        check(&[], &[], &[]);
        check(&[], &[1], &[1]);
        check(&[1], &[1], &[2]);
        check(&[1, 0, 1], &[1], &[2, 0, 1]);
        check(&[1, 0, -1], &[-1, 0, 1], &[]);
    }

    #[test]
    fn mul() {
        fn check(a: &[i32], b: &[i32], c: &[i32]) {
            let a = Polynomial::new(a.to_vec());
            let b = Polynomial::new(b.to_vec());
            let c = Polynomial::new(c.to_vec());
            assert_eq!(c, &a * &b);
            assert_eq!(c, &b * &a);
        }
        check(&[], &[], &[]);
        check(&[0, 0], &[], &[]);
        check(&[0, 0], &[1], &[]);
        check(&[1, 0], &[1], &[1]);
        check(&[1, 0, 1], &[1], &[1, 0, 1]);
        check(&[1, 1], &[1, 1], &[1, 2, 1]);
        check(&[1, 1], &[1, 0, 1], &[1, 1, 1, 1]);
        check(&[0, 0, 1], &[0, 0, 1], &[0, 0, 0, 0, 1]);
    }

    #[test]
    fn eval() {
        fn check<F: Fn(i32) -> i32>(pol: &[i32], f: F) {
            for n in -10..10 {
                assert_eq!(f(n), Polynomial::new(pol.to_vec()).eval(n));
            }
        }
        check(&[], |_x| 0);
        check(&[1], |_x| 1);
        check(&[1, 1], |x| x + 1);
        check(&[0, 1], |x| x);
        check(&[10, -10, 10], |x| 10 * x * x - 10 * x + 10);
    }

    #[test]
    fn pretty() {
        fn check(slice: &[i32], s: &str) {
            assert_eq!(s.to_string(), Polynomial::new(slice.to_vec()).pretty("x"));
        }
        check(&[0], "0");
        check(&[1], "1");
        check(&[1, 1], "1+x");
        check(&[1, 1, 1], "1+x+x^2");
        check(&[2, 2, 2], "2+2*x+2*x^2");
        check(&[0, 0, 0, 1], "x^3");
        check(&[0, 0, 0, -1], "-x^3");
        check(&[-1, 0, 0, -1], "-1-x^3");
        check(&[-1, 1, 0, -1], "-1+x-x^3");
        check(&[-1, 1, -1, -1], "-1+x-x^2-x^3");
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#![cfg_attr(feature = "serde_derive", feature(proc_macro))]

#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;
extern crate serde_urlencoded;

#[macro_use]
extern crate error_chain;

// We'll put our errors in an `errors` module, and other modules in
// this crate will `use errors::*;` to get access to everything
// `error_chain!` creates.
pub mod errors {
    // Create the Error, ErrorKind, ResultExt, and Result types
    error_chain!{}
}

use ::errors::*;

#[cfg(feature = "serde_derive")]
include!("serde_types.in.rs");

#[cfg(feature = "serde_codegen")]
include!(concat!(env!("OUT_DIR"), "/serde_types.rs"));

#[macro_use]
extern crate log;
extern crate hyper;

extern crate regex;
extern crate url;

pub mod gitlab;
pub mod groups;
pub mod projects;
pub mod issues;
pub mod merge_requests;

// Re-export those structs
pub use gitlab::GitLab;
// pub use projects::Project;
// Re-export those traits

trait BuildQuery {
    fn build_query(&self) -> String;
}

pub trait Lister<T> {
    fn list(&self) -> Result<T>;
    fn list_paginated(&self, page: u16, per_page: u16) -> Result<T>;
}

#[cfg(test)]
mod tests {
    // use gitlab::GitLab;
    // use hyper;

    // #[test]
    // fn unauthorized() {
    //     let gl = GitLab::new("http", "gitlab.com", 80, "XXXXXXXXXXXXX").unwrap();
    //     println!("gl: {:?}", gl);
    //     assert_eq!(gl.attempt_connection().unwrap().status,
    //                hyper::status::StatusCode::Unauthorized);
    // }
}
<commit_msg>Add a test deserializing a search for project<commit_after>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#![cfg_attr(feature = "serde_derive", feature(proc_macro))]

#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;
extern crate serde_urlencoded;

#[macro_use]
extern crate error_chain;

// We'll put our errors in an `errors` module, and other modules in
// this crate will `use errors::*;` to get access to everything
// `error_chain!` creates.
pub mod errors {
    // Create the Error, ErrorKind, ResultExt, and Result types
    error_chain!{}
}

use ::errors::*;

#[cfg(feature = "serde_derive")]
include!("serde_types.in.rs");

#[cfg(feature = "serde_codegen")]
include!(concat!(env!("OUT_DIR"), "/serde_types.rs"));

#[macro_use]
extern crate log;
extern crate hyper;

extern crate regex;
extern crate url;

pub mod gitlab;
pub mod groups;
pub mod projects;
pub mod issues;
pub mod merge_requests;

// Re-export those structs
pub use gitlab::GitLab;
// pub use projects::Project;
// Re-export those traits

trait BuildQuery {
    fn build_query(&self) -> String;
}

pub trait Lister<T> {
    fn list(&self) -> Result<T>;
    fn list_paginated(&self, page: u16, per_page: u16) -> Result<T>;
}

#[cfg(test)]
mod tests {
    // use gitlab::GitLab;
    // use hyper;
    use serde_json;
    use std::error::Error;

    // #[test]
    // fn unauthorized() {
    //     let gl = GitLab::new("http", "gitlab.com", 80, "XXXXXXXXXXXXX").unwrap();
    //     println!("gl: {:?}", gl);
    //     assert_eq!(gl.attempt_connection().unwrap().status,
    //                hyper::status::StatusCode::Unauthorized);
    // }

    #[test]
    fn deserialize_project() {
        let json_reply = r##"[
            {
                "id": 517564,
                "description": "GitLab API library and client in Rust",
                "default_branch": "master",
                "tag_list": [],
                "public": false,
                "archived": false,
                "visibility_level": 0,
                "ssh_url_to_repo": "git@gitlab.com:nbigaouette1/gitlab-api-rs.git",
                "http_url_to_repo": "https://gitlab.com/nbigaouette1/gitlab-api-rs.git",
                "web_url": "https://gitlab.com/nbigaouette1/gitlab-api-rs",
                "owner": {
                    "name": "Nicolas Bigaouette",
                    "username": "nbigaouette1",
                    "id": 163821,
                    "state": "active",
                    "avatar_url": "https://secure.gravatar.com/avatar/3325e461df2fda8738f35a8bf4fd735e?s=80&d=identicon",
                    "web_url": "https://gitlab.com/nbigaouette1"
                },
                "name": "gitlab-api-rs",
                "name_with_namespace": "Nicolas Bigaouette / gitlab-api-rs",
                "path": "gitlab-api-rs",
                "path_with_namespace": "nbigaouette1/gitlab-api-rs",
                "container_registry_enabled": null,
                "issues_enabled": true,
                "merge_requests_enabled": true,
                "wiki_enabled": true,
                "builds_enabled": false,
                "snippets_enabled": false,
                "created_at": "2015-10-09T00:32:18.646Z",
                "last_activity_at": "2017-01-31T14:46:26.638Z",
                "shared_runners_enabled": true,
                "lfs_enabled": true,
                "creator_id": 163821,
                "namespace": {
                    "id": 193119,
                    "name": "nbigaouette1",
                    "path": "nbigaouette1",
                    "kind": "user"
                },
                "avatar_url": null,
                "star_count": 0,
                "forks_count": 0,
                "open_issues_count": 1,
                "public_builds": true,
                "shared_with_groups": [],
                "only_allow_merge_if_build_succeeds": false,
                "request_access_enabled": true,
                "only_allow_merge_if_all_discussions_are_resolved": null,
                "approvals_before_merge": 0
            }
        ]"##;

        let project: ::Projects = serde_json::from_str(json_reply).expect("JSON deserialization failed");
    }
}
<|endoftext|>


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

//! A bare-metal library supplying functions rustc may lower code to
//!
//! This library is not intended for general use, and is superseded by a system
//! libc if one is available. In a freestanding context, however, common
//! functions such as memset, memcpy, etc are not implemented. This library
//! provides an implementation of these functions which are either required by
//! libcore or called by rustc implicitly.
//!
//! This library is never included by default, and must be manually included if
//! necessary. It is an error to include this library when also linking with
//! the system libc library.

#![no_std]
#![feature(no_std, core)]
#![cfg_attr(test, feature(core_str_ext, core_slice_ext))]

// This library defines the builtin functions, so it would be a shame for
// LLVM to optimize these function calls to themselves!
#![no_builtins]

extern crate core;

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

#[no_mangle]
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
                            n: usize) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *dest.offset(i as isize) = *src.offset(i as isize);
        i += 1;
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
                             n: usize) -> *mut u8 {
    if src < dest as *const u8 { // copy from end
        let mut i = n;
        while i != 0 {
            i -= 1;
            *dest.offset(i as isize) = *src.offset(i as isize);
        }
    } else { // copy from beginning
        let mut i = 0;
        while i < n {
            *dest.offset(i as isize) = *src.offset(i as isize);
            i += 1;
        }
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *s.offset(i as isize) = c as u8;
        i += 1;
    }
    return s;
}

#[no_mangle]
pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
    let mut i = 0;
    while i < n {
        let a = *s1.offset(i as isize);
        let b = *s2.offset(i as isize);
        if a != b {
            return a as i32 - b as i32
        }
        i += 1;
    }
    return 0;
}

#[cfg(test)]
mod test {
    use core::str::StrExt;
    use core::slice::SliceExt;

    use super::{memcmp, memset, memcpy, memmove};

    #[test]
    fn memcmp_single_byte_pointers() {
        unsafe {
            assert_eq!(memcmp(&0xFAu8, &0xFAu8, 1), 0x00);
            assert!(memcmp(&0xEFu8, &0xFEu8, 1) < 0x00);
        }
    }

    #[test]
    fn memcmp_strings() {
        {
            let (x, z) = ("Hello!", "Good Bye.");
            let l = x.len();
            unsafe {
                assert_eq!(memcmp(x.as_ptr(), x.as_ptr(), l), 0);
                assert!(memcmp(x.as_ptr(), z.as_ptr(), l) > 0);
                assert!(memcmp(z.as_ptr(), x.as_ptr(), l) < 0);
            }
        }
        {
            let (x, z) = ("hey!", "hey.");
            let l = x.len();
            unsafe {
                assert!(memcmp(x.as_ptr(), z.as_ptr(), l) < 0);
            }
        }
    }

    #[test]
    fn memset_single_byte_pointers() {
        let mut x: u8 = 0xFF;
        unsafe {
            memset(&mut x, 0xAA, 1);
            assert_eq!(x, 0xAA);
            memset(&mut x, 0x00, 1);
            assert_eq!(x, 0x00);
            x = 0x01;
            memset(&mut x, 0x12, 0);
            assert_eq!(x, 0x01);
        }
    }

    #[test]
    fn memset_array() {
        let mut buffer = [b'X';  100];
        unsafe {
            memset(buffer.as_mut_ptr(), b'#' as i32, buffer.len());
        }
        for byte in buffer.iter() { assert_eq!(*byte, b'#'); }
    }

    #[test]
    fn memcpy_and_memcmp_arrays() {
        let (src, mut dst) = ([b'X';  100], [b'Y';  100]);
        unsafe {
            assert!(memcmp(src.as_ptr(), dst.as_ptr(), 100) != 0);
            let _ = memcpy(dst.as_mut_ptr(), src.as_ptr(), 100);
            assert_eq!(memcmp(src.as_ptr(), dst.as_ptr(), 100), 0);
        }
    }

    #[test]
    fn memmove_overlapping() {
        {
            let mut buffer = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9' ];
            unsafe {
                memmove(&mut buffer[4], &buffer[0], 6);
                let mut i = 0;
                for byte in b"0123012345".iter() {
                    assert_eq!(buffer[i], *byte);
                    i += 1;
                }
            }
        }
        {
            let mut buffer = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9' ];
            unsafe {
                memmove(&mut buffer[0], &buffer[4], 6);
                let mut i = 0;
                for byte in b"4567896789".iter() {
                    assert_eq!(buffer[i], *byte);
                    i += 1;
                }
            }
        }
    }
}
<commit_msg>Update to nightly Rust<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A bare-metal library supplying functions rustc may lower code to
//!
//! This library is not intended for general use, and is superseded by a system
//! libc if one is available. In a freestanding context, however, common
//! functions such as memset, memcpy, etc are not implemented. This library
//! provides an implementation of these functions which are either required by
//! libcore or called by rustc implicitly.
//!
//! This library is never included by default, and must be manually included if
//! necessary. It is an error to include this library when also linking with
//! the system libc library.

#![no_std]
#![feature(no_std)]
#![cfg_attr(test, feature(core_str_ext, core_slice_ext))]

// This library defines the builtin functions, so it would be a shame for
// LLVM to optimize these function calls to themselves!
#![no_builtins]

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

#[no_mangle]
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
                            n: usize) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *dest.offset(i as isize) = *src.offset(i as isize);
        i += 1;
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
                             n: usize) -> *mut u8 {
    if src < dest as *const u8 { // copy from end
        let mut i = n;
        while i != 0 {
            i -= 1;
            *dest.offset(i as isize) = *src.offset(i as isize);
        }
    } else { // copy from beginning
        let mut i = 0;
        while i < n {
            *dest.offset(i as isize) = *src.offset(i as isize);
            i += 1;
        }
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *s.offset(i as isize) = c as u8;
        i += 1;
    }
    return s;
}

#[no_mangle]
pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
    let mut i = 0;
    while i < n {
        let a = *s1.offset(i as isize);
        let b = *s2.offset(i as isize);
        if a != b {
            return a as i32 - b as i32
        }
        i += 1;
    }
    return 0;
}

#[cfg(test)]
mod test {
    use core::str::StrExt;
    use core::slice::SliceExt;

    use super::{memcmp, memset, memcpy, memmove};

    #[test]
    fn memcmp_single_byte_pointers() {
        unsafe {
            assert_eq!(memcmp(&0xFAu8, &0xFAu8, 1), 0x00);
            assert!(memcmp(&0xEFu8, &0xFEu8, 1) < 0x00);
        }
    }

    #[test]
    fn memcmp_strings() {
        {
            let (x, z) = ("Hello!", "Good Bye.");
            let l = x.len();
            unsafe {
                assert_eq!(memcmp(x.as_ptr(), x.as_ptr(), l), 0);
                assert!(memcmp(x.as_ptr(), z.as_ptr(), l) > 0);
                assert!(memcmp(z.as_ptr(), x.as_ptr(), l) < 0);
            }
        }
        {
            let (x, z) = ("hey!", "hey.");
            let l = x.len();
            unsafe {
                assert!(memcmp(x.as_ptr(), z.as_ptr(), l) < 0);
            }
        }
    }

    #[test]
    fn memset_single_byte_pointers() {
        let mut x: u8 = 0xFF;
        unsafe {
            memset(&mut x, 0xAA, 1);
            assert_eq!(x, 0xAA);
            memset(&mut x, 0x00, 1);
            assert_eq!(x, 0x00);
            x = 0x01;
            memset(&mut x, 0x12, 0);
            assert_eq!(x, 0x01);
        }
    }

    #[test]
    fn memset_array() {
        let mut buffer = [b'X';  100];
        unsafe {
            memset(buffer.as_mut_ptr(), b'#' as i32, buffer.len());
        }
        for byte in buffer.iter() { assert_eq!(*byte, b'#'); }
    }

    #[test]
    fn memcpy_and_memcmp_arrays() {
        let (src, mut dst) = ([b'X';  100], [b'Y';  100]);
        unsafe {
            assert!(memcmp(src.as_ptr(), dst.as_ptr(), 100) != 0);
            let _ = memcpy(dst.as_mut_ptr(), src.as_ptr(), 100);
            assert_eq!(memcmp(src.as_ptr(), dst.as_ptr(), 100), 0);
        }
    }

    #[test]
    fn memmove_overlapping() {
        {
            let mut buffer = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9' ];
            unsafe {
                memmove(&mut buffer[4], &buffer[0], 6);
                let mut i = 0;
                for byte in b"0123012345".iter() {
                    assert_eq!(buffer[i], *byte);
                    i += 1;
                }
            }
        }
        {
            let mut buffer = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9' ];
            unsafe {
                memmove(&mut buffer[0], &buffer[4], 6);
                let mut i = 0;
                for byte in b"4567896789".iter() {
                    assert_eq!(buffer[i], *byte);
                    i += 1;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>#![crate_name = "librespot"]

pub extern crate librespot_audio as audio;
pub extern crate librespot_connect as connect;
pub extern crate librespot_core as core;
pub extern crate librespot_metadata as metadata;
pub extern crate librespot_playback as playback;
pub extern crate librespot_protocol as protocol;
<commit_msg>Replace "extern crate"s<commit_after>#![crate_name = "librespot"]

pub use librespot_audio as audio;
pub use librespot_connect as connect;
pub use librespot_core as core;
pub use librespot_metadata as metadata;
pub use librespot_playback as playback;
pub use librespot_protocol as protocol;
<|endoftext|>


<commit_before>#[macro_use] extern crate lazy_static;
pub use dynamic::dlsym_next;
pub use serverset::Serverset;
pub mod hooks;
pub mod dynamic;
pub mod serverset;
pub mod chain;
pub mod util;
<commit_msg>initial dns client scaffolding<commit_after>#[macro_use] extern crate lazy_static;
pub use dynamic::dlsym_next;
pub use serverset::Serverset;
pub mod hooks;
pub mod dynamic;
pub mod serverset;
pub mod chain;
pub mod util;
pub mod dns;
<|endoftext|>


<commit_before>#![allow(clippy::cyclomatic_complexity)]
#![allow(clippy::let_and_return)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::write_literal)]

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;

/// Log warning only if type in generated library
macro_rules! warn_main {
    ($tid: expr, $target:expr, $($arg:tt)*) => (
        if $tid.ns_id == crate::library::MAIN_NAMESPACE {
            warn!($target, $($arg)*);
        }
    );
}

//generated by build.rs
mod gir_version;

pub mod analysis;
mod case;
mod chunk;
mod codegen;
mod config;
mod consts;
mod custom_type_glib_priority;
mod env;
mod file_saver;
mod git;
pub mod library;
mod library_postprocessing;
mod library_preprocessing;
mod nameutil;
mod parser;
mod traits;
pub mod update_version;
mod version;
mod visitors;
mod writer;
mod xmlparser;

pub use crate::{
    analysis::{
        class_hierarchy::run as class_hierarchy_run, namespaces::run as namespaces_run,
        run as analysis_run, symbols::run as symbols_run,
    },
    codegen::generate as codegen_generate,
    config::{Config, WorkMode},
    env::Env,
    library::Library,
};
<commit_msg>Activate lints for edition idioms<commit_after>#![allow(clippy::cyclomatic_complexity)]
#![allow(clippy::let_and_return)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::write_literal)]
#![deny(bare_trait_objects)]
#![deny(elided_lifetimes_in_paths)]

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;

/// Log warning only if type in generated library
macro_rules! warn_main {
    ($tid: expr, $target:expr, $($arg:tt)*) => (
        if $tid.ns_id == crate::library::MAIN_NAMESPACE {
            warn!($target, $($arg)*);
        }
    );
}

//generated by build.rs
mod gir_version;

pub mod analysis;
mod case;
mod chunk;
mod codegen;
mod config;
mod consts;
mod custom_type_glib_priority;
mod env;
mod file_saver;
mod git;
pub mod library;
mod library_postprocessing;
mod library_preprocessing;
mod nameutil;
mod parser;
mod traits;
pub mod update_version;
mod version;
mod visitors;
mod writer;
mod xmlparser;

pub use crate::{
    analysis::{
        class_hierarchy::run as class_hierarchy_run, namespaces::run as namespaces_run,
        run as analysis_run, symbols::run as symbols_run,
    },
    codegen::generate as codegen_generate,
    config::{Config, WorkMode},
    env::Env,
    library::Library,
};
<|endoftext|>