<commit_before>// Copyright (c) 2016 Anatoly Ikorsky
//
// 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. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use BoxFuture;
use conn::Conn;
use errors::*;
use lib_futures::Async;
use lib_futures::Async::Ready;
use lib_futures::Async::NotReady;
use lib_futures::Future;
use lib_futures::task::{self, Task};
use queryable::Queryable;
use queryable::transaction::{Transaction, TransactionOptions};
use std::fmt;
use opts::Opts;
use self::futures::*;
use std::cell::Ref;
use std::cell::RefCell;
use std::cell::RefMut;
use std::rc::Rc;
use tokio::reactor::Handle;

pub mod futures;

pub struct Inner {
    closed: bool,
    new: Vec<BoxFuture<Conn>>,
    idle: Vec<Conn>,
    disconnecting: Vec<BoxFuture<()>>,
    dropping: Vec<BoxFuture<Conn>>,
    rollback: Vec<BoxFuture<Conn>>,
    ongoing: usize,
    tasks: Vec<Task>,
}

#[derive(Clone)]
/// Asynchronous pool of MySql connections.
pub struct Pool {
    handle: Handle,
    opts: Opts,
    inner: Rc<RefCell<Inner>>,
    min: usize,
    max: usize,
}

impl fmt::Debug for Pool {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Pool")
            .field("min", &self.min)
            .field("max", &self.max)
            .field("new connections count", &self.inner_ref().new.len())
            .field("idle connections count", &self.inner_ref().idle.len())
            .field(
                "disconnecting connections count",
                &self.inner_ref().disconnecting.len(),
            )
            .finish()
    }
}

impl Pool {
    /// Creates new pool of connections.
    pub fn new<O: Into<Opts>>(opts: O, handle: &Handle) -> Pool {
        let opts = opts.into();
        let pool_min = opts.get_pool_min();
        let pool_max = opts.get_pool_max();
        let pool = Pool {
            handle: handle.clone(),
            opts: opts,
            inner: Rc::new(RefCell::new(Inner {
                closed: false,
                new: Vec::with_capacity(pool_min),
                idle: Vec::new(),
                disconnecting: Vec::new(),
                dropping: Vec::new(),
                rollback: Vec::new(),
                ongoing: 0,
                tasks: Vec::new(),
            })),
            min: pool_min,
            max: pool_max,
        };

        pool
    }

    /// Returns future that resolves to `Conn`.
    pub fn get_conn(&self) -> GetConn {
        new_get_conn(self)
    }

    /// Shortcut for `get_conn` followed by `start_transaction`.
    pub fn start_transaction(&self, options: TransactionOptions) -> BoxFuture<Transaction<Conn>> {
        let fut = self.get_conn().and_then(|conn| {
            Queryable::start_transaction(conn, options)
        });
        Box::new(fut)
    }

    /// Returns future that disconnects this pool from server and resolves to `()`.
    ///
    /// Active connections taken from this pool should be disconnected manually.
    /// Also all pending and new `GetConn`'s will resolve to error.
    pub fn disconnect(mut self) -> DisconnectPool {
        if !self.inner_ref().closed {
            self.inner_mut().closed = true;
            while let Some(conn) = self.take_conn() {
                self.inner_mut().disconnecting.push(conn.disconnect());
            }
        }
        new_disconnect_pool(self)
    }

    /// Returns true if futures is in queue.
    fn in_queue(&self) -> bool {
        let inner = self.inner_ref();
        let count = inner.new.len() + inner.disconnecting.len() + inner.dropping.len() +
            inner.rollback.len();
        count > 0
    }

    /// A way to take connection from a pool.
    fn take_conn(&mut self) -> Option<Conn> {
        if self.in_queue() {
            // Do not return connection until queue is empty
            return None;
        }
        while self.inner_ref().idle.len() > 0 {
            let conn = self.inner_mut().idle.pop();
            let conn = conn.and_then(|mut conn| if conn.expired() {
                self.inner_mut().disconnecting.push(conn.disconnect());
                None
            } else {
                conn.pool = Some(self.clone());
                Some(conn)
            });
            if conn.is_some() {
                self.inner_mut().ongoing += 1;
                return conn;
            }
        }
        None
    }

    /// A way to return connection taken from a pool.
    fn return_conn(&mut self, conn: Conn) {
        if self.inner_ref().closed {
            return;
        }
        let min = self.min;
        let mut inner = self.inner_mut();
        inner.ongoing -= 1;

        if conn.has_result.is_some() {
            inner.dropping.push(conn.drop_result());
        } else if conn.in_transaction {
            inner.rollback.push(conn.rollback_transaction())
        } else {
            let idle_len = inner.idle.len();
            if idle_len >= min {
                inner.disconnecting.push(conn.disconnect());
            } else {
                inner.idle.push(conn);
            }
        }

        while let Some(task) = inner.tasks.pop() {
            task.notify()
        }
    }

    fn inner_ref(&self) -> Ref<Inner> {
        self.inner.borrow()
    }

    fn inner_mut(&mut self) -> RefMut<Inner> {
        self.inner.borrow_mut()
    }

    /// Will manage lifetime of futures stored in a pool.
    fn handle_futures(&mut self) -> Result<()> {
        if !self.in_queue() {
            // There is no futures in queue
            return Ok(());
        }

        macro_rules! handle {
            ($vec:ident { $($p:pat => $b:block,)+ }) => ({
                let len = self.inner_ref().$vec.len();
                let mut done_fut_idxs = Vec::new();
                for i in 0..len {
                    let result = self.inner_mut().$vec.get_mut(i).unwrap().poll();
                    match result {
                        Ok(Ready(_)) | Err(_) => done_fut_idxs.push(i),
                        _ => (),
                    }

                    let out: Result<()> = match result {
                        $($p => $b),+
                        _ => {
                            Ok(())
                        }
                    };

                    match out {
                        Err(err) => {
                            // early return in case of error
                            while let Some(i) = done_fut_idxs.pop() {
                                let _ = self.inner_mut().$vec.swap_remove(i);
                            }
                            return Err(err)
                        }
                        _ => (),
                    }
                }

                while let Some(i) = done_fut_idxs.pop() {
                    let _ = self.inner_mut().$vec.swap_remove(i);
                }
            });
        }

        let mut handled = false;

        // Handle closing connections.
        handle!(disconnecting {
            Ok(Ready(_)) => {
                handled = true;
                Ok(())
            },
            Err(_) => { Ok(()) },
        });

        // Handle dirty connections.
        handle!(dropping {
            Ok(Ready(conn)) => {
                let closed = self.inner_ref().closed;
                if closed {
                    self.inner_mut().disconnecting.push(conn.disconnect());
                } else {
                    self.return_conn(conn);
                }
                handled = true;
                Ok(())
            },
            Err(_) => { Ok(()) },
        });

        // Handle in-transaction connections
        handle!(rollback {
            Ok(Ready(conn)) => {
                let closed = self.inner_ref().closed;
                if closed {
                    self.inner_mut().disconnecting.push(conn.disconnect());
                } else {
                    self.return_conn(conn);
                }
                handled = true;
                Ok(())
            },
            Err(_) => { Ok(()) },
        });

        // Handle connecting connections.
        handle!(new {
            Ok(Ready(conn)) => {
                let closed = self.inner_ref().closed;
                if closed {
                    self.inner_mut().disconnecting.push(conn.disconnect());
                } else {
                    self.inner_mut().ongoing += 1;
                    self.return_conn(conn);
                }
                handled = true;
                Ok(())
            },
            Err(err) => {
                if ! self.inner_ref().closed {
                    Err(err)
                } else {
                    Ok(())
                }
            },
        });

        if handled {
            self.handle_futures()
        } else {
            Ok(())
        }
    }

    fn conn_count(&self) -> usize {
        let inner = self.inner_ref();
        inner.new.len() + inner.idle.len() + inner.disconnecting.len() + inner.dropping.len()
            + inner.rollback.len() + inner.ongoing
    }

    /// Will poll pool for connection.
    fn poll(&mut self) -> Result<Async<Conn>> {
        if self.inner_ref().closed {
            return Err(ErrorKind::PoolDisconnected.into());
        }

        self.handle_futures()?;

        match self.take_conn() {
            Some(conn) => Ok(Ready(conn)),
            None => {
                let new_len = self.inner_ref().new.len();
                if new_len == 0 && self.conn_count() < self.max {
                    let new_conn = Conn::new(self.opts.clone(), &self.handle);
                    self.inner_mut().new.push(new_conn);
                    self.poll()
                } else {
                    self.inner_mut().tasks.push(task::current());
                    Ok(NotReady)
                }
            }
        }
    }
}

impl Drop for Conn {
    fn drop(&mut self) {
        if let Some(mut pool) = self.pool.take() {
            let conn = self.take();
            if conn.stream.is_some() {
                pool.return_conn(conn)
            } // drop incomplete connection
        }
    }
}

#[cfg(test)]
mod test {
    use TransactionOptions;
    use conn::pool::Pool;
    use lib_futures::Future;
    use queryable::Queryable;
    use test_misc::DATABASE_URL;
    use tokio::reactor::Core;

    #[test]
    fn should_connect() {
        let mut lp = Core::new().unwrap();

        let pool = Pool::new(&**DATABASE_URL, &lp.handle());
        let fut = pool.get_conn()
            .and_then(|conn| conn.ping().map(|_| ()))
            .and_then(|_| pool.disconnect());

        lp.run(fut).unwrap();
    }

    #[test]
    fn should_start_transaction() {
        let mut lp = Core::new().unwrap();

        let pool = Pool::new(
            format!("{}?pool_min=1&pool_max=1", &**DATABASE_URL),
            &lp.handle(),
        );
        let fut = pool.get_conn()
            .and_then(|conn| conn.drop_query("CREATE TABLE IF NOT EXISTS tmp(id int)"))
            .and_then({
                let pool = pool.clone();
                move |_| pool.start_transaction(TransactionOptions::default())
            })
            .and_then(|transaction| {
                transaction.batch_exec("INSERT INTO tmp (id) VALUES (?)", vec![(1,), (2,)])
            })
            .and_then(|transaction| transaction.prep_exec("SELECT * FROM tmp", ()))
            .map(|_| ())
            .and_then({
                let pool = pool.clone();
                move |_| pool.get_conn()
            })
            .and_then(|conn| conn.first("SELECT COUNT(*) FROM tmp"))
            .and_then(|(_, row_opt)| {
                assert_eq!(row_opt, Some((0u8,)));
                pool.get_conn()
                    .and_then(|conn| conn.drop_query("DROP TABLE tmp"))
                    .and_then(move |_| pool.disconnect())
            });

        lp.run(fut).unwrap();
    }

    #[test]
    fn should_hold_bounds() {
        let mut lp = Core::new().unwrap();

        let pool = Pool::new(
            format!("{}?pool_min=1&pool_max=2", &**DATABASE_URL),
            &lp.handle(),
        );
        let pool_clone = pool.clone();
        let fut = pool.get_conn()
            .join(pool.get_conn())
            .and_then(|(mut conn1, conn2)| {
                let new_conn = pool_clone.get_conn();
                conn1.pool.as_mut().unwrap().handle_futures().unwrap();
                assert_eq!(conn1.pool.as_ref().unwrap().inner_ref().new.len(), 0);
                assert_eq!(conn1.pool.as_ref().unwrap().inner_ref().idle.len(), 0);
                assert_eq!(conn2.pool.as_ref().unwrap().inner_ref().disconnecting.len(), 0);
                assert_eq!(conn2.pool.as_ref().unwrap().inner_ref().dropping.len(), 0);
                new_conn
            })
            .and_then(|conn1| {
                assert_eq!(conn1.pool.as_ref().unwrap().inner_ref().new.len(), 0);
                assert_eq!(conn1.pool.as_ref().unwrap().inner_ref().idle.len(), 0);
                assert_eq!(conn1.pool.as_ref().unwrap().inner_ref().disconnecting.len(), 0);
                assert_eq!(conn1.pool.as_ref().unwrap().inner_ref().dropping.len(), 0);
                Ok(())
            })
            .and_then(|_| {
                assert_eq!(pool.inner_ref().new.len(), 0);
                assert_eq!(pool.inner_ref().idle.len(), 1);
                assert_eq!(pool.inner_ref().disconnecting.len(), 0);
                assert_eq!(pool.inner_ref().dropping.len(), 0);
                pool.disconnect()
            });

        lp.run(fut).unwrap();
    }

