<commit_before>//! A library providing a generic connection pool.
#![feature(unsafe_destructor, phase, if_let)]
#![warn(missing_docs)]
#![doc(html_root_url="https://sfackler.github.io/doc")]

#[phase(plugin, link)]
extern crate log;
extern crate serialize;

use std::comm;
use std::collections::{Deque, RingBuf};
use std::sync::{Arc, Mutex};
use std::fmt;

pub use config::{Config, ConfigError, ZeroPoolSize, ZeroHelperTasks};

mod config;

/// A trait which provides database-specific functionality.
pub trait PoolManager<C, E>: Send+Sync {
    /// Attempts to create a new connection.
    fn connect(&self) -> Result<C, E>;

    /// Determines if the connection is still connected to the database.
    ///
    /// A standard implementation would check if a simple query like `SELECT 1`
    /// succeeds.
    fn is_valid(&self, conn: &mut C) -> Result<(), E>;

    /// *Quickly* determines if the connection is no longer usable.
    ///
    /// This will be called synchronously every time a connection is returned
    /// to the pool, so it should *not* block. If it returns `true`, the
    /// connection will be discarded.
    ///
    /// For example, an implementation might check if the underlying TCP socket
    /// has disconnected. Implementations that do not support this kind of
    /// fast health check may simply return `false`.
    fn has_broken(&self, conn: &mut C) -> bool;
}

/// A trait which handles errors reported by the `PoolManager`.
pub trait ErrorHandler<E>: Send+Sync {
    /// Handles an error.
    fn handle_error(&self, error: E);
}

impl<E> ErrorHandler<E> for Box<ErrorHandler<E>+Sync+Send> {
    fn handle_error(&self, error: E) {
        (**self).handle_error(error)
    }
}

/// An `ErrorHandler` which does nothing.
pub struct NoopErrorHandler;

impl<E> ErrorHandler<E> for NoopErrorHandler {
    fn handle_error(&self, _: E) {}
}

/// An `ErrorHandler` which logs at the error level.
pub struct LoggingErrorHandler;

impl<E> ErrorHandler<E> for LoggingErrorHandler where E: fmt::Show {
    fn handle_error(&self, error: E) {
        error!("{}", error);
    }
}

enum Command<C> {
    AddConnection,
    TestConnection(C),
}

struct PoolInternals<C> {
    conns: RingBuf<C>,
    num_conns: uint,
}

struct InnerPool<C, E, M, H> where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    config: Config,
    manager: M,
    error_handler: H,
    internals: Mutex<PoolInternals<C>>,
}

/// A generic connection pool.
pub struct Pool<C, E, M, H> where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    helper_chan: Mutex<Sender<Command<C>>>,
    inner: Arc<InnerPool<C, E, M, H>>
}

impl<C, E, M, H> Pool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    /// Creates a new connection pool.
    ///
    /// Returns an `Err` value only if `config` is invalid.
    pub fn new(config: Config, manager: M, error_handler: H)
               -> Result<Pool<C, E, M, H>, ConfigError> {
        try!(config.validate());

        let internals = PoolInternals {
            conns: RingBuf::new(),
            num_conns: config.pool_size,
        };

        let inner = Arc::new(InnerPool {
            config: config,
            manager: manager,
            error_handler: error_handler,
            internals: Mutex::new(internals),
        });

        let (sender, receiver) = comm::channel();
        // FIXME :(
        let receiver = Arc::new(Mutex::new(receiver));

        for _ in range(0, config.helper_tasks) {
            let inner = inner.clone();
            let receiver = receiver.clone();
            spawn(proc() helper_task(receiver, inner));
        }

        for _ in range(0, config.pool_size) {
            sender.send(AddConnection);
        }

        Ok(Pool {
            helper_chan: Mutex::new(sender),
            inner: inner,
        })
    }

    /// Retrieves a connection from the pool.
    pub fn get<'a>(&'a self) -> Result<PooledConnection<'a, C, E, M, H>, ()> {
        let mut internals = self.inner.internals.lock();

        loop {
            match internals.conns.pop_front() {
                Some(mut conn) => {
                    drop(internals);

                    if self.inner.config.test_on_check_out {
                        if let Err(e) = self.inner.manager.is_valid(&mut conn) {
                            self.inner.error_handler.handle_error(e);
                            internals = self.inner.internals.lock();
                            internals.num_conns -= 1;
                            continue
                        }
                    }

                    return Ok(PooledConnection {
                        pool: self,
                        conn: Some(conn),
                    })
                }
                None => internals.cond.wait(),
            }
        }
    }

    fn put_back(&self, mut conn: C) {
        // This is specified to be fast, but call it before locking anyways
        let broken = self.inner.manager.has_broken(&mut conn);

        let mut internals = self.inner.internals.lock();
        if broken {
            internals.num_conns -= 1;
        } else {
            internals.conns.push(conn);
            internals.cond.signal();
        }
    }
}

fn helper_task<C, E, M, H>(receiver: Arc<Mutex<Receiver<Command<C>>>>,
                           inner: Arc<InnerPool<C, E, M, H>>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    loop {
        let receiver = receiver.lock();
        let res = receiver.recv_opt();
        drop(receiver);

        match res {
            // FIXME(rust-lang/rust#18258): shouldn't need to specify these type
            //                              parameters explicitly
            Ok(AddConnection) => add_connection::<C, E, M, H>(&*inner),
            Ok(TestConnection(conn)) => test_connection::<C, E, M, H>(&*inner, conn),
            Err(()) => break,
        }
    }
}

fn add_connection<C, E, M, H>(inner: &InnerPool<C, E, M, H>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    match inner.manager.connect() {
        Ok(conn) => {
            let mut internals = inner.internals.lock();
            internals.conns.push(conn);
            internals.num_conns += 1;
            internals.cond.signal();
        }
        Err(err) => inner.error_handler.handle_error(err),
    }
}

fn test_connection<C, E, M, H>(inner: &InnerPool<C, E, M, H>, mut conn: C)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    match inner.manager.is_valid(&mut conn) {
        Ok(()) => inner.internals.lock().conns.push(conn),
        Err(e) => {
            inner.error_handler.handle_error(e);
            inner.internals.lock().num_conns -= 1;
        }
    }
}

/// A smart pointer wrapping a connection.
pub struct PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    pool: &'a Pool<C, E, M, H>,
    conn: Option<C>,
}

#[unsafe_destructor]
impl<'a, C, E, M, H> Drop for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn drop(&mut self) {
        self.pool.put_back(self.conn.take().unwrap());
    }
}

impl<'a, C, E, M, H> Deref<C> for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn deref(&self) -> &C {
        self.conn.as_ref().unwrap()
    }
}

impl<'a, C, E, M, H> DerefMut<C> for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn deref_mut(&mut self) -> &mut C {
        self.conn.as_mut().unwrap()
    }
}
<commit_msg>Remove workaround for fixed bug<commit_after>//! A library providing a generic connection pool.
#![feature(unsafe_destructor, phase, if_let)]
#![warn(missing_docs)]
#![doc(html_root_url="https://sfackler.github.io/doc")]

#[phase(plugin, link)]
extern crate log;
extern crate serialize;

use std::comm;
use std::collections::{Deque, RingBuf};
use std::sync::{Arc, Mutex};
use std::fmt;

pub use config::{Config, ConfigError, ZeroPoolSize, ZeroHelperTasks};

mod config;

/// A trait which provides database-specific functionality.
pub trait PoolManager<C, E>: Send+Sync {
    /// Attempts to create a new connection.
    fn connect(&self) -> Result<C, E>;

    /// Determines if the connection is still connected to the database.
    ///
    /// A standard implementation would check if a simple query like `SELECT 1`
    /// succeeds.
    fn is_valid(&self, conn: &mut C) -> Result<(), E>;

    /// *Quickly* determines if the connection is no longer usable.
    ///
    /// This will be called synchronously every time a connection is returned
    /// to the pool, so it should *not* block. If it returns `true`, the
    /// connection will be discarded.
    ///
    /// For example, an implementation might check if the underlying TCP socket
    /// has disconnected. Implementations that do not support this kind of
    /// fast health check may simply return `false`.
    fn has_broken(&self, conn: &mut C) -> bool;
}

/// A trait which handles errors reported by the `PoolManager`.
pub trait ErrorHandler<E>: Send+Sync {
    /// Handles an error.
    fn handle_error(&self, error: E);
}

impl<E> ErrorHandler<E> for Box<ErrorHandler<E>+Sync+Send> {
    fn handle_error(&self, error: E) {
        (**self).handle_error(error)
    }
}

/// An `ErrorHandler` which does nothing.
pub struct NoopErrorHandler;

impl<E> ErrorHandler<E> for NoopErrorHandler {
    fn handle_error(&self, _: E) {}
}

/// An `ErrorHandler` which logs at the error level.
pub struct LoggingErrorHandler;

impl<E> ErrorHandler<E> for LoggingErrorHandler where E: fmt::Show {
    fn handle_error(&self, error: E) {
        error!("{}", error);
    }
}

enum Command<C> {
    AddConnection,
    TestConnection(C),
}

struct PoolInternals<C> {
    conns: RingBuf<C>,
    num_conns: uint,
}

struct InnerPool<C, E, M, H> where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    config: Config,
    manager: M,
    error_handler: H,
    internals: Mutex<PoolInternals<C>>,
}

/// A generic connection pool.
pub struct Pool<C, E, M, H> where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    helper_chan: Mutex<Sender<Command<C>>>,
    inner: Arc<InnerPool<C, E, M, H>>
}

impl<C, E, M, H> Pool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    /// Creates a new connection pool.
    ///
    /// Returns an `Err` value only if `config` is invalid.
    pub fn new(config: Config, manager: M, error_handler: H)
               -> Result<Pool<C, E, M, H>, ConfigError> {
        try!(config.validate());

        let internals = PoolInternals {
            conns: RingBuf::new(),
            num_conns: config.pool_size,
        };

        let inner = Arc::new(InnerPool {
            config: config,
            manager: manager,
            error_handler: error_handler,
            internals: Mutex::new(internals),
        });

        let (sender, receiver) = comm::channel();
        // FIXME :(
        let receiver = Arc::new(Mutex::new(receiver));

        for _ in range(0, config.helper_tasks) {
            let inner = inner.clone();
            let receiver = receiver.clone();
            spawn(proc() helper_task(receiver, inner));
        }

        for _ in range(0, config.pool_size) {
            sender.send(AddConnection);
        }

        Ok(Pool {
            helper_chan: Mutex::new(sender),
            inner: inner,
        })
    }

    /// Retrieves a connection from the pool.
    pub fn get<'a>(&'a self) -> Result<PooledConnection<'a, C, E, M, H>, ()> {
        let mut internals = self.inner.internals.lock();

        loop {
            match internals.conns.pop_front() {
                Some(mut conn) => {
                    drop(internals);

                    if self.inner.config.test_on_check_out {
                        if let Err(e) = self.inner.manager.is_valid(&mut conn) {
                            self.inner.error_handler.handle_error(e);
                            internals = self.inner.internals.lock();
                            internals.num_conns -= 1;
                            continue
                        }
                    }

                    return Ok(PooledConnection {
                        pool: self,
                        conn: Some(conn),
                    })
                }
                None => internals.cond.wait(),
            }
        }
    }

    fn put_back(&self, mut conn: C) {
        // This is specified to be fast, but call it before locking anyways
        let broken = self.inner.manager.has_broken(&mut conn);

        let mut internals = self.inner.internals.lock();
        if broken {
            internals.num_conns -= 1;
        } else {
            internals.conns.push(conn);
            internals.cond.signal();
        }
    }
}

fn helper_task<C, E, M, H>(receiver: Arc<Mutex<Receiver<Command<C>>>>,
                           inner: Arc<InnerPool<C, E, M, H>>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    loop {
        let receiver = receiver.lock();
        let res = receiver.recv_opt();
        drop(receiver);

        match res {
            Ok(AddConnection) => add_connection(&*inner),
            Ok(TestConnection(conn)) => test_connection(&*inner, conn),
            Err(()) => break,
        }
    }
}

fn add_connection<C, E, M, H>(inner: &InnerPool<C, E, M, H>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    match inner.manager.connect() {
        Ok(conn) => {
            let mut internals = inner.internals.lock();
            internals.conns.push(conn);
            internals.num_conns += 1;
            internals.cond.signal();
        }
        Err(err) => inner.error_handler.handle_error(err),
    }
}

fn test_connection<C, E, M, H>(inner: &InnerPool<C, E, M, H>, mut conn: C)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    match inner.manager.is_valid(&mut conn) {
        Ok(()) => inner.internals.lock().conns.push(conn),
        Err(e) => {
            inner.error_handler.handle_error(e);
            inner.internals.lock().num_conns -= 1;
        }
    }
}

/// A smart pointer wrapping a connection.
pub struct PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    pool: &'a Pool<C, E, M, H>,
    conn: Option<C>,
}

#[unsafe_destructor]
impl<'a, C, E, M, H> Drop for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn drop(&mut self) {
        self.pool.put_back(self.conn.take().unwrap());
    }
}

impl<'a, C, E, M, H> Deref<C> for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn deref(&self) -> &C {
        self.conn.as_ref().unwrap()
    }
}

impl<'a, C, E, M, H> DerefMut<C> for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn deref_mut(&mut self) -> &mut C {
        self.conn.as_mut().unwrap()
    }
}
<|endoftext|>


<commit_before>//! A Little implementation of the roulette-wheel principle, `RouletteWheel<T>`.
//! https://wikipedia.org/wiki/Fitness_proportionate_selection
//!
//! ![Fitness proportionate selection](https://upload.wikimedia.org/wikipedia/commons/2/2a/Fitness_proportionate_selection_example.png)
//!
//! # Examples usages
//!
//! You can explicitly create a `RouletteWheel<T>` with `new()`:
//!
//! ```
//! use roulette_wheel::RouletteWheel;
//!
//! let rw = RouletteWheel::<u8>::new();
//! ```
//!
//! You can `push` values in the roulette-wheel (which will grow the wheel as needed):
//!
//! ```
//! use roulette_wheel::RouletteWheel;
//! use std::iter;
//!
//! let rw: RouletteWheel<_> = iter::repeat(1.0).zip(1..5).collect();
//!
//! // .select_iter() will not consume the roulette wheel
//! for (fit, &ind) in rw.select_iter() {
//!    // do things with individuals here
//! }
//!
//! // .into_iter() consume the roulette wheel
//! for (fit, ind) in rw {
//!     // do things with individuals here
//! }
//!
//! ```

extern crate rand;

use std::iter::{FromIterator, Iterator, IntoIterator};
use rand::{Rng, ThreadRng, thread_rng};
use rand::distributions::{Range, IndependentSample};

/// A roulette-wheel container
pub struct RouletteWheel<T> {
    total_fitness: f32,
    fitnesses: Vec<f32>,
    population: Vec<T>
}

impl<T: Clone> Clone for RouletteWheel<T> {
    fn clone(&self) -> RouletteWheel<T> {
        RouletteWheel {
            total_fitness: self.total_fitness,
            fitnesses: self.fitnesses.clone(),
            population: self.population.clone()
        }
    }
}

impl<T> FromIterator<(f32, T)> for RouletteWheel<T> {
    fn from_iter<A>(iter: A) -> Self where A: IntoIterator<Item=(f32, T)> {
        let iter = iter.into_iter();
        let (lower, _) = iter.size_hint();

        let mut total_fitness = 0.0;
        let mut fitnesses = Vec::with_capacity(lower);
        let mut population = Vec::with_capacity(lower);

        for (fitness, individual) in iter {
            total_fitness += fitness;
            fitnesses.push(fitness);
            population.push(individual);
        }

        RouletteWheel { total_fitness, fitnesses, population }
    }
}

impl<T> RouletteWheel<T> {
    /// create a new empty random-wheel.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let rw = RouletteWheel::<u8>::new();
    /// ```
    pub fn new() -> RouletteWheel<T> {
        RouletteWheel {
            total_fitness: 0.0,
            fitnesses: Vec::new(),
            population: Vec::new()
        }
    }

    /// Creates an empty RouletteWheel with space for at least n elements.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let rw = RouletteWheel::<u8>::with_capacity(15);
    ///
    /// assert_eq!(rw.len(), 0);
    /// ```
    pub fn with_capacity(cap: usize) -> RouletteWheel<T> {
        RouletteWheel {
            total_fitness: 0.0,
            fitnesses: Vec::with_capacity(cap),
            population: Vec::with_capacity(cap)
        }
    }

    /// Reserves capacity for at least `additional` more elements to be inserted.
    /// The collection may reserve more space to avoid frequent reallocations.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let mut rw = RouletteWheel::<u8>::new();
    /// rw.reserve(20);
    ///
    /// assert_eq!(rw.len(), 0);
    /// ```
    pub fn reserve(&mut self, additional: usize) {
        self.fitnesses.reserve(additional);
        self.population.reserve(additional);
    }

    /// Returns the number of elements in the wheel.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let rw: RouletteWheel<_> = [(0.1, 10), (0.2, 15), (0.5, 20)].iter().cloned().collect();
    ///
    /// assert_eq!(rw.len(), 3);
    /// ```
    pub fn len(&self) -> usize {
        self.population.len()
    }

    /// Returns `true` if empty else return `false`.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let empty_rw = RouletteWheel::<u8>::new();
    ///
    /// assert_eq!(empty_rw.is_empty(), true);
    ///
    /// let non_empty_rw: RouletteWheel<_> = [(0.1, 10), (0.2, 15), (0.5, 20)].iter().cloned().collect();
    ///
    /// assert_eq!(non_empty_rw.is_empty(), false);
    /// ```
    pub fn is_empty(&self) -> bool {
        self.population.is_empty()
    }

    /// Remove all elements in this wheel.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let mut rw: RouletteWheel<_> = [(0.1, 10), (0.2, 15), (0.5, 20)].iter().cloned().collect();
    ///
    /// assert_eq!(rw.len(), 3);
    ///
    /// rw.clear();
    ///
    /// assert_eq!(rw.len(), 0);
    /// ```
    pub fn clear(&mut self) {
        self.fitnesses.clear();
        self.population.clear();
    }

    /// Add an element associated with a probability.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let mut rw = RouletteWheel::new();
    ///
    /// rw.push(1.0, 'r');
    /// rw.push(1.0, 'c');
    /// rw.push(1.0, 'a');
    ///
    /// assert_eq!(rw.len(), 3);
    /// ```
    pub fn push(&mut self, fitness: f32, individual: T) {
        assert!(fitness >= 0.0, "Can't push the less than zero fitness: {:?}", fitness);
        assert!((self.total_fitness + fitness).is_finite(), "Fitnesses sum reached a non-finite value!");
        unsafe { self.unchecked_push(fitness, individual) }
    }

    /// Add an element associated with a probability.
    /// This unsafe function doesn't check for total fitness overflow
    /// nether fitness positivity.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let mut rw = RouletteWheel::new();
    ///
    /// unsafe { rw.unchecked_push(1.0, 'r') };
    /// unsafe { rw.unchecked_push(1.0, 'c') };
    /// unsafe { rw.unchecked_push(1.0, 'a') };
    ///
    /// assert_eq!(rw.len(), 3);
    /// ```
    pub unsafe fn unchecked_push(&mut self, fitness: f32, individual: T) {
        self.total_fitness += fitness;
        self.fitnesses.push(fitness);
        self.population.push(individual);
    }

    /// Returns the sum of all individual fitnesses.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let mut rw = RouletteWheel::new();
    ///
    /// rw.push(3.0, 'r');
    /// rw.push(2.0, 'c');
    /// rw.push(1.5, 'a');
    ///
    /// assert_eq!(rw.total_fitness(), 6.5);
    /// ```
    pub fn total_fitness(&self) -> f32 {
        self.total_fitness
    }

    pub fn select_iter(&self) -> SelectIter<ThreadRng, T> {
        SelectIter::<ThreadRng, _>::new(&self)
    }
}

pub struct SelectIter<'a, R: Rng, T: 'a> {
    distribution_range: Range<f32>,
    rng: R,
    total_fitness: f32,
    fitnesses_ids: Vec<(usize, f32)>,
    roulette_wheel: &'a RouletteWheel<T>
}

impl<'a, R: Rng, T> SelectIter<'a, R, T> {
    pub fn new(roulette_wheel: &'a RouletteWheel<T>) -> SelectIter<'a, ThreadRng, T> {
        SelectIter::from_rng(roulette_wheel, thread_rng())
    }

    pub fn from_rng(roulette_wheel: &'a RouletteWheel<T>, rng: R) -> SelectIter<'a, R, T> {
        SelectIter {
            distribution_range: Range::new(0.0, 1.0),
            rng: rng,
            total_fitness: roulette_wheel.total_fitness,
            fitnesses_ids: roulette_wheel.fitnesses.iter().cloned().enumerate().collect(),
            roulette_wheel: roulette_wheel
        }
    }
}

impl<'a, R: Rng, T: 'a> Iterator for SelectIter<'a, R, T> {
    type Item = (f32, &'a T);

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.fitnesses_ids.len(), Some(self.fitnesses_ids.len()))
    }