    #[cfg(feature = "nightly")]
    mod bench {
        use test;
        use conn::pool::Pool;
        use tokio::reactor::Core;
        use lib_futures::Future;
        use test_misc::DATABASE_URL;

        #[bench]
        fn connect(bencher: &mut test::Bencher) {
            let mut lp = Core::new().unwrap();
            let pool = Pool::new(&**DATABASE_URL, &lp.handle());

            bencher.iter(|| {
                let fut = pool.get_conn().and_then(|conn| conn.ping());
                lp.run(fut).unwrap();
            })
        }
    }
}
<commit_msg>Fix ongoing connections counter<commit_after>// Copyright (c) 2016 Anatoly Ikorsky
//
// 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. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use BoxFuture;
use conn::Conn;
use errors::*;
use lib_futures::Async;
use lib_futures::Async::Ready;
use lib_futures::Async::NotReady;
use lib_futures::Future;
use lib_futures::task::{self, Task};
use queryable::Queryable;
use queryable::transaction::{Transaction, TransactionOptions};
use std::fmt;
use opts::Opts;
use self::futures::*;
use std::cell::Ref;
use std::cell::RefCell;
use std::cell::RefMut;
use std::rc::Rc;
use tokio::reactor::Handle;

pub mod futures;

pub struct Inner {
    closed: bool,
    new: Vec<BoxFuture<Conn>>,
    idle: Vec<Conn>,
    disconnecting: Vec<BoxFuture<()>>,
    dropping: Vec<BoxFuture<Conn>>,
    rollback: Vec<BoxFuture<Conn>>,
    ongoing: usize,
    tasks: Vec<Task>,
}

#[derive(Clone)]
/// Asynchronous pool of MySql connections.
pub struct Pool {
    handle: Handle,
    opts: Opts,
    inner: Rc<RefCell<Inner>>,
    min: usize,
    max: usize,
}

impl fmt::Debug for Pool {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Pool")
            .field("min", &self.min)
            .field("max", &self.max)
            .field("new connections count", &self.inner_ref().new.len())
            .field("idle connections count", &self.inner_ref().idle.len())
            .field(
                "disconnecting connections count",
                &self.inner_ref().disconnecting.len(),
            )
            .finish()
    }
}

impl Pool {
    /// Creates new pool of connections.
    pub fn new<O: Into<Opts>>(opts: O, handle: &Handle) -> Pool {
        let opts = opts.into();
        let pool_min = opts.get_pool_min();
        let pool_max = opts.get_pool_max();
        let pool = Pool {
            handle: handle.clone(),
            opts: opts,
            inner: Rc::new(RefCell::new(Inner {
                closed: false,
                new: Vec::with_capacity(pool_min),
                idle: Vec::new(),
                disconnecting: Vec::new(),
                dropping: Vec::new(),
                rollback: Vec::new(),
                ongoing: 0,
                tasks: Vec::new(),
            })),
            min: pool_min,
            max: pool_max,
        };

        pool
    }

    /// Returns future that resolves to `Conn`.
    pub fn get_conn(&self) -> GetConn {
        new_get_conn(self)
    }

    /// Shortcut for `get_conn` followed by `start_transaction`.
    pub fn start_transaction(&self, options: TransactionOptions) -> BoxFuture<Transaction<Conn>> {
        let fut = self.get_conn().and_then(|conn| {
            Queryable::start_transaction(conn, options)
        });
        Box::new(fut)
    }

    /// Returns future that disconnects this pool from server and resolves to `()`.
    ///
    /// Active connections taken from this pool should be disconnected manually.
    /// Also all pending and new `GetConn`'s will resolve to error.
    pub fn disconnect(mut self) -> DisconnectPool {
        if !self.inner_ref().closed {
            self.inner_mut().closed = true;
            while let Some(conn) = self.take_conn() {
                self.inner_mut().disconnecting.push(conn.disconnect());
            }
        }
        new_disconnect_pool(self)
    }

    /// Returns true if futures is in queue.
    fn in_queue(&self) -> bool {
        let inner = self.inner_ref();
        let count = inner.new.len() + inner.disconnecting.len() + inner.dropping.len() +
            inner.rollback.len();
        count > 0
    }

    /// A way to take connection from a pool.
    fn take_conn(&mut self) -> Option<Conn> {
        if self.in_queue() {
            // Do not return connection until queue is empty
            return None;
        }
        while self.inner_ref().idle.len() > 0 {
            let conn = self.inner_mut().idle.pop();
            let conn = conn.and_then(|mut conn| if conn.expired() {
                self.inner_mut().disconnecting.push(conn.disconnect());
                None
            } else {
                conn.pool = Some(self.clone());
                Some(conn)
            });
            if conn.is_some() {
                self.inner_mut().ongoing += 1;
                return conn;
            }
        }
        None
    }

    /// A way to return connection taken from a pool.
    fn return_conn(&mut self, conn: Conn) {
        if self.inner_ref().closed {
            return;
        }
        let min = self.min;
        let mut inner = self.inner_mut();

        if conn.has_result.is_some() {
            inner.dropping.push(conn.drop_result());
        } else if conn.in_transaction {
            inner.rollback.push(conn.rollback_transaction())
        } else {
            let idle_len = inner.idle.len();
            if idle_len >= min {
                inner.disconnecting.push(conn.disconnect());
            } else {
                inner.ongoing -= 1;
                inner.idle.push(conn);
            }
        }

        while let Some(task) = inner.tasks.pop() {
            task.notify()
        }
    }

    fn inner_ref(&self) -> Ref<Inner> {
        self.inner.borrow()
    }

    fn inner_mut(&mut self) -> RefMut<Inner> {
        self.inner.borrow_mut()
    }

    /// Will manage lifetime of futures stored in a pool.
    fn handle_futures(&mut self) -> Result<()> {
        if !self.in_queue() {
            // There is no futures in queue
            return Ok(());
        }

        macro_rules! handle {
            ($vec:ident { $($p:pat => $b:block,)+ }) => ({
                let len = self.inner_ref().$vec.len();
                let mut done_fut_idxs = Vec::new();
                for i in 0..len {
                    let result = self.inner_mut().$vec.get_mut(i).unwrap().poll();
                    match result {
                        Ok(Ready(_)) | Err(_) => done_fut_idxs.push(i),
                        _ => (),
                    }

                    let out: Result<()> = match result {
                        $($p => $b),+
                        _ => {
                            Ok(())
                        }
                    };

                    match out {
                        Err(err) => {
                            // early return in case of error
                            while let Some(i) = done_fut_idxs.pop() {
                                let _ = self.inner_mut().$vec.swap_remove(i);
                            }
                            return Err(err)
                        }
                        _ => (),
                    }
                }

                while let Some(i) = done_fut_idxs.pop() {
                    let _ = self.inner_mut().$vec.swap_remove(i);
                }
            });
        }

        let mut handled = false;

        // Handle closing connections.
        handle!(disconnecting {
            Ok(Ready(_)) => {
                handled = true;
                Ok(())
            },
            Err(_) => { Ok(()) },
        });

        // Handle dirty connections.
        handle!(dropping {
            Ok(Ready(conn)) => {
                let closed = self.inner_ref().closed;
                if closed {
                    self.inner_mut().disconnecting.push(conn.disconnect());
                } else {
                    self.return_conn(conn);
                }
                handled = true;
                Ok(())
            },
            Err(_) => { Ok(()) },
        });

        // Handle in-transaction connections
        handle!(rollback {
            Ok(Ready(conn)) => {
                let closed = self.inner_ref().closed;
                if closed {
                    self.inner_mut().disconnecting.push(conn.disconnect());
                } else {
                    self.return_conn(conn);
                }
                handled = true;
                Ok(())
            },
            Err(_) => { Ok(()) },
        });

        // Handle connecting connections.
        handle!(new {
            Ok(Ready(conn)) => {
                let closed = self.inner_ref().closed;
                if closed {
                    self.inner_mut().disconnecting.push(conn.disconnect());
                } else {
                    self.inner_mut().ongoing += 1;
                    self.return_conn(conn);
                }
                handled = true;
                Ok(())
            },
            Err(err) => {
                if ! self.inner_ref().closed {
                    Err(err)
                } else {
                    Ok(())
                }
            },
        });

        if handled {
            self.handle_futures()
        } else {
            Ok(())
        }
    }

    fn conn_count(&self) -> usize {
        let inner = self.inner_ref();
        inner.new.len() + inner.idle.len() + inner.disconnecting.len() + inner.dropping.len()
            + inner.rollback.len() + inner.ongoing
    }

    /// Will poll pool for connection.
    fn poll(&mut self) -> Result<Async<Conn>> {
        if self.inner_ref().closed {
            return Err(ErrorKind::PoolDisconnected.into());
        }

        self.handle_futures()?;

        match self.take_conn() {
            Some(conn) => Ok(Ready(conn)),
            None => {
                let new_len = self.inner_ref().new.len();
                if new_len == 0 && self.conn_count() < self.max {
                    let new_conn = Conn::new(self.opts.clone(), &self.handle);
                    self.inner_mut().new.push(new_conn);
                    self.poll()
                } else {
                    self.inner_mut().tasks.push(task::current());
                    Ok(NotReady)
                }
            }
        }
    }
}

impl Drop for Conn {
    fn drop(&mut self) {
        if let Some(mut pool) = self.pool.take() {
            let conn = self.take();
            if conn.stream.is_some() {
                pool.return_conn(conn)
            } // drop incomplete connection
        }
    }
}

#[cfg(test)]
mod test {
    use TransactionOptions;
    use conn::pool::Pool;
    use lib_futures::Future;
    use queryable::Queryable;
    use test_misc::DATABASE_URL;
    use tokio::reactor::Core;

    #[test]
    fn should_connect() {
        let mut lp = Core::new().unwrap();

        let pool = Pool::new(&**DATABASE_URL, &lp.handle());
        let fut = pool.get_conn()
            .and_then(|conn| conn.ping().map(|_| ()))
            .and_then(|_| pool.disconnect());

        lp.run(fut).unwrap();
    }

    #[test]
    fn should_start_transaction() {
        let mut lp = Core::new().unwrap();

        let pool = Pool::new(
            format!("{}?pool_min=1&pool_max=1", &**DATABASE_URL),
            &lp.handle(),
        );
        let fut = pool.get_conn()
            .and_then(|conn| conn.drop_query("CREATE TABLE IF NOT EXISTS tmp(id int)"))
            .and_then({
                let pool = pool.clone();
                move |_| pool.start_transaction(TransactionOptions::default())
            })
            .and_then(|transaction| {
                transaction.batch_exec("INSERT INTO tmp (id) VALUES (?)", vec![(1,), (2,)])
            })
            .and_then(|transaction| transaction.prep_exec("SELECT * FROM tmp", ()))
            .map(|_| ())
            .and_then({
                let pool = pool.clone();
                move |_| pool.get_conn()
            })
            .and_then(|conn| conn.first("SELECT COUNT(*) FROM tmp"))
            .and_then(|(_, row_opt)| {
                assert_eq!(row_opt, Some((0u8,)));
                pool.get_conn()
                    .and_then(|conn| conn.drop_query("DROP TABLE tmp"))
                    .and_then(move |_| pool.disconnect())
            });

        lp.run(fut).unwrap();
    }