    fn next(&mut self) -> Option<Self::Item> {
        if !self.fitnesses_ids.is_empty() {
            let sample = self.distribution_range.ind_sample(&mut self.rng);
            let mut selection = sample * self.total_fitness;
            let index = self.fitnesses_ids.iter().position(|&(_, fit)| {
                            selection -= fit;
                            selection <= 0.0
                        }).unwrap();
            let (index, fitness) = self.fitnesses_ids.swap_remove(index);
            self.total_fitness -= fitness;
            Some((fitness, &self.roulette_wheel.population[index]))
        }
        else { None }
    }
}

impl<T> IntoIterator for RouletteWheel<T> {
    type Item = (f32, T);
    type IntoIter = IntoSelectIter<ThreadRng, T>;

    fn into_iter(self) -> IntoSelectIter<ThreadRng, T> {
        IntoSelectIter::<ThreadRng, _>::new(self)
    }
}

pub struct IntoSelectIter<R: Rng, T> {
    distribution_range: Range<f32>,
    rng: R,
    total_fitness: f32,
    fitnesses: Vec<f32>,
    population: Vec<T>
}

impl<R: Rng, T> IntoSelectIter<R, T> {
    pub fn new(roulette_wheel: RouletteWheel<T>) -> IntoSelectIter<ThreadRng, T> {
        IntoSelectIter::from_rng(roulette_wheel, thread_rng())
    }

    pub fn from_rng(roulette_wheel: RouletteWheel<T>, rng: R) -> IntoSelectIter<R, T> {
        IntoSelectIter {
            distribution_range: Range::new(0.0, 1.0),
            rng: rng,
            total_fitness: roulette_wheel.total_fitness,
            fitnesses: roulette_wheel.fitnesses,
            population: roulette_wheel.population
        }
    }
}

impl<R: Rng, T> Iterator for IntoSelectIter<R, T> {
    type Item = (f32, T);

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.fitnesses.len(), Some(self.fitnesses.len()))
    }

    fn next(&mut self) -> Option<Self::Item> {
        if !self.fitnesses.is_empty() {
            let sample = self.distribution_range.ind_sample(&mut self.rng);
            let mut selection = sample * self.total_fitness;
            let index = self.fitnesses.iter().position(|fit| {
                            selection -= *fit;
                            selection <= 0.0
                        }).unwrap();
            let fitness = self.fitnesses.swap_remove(index);
            let individual = self.population.swap_remove(index);
            self.total_fitness -= fitness;
            Some((fitness, individual))
        }
        else { None }
    }
}

#[cfg(test)]
mod tests {
    use rand::SeedableRng;
    use rand::StdRng;
    use {RouletteWheel, SelectIter, IntoSelectIter};

    const SEED: [usize; 4] = [4, 2, 42, 4242];

    #[test]
    fn test_select_iter_seeded() {
        let rng = StdRng::from_seed(&SEED);

        let fitnesses = [0.1, 0.2, 0.3, 0.4, 0.5];
        let fitnesses = fitnesses.iter().cloned();
        let population = 15..20;
        let rw: RouletteWheel<_> = fitnesses.zip(population).collect();

        let mut iter = SelectIter::from_rng(&rw, rng);

        assert_eq!(iter.next(), Some((0.5, &19)));
        assert_eq!(iter.next(), Some((0.3, &17)));
        assert_eq!(iter.next(), Some((0.4, &18)));
        assert_eq!(iter.next(), Some((0.2, &16)));
        assert_eq!(iter.next(), Some((0.1, &15)));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn test_into_select_iter_seeded() {
        let rng = StdRng::from_seed(&SEED);

        let fitnesses = [0.1, 0.2, 0.3, 0.4, 0.5];
        let fitnesses = fitnesses.iter().cloned();
        let population = 15..20;
        let rw: RouletteWheel<_> = fitnesses.zip(population).collect();

        let mut iter = IntoSelectIter::from_rng(rw, rng);

        assert_eq!(iter.next(), Some((0.5, 19)));
        assert_eq!(iter.next(), Some((0.3, 17)));
        assert_eq!(iter.next(), Some((0.4, 18)));
        assert_eq!(iter.next(), Some((0.2, 16)));
        assert_eq!(iter.next(), Some((0.1, 15)));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn test_len() {
        let mut rw = RouletteWheel::<u8>::new();

        assert_eq!(rw.len(), 0);

        rw.push(0.1, 1);
        rw.push(0.1, 1);
        rw.push(0.1, 1);
        rw.push(0.1, 1);

        assert_eq!(rw.len(), 4);
    }
}
<commit_msg>rw: Clean up the roulette wheel FromIterator method<commit_after>//! A Little implementation of the roulette-wheel principle, `RouletteWheel<T>`.
//! https://wikipedia.org/wiki/Fitness_proportionate_selection
//!
//! ![Fitness proportionate selection](https://upload.wikimedia.org/wikipedia/commons/2/2a/Fitness_proportionate_selection_example.png)
//!
//! # Examples usages
//!
//! You can explicitly create a `RouletteWheel<T>` with `new()`:
//!
//! ```
//! use roulette_wheel::RouletteWheel;
//!
//! let rw = RouletteWheel::<u8>::new();
//! ```
//!
//! You can `push` values in the roulette-wheel (which will grow the wheel as needed):
//!
//! ```
//! use roulette_wheel::RouletteWheel;
//! use std::iter;
//!
//! let rw: RouletteWheel<_> = iter::repeat(1.0).zip(1..5).collect();
//!
//! // .select_iter() will not consume the roulette wheel
//! for (fit, &ind) in rw.select_iter() {
//!    // do things with individuals here
//! }
//!
//! // .into_iter() consume the roulette wheel
//! for (fit, ind) in rw {
//!     // do things with individuals here
//! }
//!
//! ```

extern crate rand;

use std::iter::{FromIterator, Iterator, IntoIterator};
use rand::{Rng, ThreadRng, thread_rng};
use rand::distributions::{Range, IndependentSample};

/// A roulette-wheel container
pub struct RouletteWheel<T> {
    total_fitness: f32,
    fitnesses: Vec<f32>,
    population: Vec<T>
}

impl<T: Clone> Clone for RouletteWheel<T> {
    fn clone(&self) -> RouletteWheel<T> {
        RouletteWheel {
            total_fitness: self.total_fitness,
            fitnesses: self.fitnesses.clone(),
            population: self.population.clone()
        }
    }
}

impl<T> FromIterator<(f32, T)> for RouletteWheel<T> {
    fn from_iter<A>(iter: A) -> Self where A: IntoIterator<Item=(f32, T)> {
        let (fitnesses, population): (Vec<f32>, _) = iter.into_iter().unzip();
        let total_fitness = fitnesses.iter().sum();
        RouletteWheel { total_fitness, fitnesses, population }
    }
}

impl<T> RouletteWheel<T> {
    /// create a new empty random-wheel.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let rw = RouletteWheel::<u8>::new();
    /// ```
    pub fn new() -> RouletteWheel<T> {
        RouletteWheel {
            total_fitness: 0.0,
            fitnesses: Vec::new(),
            population: Vec::new()
        }
    }

    /// Creates an empty RouletteWheel with space for at least n elements.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let rw = RouletteWheel::<u8>::with_capacity(15);
    ///
    /// assert_eq!(rw.len(), 0);
    /// ```
    pub fn with_capacity(cap: usize) -> RouletteWheel<T> {
        RouletteWheel {
            total_fitness: 0.0,
            fitnesses: Vec::with_capacity(cap),
            population: Vec::with_capacity(cap)
        }
    }

    /// Reserves capacity for at least `additional` more elements to be inserted.
    /// The collection may reserve more space to avoid frequent reallocations.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let mut rw = RouletteWheel::<u8>::new();
    /// rw.reserve(20);
    ///
    /// assert_eq!(rw.len(), 0);
    /// ```
    pub fn reserve(&mut self, additional: usize) {
        self.fitnesses.reserve(additional);
        self.population.reserve(additional);
    }

    /// Returns the number of elements in the wheel.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let rw: RouletteWheel<_> = [(0.1, 10), (0.2, 15), (0.5, 20)].iter().cloned().collect();
    ///
    /// assert_eq!(rw.len(), 3);
    /// ```
    pub fn len(&self) -> usize {
        self.population.len()
    }

    /// Returns `true` if empty else return `false`.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let empty_rw = RouletteWheel::<u8>::new();
    ///
    /// assert_eq!(empty_rw.is_empty(), true);
    ///
    /// let non_empty_rw: RouletteWheel<_> = [(0.1, 10), (0.2, 15), (0.5, 20)].iter().cloned().collect();
    ///
    /// assert_eq!(non_empty_rw.is_empty(), false);
    /// ```
    pub fn is_empty(&self) -> bool {
        self.population.is_empty()
    }

    /// Remove all elements in this wheel.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let mut rw: RouletteWheel<_> = [(0.1, 10), (0.2, 15), (0.5, 20)].iter().cloned().collect();
    ///
    /// assert_eq!(rw.len(), 3);
    ///
    /// rw.clear();
    ///
    /// assert_eq!(rw.len(), 0);
    /// ```
    pub fn clear(&mut self) {
        self.fitnesses.clear();
        self.population.clear();
    }

    /// Add an element associated with a probability.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let mut rw = RouletteWheel::new();
    ///
    /// rw.push(1.0, 'r');
    /// rw.push(1.0, 'c');
    /// rw.push(1.0, 'a');
    ///
    /// assert_eq!(rw.len(), 3);
    /// ```
    pub fn push(&mut self, fitness: f32, individual: T) {
        assert!(fitness >= 0.0, "Can't push the less than zero fitness: {:?}", fitness);
        assert!((self.total_fitness + fitness).is_finite(), "Fitnesses sum reached a non-finite value!");
        unsafe { self.unchecked_push(fitness, individual) }
    }

    /// Add an element associated with a probability.
    /// This unsafe function doesn't check for total fitness overflow
    /// nether fitness positivity.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let mut rw = RouletteWheel::new();
    ///
    /// unsafe { rw.unchecked_push(1.0, 'r') };
    /// unsafe { rw.unchecked_push(1.0, 'c') };
    /// unsafe { rw.unchecked_push(1.0, 'a') };
    ///
    /// assert_eq!(rw.len(), 3);
    /// ```
    pub unsafe fn unchecked_push(&mut self, fitness: f32, individual: T) {
        self.total_fitness += fitness;
        self.fitnesses.push(fitness);
        self.population.push(individual);
    }

    /// Returns the sum of all individual fitnesses.
    /// # Example
    ///
    /// ```
    /// use roulette_wheel::RouletteWheel;
    ///
    /// let mut rw = RouletteWheel::new();
    ///
    /// rw.push(3.0, 'r');
    /// rw.push(2.0, 'c');
    /// rw.push(1.5, 'a');
    ///
    /// assert_eq!(rw.total_fitness(), 6.5);
    /// ```
    pub fn total_fitness(&self) -> f32 {
        self.total_fitness
    }

    pub fn select_iter(&self) -> SelectIter<ThreadRng, T> {
        SelectIter::<ThreadRng, _>::new(&self)
    }
}

pub struct SelectIter<'a, R: Rng, T: 'a> {
    distribution_range: Range<f32>,
    rng: R,
    total_fitness: f32,
    fitnesses_ids: Vec<(usize, f32)>,
    roulette_wheel: &'a RouletteWheel<T>
}

impl<'a, R: Rng, T> SelectIter<'a, R, T> {
    pub fn new(roulette_wheel: &'a RouletteWheel<T>) -> SelectIter<'a, ThreadRng, T> {
        SelectIter::from_rng(roulette_wheel, thread_rng())
    }

    pub fn from_rng(roulette_wheel: &'a RouletteWheel<T>, rng: R) -> SelectIter<'a, R, T> {
        SelectIter {
            distribution_range: Range::new(0.0, 1.0),
            rng: rng,
            total_fitness: roulette_wheel.total_fitness,
            fitnesses_ids: roulette_wheel.fitnesses.iter().cloned().enumerate().collect(),
            roulette_wheel: roulette_wheel
        }
    }
}

impl<'a, R: Rng, T: 'a> Iterator for SelectIter<'a, R, T> {
    type Item = (f32, &'a T);

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.fitnesses_ids.len(), Some(self.fitnesses_ids.len()))
    }

    fn next(&mut self) -> Option<Self::Item> {
        if !self.fitnesses_ids.is_empty() {
            let sample = self.distribution_range.ind_sample(&mut self.rng);
            let mut selection = sample * self.total_fitness;
            let index = self.fitnesses_ids.iter().position(|&(_, fit)| {
                            selection -= fit;
                            selection <= 0.0
                        }).unwrap();
            let (index, fitness) = self.fitnesses_ids.swap_remove(index);
            self.total_fitness -= fitness;
            Some((fitness, &self.roulette_wheel.population[index]))
        }
        else { None }
    }
}

impl<T> IntoIterator for RouletteWheel<T> {
    type Item = (f32, T);
    type IntoIter = IntoSelectIter<ThreadRng, T>;

    fn into_iter(self) -> IntoSelectIter<ThreadRng, T> {
        IntoSelectIter::<ThreadRng, _>::new(self)
    }
}

pub struct IntoSelectIter<R: Rng, T> {
    distribution_range: Range<f32>,
    rng: R,
    total_fitness: f32,
    fitnesses: Vec<f32>,
    population: Vec<T>
}

impl<R: Rng, T> IntoSelectIter<R, T> {
    pub fn new(roulette_wheel: RouletteWheel<T>) -> IntoSelectIter<ThreadRng, T> {
        IntoSelectIter::from_rng(roulette_wheel, thread_rng())
    }

    pub fn from_rng(roulette_wheel: RouletteWheel<T>, rng: R) -> IntoSelectIter<R, T> {
        IntoSelectIter {
            distribution_range: Range::new(0.0, 1.0),
            rng: rng,
            total_fitness: roulette_wheel.total_fitness,
            fitnesses: roulette_wheel.fitnesses,
            population: roulette_wheel.population
        }
    }
}

impl<R: Rng, T> Iterator for IntoSelectIter<R, T> {
    type Item = (f32, T);

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.fitnesses.len(), Some(self.fitnesses.len()))
    }

    fn next(&mut self) -> Option<Self::Item> {
        if !self.fitnesses.is_empty() {
            let sample = self.distribution_range.ind_sample(&mut self.rng);
            let mut selection = sample * self.total_fitness;
            let index = self.fitnesses.iter().position(|fit| {
                            selection -= *fit;
                            selection <= 0.0
                        }).unwrap();
            let fitness = self.fitnesses.swap_remove(index);
            let individual = self.population.swap_remove(index);
            self.total_fitness -= fitness;
            Some((fitness, individual))
        }
        else { None }
    }
}

#[cfg(test)]
mod tests {
    use rand::SeedableRng;
    use rand::StdRng;
    use {RouletteWheel, SelectIter, IntoSelectIter};

    const SEED: [usize; 4] = [4, 2, 42, 4242];

    #[test]
    fn test_select_iter_seeded() {
        let rng = StdRng::from_seed(&SEED);

        let fitnesses = [0.1, 0.2, 0.3, 0.4, 0.5];
        let fitnesses = fitnesses.iter().cloned();
        let population = 15..20;
        let rw: RouletteWheel<_> = fitnesses.zip(population).collect();

        let mut iter = SelectIter::from_rng(&rw, rng);

        assert_eq!(iter.next(), Some((0.5, &19)));
        assert_eq!(iter.next(), Some((0.3, &17)));
        assert_eq!(iter.next(), Some((0.4, &18)));
        assert_eq!(iter.next(), Some((0.2, &16)));
        assert_eq!(iter.next(), Some((0.1, &15)));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn test_into_select_iter_seeded() {
        let rng = StdRng::from_seed(&SEED);

        let fitnesses = [0.1, 0.2, 0.3, 0.4, 0.5];
        let fitnesses = fitnesses.iter().cloned();
        let population = 15..20;
        let rw: RouletteWheel<_> = fitnesses.zip(population).collect();

        let mut iter = IntoSelectIter::from_rng(rw, rng);

        assert_eq!(iter.next(), Some((0.5, 19)));
        assert_eq!(iter.next(), Some((0.3, 17)));
        assert_eq!(iter.next(), Some((0.4, 18)));
        assert_eq!(iter.next(), Some((0.2, 16)));
        assert_eq!(iter.next(), Some((0.1, 15)));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn test_len() {
        let mut rw = RouletteWheel::<u8>::new();

        assert_eq!(rw.len(), 0);

        rw.push(0.1, 1);
        rw.push(0.1, 1);
        rw.push(0.1, 1);
        rw.push(0.1, 1);

        assert_eq!(rw.len(), 4);
    }
}
<|endoftext|>


<commit_before>extern crate rand;
use HaltCondition::{ Epochs, MSE };
use UpdateRule::{ Stochastic, Batch };
use std::iter::{Zip, Enumerate};
use std::slice;

#[test]
fn it_works() {
}

type Node = Vec<f64>;
type Layer = Vec<Node>;

#[derive(Debug)]
pub enum HaltCondition {
    Epochs(usize),
    MSE(f64),
}

#[derive(Debug)]
pub enum UpdateRule {
    Stochastic,
    Batch
}

#[derive(Debug)]
struct Trainer {
    rate: f64,
    momentum: f64,
    log_interval: Option<usize>,
    halt_condition: HaltCondition,
    update_rule: UpdateRule,
    threads: usize,
}

#[derive(Debug)]
#[derive(Clone)]
pub struct NN {
    layers: Vec<Layer>,
    num_inputs: usize,
}

impl NN {
    fn train(&self) -> Trainer {
        unimplemented!()
    }

    // returns a results with ok being the error rate of the network found at the end and
    // Err is a string with an explaination
    fn train_option(&mut self, examples: &[(&[f64], &[f64])], rate: f64, momentum: f64, log_interval: Option<usize>,
                    halt_condition: HaltCondition, update_rule: UpdateRule, threads: usize) -> Result<usize, &str> {

        let mut epochs = 0;
        let mut error_rate = 0.0;

        loop {

            let mut prev_deltas = make_weights_tracker(&self.layers, 0.0f64);
            let mut batch_data = make_weights_tracker(&self.layers, 0.0f64);
            let mut error_sum: f64 = 0.0;

            for &(inputs, targets) in examples.iter() {
                let results = do_run(self, inputs);
                let weight_updates = calculate_weight_update_info(self, &results, &targets);
                error_sum += calculate_error(&results, targets);
                match update_rule {
                    Batch => update_batch_data(&mut batch_data, &weight_updates),
                    Stochastic => update_weights(self, &weight_updates, &mut prev_deltas, rate, momentum),
                }
            }

            // if we're in batch mode, update the weights now
            match update_rule {
                Batch => update_weights(self, &batch_data, &mut prev_deltas, rate, momentum),
                Stochastic => (),
            }

            epochs += 1;

            // log error rate if neccessary
            match log_interval {
                Some(interval) if epochs % interval == 0 => {
                    println!("error rate: {}", error_rate);
                },
                _ => (),
            }

            // check if we've met the halt condition yet
            match halt_condition {
                Epochs(epochs_halt) => {
                    if epochs == epochs_halt { break; }
                },
                MSE(target_error) => {
                    if target_error == error_rate { break; }
                }
            }
        }

        unimplemented!();
    }

    fn run(&self, inputs: &[f64]) -> &[f64]{
        unimplemented!()
    }
}

fn do_run(nn: &NN, inputs: &[f64]) -> Vec<Vec<f64>>{
    unimplemented!()
}

fn update_batch_data(batch_data: &mut Vec<Vec<Vec<f64>>> , weight_updates: &Vec<Vec<Vec<f64>>>) {
    unimplemented!()
}

fn update_weights(nn: &mut NN, network_weight_updates: &Vec<Vec<Vec<f64>>>, prev_deltas: &mut Vec<Vec<Vec<f64>>>, rate: f64, momentum: f64) {
    for layer_index in 0..nn.layers.len() {
        let mut layer = &mut nn.layers[layer_index];
        let layer_weight_updates = &network_weight_updates[layer_index];
        for node_index in 0..layer.len() {
            let mut node = &mut layer[node_index];
            let node_weight_updates = &layer_weight_updates[node_index];
            for weight_index in 0..node.len() {
                let weight = node[weight_index];
                let weight_update = node_weight_updates[weight_index];
                let prev_delta = prev_deltas[layer_index][node_index][weight_index];
                let delta = (rate * weight_update) + (momentum * prev_delta);
                node[weight_index] += delta;
                prev_deltas[layer_index][node_index][weight_index] = delta;
            }
        }
    }
}

fn calculate_weight_update_info(nn: &NN, results: &Vec<Vec<f64>>, targets: &[f64]) -> Vec<Vec<Vec<f64>>> {
    let mut network_errors = Vec::new();
    let mut network_weight_updates = Vec::new();

    let mut next_layer_errors: Vec<f64> = Vec::new(); // TODO: find a way to not do this

    let layers = &nn.layers;
    let network_results = &results[1..]; // skip the input layer

    for (layer_index, (layer_nodes, layer_results)) in iterZipEnum(layers, network_results) {
        let prev_layer_results = &results[layer_index];
        let mut layer_errors = Vec::new();
        let mut layer_weight_updates = Vec::new();

        let next_layer_nodes: &Layer = &&layers[layer_index+1];

        for (node_index, (node, &result)) in iterZipEnum(layer_nodes, layer_results) {
            let mut node_weight_updates = Vec::new();
            let mut node_error = 0f64;

            // calculate error for this node
            if layer_index == layers.len() - 1 {
                node_error = result * (1f64 - result) * (targets[node_index] - result);
            } else {
                let mut sum = 0f64;
                for (next_node, &next_node_error_data) in next_layer_nodes.iter().zip(next_layer_errors.iter()) {
                    sum += next_node[node_index+1] * next_node_error_data; // +1 because the 0th weight is the threshold
                }
                node_error = result * (1f64 - result) * sum;
            }

            // calculate weight updates for this node
            for weight_index in 0..node.len() {
                let mut prev_layer_result = 1f64;
                if weight_index == 0 {
                    prev_layer_result = 1.0; // theshold
                } else {
                    prev_layer_result = prev_layer_results[weight_index-1];
                }
                let weight_update = node_error * prev_layer_result;
                node_weight_updates.push(weight_update);
            }

            layer_errors.push(node_error);
            layer_weight_updates.push(node_weight_updates);
        }

        next_layer_errors = layer_errors.clone();

        network_errors.push(layer_errors);
        network_weight_updates.push(layer_weight_updates);
    }

    // updates were build by backpropagation so reverse them
    network_weight_updates.reverse();

    network_weight_updates
}

fn iterZipEnum<'s, 't, S: 's, T: 't>(s: &'s [S], t: &'t [T]) ->
    Enumerate<Zip<slice::Iter<'s, S>, slice::Iter<'t, T>>>  {
    s.iter().zip(t.iter()).enumerate()
}

fn calculate_error(results: &Vec<Vec<f64>>, targets: &[f64]) -> f64 {
    unimplemented!()
}

fn make_weights_tracker<T: Clone>(layers: &Vec<Layer>, place_holder: T) -> Vec<Vec<Vec<T>>> {
    let mut network_level = Vec::new();
    for layer in layers.iter() {
        let mut layer_level = Vec::new();
        for node in layer.iter() {
            let mut node_level = Vec::new();
            for weight in node.iter() {
                node_level.push(place_holder.clone());
            }
            layer_level.push(node_level);
        }
        network_level.push(layer_level);
    }

    network_level
}

fn new_nn(layers_sizes: &[usize]) -> NN {
        if layers_sizes.len() < 2 {
            panic!("must have at least two layers");
        }
        let mut layers = Vec::new();
        let mut it = layers_sizes.iter();
        // get the first layer size
        let first_layer_size = *it.next().unwrap();

        // setup the rest of the layers
        let mut prev_layer_size = first_layer_size;
        for &layer_size in it {
            let mut layer: Layer = Vec::new();
            for _ in 0..layer_size {
                let mut node: Node = vec![rand::random(); prev_layer_size];
                node.shrink_to_fit();
                layer.push(node)
            }
            layer.shrink_to_fit();
            layers.push(layer);
            prev_layer_size = layer_size;
        }
        layers.shrink_to_fit();
        NN { layers: layers, num_inputs: first_layer_size }
    }<commit_msg>running network written<commit_after>extern crate rand;
use HaltCondition::{ Epochs, MSE };
use UpdateRule::{ Stochastic, Batch };
use std::iter::{Zip, Enumerate};
use std::slice;
use std::num::Float;

#[test]
fn it_works() {
}

type Node = Vec<f64>;
type Layer = Vec<Node>;

#[derive(Debug)]
pub enum HaltCondition {
    Epochs(usize),
    MSE(f64),
}

#[derive(Debug)]
pub enum UpdateRule {
    Stochastic,
    Batch
}

#[derive(Debug)]
struct Trainer {
    rate: f64,
    momentum: f64,
    log_interval: Option<usize>,
    halt_condition: HaltCondition,
    update_rule: UpdateRule,
    threads: usize,
}

#[derive(Debug)]
#[derive(Clone)]
pub struct NN {
    layers: Vec<Layer>,
    num_inputs: usize,
}

impl NN {
    fn train(&self) -> Trainer {
        unimplemented!()
    }

    // returns a results with ok being the error rate of the network found at the end and
    // Err is a string with an explaination
    fn train_option(&mut self, examples: &[(&Vec<f64>, &Vec<f64>)], rate: f64, momentum: f64, log_interval: Option<usize>,
                    halt_condition: HaltCondition, update_rule: UpdateRule, threads: usize) -> Result<usize, &str> {

        let mut epochs = 0;
        let mut error_rate = 0.0;

        loop {

            let mut prev_deltas = make_weights_tracker(&self.layers, 0.0f64);
            let mut batch_data = make_weights_tracker(&self.layers, 0.0f64);
            let mut error_sum: f64 = 0.0;

            for &(inputs, targets) in examples.iter() {
                let results = do_run(self, inputs);
                let weight_updates = calculate_weight_update_info(self, &results, &targets);
                error_sum += calculate_error(&results, targets);
                match update_rule {
                    Batch => update_batch_data(&mut batch_data, &weight_updates),
                    Stochastic => update_weights(self, &weight_updates, &mut prev_deltas, rate, momentum),
                }
            }

            // if we're in batch mode, update the weights now
            match update_rule {
                Batch => update_weights(self, &batch_data, &mut prev_deltas, rate, momentum),
                Stochastic => (),
            }

            epochs += 1;

            // log error rate if neccessary
            match log_interval {
                Some(interval) if epochs % interval == 0 => {
                    println!("error rate: {}", error_rate);
                },
                _ => (),
            }

            // check if we've met the halt condition yet
            match halt_condition {
                Epochs(epochs_halt) => {
                    if epochs == epochs_halt { break; }
                },
                MSE(target_error) => {
                    if target_error == error_rate { break; }
                }
            }
        }

        unimplemented!();
    }

    fn run(&self, inputs: &Vec<f64>) -> Vec<f64>{
        unimplemented!()
    }
}

fn do_run(nn: &NN, inputs: &Vec<f64>) -> Vec<Vec<f64>>{
    let mut results = Vec::new();
    results.push(inputs.clone());
    let mut prev_layer_results = inputs;
    for layer in nn.layers.iter() {
        let mut layer_results = Vec::new();
        for node in layer.iter() {
            layer_results.push( sigmoid(modified_dotprod(&node, &prev_layer_results)) )
        }
        results.push(layer_results);
    }
    results
}

fn modified_dotprod(node: &Node, values: &Vec<f64>) -> f64 {
    let mut total = node[0]; // for the threshold weight
    for (weight, value) in node.iter().skip(1).zip(values.iter()) {
        total += weight * value;
    }
    total
}

fn sigmoid(y: f64) -> f64 {
    1.0 / (1.0 + Float::exp(-y))
}

fn update_batch_data(batch_data: &mut Vec<Vec<Vec<f64>>> , weight_updates: &Vec<Vec<Vec<f64>>>) {
    unimplemented!()
}

fn update_weights(nn: &mut NN, network_weight_updates: &Vec<Vec<Vec<f64>>>, prev_deltas: &mut Vec<Vec<Vec<f64>>>, rate: f64, momentum: f64) {
    for layer_index in 0..nn.layers.len() {
        let mut layer = &mut nn.layers[layer_index];
        let layer_weight_updates = &network_weight_updates[layer_index];
        for node_index in 0..layer.len() {
            let mut node = &mut layer[node_index];
            let node_weight_updates = &layer_weight_updates[node_index];
            for weight_index in 0..node.len() {
                let weight = node[weight_index];
                let weight_update = node_weight_updates[weight_index];
                let prev_delta = prev_deltas[layer_index][node_index][weight_index];
                let delta = (rate * weight_update) + (momentum * prev_delta);
                node[weight_index] += delta;
                prev_deltas[layer_index][node_index][weight_index] = delta;
            }
        }
    }
}

fn calculate_weight_update_info(nn: &NN, results: &Vec<Vec<f64>>, targets: &[f64]) -> Vec<Vec<Vec<f64>>> {
    let mut network_errors = Vec::new();
    let mut network_weight_updates = Vec::new();

    let mut next_layer_errors: Vec<f64> = Vec::new(); // TODO: find a way to not do this

    let layers = &nn.layers;
    let network_results = &results[1..]; // skip the input layer

    for (layer_index, (layer_nodes, layer_results)) in iterZipEnum(layers, network_results) {
        let prev_layer_results = &results[layer_index];
        let mut layer_errors = Vec::new();
        let mut layer_weight_updates = Vec::new();

        let next_layer_nodes: &Layer = &&layers[layer_index+1];

        for (node_index, (node, &result)) in iterZipEnum(layer_nodes, layer_results) {
            let mut node_weight_updates = Vec::new();
            let mut node_error = 0f64;

            // calculate error for this node
            if layer_index == layers.len() - 1 {
                node_error = result * (1f64 - result) * (targets[node_index] - result);
            } else {
                let mut sum = 0f64;
                for (next_node, &next_node_error_data) in next_layer_nodes.iter().zip(next_layer_errors.iter()) {
                    sum += next_node[node_index+1] * next_node_error_data; // +1 because the 0th weight is the threshold
                }
                node_error = result * (1f64 - result) * sum;
            }

            // calculate weight updates for this node
            for weight_index in 0..node.len() {
                let mut prev_layer_result = 1f64;
                if weight_index == 0 {
                    prev_layer_result = 1.0; // theshold
                } else {
                    prev_layer_result = prev_layer_results[weight_index-1];
                }
                let weight_update = node_error * prev_layer_result;
                node_weight_updates.push(weight_update);
            }

            layer_errors.push(node_error);
            layer_weight_updates.push(node_weight_updates);
        }

        next_layer_errors = layer_errors.clone();

        network_errors.push(layer_errors);
        network_weight_updates.push(layer_weight_updates);
    }

    // updates were build by backpropagation so reverse them
    network_weight_updates.reverse();

    network_weight_updates
}

fn iterZipEnum<'s, 't, S: 's, T: 't>(s: &'s [S], t: &'t [T]) ->
    Enumerate<Zip<slice::Iter<'s, S>, slice::Iter<'t, T>>>  {
    s.iter().zip(t.iter()).enumerate()
}

fn calculate_error(results: &Vec<Vec<f64>>, targets: &[f64]) -> f64 {
    unimplemented!()
}

fn make_weights_tracker<T: Clone>(layers: &Vec<Layer>, place_holder: T) -> Vec<Vec<Vec<T>>> {
    let mut network_level = Vec::new();
    for layer in layers.iter() {
        let mut layer_level = Vec::new();
        for node in layer.iter() {
            let mut node_level = Vec::new();
            for weight in node.iter() {
                node_level.push(place_holder.clone());
            }
            layer_level.push(node_level);
        }
        network_level.push(layer_level);
    }

    network_level
}

fn new_nn(layers_sizes: &[usize]) -> NN {
        if layers_sizes.len() < 2 {
            panic!("must have at least two layers");
        }
        let mut layers = Vec::new();
        let mut it = layers_sizes.iter();
        // get the first layer size
        let first_layer_size = *it.next().unwrap();

        // setup the rest of the layers
        let mut prev_layer_size = first_layer_size;
        for &layer_size in it {
            let mut layer: Layer = Vec::new();
            for _ in 0..layer_size {
                let mut node: Node = vec![rand::random(); prev_layer_size];
                node.shrink_to_fit();
                layer.push(node)
            }
            layer.shrink_to_fit();
            layers.push(layer);
            prev_layer_size = layer_size;
        }
        layers.shrink_to_fit();
        NN { layers: layers, num_inputs: first_layer_size }
    }<|endoftext|>


<commit_before>//! [![github]](https://github.com/dtolnay/thiserror) [![crates-io]](https://crates.io/crates/thiserror) [![docs-rs]](https://docs.rs/thiserror)
//!
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
//!
//!

//!
//! This library provides a convenient derive macro for the standard library's
//! [`std::error::Error`] trait.
//!
//! [`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html
//!
//!

//!
//! # Example
//!
//! ```rust
//! # use std::io;
//! use thiserror::Error;
//!
//! #[derive(Error, Debug)]
//! pub enum DataStoreError {
//!     #[error("data store disconnected")]
//!     Disconnect(#[from] io::Error),
//!     #[error("the data for key `{0}` is not available")]
//!     Redaction(String),
//!     #[error("invalid header (expected {expected:?}, found {found:?})")]
//!     InvalidHeader {
//!         expected: String,
//!         found: String,
//!     },
//!     #[error("unknown data store error")]
//!     Unknown,
//! }
//! ```
//!
//!

//!
//! # Details
//!
//! - Thiserror deliberately does not appear in your public API. You get the
//!   same thing as if you had written an implementation of `std::error::Error`
//!   by hand, and switching from handwritten impls to thiserror or vice versa
//!   is not a breaking change.
//!
//! - Errors may be enums, structs with named fields, tuple structs, or unit
//!   structs.
//!
//! - A `Display` impl is generated for your error if you provide
//!   `#[error("...")]` messages on the struct or each variant of your enum, as
//!   shown above in the example.
//!
//!   The messages support a shorthand for interpolating fields from the error.
//!
//!     - `#[error("{var}")]` ⟶ `write!("{}", self.var)`
//!     - `#[error("{0}")]` ⟶ `write!("{}", self.0)`
//!     - `#[error("{var:?}")]` ⟶ `write!("{:?}", self.var)`
//!     - `#[error("{0:?}")]` ⟶ `write!("{:?}", self.0)`
//!
//!   These shorthands can be used together with any additional format args,
//!   which may be arbitrary expressions. For example:
//!
//!   ```rust
//!   # use std::i32;
//!   # use thiserror::Error;
//!   #
//!   #[derive(Error, Debug)]
//!   pub enum Error {
//!       #[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::MAX)]
//!       InvalidLookahead(u32),
//!   }
//!   ```
//!
//!   If one of the additional expression arguments needs to refer to a field of
//!   the struct or enum, then refer to named fields as `.var` and tuple fields
//!   as `.0`.
//!
//!   ```rust
//!   # use thiserror::Error;
//!   #
//!   # fn first_char(s: &String) -> char {
//!   #     s.chars().next().unwrap()
//!   # }
//!   #
//!   # #[derive(Debug)]
//!   # struct Limits {
//!   #     lo: usize,
//!   #     hi: usize,
//!   # }
//!   #
//!   #[derive(Error, Debug)]
//!   pub enum Error {
//!       #[error("first letter must be lowercase but was {:?}", first_char(.0))]
//!       WrongCase(String),
//!       #[error("invalid index {idx}, expected at least {} and at most {}", .limits.lo, .limits.hi)]
//!       OutOfBounds { idx: usize, limits: Limits },
//!   }
//!   ```
//!
//! - A `From` impl is generated for each variant containing a `#[from]`
//!   attribute.
//!
//!   Note that the variant must not contain any other fields beyond the source
//!   error and possibly a backtrace. A backtrace is captured from within the
//!   `From` impl if there is a field for it.
//!
//!   ```rust
//!   # const IGNORE: &str = stringify! {
//!   #[derive(Error, Debug)]
//!   pub enum MyError {
//!       Io {
//!           #[from]
//!           source: io::Error,
//!           backtrace: Backtrace,
//!       },
//!   }
//!   # };
//!   ```
//!
//! - The Error trait's `source()` method is implemented to return whichever
//!   field has a `#[source]` attribute or is named `source`, if any. This is
//!   for identifying the underlying lower level error that caused your error.
//!
//!   The `#[from]` attribute always implies that the same field is `#[source]`,
//!   so you don't ever need to specify both attributes.
//!
//!   Any error type that implements `std::error::Error` or dereferences to `dyn
//!   std::error::Error` will work as a source.
//!
//!   ```rust
//!   # use std::fmt::{self, Display};
//!   # use thiserror::Error;
//!   #
//!   #[derive(Error, Debug)]
//!   pub struct MyError {
//!       msg: String,
//!       #[source]  // optional if field name is `source`
//!       source: anyhow::Error,
//!   }
//!   #
//!   # impl Display for MyError {
//!   #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   ```
//!
//! - The Error trait's `backtrace()` method is implemented to return whichever
//!   field has a type named `Backtrace`, if any.
//!
//!   ```rust
//!   # const IGNORE: &str = stringify! {
//!   use std::backtrace::Backtrace;
//!
//!   #[derive(Error, Debug)]
//!   pub struct MyError {
//!       msg: String,
//!       backtrace: Backtrace,  // automatically detected
//!   }
//!   # };
//!   ```
//!
//! - If a field is both a source (named `source`, or has `#[source]` or
//!   `#[from]` attribute) *and* is marked `#[backtrace]`, then the Error
//!   trait's `backtrace()` method is forwarded to the source's backtrace.
//!
//!   ```rust
//!   # const IGNORE: &str = stringify! {
//!   #[derive(Error, Debug)]
//!   pub enum MyError {
//!       Io {
//!           #[backtrace]
//!           source: io::Error,
//!       },
//!   }
//!   # };
//!   ```
//!
//! - Errors may use `error(transparent)` to forward the source and Display
//!   methods straight through to an underlying error without adding an
//!   additional message. This would be appropriate for enums that need an
//!   "anything else" variant.
//!
//!   ```
//!   # use thiserror::Error;
//!   #
//!   #[derive(Error, Debug)]
//!   pub enum MyError {
//!       # /*
//!       ...
//!       # */
//!
//!       #[error(transparent)]
//!       Other(#[from] anyhow::Error),  // source and Display delegate to anyhow::Error
//!   }
//!   ```
//!
//! - See also the [`anyhow`] library for a convenient single error type to use
//!   in application code.
//!
//!   [`anyhow`]: https://github.com/dtolnay/anyhow

#![allow(
    // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7421
    clippy::doc_markdown,
    clippy::module_name_repetitions,
)]