    #[test]
    fn should_hold_bounds() {
        let mut lp = Core::new().unwrap();

        let pool = Pool::new(
            format!("{}?pool_min=1&pool_max=2", &**DATABASE_URL),
            &lp.handle(),
        );
        let pool_clone = pool.clone();
        let fut = pool.get_conn()
            .join(pool.get_conn())
            .and_then(|(mut conn1, conn2)| {
                let new_conn = pool_clone.get_conn();
                conn1.pool.as_mut().unwrap().handle_futures().unwrap();
                assert_eq!(conn1.pool.as_ref().unwrap().inner_ref().new.len(), 0);
                assert_eq!(conn1.pool.as_ref().unwrap().inner_ref().idle.len(), 0);
                assert_eq!(conn2.pool.as_ref().unwrap().inner_ref().disconnecting.len(), 0);
                assert_eq!(conn2.pool.as_ref().unwrap().inner_ref().dropping.len(), 0);
                new_conn
            })
            .and_then(|conn1| {
                assert_eq!(conn1.pool.as_ref().unwrap().inner_ref().new.len(), 0);
                assert_eq!(conn1.pool.as_ref().unwrap().inner_ref().idle.len(), 0);
                assert_eq!(conn1.pool.as_ref().unwrap().inner_ref().disconnecting.len(), 0);
                assert_eq!(conn1.pool.as_ref().unwrap().inner_ref().dropping.len(), 0);
                Ok(())
            })
            .and_then(|_| {
                assert_eq!(pool.inner_ref().new.len(), 0);
                assert_eq!(pool.inner_ref().idle.len(), 1);
                assert_eq!(pool.inner_ref().disconnecting.len(), 0);
                assert_eq!(pool.inner_ref().dropping.len(), 0);
                pool.disconnect()
            });

        lp.run(fut).unwrap();
    }

    #[cfg(feature = "nightly")]
    mod bench {
        use test;
        use conn::pool::Pool;
        use tokio::reactor::Core;
        use lib_futures::Future;
        use test_misc::DATABASE_URL;

        #[bench]
        fn connect(bencher: &mut test::Bencher) {
            let mut lp = Core::new().unwrap();
            let pool = Pool::new(&**DATABASE_URL, &lp.handle());

            bencher.iter(|| {
                let fut = pool.get_conn().and_then(|conn| conn.ping());
                lp.run(fut).unwrap();
            })
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Andrew Hobden (@hoverbear) <andrew@hoverbear.org>
//
// 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.
//
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.

#[macro_use]
extern crate clap;

use clap::Clap;

use std::ffi::{OsStr, OsString};
use std::num::ParseIntError;
use std::path::PathBuf;

#[derive(Clap, PartialEq, Debug)]
struct PathOpt {
    #[clap(short = "p", long = "path", parse(from_os_str))]
    path: PathBuf,

    #[clap(short = "d", default_value = "../", parse(from_os_str))]
    default_path: PathBuf,

    #[clap(short = "v", parse(from_os_str))]
    vector_path: Vec<PathBuf>,

    #[clap(short = "o", parse(from_os_str))]
    option_path_1: Option<PathBuf>,

    #[clap(short = "q", parse(from_os_str))]
    option_path_2: Option<PathBuf>,
}

#[test]
fn test_path_opt_simple() {
    assert_eq!(
        PathOpt {
            path: PathBuf::from("/usr/bin"),
            default_path: PathBuf::from("../"),
            vector_path: vec![
                PathBuf::from("/a/b/c"),
                PathBuf::from("/d/e/f"),
                PathBuf::from("/g/h/i"),
            ],
            option_path_1: None,
            option_path_2: Some(PathBuf::from("j.zip")),
        },
        PathOpt::from_argmatches(&PathOpt::into_app().get_matches_from(&[
            "test", "-p", "/usr/bin", "-v", "/a/b/c", "-v", "/d/e/f", "-v", "/g/h/i", "-q",
            "j.zip",
        ]))
    );
}

fn parse_hex(input: &str) -> Result<u64, ParseIntError> { u64::from_str_radix(input, 16) }

#[derive(Clap, PartialEq, Debug)]
struct HexOpt {
    #[clap(short = "n", parse(try_from_str = "parse_hex"))]
    number: u64,
}

#[test]
fn test_parse_hex() {
    assert_eq!(
        HexOpt { number: 5 },
        HexOpt::from_argmatches(&HexOpt::into_app().get_matches_from(&["test", "-n", "5"]))
    );
    assert_eq!(
        HexOpt { number: 0xabcdef },
        HexOpt::from_argmatches(&HexOpt::into_app().get_matches_from(&["test", "-n", "abcdef"]))
    );

    let err = HexOpt::into_app()
        .get_matches_from_safe(&["test", "-n", "gg"])
        .unwrap_err();
    assert!(err.message.contains("invalid digit found in string"), err);
}

fn custom_parser_1(_: &str) -> &'static str { "A" }
fn custom_parser_2(_: &str) -> Result<&'static str, u32> { Ok("B") }
fn custom_parser_3(_: &OsStr) -> &'static str { "C" }
fn custom_parser_4(_: &OsStr) -> Result<&'static str, OsString> { Ok("D") }

#[derive(Clap, PartialEq, Debug)]
struct NoOpOpt {
    #[clap(short = "a", parse(from_str = "custom_parser_1"))]
    a: &'static str,
    #[clap(short = "b", parse(try_from_str = "custom_parser_2"))]
    b: &'static str,
    #[clap(short = "c", parse(from_os_str = "custom_parser_3"))]
    c: &'static str,
    #[clap(short = "d", parse(try_from_os_str = "custom_parser_4"))]
    d: &'static str,
}

#[test]
fn test_every_custom_parser() {
    assert_eq!(
        NoOpOpt {
            a: "A",
            b: "B",
            c: "C",
            d: "D"
        },
        NoOpOpt::from_argmatches(
            &NoOpOpt::into_app().get_matches_from(&["test", "-a=?", "-b=?", "-c=?", "-d=?"])
        )
    );
}

// Note: can't use `Vec<u8>` directly, as structopt would instead look for
// conversion function from `&str` to `u8`.
type Bytes = Vec<u8>;

#[derive(Clap, PartialEq, Debug)]
struct DefaultedOpt {
    #[clap(short = "b", parse(from_str))]
    bytes: Bytes,

    #[clap(short = "i", parse(try_from_str))]
    integer: u64,

    #[clap(short = "p", parse(from_os_str))]
    path: PathBuf,
}

#[test]
fn test_parser_with_default_value() {
    assert_eq!(
        DefaultedOpt {
            bytes: b"E\xc2\xb2=p\xc2\xb2c\xc2\xb2+m\xc2\xb2c\xe2\x81\xb4".to_vec(),
            integer: 9000,
            path: PathBuf::from("src/lib.rs"),
        },
        DefaultedOpt::from_argmatches(&DefaultedOpt::into_app().get_matches_from(&[
            "test",
            "-b",
            "E²=p²c²+m²c⁴",
            "-i",
            "9000",
            "-p",
            "src/lib.rs",
        ]))
    );
}

#[derive(PartialEq, Debug)]
struct Foo(u8);

fn foo(value: u64) -> Foo { Foo(value as u8) }

#[derive(Clap, PartialEq, Debug)]
struct Occurrences {
    #[clap(short = "s", long = "signed", parse(from_occurrences))]
    signed: i32,

    #[clap(short = "l", parse(from_occurrences))]
    little_signed: i8,

    #[clap(short = "u", parse(from_occurrences))]
    unsigned: usize,

    #[clap(short = "r", parse(from_occurrences))]
    little_unsigned: u8,

    #[clap(short = "c", long = "custom", parse(from_occurrences = "foo"))]
    custom: Foo,
}

#[test]
fn test_parser_occurrences() {
    assert_eq!(
        Occurrences {
            signed: 3,
            little_signed: 1,
            unsigned: 0,
            little_unsigned: 4,
            custom: Foo(5),
        },
        Occurrences::from_argmatches(&Occurrences::into_app().get_matches_from(&[
            "test", "-s", "--signed", "--signed", "-l", "-rrrr", "-cccc", "--custom",
        ]))
    );
}

#[test]
fn test_custom_bool() {
    fn parse_bool(s: &str) -> Result<bool, String> {
        match s {
            "true" => Ok(true),
            "false" => Ok(false),
            _ => Err(format!("invalid bool {}", s)),
        }
    }
    #[derive(Clap, PartialEq, Debug)]
    struct Opt {
        #[clap(short = "d", parse(try_from_str = "parse_bool"))]
        debug: bool,
        #[clap(short = "v", default_value = "false", parse(try_from_str = "parse_bool"))]
        verbose: bool,
        #[clap(short = "t", parse(try_from_str = "parse_bool"))]
        tribool: Option<bool>,
        #[clap(short = "b", parse(try_from_str = "parse_bool"))]
        bitset: Vec<bool>,
    }

    assert!(Opt::into_app().get_matches_from_safe(&["test"]).is_err());
    assert!(
        Opt::into_app()
            .get_matches_from_safe(&["test", "-d"])
            .is_err()
    );
    assert!(
        Opt::into_app()
            .get_matches_from_safe(&["test", "-dfoo"])
            .is_err()
    );
    assert_eq!(
        Opt {
            debug: false,
            verbose: false,
            tribool: None,
            bitset: vec![],
        },
        Opt::parse_from(&["test", "-dfalse"])
    );
    assert_eq!(
        Opt {
            debug: true,
            verbose: false,
            tribool: None,
            bitset: vec![],
        },
        Opt::parse_from(&["test", "-dtrue"])
    );
    assert_eq!(
        Opt {
            debug: true,
            verbose: false,
            tribool: None,
            bitset: vec![],
        },
        Opt::parse_from(&["test", "-dtrue", "-vfalse"])
    );
    assert_eq!(
        Opt {
            debug: true,
            verbose: true,
            tribool: None,
            bitset: vec![],
        },
        Opt::parse_from(&["test", "-dtrue", "-vtrue"])
    );
    assert_eq!(
        Opt {
            debug: true,
            verbose: false,
            tribool: Some(false),
            bitset: vec![],
        },
        Opt::parse_from(&["test", "-dtrue", "-tfalse"])
    );
    assert_eq!(
        Opt {
            debug: true,
            verbose: false,
            tribool: Some(true),
            bitset: vec![],
        },
        Opt::parse_from(&["test", "-dtrue", "-ttrue"])
    );
    assert_eq!(
        Opt {
            debug: true,
            verbose: false,
            tribool: None,
            bitset: vec![false, true, false, false],
        },
        Opt::parse_from(&["test", "-dtrue", "-bfalse", "-btrue", "-bfalse", "-bfalse"])
    );
}
<commit_msg>refactor: changes validator signature to match v3<commit_after>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Andrew Hobden (@hoverbear) <andrew@hoverbear.org>
//
// 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.
//
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.

#[macro_use]
extern crate clap;

use clap::Clap;

use std::ffi::{OsStr, OsString};
use std::num::ParseIntError;
use std::path::PathBuf;

#[derive(Clap, PartialEq, Debug)]
struct PathOpt {
    #[clap(short = "p", long = "path", parse(from_os_str))]
    path: PathBuf,

    #[clap(short = "d", default_value = "../", parse(from_os_str))]
    default_path: PathBuf,

    #[clap(short = "v", parse(from_os_str))]
    vector_path: Vec<PathBuf>,

    #[clap(short = "o", parse(from_os_str))]
    option_path_1: Option<PathBuf>,

    #[clap(short = "q", parse(from_os_str))]
    option_path_2: Option<PathBuf>,
}

#[test]
fn test_path_opt_simple() {
    assert_eq!(
        PathOpt {
            path: PathBuf::from("/usr/bin"),
            default_path: PathBuf::from("../"),
            vector_path: vec![
                PathBuf::from("/a/b/c"),
                PathBuf::from("/d/e/f"),
                PathBuf::from("/g/h/i"),
            ],
            option_path_1: None,
            option_path_2: Some(PathBuf::from("j.zip")),
        },
        PathOpt::from_argmatches(&PathOpt::into_app().get_matches_from(&[
            "test", "-p", "/usr/bin", "-v", "/a/b/c", "-v", "/d/e/f", "-v", "/g/h/i", "-q",
            "j.zip",
        ]))
    );
}

fn parse_hex(input: &str) -> Result<u64, ParseIntError> { u64::from_str_radix(input, 16) }

#[derive(Clap, PartialEq, Debug)]
struct HexOpt {
    #[clap(short = "n", parse(try_from_str = "parse_hex"))]
    number: u64,
}

#[test]
fn test_parse_hex() {
    assert_eq!(
        HexOpt { number: 5 },
        HexOpt::from_argmatches(&HexOpt::into_app().get_matches_from(&["test", "-n", "5"]))
    );
    assert_eq!(
        HexOpt { number: 0xabcdef },
        HexOpt::from_argmatches(&HexOpt::into_app().get_matches_from(&["test", "-n", "abcdef"]))
    );

    let err = HexOpt::into_app()
        .get_matches_from_safe(&["test", "-n", "gg"])
        .unwrap_err();
    assert!(err.message.contains("invalid digit found in string"), err);
}

fn custom_parser_1(_: &str) -> &'static str { "A" }
fn custom_parser_2(_: &str) -> Result<&'static str, u32> { Ok("B") }
fn custom_parser_3(_: &OsStr) -> &'static str { "C" }
fn custom_parser_4(_: &OsStr) -> Result<&'static str, String> { Ok("D") }

#[derive(Clap, PartialEq, Debug)]
struct NoOpOpt {
    #[clap(short = "a", parse(from_str = "custom_parser_1"))]
    a: &'static str,
    #[clap(short = "b", parse(try_from_str = "custom_parser_2"))]
    b: &'static str,
    #[clap(short = "c", parse(from_os_str = "custom_parser_3"))]
    c: &'static str,
    #[clap(short = "d", parse(try_from_os_str = "custom_parser_4"))]
    d: &'static str,
}

#[test]
fn test_every_custom_parser() {
    assert_eq!(
        NoOpOpt {
            a: "A",
            b: "B",
            c: "C",
            d: "D"
        },
        NoOpOpt::from_argmatches(
            &NoOpOpt::into_app().get_matches_from(&["test", "-a=?", "-b=?", "-c=?", "-d=?"])
        )
    );
}

// Note: can't use `Vec<u8>` directly, as structopt would instead look for
// conversion function from `&str` to `u8`.
type Bytes = Vec<u8>;

#[derive(Clap, PartialEq, Debug)]
struct DefaultedOpt {
    #[clap(short = "b", parse(from_str))]
    bytes: Bytes,

    #[clap(short = "i", parse(try_from_str))]
    integer: u64,

    #[clap(short = "p", parse(from_os_str))]
    path: PathBuf,
}

#[test]
fn test_parser_with_default_value() {
    assert_eq!(
        DefaultedOpt {
            bytes: b"E\xc2\xb2=p\xc2\xb2c\xc2\xb2+m\xc2\xb2c\xe2\x81\xb4".to_vec(),
            integer: 9000,
            path: PathBuf::from("src/lib.rs"),
        },
        DefaultedOpt::from_argmatches(&DefaultedOpt::into_app().get_matches_from(&[
            "test",
            "-b",
            "E²=p²c²+m²c⁴",
            "-i",
            "9000",
            "-p",
            "src/lib.rs",
        ]))
    );
}

#[derive(PartialEq, Debug)]
struct Foo(u8);

fn foo(value: u64) -> Foo { Foo(value as u8) }

#[derive(Clap, PartialEq, Debug)]
struct Occurrences {
    #[clap(short = "s", long = "signed", parse(from_occurrences))]
    signed: i32,

    #[clap(short = "l", parse(from_occurrences))]
    little_signed: i8,

    #[clap(short = "u", parse(from_occurrences))]
    unsigned: usize,

    #[clap(short = "r", parse(from_occurrences))]
    little_unsigned: u8,

    #[clap(
        short = "c",
        long = "custom",
        parse(from_occurrences = "foo")
    )]
    custom: Foo,
}

#[test]
fn test_parser_occurrences() {
    assert_eq!(
        Occurrences {
            signed: 3,
            little_signed: 1,
            unsigned: 0,
            little_unsigned: 4,
            custom: Foo(5),
        },
        Occurrences::from_argmatches(&Occurrences::into_app().get_matches_from(&[
            "test", "-s", "--signed", "--signed", "-l", "-rrrr", "-cccc", "--custom",
        ]))
    );
}

#[test]
fn test_custom_bool() {
    fn parse_bool(s: &str) -> Result<bool, String> {
        match s {
            "true" => Ok(true),
            "false" => Ok(false),
            _ => Err(format!("invalid bool {}", s)),
        }
    }
    #[derive(Clap, PartialEq, Debug)]
    struct Opt {
        #[clap(short = "d", parse(try_from_str = "parse_bool"))]
        debug: bool,
        #[clap(
            short = "v",
            default_value = "false",
            parse(try_from_str = "parse_bool")
        )]
        verbose: bool,
        #[clap(short = "t", parse(try_from_str = "parse_bool"))]
        tribool: Option<bool>,
        #[clap(short = "b", parse(try_from_str = "parse_bool"))]
        bitset: Vec<bool>,
    }

    assert!(Opt::into_app().get_matches_from_safe(&["test"]).is_err());
    assert!(
        Opt::into_app()
            .get_matches_from_safe(&["test", "-d"])
            .is_err()
    );
    assert!(
        Opt::into_app()
            .get_matches_from_safe(&["test", "-dfoo"])
            .is_err()
    );
    assert_eq!(
        Opt {
            debug: false,
            verbose: false,
            tribool: None,
            bitset: vec![],
        },
        Opt::parse_from(&["test", "-dfalse"])
    );
    assert_eq!(
        Opt {
            debug: true,
            verbose: false,
            tribool: None,
            bitset: vec![],
        },
        Opt::parse_from(&["test", "-dtrue"])
    );
    assert_eq!(
        Opt {
            debug: true,
            verbose: false,
            tribool: None,
            bitset: vec![],
        },
        Opt::parse_from(&["test", "-dtrue", "-vfalse"])
    );
    assert_eq!(
        Opt {
            debug: true,
            verbose: true,
            tribool: None,
            bitset: vec![],
        },
        Opt::parse_from(&["test", "-dtrue", "-vtrue"])
    );
    assert_eq!(
        Opt {
            debug: true,
            verbose: false,
            tribool: Some(false),
            bitset: vec![],
        },
        Opt::parse_from(&["test", "-dtrue", "-tfalse"])
    );
    assert_eq!(
        Opt {
            debug: true,
            verbose: false,
            tribool: Some(true),
            bitset: vec![],
        },
        Opt::parse_from(&["test", "-dtrue", "-ttrue"])
    );
    assert_eq!(
        Opt {
            debug: true,
            verbose: false,
            tribool: None,
            bitset: vec![false, true, false, false],
        },
        Opt::parse_from(&["test", "-dtrue", "-bfalse", "-btrue", "-bfalse", "-bfalse"])
    );
}
<|endoftext|>