mod aserror;
mod display;

pub use thiserror_impl::*;

// Not public API.
#[doc(hidden)]
pub mod private {
    pub use crate::aserror::AsDynError;
    pub use crate::display::{DisplayAsDisplay, PathAsDisplay};
}
<commit_msg>Ignore return_self_not_must_use clippy lint<commit_after>//! [![github]](https://github.com/dtolnay/thiserror) [![crates-io]](https://crates.io/crates/thiserror) [![docs-rs]](https://docs.rs/thiserror)
//!
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
//!
//!

//!
//! This library provides a convenient derive macro for the standard library's
//! [`std::error::Error`] trait.
//!
//! [`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html
//!
//!

//!
//! # Example
//!
//! ```rust
//! # use std::io;
//! use thiserror::Error;
//!
//! #[derive(Error, Debug)]
//! pub enum DataStoreError {
//!     #[error("data store disconnected")]
//!     Disconnect(#[from] io::Error),
//!     #[error("the data for key `{0}` is not available")]
//!     Redaction(String),
//!     #[error("invalid header (expected {expected:?}, found {found:?})")]
//!     InvalidHeader {
//!         expected: String,
//!         found: String,
//!     },
//!     #[error("unknown data store error")]
//!     Unknown,
//! }
//! ```
//!
//!

//!
//! # Details
//!
//! - Thiserror deliberately does not appear in your public API. You get the
//!   same thing as if you had written an implementation of `std::error::Error`
//!   by hand, and switching from handwritten impls to thiserror or vice versa
//!   is not a breaking change.
//!
//! - Errors may be enums, structs with named fields, tuple structs, or unit
//!   structs.
//!
//! - A `Display` impl is generated for your error if you provide
//!   `#[error("...")]` messages on the struct or each variant of your enum, as
//!   shown above in the example.
//!
//!   The messages support a shorthand for interpolating fields from the error.
//!
//!     - `#[error("{var}")]` ⟶ `write!("{}", self.var)`
//!     - `#[error("{0}")]` ⟶ `write!("{}", self.0)`
//!     - `#[error("{var:?}")]` ⟶ `write!("{:?}", self.var)`
//!     - `#[error("{0:?}")]` ⟶ `write!("{:?}", self.0)`
//!
//!   These shorthands can be used together with any additional format args,
//!   which may be arbitrary expressions. For example:
//!
//!   ```rust
//!   # use std::i32;
//!   # use thiserror::Error;
//!   #
//!   #[derive(Error, Debug)]
//!   pub enum Error {
//!       #[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::MAX)]
//!       InvalidLookahead(u32),
//!   }
//!   ```
//!
//!   If one of the additional expression arguments needs to refer to a field of
//!   the struct or enum, then refer to named fields as `.var` and tuple fields
//!   as `.0`.
//!
//!   ```rust
//!   # use thiserror::Error;
//!   #
//!   # fn first_char(s: &String) -> char {
//!   #     s.chars().next().unwrap()
//!   # }
//!   #
//!   # #[derive(Debug)]
//!   # struct Limits {
//!   #     lo: usize,
//!   #     hi: usize,
//!   # }
//!   #
//!   #[derive(Error, Debug)]
//!   pub enum Error {
//!       #[error("first letter must be lowercase but was {:?}", first_char(.0))]
//!       WrongCase(String),
//!       #[error("invalid index {idx}, expected at least {} and at most {}", .limits.lo, .limits.hi)]
//!       OutOfBounds { idx: usize, limits: Limits },
//!   }
//!   ```
//!
//! - A `From` impl is generated for each variant containing a `#[from]`
//!   attribute.
//!
//!   Note that the variant must not contain any other fields beyond the source
//!   error and possibly a backtrace. A backtrace is captured from within the
//!   `From` impl if there is a field for it.
//!
//!   ```rust
//!   # const IGNORE: &str = stringify! {
//!   #[derive(Error, Debug)]
//!   pub enum MyError {
//!       Io {
//!           #[from]
//!           source: io::Error,
//!           backtrace: Backtrace,
//!       },
//!   }
//!   # };
//!   ```
//!
//! - The Error trait's `source()` method is implemented to return whichever
//!   field has a `#[source]` attribute or is named `source`, if any. This is
//!   for identifying the underlying lower level error that caused your error.
//!
//!   The `#[from]` attribute always implies that the same field is `#[source]`,
//!   so you don't ever need to specify both attributes.
//!
//!   Any error type that implements `std::error::Error` or dereferences to `dyn
//!   std::error::Error` will work as a source.
//!
//!   ```rust
//!   # use std::fmt::{self, Display};
//!   # use thiserror::Error;
//!   #
//!   #[derive(Error, Debug)]
//!   pub struct MyError {
//!       msg: String,
//!       #[source]  // optional if field name is `source`
//!       source: anyhow::Error,
//!   }
//!   #
//!   # impl Display for MyError {
//!   #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   ```
//!
//! - The Error trait's `backtrace()` method is implemented to return whichever
//!   field has a type named `Backtrace`, if any.
//!
//!   ```rust
//!   # const IGNORE: &str = stringify! {
//!   use std::backtrace::Backtrace;
//!
//!   #[derive(Error, Debug)]
//!   pub struct MyError {
//!       msg: String,
//!       backtrace: Backtrace,  // automatically detected
//!   }
//!   # };
//!   ```
//!
//! - If a field is both a source (named `source`, or has `#[source]` or
//!   `#[from]` attribute) *and* is marked `#[backtrace]`, then the Error
//!   trait's `backtrace()` method is forwarded to the source's backtrace.
//!
//!   ```rust
//!   # const IGNORE: &str = stringify! {
//!   #[derive(Error, Debug)]
//!   pub enum MyError {
//!       Io {
//!           #[backtrace]
//!           source: io::Error,
//!       },
//!   }
//!   # };
//!   ```
//!
//! - Errors may use `error(transparent)` to forward the source and Display
//!   methods straight through to an underlying error without adding an
//!   additional message. This would be appropriate for enums that need an
//!   "anything else" variant.
//!
//!   ```
//!   # use thiserror::Error;
//!   #
//!   #[derive(Error, Debug)]
//!   pub enum MyError {
//!       # /*
//!       ...
//!       # */
//!
//!       #[error(transparent)]
//!       Other(#[from] anyhow::Error),  // source and Display delegate to anyhow::Error
//!   }
//!   ```
//!
//! - See also the [`anyhow`] library for a convenient single error type to use
//!   in application code.
//!
//!   [`anyhow`]: https://github.com/dtolnay/anyhow