<commit_before>//! Utilities for use with
//! [`DynamicBoundingVolumeTree`](struct.DynamicBoundingVolumeTree.html).
//!

use std::marker::PhantomData;

use cgmath::BaseFloat;
use cgmath::prelude::*;

use super::{DynamicBoundingVolumeTree, TreeValue, Visitor};
use Ray;
use prelude::*;

struct RayClosestVisitor<S, P, T>
where
    S: BaseFloat,
    T: TreeValue,
    P: EuclideanSpace<Scalar = S>,
{
    ray: Ray<S, P, P::Diff>,
    min: S,
    marker: PhantomData<T>,
}

impl<S, P, T> RayClosestVisitor<S, P, T>
where
    S: BaseFloat,
    T: TreeValue,
    P: EuclideanSpace<Scalar = S>,
{
    pub fn new(ray: Ray<S, P, P::Diff>) -> Self {
        Self {
            ray,
            min: S::infinity(),
            marker: PhantomData,
        }
    }
}

impl<S, P, T> Visitor for RayClosestVisitor<S, P, T>
where
    S: BaseFloat,
    T: TreeValue,
    P: EuclideanSpace<Scalar = S>,
    P::Diff: VectorSpace<Scalar = S> + InnerSpace,
    T::Bound: Clone
        + Contains<T::Bound>
        + SurfaceArea<Scalar = S>
        + Union<T::Bound, Output = T::Bound>
        + Continuous<Ray<S, P, P::Diff>, Result = P>,
{
    type Bound = T::Bound;
    type Result = P;

    fn accept(&mut self, bound: &Self::Bound, is_leaf: bool) -> Option<Self::Result> {
        match bound.intersection(&self.ray) {
            Some(point) => {
                let offset = point - self.ray.origin;
                let t = offset.dot(self.ray.direction);
                if t < self.min {
                    if is_leaf {
                        self.min = t;
                    }
                    Some(point)
                } else {
                    None
                }
            }
            None => None,
        }
    }
}

/// Query the given tree for the closest value that intersects the given ray.
///
/// ### Parameters:
///
/// - `tree`: DBVT to query.
/// - `ray`: Ray to find the closest intersection for.
///
/// ### Returns
///
/// Optionally returns the value that had the closest intersection with the ray, along with the
/// actual intersection point.
///
pub fn query_ray_closest<'a, S, T: 'a, P>(
    tree: &'a DynamicBoundingVolumeTree<T>,
    ray: Ray<S, P, P::Diff>,
) -> Option<(&'a T, P)>
where
    S: BaseFloat,
    T: TreeValue,
    P: EuclideanSpace<Scalar = S>,
    P::Diff: VectorSpace<Scalar = S> + InnerSpace,
    T::Bound: Clone
        + Contains<T::Bound>
        + SurfaceArea<Scalar = S>
        + Union<T::Bound, Output = T::Bound>
        + Continuous<Ray<S, P, P::Diff>, Result = P>
        + Discrete<Ray<S, P, P::Diff>>,
{
    let mut saved = None;
    let mut tmin = S::infinity();
    let mut visitor = RayClosestVisitor::<S, P, T>::new(ray);
    for (value, point) in tree.query(&mut visitor) {
        let offset = point - ray.origin;
        let t = offset.dot(ray.direction);
        if t < tmin {
            tmin = t;
            saved = Some((value, point.clone()));
        }
    }
    saved
}
<commit_msg>feat: Add utility function that returns all values in DBVT that intersects a given ray<commit_after>//! Utilities for use with
//! [`DynamicBoundingVolumeTree`](struct.DynamicBoundingVolumeTree.html).
//!

use std::marker::PhantomData;

use cgmath::BaseFloat;
use cgmath::prelude::*;

use super::{ContinuousVisitor, DynamicBoundingVolumeTree, TreeValue, Visitor};
use Ray;
use prelude::*;

struct RayClosestVisitor<S, P, T>
where
    S: BaseFloat,
    T: TreeValue,
    P: EuclideanSpace<Scalar = S>,
{
    ray: Ray<S, P, P::Diff>,
    min: S,
    marker: PhantomData<T>,
}

impl<S, P, T> RayClosestVisitor<S, P, T>
where
    S: BaseFloat,
    T: TreeValue,
    P: EuclideanSpace<Scalar = S>,
{
    pub fn new(ray: Ray<S, P, P::Diff>) -> Self {
        Self {
            ray,
            min: S::infinity(),
            marker: PhantomData,
        }
    }
}

impl<S, P, T> Visitor for RayClosestVisitor<S, P, T>
where
    S: BaseFloat,
    T: TreeValue,
    P: EuclideanSpace<Scalar = S>,
    P::Diff: VectorSpace<Scalar = S> + InnerSpace,
    T::Bound: Clone
        + Contains<T::Bound>
        + SurfaceArea<Scalar = S>
        + Union<T::Bound, Output = T::Bound>
        + Continuous<Ray<S, P, P::Diff>, Result = P>,
{
    type Bound = T::Bound;
    type Result = P;

    fn accept(&mut self, bound: &Self::Bound, is_leaf: bool) -> Option<Self::Result> {
        match bound.intersection(&self.ray) {
            Some(point) => {
                let offset = point - self.ray.origin;
                let t = offset.dot(self.ray.direction);
                if t < self.min {
                    if is_leaf {
                        self.min = t;
                    }
                    Some(point)
                } else {
                    None
                }
            }
            None => None,
        }
    }
}

/// Query the given tree for the closest value that intersects the given ray.
///
/// ### Parameters:
///
/// - `tree`: DBVT to query.
/// - `ray`: Ray to find the closest intersection for.
///
/// ### Returns
///
/// Optionally returns the value that had the closest intersection with the ray, along with the
/// actual intersection point.
///
pub fn query_ray_closest<'a, S, T: 'a, P>(
    tree: &'a DynamicBoundingVolumeTree<T>,
    ray: Ray<S, P, P::Diff>,
) -> Option<(&'a T, P)>
where
    S: BaseFloat,
    T: TreeValue,
    P: EuclideanSpace<Scalar = S>,
    P::Diff: VectorSpace<Scalar = S> + InnerSpace,
    T::Bound: Clone
        + Contains<T::Bound>
        + SurfaceArea<Scalar = S>
        + Union<T::Bound, Output = T::Bound>
        + Continuous<Ray<S, P, P::Diff>, Result = P>
        + Discrete<Ray<S, P, P::Diff>>,
{
    let mut saved = None;
    let mut tmin = S::infinity();
    let mut visitor = RayClosestVisitor::<S, P, T>::new(ray);
    for (value, point) in tree.query(&mut visitor) {
        let offset = point - ray.origin;
        let t = offset.dot(ray.direction);
        if t < tmin {
            tmin = t;
            saved = Some((value, point.clone()));
        }
    }
    saved
}

/// Query the given tree for all values that intersects the given ray.
///
/// ### Parameters:
///
/// - `tree`: DBVT to query.
/// - `ray`: Ray to find intersections for.
///
/// ### Returns
///
/// Returns all values that intersected the ray, and also at which point the intersections occurred.
pub fn query_ray<'a, S, T: 'a, P>(
    tree: &'a DynamicBoundingVolumeTree<T>,
    ray: Ray<S, P, P::Diff>,
) -> Vec<(&'a T, P)>
where
    S: BaseFloat,
    T: TreeValue,
    P: EuclideanSpace<Scalar = S>,
    P::Diff: VectorSpace<Scalar = S> + InnerSpace,
    T::Bound: Clone
        + Contains<T::Bound>
        + SurfaceArea<Scalar = S>
        + Union<T::Bound, Output = T::Bound>
        + Continuous<Ray<S, P, P::Diff>, Result = P>
        + Discrete<Ray<S, P, P::Diff>>,
{
    let mut visitor = ContinuousVisitor::<_, T>::new(&ray);
    tree.query(&mut visitor)
}
<|endoftext|>


<commit_before>use css;

pub struct Parser {
    pub stylesheet: String,
    current: Vec<char>,
}

impl Parser {
    pub fn new(full_css: String) -> Parser {
        Parser {
            current: full_css.chars().collect(),
            stylesheet: full_css,
        }
    }

    pub fn parse_stylesheet(&mut self) -> css::Stylesheet {
        let mut stylesheet = css::Stylesheet::new();

        while self.has_chars() {
            let selectors = self.parse_selectors();
            let styles = self.parse_declarations();

            println!("{:?} {:?}", selectors, styles);
        }

        css::Stylesheet::new()
    }

    fn parse_selectors(&mut self) -> Vec<css::Selector> {
        let selectors = Vec::<css::Selector>::new();

        while self.has_chars() && self.peek() != '{' {
            self.consume();
        }

        if self.has_chars() {
            self.consume();
        }

        selectors
    }

    fn parse_declarations(&mut self) -> Vec<css::Declaration> {
        let declarations = Vec::<css::Declaration>::new();

        while self.has_chars() && self.peek() != '}' {
            self.consume();
        }

        if self.has_chars() {
            self.consume();
        }

        declarations
    }

    fn has_chars(&self) -> bool {
        self.current.len() > 0
    }

    fn consume(&mut self) -> char {
        self.current.remove(0)
    }

    fn peek(&self) -> char {
        self.current[0]
    }

    fn consume_while<F>(&mut self, condition: F) -> String
        where F : Fn(char) -> bool {
            let mut result = String::new();
            while self.has_chars() && condition(self.peek()) {
                result.push(self.consume());
            }
            result
        }
}<commit_msg>css parser started<commit_after>use css;

pub struct Parser {
    pub stylesheet: String,
    current: Vec<char>,
}

impl Parser {
    pub fn new(full_css: String) -> Parser {
        Parser {
            current: full_css.chars().collect(),
            stylesheet: full_css,
        }
    }

    pub fn parse_stylesheet(&mut self) -> css::Stylesheet {
        let mut stylesheet = css::Stylesheet::new();

        while self.has_chars() {
            let selectors = self.parse_selectors();
            let styles = self.parse_declarations();

            println!("{:?} {:?}", selectors, styles);
        }

        css::Stylesheet::new()
    }

    fn parse_selectors(&mut self) -> Vec<css::Selector> {
        let mut selectors = Vec::<css::Selector>::new();

        while self.has_chars() && self.peek() != '{' {
            self.consume_while(char::is_whitespace);

            let sel_string = self.consume_while(|x| x != ',' && x != '{');
            println!("{}", sel_string);

            if self.has_chars() && self.peek() == ',' {
                self.consume();
            }
        }

        if self.has_chars() {
            self.consume();
        }

        selectors
    }

    fn parse_declarations(&mut self) -> Vec<css::Declaration> {
        let declarations = Vec::<css::Declaration>::new();

        while self.has_chars() && self.peek() != '}' {
            self.consume();
        }

        if self.has_chars() {
            self.consume();
        }

        declarations
    }

    fn has_chars(&self) -> bool {
        self.current.len() > 0
    }

    fn consume(&mut self) -> char {
        self.current.remove(0)
    }

    fn peek(&self) -> char {
        self.current[0]
    }

    fn consume_while<F>(&mut self, condition: F) -> String
        where F : Fn(char) -> bool {
            let mut result = String::new();
            while self.has_chars() && condition(self.peek()) {
                result.push(self.consume());
            }
            result
        }
}<|endoftext|>


<commit_before>use std::fmt::Show;
use std::rand::Rng;
use ::dice::Dice;
use std::num::SignedInt;

pub struct DiceRoll {
    dice: Dice,
    d4_result: Vec<usize>,
    d6_result: Vec<usize>,
    d8_result: Vec<usize>,
    d10_result: Vec<usize>,
    d12_result: Vec<usize>,
    d20_result: Vec<usize>,
}

impl DiceRoll {
    pub fn new(dice: Dice) -> Self {
        let mut rng = ::std::rand::thread_rng();
        let mut result = DiceRoll {
            dice: dice,
            d4_result: Vec::new(),
            d6_result: Vec::new(),
            d8_result: Vec::new(),
            d10_result: Vec::new(),
            d12_result: Vec::new(),
            d20_result: Vec::new()
        };

        // Roll d4s
        for _ in range(0, result.dice.d4s) {
            result.d4_result.push(rng.gen_range(1, 5));
        }
        // Roll d6s
        for _ in range(0, result.dice.d6s) {
            result.d6_result.push(rng.gen_range(1, 7));
        }
        // Roll d8s
        for _ in range(0, result.dice.d8s) {
            result.d8_result.push(rng.gen_range(1, 9));
        }
        // Roll d10s
        for _ in range(0, result.dice.d10s) {
            result.d10_result.push(rng.gen_range(1, 11));
        }
        // Roll d12s
        for _ in range(0, result.dice.d12s) {
            result.d12_result.push(rng.gen_range(1, 13));
        }
        // Roll d20s
        for _ in range(0, result.dice.d20s) {
            result.d20_result.push(rng.gen_range(1, 21));
        }

        result
    }

    pub fn result(&self) -> isize {
        let mut result = self.dice.modifier;
        result += DiceRoll::sum(&self.d4_result) as isize;
        result += DiceRoll::sum(&self.d6_result) as isize;
        result += DiceRoll::sum(&self.d8_result) as isize;
        result += DiceRoll::sum(&self.d10_result) as isize;
        result += DiceRoll::sum(&self.d12_result) as isize;
        result += DiceRoll::sum(&self.d20_result) as isize;
        result
    }

    fn sum(list: &Vec<usize>) -> usize {
        let mut result = 0us;
        for item in list.iter() {
            result += *item;
        }
        result
    }

    fn format(list: &Vec<usize>, name: &str) -> String {
        let mut buff = String::new();
        if list.len() == 1 {
            buff.push_str(format!("1{}({}) ", name, list[0]).as_slice());
        } else if list.len() > 1 {
            buff.push_str(format!("{}{}(", list.len(), name).as_slice());
            for (i, value) in list.iter().enumerate() {
                buff.push_str(format!("{}", value).as_slice());
                if i != list.len() - 1 {
                    buff.push_str("+");
                }
            }
            buff.push_str(format!("={}) ", DiceRoll::sum(list)).as_slice());
        }
        buff
    }
}

impl Show for DiceRoll {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let mut buff = format!("{} = ", self.result());
        buff.push_str(DiceRoll::format(&self.d4_result, "d4").as_slice());
        buff.push_str(DiceRoll::format(&self.d6_result, "d6").as_slice());
        buff.push_str(DiceRoll::format(&self.d8_result, "d8").as_slice());
        buff.push_str(DiceRoll::format(&self.d10_result, "d10").as_slice());
        buff.push_str(DiceRoll::format(&self.d12_result, "d12").as_slice());
        buff.push_str(DiceRoll::format(&self.d20_result, "d20").as_slice());
        if self.dice.modifier > 0 {
            buff.push_str(format!("+ {}", self.dice.modifier).as_slice());
        } else if self.dice.modifier < 0 {
            buff.push_str(format!("- {}", self.dice.modifier.abs()).as_slice());
        }
        write!(f, "{}", buff.as_slice().trim())
    }
}
<commit_msg>made some changes to clean up code a bit<commit_after>use std::fmt::Show;
use std::rand::Rng;
use ::dice::Dice;
use std::num::SignedInt;

pub struct DiceRoll {
    dice: Dice,
    d4_result: Vec<usize>,
    d6_result: Vec<usize>,
    d8_result: Vec<usize>,
    d10_result: Vec<usize>,
    d12_result: Vec<usize>,
    d20_result: Vec<usize>,
}

impl DiceRoll {
    pub fn new(dice: Dice) -> Self {
        let d4_result = DiceRoll::generate_rolls(4, dice.d4s);
        let d6_result = DiceRoll::generate_rolls(6, dice.d6s);
        let d8_result = DiceRoll::generate_rolls(8, dice.d8s);
        let d10_result = DiceRoll::generate_rolls(10, dice.d10s);
        let d12_result = DiceRoll::generate_rolls(12, dice.d12s);
        let d20_result = DiceRoll::generate_rolls(20, dice.d20s);
        DiceRoll {
            dice: dice,
            d4_result: d4_result,
            d6_result: d6_result,
            d8_result: d8_result,
            d10_result: d10_result,
            d12_result: d12_result,
            d20_result: d20_result
        }
    }

    fn generate_rolls(dice_max: usize, number: usize) -> Vec<usize> {
        let mut result: Vec<usize> = Vec::new();
        let mut rng = ::std::rand::thread_rng();
        for _ in range(0, number) {
            result.push(rng.gen_range(0, dice_max) + 1);
        }
        result
    }

    pub fn result(&self) -> isize {
        let mut result = self.dice.modifier;
        result += DiceRoll::sum(&self.d4_result) as isize;
        result += DiceRoll::sum(&self.d6_result) as isize;
        result += DiceRoll::sum(&self.d8_result) as isize;
        result += DiceRoll::sum(&self.d10_result) as isize;
        result += DiceRoll::sum(&self.d12_result) as isize;
        result += DiceRoll::sum(&self.d20_result) as isize;
        result
    }

    fn sum(list: &Vec<usize>) -> usize {
        let mut result = 0us;
        for item in list.iter() {
            result += *item;
        }
        result
    }

    fn format(list: &Vec<usize>, name: &str) -> String {
        let mut buff = String::new();
        if list.len() == 1 {
            buff.push_str(format!("1{}({}) ", name, list[0]).as_slice());
        } else if list.len() > 1 {
            buff.push_str(format!("{}{}(", list.len(), name).as_slice());
            for (i, value) in list.iter().enumerate() {
                buff.push_str(format!("{}", value).as_slice());
                if i != list.len() - 1 {
                    buff.push_str("+");
                }
            }
            buff.push_str(format!("={}) ", DiceRoll::sum(list)).as_slice());
        }
        buff
    }
}

impl Show for DiceRoll {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let mut buff = format!("{} = ", self.result());
        buff.push_str(DiceRoll::format(&self.d4_result, "d4").as_slice());
        buff.push_str(DiceRoll::format(&self.d6_result, "d6").as_slice());
        buff.push_str(DiceRoll::format(&self.d8_result, "d8").as_slice());
        buff.push_str(DiceRoll::format(&self.d10_result, "d10").as_slice());
        buff.push_str(DiceRoll::format(&self.d12_result, "d12").as_slice());
        buff.push_str(DiceRoll::format(&self.d20_result, "d20").as_slice());
        if self.dice.modifier > 0 {
            buff.push_str(format!("+ {}", self.dice.modifier).as_slice());
        } else if self.dice.modifier < 0 {
            buff.push_str(format!("- {}", self.dice.modifier.abs()).as_slice());
        }
        write!(f, "{}", buff.as_slice().trim())
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use lexer::position::Position;

pub mod diag;
pub mod msg;

#[derive(PartialEq, Eq, Debug)]
pub enum ErrorCode {
    UnclosedComment, UnknownChar, UnclosedString, NumberOverflow, UnknownFactor,
    UnexpectedToken, ExpectedTopLevelElement, ExpectedType, ExpectedIdentifier,
    MisplacedElse, IoError, CommaExpected, ExpectedValue, ExpectedClassElement,
    RedundantModifier, MisplacedModifier, Unimplemented, InvalidEscapeSequence,
}

#[derive(Debug)]
pub struct ParseError {
    pub position: Position,
    pub message: String,
    pub code: ErrorCode
}

impl ParseError {
    pub fn print(&self) {
        println!("{}", self);
    }
}

pub fn err<T>(pos: Position, msg: String, code: ErrorCode) -> Result<T, ParseError> {
    Err(ParseError {
        position: pos,
        message: msg,
        code: code,
    })
}

pub fn unimplemented(pos: Position) -> Result<(), ParseError> {
    err(pos, "not yet implemented".to_string(), ErrorCode::Unimplemented)
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "error at line {}: {}", self.position, self.message)
    }
}
<commit_msg>removed ErrorCode and ParseError<commit_after>pub mod diag;
pub mod msg;
<|endoftext|>


<commit_before>fn drop<T: Clone>(list: &[T], n: uint) -> ~[T] {
    list.iter().enumerate().filter_map(
        |(i,&ref e)|
            if i%n < n-1 {
                Some(e.clone())
            } else {
                None
            }
        ).collect()
}

fn main() {
    let list = ~['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
    println!("{:?}", drop(list, 3));
}

<commit_msg>Cleanup Problem 16<commit_after>// The author of this work hereby waives all claim of copyright (economic and
// moral) in this work and immediately places it in the public domain; it may
// be used, distorted or destroyed in any manner whatsoever without further
// attribution or notice to the creator.

//! Problem 16: Vectors: drop
//!
//! Drop every `n`th element of a vector.
//!
//! Your function could have this signature:
//! `fn drop<T>(n: uint, vec: ~[T]) -> ~[T]`

fn drop<T>(vec: ~[T], n: uint) -> ~[T] {
    vec.move_iter().enumerate().filter_map(
        |(i,e)|
            if i%n < n-1 {
                Some(e)
            } else {
                None
            }
        ).collect()
}

#[test]
fn drop_test() {
    let vec = ~['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
    assert_eq!(drop(vec, 3), ~['a', 'b', 'd', 'e', 'g', 'h', 'j']);
}

<|endoftext|>


<commit_before>pub use self::os::{flock};
pub use self::os::{F_DUPFD};
pub use self::os::{F_DUPFD_CLOEXEC};
pub use self::os::{F_GETFD};
pub use self::os::{F_SETFD};
pub use self::os::{F_GETFL};
pub use self::os::{F_SETFL};
pub use self::os::{F_GETLK};
pub use self::os::{F_SETLK};
pub use self::os::{F_SETLKW};
pub use self::os::{F_GETOWN};
pub use self::os::{F_SETOWN};
pub use self::os::{FD_CLOEXEC};
pub use self::os::{F_RDLCK};
pub use self::os::{F_UNLCK};
pub use self::os::{F_WRLCK};
pub use self::os::{O_CLOEXEC};
pub use self::os::{O_CREAT};
pub use self::os::{O_DIRECTORY};
pub use self::os::{O_EXCL};
pub use self::os::{O_NOCTTY};
pub use self::os::{O_NOFOLLOW};
pub use self::os::{O_TRUNC};
pub use self::os::{O_APPEND};
pub use self::os::{O_DSYNC};
pub use self::os::{O_NONBLOCK};
pub use self::os::{O_RSYNC};
pub use self::os::{O_SYNC};
pub use self::os::{O_ACCMODE};
pub use self::os::{O_RDONLY};
pub use self::os::{O_RDWR};
pub use self::os::{O_WRONLY};
pub use self::os::{AT_FDCWD};
pub use self::os::{AT_EACCESS};
pub use self::os::{AT_SYMLINK_NOFOLLOW};
pub use self::os::{AT_SYMLINK_FOLLOW};
pub use self::os::{AT_REMOVEDIR};
pub use self::os::{POSIX_FADV_DONTNEED};
pub use self::os::{POSIX_FADV_NOREUSE};
pub use self::os::{POSIX_FADV_NORMAL};
pub use self::os::{POSIX_FADV_RANDOM};
pub use self::os::{POSIX_FADV_SEQUENTIAL};
pub use self::os::{POSIX_FADV_WILLNEED};

use {NTStr, int_t, char_t};
use sys::types::{mode_t, off_t};

#[cfg(target_os = "linux")]
#[path = "linux/mod.rs"]
mod os;

pub fn creat<T: NTStr>(file: &T, mode: mode_t) -> int_t {
    extern { fn creat(file: *const char_t, mode: mode_t) -> int_t; }
    unsafe { creat(file.as_ptr(), mode) }
}

pub fn posix_fadvise(fd: int_t, off: off_t, len: off_t, advise: int_t) -> int_t {
    extern {
        fn posix_fadvise(fd: int_t, off: off_t, len: off_t, advise: int_t) -> int_t;
    }
    unsafe { posix_fadvise(fd, off, len, advise) }
}

pub fn posix_fallocate(fd: int_t, off: off_t, len: off_t) -> int_t {
    extern { fn posix_fallocate(fd: int_t, off: off_t, len: off_t) -> int_t; }
    unsafe { posix_fallocate(fd, off, len) }
}

extern "C" {
    pub fn fcntl(fd: int_t, cmd: int_t, ...) -> int_t;
    pub fn open(file: *const char_t, oflag: int_t, ...) -> int_t;
    pub fn openat(fd: int_t, file: *const char_t, oflag: int_t, ...) -> int_t;
}
<commit_msg>fcntl::open1<commit_after>pub use self::os::{flock};
pub use self::os::{F_DUPFD};
pub use self::os::{F_DUPFD_CLOEXEC};
pub use self::os::{F_GETFD};
pub use self::os::{F_SETFD};
pub use self::os::{F_GETFL};
pub use self::os::{F_SETFL};
pub use self::os::{F_GETLK};
pub use self::os::{F_SETLK};
pub use self::os::{F_SETLKW};
pub use self::os::{F_GETOWN};
pub use self::os::{F_SETOWN};
pub use self::os::{FD_CLOEXEC};
pub use self::os::{F_RDLCK};
pub use self::os::{F_UNLCK};
pub use self::os::{F_WRLCK};
pub use self::os::{O_CLOEXEC};
pub use self::os::{O_CREAT};
pub use self::os::{O_DIRECTORY};
pub use self::os::{O_EXCL};
pub use self::os::{O_NOCTTY};
pub use self::os::{O_NOFOLLOW};
pub use self::os::{O_TRUNC};
pub use self::os::{O_APPEND};
pub use self::os::{O_DSYNC};
pub use self::os::{O_NONBLOCK};
pub use self::os::{O_RSYNC};
pub use self::os::{O_SYNC};
pub use self::os::{O_ACCMODE};
pub use self::os::{O_RDONLY};
pub use self::os::{O_RDWR};
pub use self::os::{O_WRONLY};
pub use self::os::{AT_FDCWD};
pub use self::os::{AT_EACCESS};
pub use self::os::{AT_SYMLINK_NOFOLLOW};
pub use self::os::{AT_SYMLINK_FOLLOW};
pub use self::os::{AT_REMOVEDIR};
pub use self::os::{POSIX_FADV_DONTNEED};
pub use self::os::{POSIX_FADV_NOREUSE};
pub use self::os::{POSIX_FADV_NORMAL};
pub use self::os::{POSIX_FADV_RANDOM};
pub use self::os::{POSIX_FADV_SEQUENTIAL};
pub use self::os::{POSIX_FADV_WILLNEED};

use {NTStr, int_t, char_t};
use sys::types::{mode_t, off_t};

#[cfg(target_os = "linux")]
#[path = "linux/mod.rs"]
mod os;

pub fn creat<T: NTStr>(file: &T, mode: mode_t) -> int_t {
    extern { fn creat(file: *const char_t, mode: mode_t) -> int_t; }
    unsafe { creat(file.as_ptr(), mode) }
}

pub fn posix_fadvise(fd: int_t, off: off_t, len: off_t, advise: int_t) -> int_t {
    extern {
        fn posix_fadvise(fd: int_t, off: off_t, len: off_t, advise: int_t) -> int_t;
    }
    unsafe { posix_fadvise(fd, off, len, advise) }
}

pub fn posix_fallocate(fd: int_t, off: off_t, len: off_t) -> int_t {
    extern { fn posix_fallocate(fd: int_t, off: off_t, len: off_t) -> int_t; }
    unsafe { posix_fallocate(fd, off, len) }
}

pub fn open1<T: NTStr>(file: &T, oflag: int_t) -> int_t {
    unsafe { open(file.as_ptr(), oflag) }
}

extern "C" {
    pub fn fcntl(fd: int_t, cmd: int_t, ...) -> int_t;
    pub fn open(file: *const char_t, oflag: int_t, ...) -> int_t;
    pub fn openat(fd: int_t, file: *const char_t, oflag: int_t, ...) -> int_t;
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Fibonacci_sequence
#[cfg(not(test))]
fn main() {
    let fns=vec![
        (fib_recursive, "recursive implementation"),
        (fib_tail_recursive, "tail recursive implementation"),
        (fib_iterative, "iterative implementation")];

for &(f, desc) in fns.iter() {
    println!("{}", desc);
    for i in range(0u64, 10) {
        print!("{} ", f(i));
    }
    println!("\n");
    }
}

// Fibonacci "classic" recursive version
// not tail recursive (it's going to blow the stack
// for n too high)
fn fib_recursive(n: u64) -> u64 {
    match n {
        n if n<2 => n,
        m => fib_recursive(m - 1) + fib_recursive(m - 2)
    }
}

// tail recursive version
fn fib_tail_recursive(n: u64) -> u64 {
        fn in_fib(n : u64, current : u64, next : u64) -> u64 {
            match n {
                0 => current,
                _ => in_fib(n - 1, next, current + next)
            }
        }
        in_fib(n, 0, 1)
}

// iterative version
fn fib_iterative(n: u64) -> u64 {
    let (mut fib1, mut fib2) = (0u64, 1u64);
    let mut fib = n;

    for _ in range(1u64,n) {
        fib = fib1 + fib2;
        fib1 = fib2;
        fib2 = fib;
    }
    fib
}

// helper function to test that all versions of the fib function
// return the expected values.
#[cfg(test)]
fn tester(f: fn(u64)->u64) {
    let exp = [0u64,1,1,2,3,5,8,13,21,34];
    for i in range(0u64, 10) {
        let ret=f(i);
        assert_eq!(ret, exp[i as uint]);
    }
}

#[test]
fn fib_values() {
    let fns=vec![fib_recursive, fib_tail_recursive, fib_iterative];
    fns.iter()
        .advance(|&f| {tester(f); true});
}<commit_msg>re-refactoring<commit_after>// Implements http://rosettacode.org/wiki/Fibonacci_sequence
#[cfg(not(test))]
fn main() {
    let fns=vec![
        (fib_recursive, "recursive implementation"),
        (fib_tail_recursive, "tail recursive implementation"),
        (fib_iterative, "iterative implementation")];

    for (f, desc) in fns.move_iter() {
        let r: Vec<u64> = range(0u64, 10).map(|i| f(i)).collect();
        println!("{}:\n {}\n", desc, r);
    }
}

// Fibonacci "classic" recursive version
// not tail recursive (it's going to blow the stack
// for n too high)
fn fib_recursive(n: u64) -> u64 {
    match n {
        n if n<2 => n,
        m => fib_recursive(m - 1) + fib_recursive(m - 2)
    }
}

// tail recursive version
fn fib_tail_recursive(n: u64) -> u64 {
        fn in_fib(n : u64, current : u64, next : u64) -> u64 {
            match n {
                0 => current,
                _ => in_fib(n - 1, next, current + next)
            }
        }
        in_fib(n, 0, 1)
}

// iterative version
fn fib_iterative(n: u64) -> u64 {
    let (mut fib1, mut fib2) = (0u64, 1u64);
    let mut fib = n;

    for _ in range(1u64,n) {
        fib = fib1 + fib2;
        fib1 = fib2;
        fib2 = fib;
    }
    fib
}

// helper function to test that all versions of the fib function
// return the expected values.
#[cfg(test)]
fn tester(f: fn(u64)->u64) {
    let exp = [0u64,1,1,2,3,5,8,13,21,34];
    for i in range(0u64, 10) {
        let ret=f(i);
        assert_eq!(ret, exp[i as uint]);
    }
}

#[test]
fn fib_values() {
    let fns=vec![fib_recursive, fib_tail_recursive, fib_iterative];
    for &f in fns.iter() {
        tester(f);
    }
}<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! The Global Descriptor Table (GDT) is used for configuring segmentation.
//!
//! As we use paging rather than segmentation for memory management, we do
//! not actually use the GDT, but some x86 functionality still require it
//! to be properly configured.
use arch::cpu::segment;

const GDT_SIZE: usize = 512;

type Gdt = [segment::Descriptor; GDT_SIZE];
<commit_msg>[x86_64] make GDT type pub to suppress warning<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! The Global Descriptor Table (GDT) is used for configuring segmentation.
//!
//! As we use paging rather than segmentation for memory management, we do
//! not actually use the GDT, but some x86 functionality still require it
//! to be properly configured.
use arch::cpu::segment;

const GDT_SIZE: usize = 512;

pub type Gdt = [segment::Descriptor; GDT_SIZE];
<|endoftext|>


<commit_before>//! Functions for signing and verifying JSON and events.

use base64::{encode_config, STANDARD_NO_PAD};
use ring::digest::{digest, SHA256};
use serde_json::{from_str, map::Map, to_string, to_value, Value};

use crate::{
    keys::KeyPair,
    signatures::{Signature, SignatureMap, SignatureSet},
    verification::Verifier,
    Error,
};

/// The fields that are allowed to remain in an event during redaction.
static ALLOWED_KEYS: &[&str] = &[
    "event_id",
    "type",
    "room_id",
    "sender",
    "state_key",
    "content",
    "hashes",
    "signatures",
    "depth",
    "prev_events",
    "prev_state",
    "auth_events",
    "origin",
    "origin_server_ts",
    "membership",
];

/// The fields of an *m.room.power_levels* event's `content` key that are allowed to remain in an
/// event during redaction.
static ALLOWED_POWER_LEVELS_KEYS: &[&str] = &[
    "ban",
    "events",
    "events_default",
    "kick",
    "redact",
    "state_default",
    "users",
    "users_default",
];

/// The fields to remove from a JSON object when converting JSON into the "canonical" form.
static CANONICAL_JSON_FIELDS_TO_REMOVE: &[&str] = &["signatures", "unsigned"];

/// The fields to remove from a JSON object when creating a content hash of an event.
static CONTENT_HASH_FIELDS_TO_REMOVE: &[&str] = &["hashes", "signatures", "unsigned"];

/// The fields to remove from a JSON object when creating a reference hash of an event.
static REFERENCE_HASH_FIELDS_TO_REMOVE: &[&str] = &["age_ts", "signatures", "unsigned"];

/// Signs an arbitrary JSON object and adds the signature to an object under the key `signatures`.
///
/// If `signatures` is already present, the new signature will be appended to the existing ones.
///
/// # Parameters
///
/// * server_name: The hostname or IP of the homeserver, e.g. `example.com`.
/// * key_pair: A cryptographic key pair used to sign the JSON.
/// * value: A JSON object to sign according and append a signature to.
///
/// # Errors
///
/// Returns an error if:
///
/// * `value` is not a JSON object.
/// * `value` contains a field called `signatures` that is not a JSON object.
/// * `server_name` cannot be parsed as a valid host.
pub fn sign_json<K>(server_name: &str, key_pair: &K, value: &mut Value) -> Result<(), Error>
where
    K: KeyPair,
{
    let mut signature_map;
    let maybe_unsigned;

    // Pull `signatures` and `unsigned` out of the object, and limit the scope of the mutable
    // borrow of `value` so we can call `to_string` with it below.
    {
        let map = match value {
            Value::Object(ref mut map) => map,
            _ => return Err(Error::new("JSON value must be a JSON object")),
        };

        signature_map = match map.remove("signatures") {
            Some(signatures_value) => match signatures_value.as_object() {
                Some(signatures) => from_str(&to_string(signatures)?)?,
                None => return Err(Error::new("Field `signatures` must be a JSON object")),
            },
            None => SignatureMap::with_capacity(1),
        };

        maybe_unsigned = map.remove("unsigned");
    }

    // Get the canonical JSON.
    let json = to_string(&value)?;

    // Sign the canonical JSON.
    let signature = key_pair.sign(json.as_bytes());

    // Insert the new signature in the map we pulled out (or created) previously.
    let signature_set = signature_map
        .entry(server_name)?
        .or_insert_with(|| SignatureSet::with_capacity(1));

    signature_set.insert(signature);

    // Safe to unwrap because we did this exact check at the beginning of the function.
    let map = value.as_object_mut().unwrap();

    // Put `signatures` and `unsigned` back in.
    map.insert("signatures".to_string(), to_value(signature_map)?);

    if let Some(unsigned) = maybe_unsigned {
        map.insert("unsigned".to_string(), to_value(unsigned)?);
    }

    Ok(())
}

/// Converts a JSON object into the "canonical" string form.
///
/// # Parameters
///
/// * value: The `serde_json::Value` (JSON value) to convert.
///
/// # Errors
///
/// Returns an error if the provided JSON value is not a JSON object.
pub fn to_canonical_json(value: &Value) -> Result<String, Error> {
    to_canonical_json_with_fields_to_remove(value, CANONICAL_JSON_FIELDS_TO_REMOVE)
}

/// Use a public key to verify a signature of a JSON object.
///
/// # Parameters
///
/// * verifier: A `Verifier` appropriate for the digital signature algorithm that was used.
/// * public_key: The public key of the key pair used to sign the JSON, as a series of bytes.
/// * signature: The `Signature` to verify.
/// * value: The `serde_json::Value` (JSON value) that was signed.
///
/// # Errors
///
/// Returns an error if verification fails.
pub fn verify_json<V>(
    verifier: &V,
    public_key: &[u8],
    signature: &Signature,
    value: &Value,
) -> Result<(), Error>
where
    V: Verifier,
{
    verifier.verify_json(public_key, signature, to_canonical_json(value)?.as_bytes())
}

/// Creates a *content hash* for the JSON representation of an event.
///
/// Returns the hash as a Base64-encoded string, using the standard character set, without padding.
///
/// The content hash of an event covers the complete event including the unredacted contents. It is
/// used during federation and is described in the Matrix server-server specification.
///
/// # Parameters
///
/// value: A JSON object to generate a content hash for.
///
/// # Errors
///
/// Returns an error if the provided JSON value is not a JSON object.
pub fn content_hash(value: &Value) -> Result<String, Error> {
    let json = to_canonical_json_with_fields_to_remove(value, CONTENT_HASH_FIELDS_TO_REMOVE)?;

    let hash = digest(&SHA256, json.as_bytes());

    Ok(encode_config(&hash, STANDARD_NO_PAD))
}

/// Creates a *reference hash* for the JSON representation of an event.
///
/// Returns the hash as a Base64-encoded string, using the standard character set, without padding.
///
/// The reference hash of an event covers the essential fields of an event, including content
/// hashes. It is used to generate event identifiers and is described in the Matrix server-server
/// specification.
///
/// # Parameters
///
/// value: A JSON object to generate a reference hash for.
///
/// # Errors
///
/// Returns an error if the provided JSON value is not a JSON object.
pub fn reference_hash(value: &Value) -> Result<String, Error> {
    let redacted_value = redact(value)?;

    let json =
        to_canonical_json_with_fields_to_remove(&redacted_value, REFERENCE_HASH_FIELDS_TO_REMOVE)?;

    let hash = digest(&SHA256, json.as_bytes());

    Ok(encode_config(&hash, STANDARD_NO_PAD))
}

/// Hashes and signs the JSON representation of an event and adds the hash and signature to objects
/// under the keys `hashes` and `signatures`, respectively.
///
/// If `hashes` and/or `signatures` are already present, the new data will be appended to the
/// existing data.
///
/// # Parameters
///
/// * server_name: The hostname or IP of the homeserver, e.g. `example.com`.
/// * key_pair: A cryptographic key pair used to sign the event.
/// * value: A JSON object to be hashed and signed according to the Matrix specification.
///
/// # Errors
///
/// Returns an error if:
///
/// * `value` is not a JSON object.
/// * `value` contains a field called `content` that is not a JSON object.
/// * `value` contains a field called `hashes` that is not a JSON object.
/// * `value` contains a field called `signatures` that is not a JSON object.
/// * `value` is missing the `type` field or the field is not a JSON string.
/// * `server_name` cannot be parsed as a valid host.
pub fn hash_and_sign_event<K>(
    server_name: &str,
    key_pair: &K,
    value: &mut Value,
) -> Result<(), Error>
where
    K: KeyPair,
{
    let hash = content_hash(value)?;

    // Limit the scope of the mutable borrow so `value` can be passed immutably to `redact` below.
    {
        let map = match value {
            Value::Object(ref mut map) => map,
            _ => return Err(Error::new("JSON value must be a JSON object")),
        };

        let hashes_value = map
            .entry("hashes")
            .or_insert_with(|| Value::Object(Map::with_capacity(1)));

        match hashes_value.as_object_mut() {
            Some(hashes) => hashes.insert("sha256".to_string(), Value::String(hash)),
            None => return Err(Error::new("Field `hashes` must be a JSON object")),
        };
    }

    let mut redacted = redact(value)?;

    sign_json(server_name, key_pair, &mut redacted)?;

    // Safe to unwrap because we did this exact check at the beginning of the function.
    let map = value.as_object_mut().unwrap();

    map.insert("signatures".to_string(), redacted["signatures"].take());

    Ok(())
}

/// Internal implementation detail of the canonical JSON algorithm. Allows customization of the
/// fields that will be removed before serializing.
fn to_canonical_json_with_fields_to_remove(
    value: &Value,
    fields: &[&str],
) -> Result<String, Error> {
    if !value.is_object() {
        return Err(Error::new("JSON value must be a JSON object"));
    }

    let mut owned_value = value.clone();

    {
        let object = owned_value
            .as_object_mut()
            .expect("safe since we checked above");

        for field in fields {
            object.remove(*field);
        }
    }

    to_string(&owned_value).map_err(Error::from)
}

/// Redact the JSON representation of an event using the rules specified in the Matrix
/// client-server specification.
///
/// This is part of the process of signing an event.
fn redact(value: &Value) -> Result<Value, Error> {
    if !value.is_object() {
        return Err(Error::new("JSON value must be a JSON object"));
    }

    let mut owned_value = value.clone();

    let event = owned_value
        .as_object_mut()
        .expect("safe since we checked above");

    let event_type_value = match event.get("type") {
        Some(event_type_value) => event_type_value,
        None => return Err(Error::new("Field `type` in JSON value must be present")),
    };

    let event_type = match event_type_value.as_str() {
        Some(event_type) => event_type.to_string(),
        None => {
            return Err(Error::new(
                "Field `type` in JSON value must be a JSON string",
            ))
        }
    };

    if let Some(content_value) = event.get_mut("content") {
        let map = match content_value {
            Value::Object(ref mut map) => map,
            _ => {
                return Err(Error::new(
                    "Field `content` in JSON value must be a JSON object",
                ))
            }
        };

        for key in map.clone().keys() {
            match event_type.as_ref() {
                "m.room.member" if key != "membership" => map.remove(key),
                "m.room.create" if key != "creator" => map.remove(key),
                "m.room.join_rules" if key != "join_rules" => map.remove(key),
                "m.room.power_levels" if !ALLOWED_POWER_LEVELS_KEYS.contains(&key.as_ref()) => {
                    map.remove(key)
                }
                "m.room.aliases" if key != "aliases" => map.remove(key),
                "m.room.history_visibility" if key != "history_visibility" => map.remove(key),
                _ => map.remove(key),
            };
        }
    }

    for key in event.clone().keys() {
        if !ALLOWED_KEYS.contains(&key.as_ref()) {
            event.remove(key);
        }
    }

    Ok(owned_value)
}
<commit_msg>Remove an unnecessary layer of JSON conversion.<commit_after>//! Functions for signing and verifying JSON and events.

use base64::{encode_config, STANDARD_NO_PAD};
use ring::digest::{digest, SHA256};
use serde_json::{from_value, map::Map, to_string, to_value, Value};

use crate::{
    keys::KeyPair,
    signatures::{Signature, SignatureMap, SignatureSet},
    verification::Verifier,
    Error,
};

/// The fields that are allowed to remain in an event during redaction.
static ALLOWED_KEYS: &[&str] = &[
    "event_id",
    "type",
    "room_id",
    "sender",
    "state_key",
    "content",
    "hashes",
    "signatures",
    "depth",
    "prev_events",
    "prev_state",
    "auth_events",
    "origin",
    "origin_server_ts",
    "membership",
];

/// The fields of an *m.room.power_levels* event's `content` key that are allowed to remain in an
/// event during redaction.
static ALLOWED_POWER_LEVELS_KEYS: &[&str] = &[
    "ban",
    "events",
    "events_default",
    "kick",
    "redact",
    "state_default",
    "users",
    "users_default",
];

/// The fields to remove from a JSON object when converting JSON into the "canonical" form.
static CANONICAL_JSON_FIELDS_TO_REMOVE: &[&str] = &["signatures", "unsigned"];

/// The fields to remove from a JSON object when creating a content hash of an event.
static CONTENT_HASH_FIELDS_TO_REMOVE: &[&str] = &["hashes", "signatures", "unsigned"];

/// The fields to remove from a JSON object when creating a reference hash of an event.
static REFERENCE_HASH_FIELDS_TO_REMOVE: &[&str] = &["age_ts", "signatures", "unsigned"];

/// Signs an arbitrary JSON object and adds the signature to an object under the key `signatures`.
///
/// If `signatures` is already present, the new signature will be appended to the existing ones.
///
/// # Parameters
///
/// * server_name: The hostname or IP of the homeserver, e.g. `example.com`.
/// * key_pair: A cryptographic key pair used to sign the JSON.
/// * value: A JSON object to sign according and append a signature to.
///
/// # Errors
///
/// Returns an error if:
///
/// * `value` is not a JSON object.
/// * `value` contains a field called `signatures` that is not a JSON object.
/// * `server_name` cannot be parsed as a valid host.
pub fn sign_json<K>(server_name: &str, key_pair: &K, value: &mut Value) -> Result<(), Error>
where
    K: KeyPair,
{
    let mut signature_map;
    let maybe_unsigned;

    // Pull `signatures` and `unsigned` out of the object, and limit the scope of the mutable
    // borrow of `value` so we can call `to_string` with it below.
    {
        let map = match value {
            Value::Object(ref mut map) => map,
            _ => return Err(Error::new("JSON value must be a JSON object")),
        };

        signature_map = match map.remove("signatures") {
            Some(signatures_value) => match signatures_value.as_object() {
                Some(signatures) => from_value(Value::Object(signatures.clone()))?,
                None => return Err(Error::new("Field `signatures` must be a JSON object")),
            },
            None => SignatureMap::with_capacity(1),
        };

        maybe_unsigned = map.remove("unsigned");
    }

    // Get the canonical JSON.
    let json = to_string(&value)?;

    // Sign the canonical JSON.
    let signature = key_pair.sign(json.as_bytes());

    // Insert the new signature in the map we pulled out (or created) previously.
    let signature_set = signature_map
        .entry(server_name)?
        .or_insert_with(|| SignatureSet::with_capacity(1));

    signature_set.insert(signature);

    // Safe to unwrap because we did this exact check at the beginning of the function.
    let map = value.as_object_mut().unwrap();

    // Put `signatures` and `unsigned` back in.
    map.insert("signatures".to_string(), to_value(signature_map)?);

    if let Some(unsigned) = maybe_unsigned {
        map.insert("unsigned".to_string(), to_value(unsigned)?);
    }

    Ok(())
}

/// Converts a JSON object into the "canonical" string form.
///
/// # Parameters
///
/// * value: The `serde_json::Value` (JSON value) to convert.
///
/// # Errors
///
/// Returns an error if the provided JSON value is not a JSON object.
pub fn to_canonical_json(value: &Value) -> Result<String, Error> {
    to_canonical_json_with_fields_to_remove(value, CANONICAL_JSON_FIELDS_TO_REMOVE)
}

/// Use a public key to verify a signature of a JSON object.
///
/// # Parameters
///
/// * verifier: A `Verifier` appropriate for the digital signature algorithm that was used.
/// * public_key: The public key of the key pair used to sign the JSON, as a series of bytes.
/// * signature: The `Signature` to verify.
/// * value: The `serde_json::Value` (JSON value) that was signed.
///
/// # Errors
///
/// Returns an error if verification fails.
pub fn verify_json<V>(
    verifier: &V,
    public_key: &[u8],
    signature: &Signature,
    value: &Value,
) -> Result<(), Error>
where
    V: Verifier,
{
    verifier.verify_json(public_key, signature, to_canonical_json(value)?.as_bytes())
}

/// Creates a *content hash* for the JSON representation of an event.
///
/// Returns the hash as a Base64-encoded string, using the standard character set, without padding.
///
/// The content hash of an event covers the complete event including the unredacted contents. It is
/// used during federation and is described in the Matrix server-server specification.
///
/// # Parameters
///
/// value: A JSON object to generate a content hash for.
///
/// # Errors
///
/// Returns an error if the provided JSON value is not a JSON object.
pub fn content_hash(value: &Value) -> Result<String, Error> {
    let json = to_canonical_json_with_fields_to_remove(value, CONTENT_HASH_FIELDS_TO_REMOVE)?;

    let hash = digest(&SHA256, json.as_bytes());

    Ok(encode_config(&hash, STANDARD_NO_PAD))
}

/// Creates a *reference hash* for the JSON representation of an event.
///
/// Returns the hash as a Base64-encoded string, using the standard character set, without padding.
///
/// The reference hash of an event covers the essential fields of an event, including content
/// hashes. It is used to generate event identifiers and is described in the Matrix server-server
/// specification.
///
/// # Parameters
///
/// value: A JSON object to generate a reference hash for.
///
/// # Errors
///
/// Returns an error if the provided JSON value is not a JSON object.
pub fn reference_hash(value: &Value) -> Result<String, Error> {
    let redacted_value = redact(value)?;

    let json =
        to_canonical_json_with_fields_to_remove(&redacted_value, REFERENCE_HASH_FIELDS_TO_REMOVE)?;

    let hash = digest(&SHA256, json.as_bytes());

    Ok(encode_config(&hash, STANDARD_NO_PAD))
}

/// Hashes and signs the JSON representation of an event and adds the hash and signature to objects
/// under the keys `hashes` and `signatures`, respectively.
///
/// If `hashes` and/or `signatures` are already present, the new data will be appended to the
/// existing data.
///
/// # Parameters
///
/// * server_name: The hostname or IP of the homeserver, e.g. `example.com`.
/// * key_pair: A cryptographic key pair used to sign the event.
/// * value: A JSON object to be hashed and signed according to the Matrix specification.
///
/// # Errors
///
/// Returns an error if:
///
/// * `value` is not a JSON object.
/// * `value` contains a field called `content` that is not a JSON object.
/// * `value` contains a field called `hashes` that is not a JSON object.
/// * `value` contains a field called `signatures` that is not a JSON object.
/// * `value` is missing the `type` field or the field is not a JSON string.
/// * `server_name` cannot be parsed as a valid host.
pub fn hash_and_sign_event<K>(
    server_name: &str,
    key_pair: &K,
    value: &mut Value,
) -> Result<(), Error>
where
    K: KeyPair,
{
    let hash = content_hash(value)?;

    // Limit the scope of the mutable borrow so `value` can be passed immutably to `redact` below.
    {
        let map = match value {
            Value::Object(ref mut map) => map,
            _ => return Err(Error::new("JSON value must be a JSON object")),
        };

        let hashes_value = map
            .entry("hashes")
            .or_insert_with(|| Value::Object(Map::with_capacity(1)));

        match hashes_value.as_object_mut() {
            Some(hashes) => hashes.insert("sha256".to_string(), Value::String(hash)),
            None => return Err(Error::new("Field `hashes` must be a JSON object")),
        };
    }

    let mut redacted = redact(value)?;

    sign_json(server_name, key_pair, &mut redacted)?;

    // Safe to unwrap because we did this exact check at the beginning of the function.
    let map = value.as_object_mut().unwrap();

    map.insert("signatures".to_string(), redacted["signatures"].take());

    Ok(())
}

/// Internal implementation detail of the canonical JSON algorithm. Allows customization of the
/// fields that will be removed before serializing.
fn to_canonical_json_with_fields_to_remove(
    value: &Value,
    fields: &[&str],
) -> Result<String, Error> {
    if !value.is_object() {
        return Err(Error::new("JSON value must be a JSON object"));
    }

    let mut owned_value = value.clone();

    {
        let object = owned_value
            .as_object_mut()
            .expect("safe since we checked above");

        for field in fields {
            object.remove(*field);
        }
    }

    to_string(&owned_value).map_err(Error::from)
}

/// Redact the JSON representation of an event using the rules specified in the Matrix
/// client-server specification.
///
/// This is part of the process of signing an event.
fn redact(value: &Value) -> Result<Value, Error> {
    if !value.is_object() {
        return Err(Error::new("JSON value must be a JSON object"));
    }

    let mut owned_value = value.clone();

    let event = owned_value
        .as_object_mut()
        .expect("safe since we checked above");

    let event_type_value = match event.get("type") {
        Some(event_type_value) => event_type_value,
        None => return Err(Error::new("Field `type` in JSON value must be present")),
    };

    let event_type = match event_type_value.as_str() {
        Some(event_type) => event_type.to_string(),
        None => {
            return Err(Error::new(
                "Field `type` in JSON value must be a JSON string",
            ))
        }
    };

    if let Some(content_value) = event.get_mut("content") {
        let map = match content_value {
            Value::Object(ref mut map) => map,
            _ => {
                return Err(Error::new(
                    "Field `content` in JSON value must be a JSON object",
                ))
            }
        };

        for key in map.clone().keys() {
            match event_type.as_ref() {
                "m.room.member" if key != "membership" => map.remove(key),
                "m.room.create" if key != "creator" => map.remove(key),
                "m.room.join_rules" if key != "join_rules" => map.remove(key),
                "m.room.power_levels" if !ALLOWED_POWER_LEVELS_KEYS.contains(&key.as_ref()) => {
                    map.remove(key)
                }
                "m.room.aliases" if key != "aliases" => map.remove(key),
                "m.room.history_visibility" if key != "history_visibility" => map.remove(key),
                _ => map.remove(key),
            };
        }
    }

    for key in event.clone().keys() {
        if !ALLOWED_KEYS.contains(&key.as_ref()) {
            event.remove(key);
        }
    }

    Ok(owned_value)
}
<|endoftext|>