#![allow(
    // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7421
    clippy::doc_markdown,
    clippy::module_name_repetitions,
    clippy::return_self_not_must_use,
)]

mod aserror;
mod display;

pub use thiserror_impl::*;

// Not public API.
#[doc(hidden)]
pub mod private {
    pub use crate::aserror::AsDynError;
    pub use crate::display::{DisplayAsDisplay, PathAsDisplay};
}
<|endoftext|>


<commit_before>//! ## Defining procedural macros
//!
//! Two crates are required to define a macro.
//!
//! ### The declaration crate
//!
//! This crate is allowed to contain other public things if you need, for example
//! traits or functions or ordinary macros.
//!
//! https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack
//!
//! ```rust
//! #[macro_use]
//! extern crate proc_macro_hack;
//!
//! #[allow(unused_imports)]
//! #[macro_use]
//! extern crate demo_hack_impl;
//! pub use demo_hack_impl::*;
//!
//! /// Add one to an expression.
//! proc_macro_expr_decl!(add_one! => add_one_impl);
//!
//! /// A function that always returns 2.
//! proc_macro_item_decl!(two_fn! => two_fn_impl);
//! ```
//!
//! ### The implementation crate
//!
//! This crate must contain nothing but procedural macros. Private helper functions
//! and private modules are fine but nothing can be public.
//!
//! https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack-impl
//!
//! ```rust
//! #[macro_use]
//! extern crate proc_macro_hack;
//!
//! proc_macro_expr_impl! {
//!     /// Add one to an expression.
//!     pub fn add_one_impl(input: &str) -> String {
//!         format!("1 + {}", input)
//!     }
//! }
//!
//! proc_macro_item_impl! {
//!     /// A function that always returns 2.
//!     pub fn two_fn_impl(input: &str) -> String {
//!         format!("fn {}() -> u8 {{ 2 }}", input)
//!     }
//! }
//! ```
//!
//! Both crates depend on `proc-macro-hack`:
//!
//! ```toml
//! [dependencies]
//! proc-macro-hack = "0.3"
//! ```
//!
//! Additionally, your implementation crate (but not your declaration crate) is a
//! proc macro:
//!
//! ```toml
//! [lib]
//! proc-macro = true
//! ```
//!
//! ## Using procedural macros
//!
//! Users of your crate depend on your declaration crate (not your implementation
//! crate), then use your procedural macros as though it were magic. They even get
//! reasonable error messages if your procedural macro panics.
//!
//! https://github.com/dtolnay/proc-macro-hack/tree/master/example
//!
//! ```rust
//! #[macro_use]
//! extern crate demo_hack;
//!
//! two_fn!(two);
//!
//! fn main() {
//!     let x = two();
//!     let nine = add_one!(x) + add_one!(2 + 3);
//!     println!("nine = {}", nine);
//! }
//! ```
//!
//! ---
//!
//! # Expansion of expression macros
//!
//! ```rust,ignore
//! m!(ARGS)
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! {
//!     #[derive(m_impl)]
//!     #[allow(unused)]
//!     enum ProcMacroHack {
//!         Input = (stringify!(ARGS), 0).1,
//!     }
//!     proc_macro_call!()
//! }
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! {
//!     macro_rules! proc_macro_call {
//!         () => { RESULT }
//!     }
//!     proc_macro_call!()
//! }
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! {
//!     RESULT
//! }
//! ```
//!
//! # Expansion of item macros
//!
//! ```rust,ignore
//! m!(ARGS);
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! #[derive(m_impl)]
//! #[allow(unused)]
//! enum ProcMacroHack {
//!     Input = (stringify!(ARGS), 0).1,
//! }
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! RESULT
//! ```

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

// Allow the "unused" #[macro_use] because there is a different un-ignorable
// warning otherwise:
//
//    proc macro crates and `#[no_link]` crates have no effect without `#[macro_use]`
#[allow(unused_imports)]
#[macro_use]
extern crate proc_macro_hack_impl;
pub use proc_macro_hack_impl::*;

#[cfg(feature = "proc_macro")]
#[doc(hidden)]
pub use proc_macro::TokenStream;

#[cfg(feature = "proc_macro")]
#[doc(hidden)]
#[macro_export]
macro_rules! proc_macro_tokenstream {
    () => {
        $crate::TokenStream
    }
}

#[cfg(not(feature = "proc_macro"))]
#[doc(hidden)]
#[macro_export]
macro_rules! proc_macro_tokenstream {
    () => {
        ::proc_macro::TokenStream
    }
}

#[macro_export]
macro_rules! proc_macro_expr_decl {
    ($name:ident ! => $name_impl:ident) => {
        #[derive(ProcMacroHackExpr)]
        #[allow(unused, non_camel_case_types)]
        enum $name {
            $name_impl
        }
    }
}

#[macro_export]
macro_rules! proc_macro_item_decl {
    ($name:ident ! => $name_impl:ident) => {
        #[derive(ProcMacroHackItem)]
        #[allow(unused, non_camel_case_types)]
        enum $name {
            $name_impl
        }
    }
}

#[macro_export]
macro_rules! proc_macro_expr_impl {
    ($(
        $( #[$attr:meta] )*
        pub fn $func:ident($input:ident: &str) -> String $body:block
    )+) => {
        $(
            $( #[$attr] )*
            #[proc_macro_derive($func)]
            pub fn $func(input: proc_macro_tokenstream!()) -> proc_macro_tokenstream!() {
                let source = input.to_string();
                let source = source.trim();

                let prefix = "#[allow(unused)]\nenum ProcMacroHack {";
                let suffix = "}";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "Input =";
                let suffix = "0).1,";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "(stringify!(";
                let suffix = "),";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let tokens = &source[prefix.len() .. source.len() - suffix.len()].trim();

                fn func($input: &str) -> String $body

                format!("
                    macro_rules! proc_macro_call {{
                        () => {{
                            {}
                        }}
                    }}
                ", func(tokens)).parse().unwrap()
            }
        )+
    }
}

#[macro_export]
macro_rules! proc_macro_item_impl {
    ($(
        $( #[$attr:meta] )*
        pub fn $func:ident($input:ident: &str) -> String $body:block
    )+) => {
        $(
            $( #[$attr] )*
            #[proc_macro_derive($func)]
            pub fn $func(input: proc_macro_tokenstream!()) -> proc_macro_tokenstream!() {
                let source = input.to_string();
                let source = source.trim();

                let prefix = "#[allow(unused)]\nenum ProcMacroHack {";
                let suffix = "}";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "Input =";
                let suffix = "0).1,";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "(stringify!(";
                let suffix = "),";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let tokens = &source[prefix.len() .. source.len() - suffix.len()].trim();

                fn func($input: &str) -> String $body

                func(tokens).parse().unwrap()
            }
        )+
    }
}
<commit_msg>Ignore the new "tests"<commit_after>//! ## Defining procedural macros
//!
//! Two crates are required to define a macro.
//!
//! ### The declaration crate
//!
//! This crate is allowed to contain other public things if you need, for example
//! traits or functions or ordinary macros.
//!
//! https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack
//!
//! ```rust,ignore
//! #[macro_use]
//! extern crate proc_macro_hack;
//!
//! #[allow(unused_imports)]
//! #[macro_use]
//! extern crate demo_hack_impl;
//! pub use demo_hack_impl::*;
//!
//! /// Add one to an expression.
//! proc_macro_expr_decl!(add_one! => add_one_impl);
//!
//! /// A function that always returns 2.
//! proc_macro_item_decl!(two_fn! => two_fn_impl);
//! ```
//!
//! ### The implementation crate
//!
//! This crate must contain nothing but procedural macros. Private helper functions
//! and private modules are fine but nothing can be public.
//!
//! https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack-impl
//!
//! ```rust,ignore
//! #[macro_use]
//! extern crate proc_macro_hack;
//!
//! proc_macro_expr_impl! {
//!     /// Add one to an expression.
//!     pub fn add_one_impl(input: &str) -> String {
//!         format!("1 + {}", input)
//!     }
//! }
//!
//! proc_macro_item_impl! {
//!     /// A function that always returns 2.
//!     pub fn two_fn_impl(input: &str) -> String {
//!         format!("fn {}() -> u8 {{ 2 }}", input)
//!     }
//! }
//! ```
//!
//! Both crates depend on `proc-macro-hack`:
//!
//! ```toml
//! [dependencies]
//! proc-macro-hack = "0.3"
//! ```
//!
//! Additionally, your implementation crate (but not your declaration crate) is a
//! proc macro:
//!
//! ```toml
//! [lib]
//! proc-macro = true
//! ```
//!
//! ## Using procedural macros
//!
//! Users of your crate depend on your declaration crate (not your implementation
//! crate), then use your procedural macros as though it were magic. They even get
//! reasonable error messages if your procedural macro panics.
//!
//! https://github.com/dtolnay/proc-macro-hack/tree/master/example
//!
//! ```rust,ignore
//! #[macro_use]
//! extern crate demo_hack;
//!
//! two_fn!(two);
//!
//! fn main() {
//!     let x = two();
//!     let nine = add_one!(x) + add_one!(2 + 3);
//!     println!("nine = {}", nine);
//! }
//! ```
//!
//! ---
//!
//! # Expansion of expression macros
//!
//! ```rust,ignore
//! m!(ARGS)
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! {
//!     #[derive(m_impl)]
//!     #[allow(unused)]
//!     enum ProcMacroHack {
//!         Input = (stringify!(ARGS), 0).1,
//!     }
//!     proc_macro_call!()
//! }
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! {
//!     macro_rules! proc_macro_call {
//!         () => { RESULT }
//!     }
//!     proc_macro_call!()
//! }
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! {
//!     RESULT
//! }
//! ```
//!
//! # Expansion of item macros
//!
//! ```rust,ignore
//! m!(ARGS);
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! #[derive(m_impl)]
//! #[allow(unused)]
//! enum ProcMacroHack {
//!     Input = (stringify!(ARGS), 0).1,
//! }
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! RESULT
//! ```

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

// Allow the "unused" #[macro_use] because there is a different un-ignorable
// warning otherwise:
//
//    proc macro crates and `#[no_link]` crates have no effect without `#[macro_use]`
#[allow(unused_imports)]
#[macro_use]
extern crate proc_macro_hack_impl;
pub use proc_macro_hack_impl::*;

#[cfg(feature = "proc_macro")]
#[doc(hidden)]
pub use proc_macro::TokenStream;

#[cfg(feature = "proc_macro")]
#[doc(hidden)]
#[macro_export]
macro_rules! proc_macro_tokenstream {
    () => {
        $crate::TokenStream
    }
}

#[cfg(not(feature = "proc_macro"))]
#[doc(hidden)]
#[macro_export]
macro_rules! proc_macro_tokenstream {
    () => {
        ::proc_macro::TokenStream
    }
}

#[macro_export]
macro_rules! proc_macro_expr_decl {
    ($name:ident ! => $name_impl:ident) => {
        #[derive(ProcMacroHackExpr)]
        #[allow(unused, non_camel_case_types)]
        enum $name {
            $name_impl
        }
    }
}

#[macro_export]
macro_rules! proc_macro_item_decl {
    ($name:ident ! => $name_impl:ident) => {
        #[derive(ProcMacroHackItem)]
        #[allow(unused, non_camel_case_types)]
        enum $name {
            $name_impl
        }
    }
}

#[macro_export]
macro_rules! proc_macro_expr_impl {
    ($(
        $( #[$attr:meta] )*
        pub fn $func:ident($input:ident: &str) -> String $body:block
    )+) => {
        $(
            $( #[$attr] )*
            #[proc_macro_derive($func)]
            pub fn $func(input: proc_macro_tokenstream!()) -> proc_macro_tokenstream!() {
                let source = input.to_string();
                let source = source.trim();

                let prefix = "#[allow(unused)]\nenum ProcMacroHack {";
                let suffix = "}";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "Input =";
                let suffix = "0).1,";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "(stringify!(";
                let suffix = "),";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let tokens = &source[prefix.len() .. source.len() - suffix.len()].trim();

                fn func($input: &str) -> String $body

                format!("
                    macro_rules! proc_macro_call {{
                        () => {{
                            {}
                        }}
                    }}
                ", func(tokens)).parse().unwrap()
            }
        )+
    }
}

#[macro_export]
macro_rules! proc_macro_item_impl {
    ($(
        $( #[$attr:meta] )*
        pub fn $func:ident($input:ident: &str) -> String $body:block
    )+) => {
        $(
            $( #[$attr] )*
            #[proc_macro_derive($func)]
            pub fn $func(input: proc_macro_tokenstream!()) -> proc_macro_tokenstream!() {
                let source = input.to_string();
                let source = source.trim();

                let prefix = "#[allow(unused)]\nenum ProcMacroHack {";
                let suffix = "}";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "Input =";
                let suffix = "0).1,";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "(stringify!(";
                let suffix = "),";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let tokens = &source[prefix.len() .. source.len() - suffix.len()].trim();

                fn func($input: &str) -> String $body

                func(tokens).parse().unwrap()
            }
        )+
    }
}
<|endoftext|>


<commit_before>extern crate libc;
use std::str;
use std::ptr;
use std::path::Path;
use std::fs::File;
use std::ffi::CStr;
use std::ffi::CString;

#[repr(C)]
struct Loc;
#[repr(C)]
struct Errno;

//This is for the opaque C pointer
enum spsps_parser_ {}
//this will be the safe abstraction
struct Parser{
	ptr: *mut spsps_parser_
}

#[link(name = "spsps")]
extern{
	//This returns an owned Parser
	fn spsps_new(name: *const libc::c_char, stream: *mut libc::FILE) -> *mut spsps_parser_;
	fn spsps_free(parser: *mut spsps_parser_);
	//This returns an owned C string.
	fn spsps_loc_to_string(loc: *mut Loc) -> *mut libc::c_char;
	//This returns a borrowed string
	fn spsps_printchar(xch: libc::c_char) -> *mut libc::c_char;
	fn spsps_consume(parser: *mut Parser) -> libc::c_char;
	fn spsps_consume_n(parser: *mut Parser, n: libc::size_t);
	fn spsps_consume_whitespace(parser: *mut Parser);
	//Not sure what return type to use for bool
	fn spsps_eof(parser: *mut Parser) -> libc::c_int;
	//This returns an owned Loc
	fn spsps_loc(parser: *mut Parser) -> *mut Loc;
	fn spsps_peek(parser: *mut Parser) -> libc::c_char;
	fn spsps_peek_n(parser: *mut Parser, n: libc::size_t) -> *mut libc::c_char;
	fn spsps_peek_str(parser: *mut Parser, next: *mut libc::c_char) -> libc::c_int;
	fn spsps_peek_and_consume(parser: *mut Parser, next: *mut libc::c_char) -> libc::c_int;
}

impl Parser{
	fn from_file(name: &str, path: &Path) -> Parser {
		unsafe{
			let path = CString::new(path.to_str().unwrap()).unwrap().as_ptr();
			let fd = libc::funcs::c95::stdio::fopen(path,  CString::new("r").unwrap().as_ptr());
			Parser{ ptr: spsps_new(CString::new(name).unwrap().as_ptr(), fd) }
		 }
	}
}

impl Drop for Parser{
	fn drop(&mut self) {
		unsafe{ spsps_free(self.ptr); }
	}
}

impl Loc{
	fn loc_to_string(loc: &mut Loc) -> String{
		let tmp = unsafe { CStr::from_ptr(spsps_loc_to_string(loc)) };
		let retval = str::from_utf8(tmp.to_bytes()).unwrap_or("").to_owned();
		unsafe {libc::free(tmp.as_ptr() as *mut libc::c_void);}
		retval
	}
}<commit_msg>Added a test of the rudimentary Parser abstraction.<commit_after>extern crate libc;
use std::str;
use std::ptr;
use std::path::Path;
use std::fs::File;
use std::ffi::CStr;
use std::ffi::CString;

#[repr(C)]
struct Loc;
#[repr(C)]
struct Errno;

//This is for the opaque C pointer
enum spsps_parser_ {}
//this will be the safe abstraction
#[derive(Debug)]
struct Parser{
	ptr: *mut spsps_parser_
}

#[link(name = "spsps")]
extern{
	//This returns an owned Parser
	fn spsps_new(name: *const libc::c_char, stream: *mut libc::FILE) -> *mut spsps_parser_;
	fn spsps_free(parser: *mut spsps_parser_);
	//This returns an owned C string.
	fn spsps_loc_to_string(loc: *mut Loc) -> *mut libc::c_char;
	//This returns a borrowed string
	fn spsps_printchar(xch: libc::c_char) -> *mut libc::c_char;
	fn spsps_consume(parser: *mut Parser) -> libc::c_char;
	fn spsps_consume_n(parser: *mut Parser, n: libc::size_t);
	fn spsps_consume_whitespace(parser: *mut Parser);
	//Not sure what return type to use for bool
	fn spsps_eof(parser: *mut Parser) -> libc::c_int;
	//This returns an owned Loc
	fn spsps_loc(parser: *mut Parser) -> *mut Loc;
	fn spsps_peek(parser: *mut Parser) -> libc::c_char;
	fn spsps_peek_n(parser: *mut Parser, n: libc::size_t) -> *mut libc::c_char;
	fn spsps_peek_str(parser: *mut Parser, next: *mut libc::c_char) -> libc::c_int;
	fn spsps_peek_and_consume(parser: *mut Parser, next: *mut libc::c_char) -> libc::c_int;
}

impl Parser{
	fn from_file(name: &str, path: &Path) -> Parser {
		unsafe{
			let path = CString::new(path.to_str().unwrap()).unwrap().as_ptr();
			let fd = libc::funcs::c95::stdio::fopen(path,  CString::new("r").unwrap().as_ptr());
			Parser{ ptr: spsps_new(CString::new(name).unwrap().as_ptr(), fd) }
		 }
	}
}

impl Drop for Parser{
	fn drop(&mut self) {
		unsafe{ spsps_free(self.ptr); }
	}
}

impl Loc{
	fn loc_to_string(loc: &mut Loc) -> String{
		let tmp = unsafe { CStr::from_ptr(spsps_loc_to_string(loc)) };
		let retval = str::from_utf8(tmp.to_bytes()).unwrap_or("").to_owned();
		unsafe {libc::free(tmp.as_ptr() as *mut libc::c_void);}
		retval
	}
}

#[test]
fn test_from_file(){
	let test_path = Path::new(file!());
	let p = Parser::from_file("test", test_path);
	println!("{:?}", p);
}<|endoftext|>