<commit_before>//! The operational library makes it easy to implement monads with tricky control flow.
//!
//! This is very useful for: writing web applications in a sequential style,
//! programming games with a uniform interface for human and AI players and easy replay,
//! implementing fast parser monads, designing monadic DSLs, etc.
//!
//! A thorough introduction to the ideas behind this library is given in
//! ["The Operational Monad Tutorial"](http://apfelmus.nfshost.com/articles/operational-monad.html),
//! published in [Issue 15 of the Monad.Reader](http://themonadreader.wordpress.com/2010/01/26/issue-15/).

extern crate functor;

use std::fmt;

mod kleisli;
pub use kleisli::Kleisli;

mod pipe;
pub use pipe::*;

enum Void {}

/// Represents a conduit, i.e. a sequence of await/yield actions.
///
/// - `A` is the return type of the conduit.
pub enum ConduitM<'a, I, O, A> {
    /// The case `Pure(a)` means that the conduit contains requires further action and just returns the result `a`.
    Pure(Box<A>),
    /// The case `Await(k)` means that the conduit waits for a value of type `I`, and the remaining (suspended) program is given by the kleisli arrow `k`.
    Await(Kleisli<'a, Option<I>, I, O, A>),
    /// The case `Yield(o, k)` means that the conduit yields a value of type `O`, and the remaining (suspended) program is given by the kleisli arrow `k`.
    Yield(Box<O>, Kleisli<'a, (), I, O, A>)
}

/// Provides a stream of output values,
/// without consuming any input or producing a final result.
pub type Source<'a, O> = ConduitM<'a, (), O, ()>;

/// Consumes a stream of input values and produces a stream of output values,
/// without producing a final result.
pub type Conduit<'a, I, O> = ConduitM<'a, I, O, ()>;

/// Consumes a stream of input values and produces a final result,
/// without producing any output.
pub type Sink<'a, I, A> = ConduitM<'a, I, Void, A>;

impl<'a, I, O, A> ConduitM<'a, I, O, A> {

    fn and_then_boxed<B, F>(self, js: F) -> ConduitM<'a, I, O, B>
        where F: 'a + Fn(Box<A>) -> ConduitM<'a, I, O, B> {
        match self {
            ConduitM::Pure(a) => js(a),
            ConduitM::Await(is) => ConduitM::Await(kleisli::append_boxed(is, js)),
            ConduitM::Yield(o, is) => ConduitM::Yield(o, kleisli::append_boxed(is, js))
        }
    }

    /// Appends a continuation to a conduit. Which means,
    /// given a function from `A` to `ConduitM<I, O, B>`,
    /// passes the return value of the conduit to the function,
    /// and returns the resulting program.
    ///
    /// Equivalent to the monadic `>>=` operator.
    pub fn and_then<B, F>(self, js: F) -> ConduitM<'a, I, O, B>
        where F: 'a + Fn(A) -> ConduitM<'a, I, O, B> {
        match self {
            ConduitM::Pure(a) => js(*a),
            ConduitM::Await(is) => ConduitM::Await(is.append(js)),
            ConduitM::Yield(o, is) => ConduitM::Yield(o, is.append(js))
        }
    }

    /// Modifies the return value of the conduit.
    /// Seen differently, it lifts a function from
    /// `A` to `B` into a function from `ConduitM<I, O, A>`
    /// to `ConduitM<I, O, B>`.
    ///
    /// Equivalent to the monadic `liftM`.
    pub fn map<B, F>(self, f: F) -> ConduitM<'a, I, O, B>
        where F: 'a + Fn(A) -> B {
        self.and_then(move |a| point(f(a)))
    }

}

impl<'a, I, O, A: PartialEq> PartialEq for ConduitM<'a, I, O, A> {
    fn eq(&self, other: &ConduitM<'a, I, O, A>) -> bool {
        match (self, other) {
            (&ConduitM::Pure(ref a), &ConduitM::Pure(ref b)) => a == b,
            _ => false
        }
    }
}

impl<'a, I, O, A: fmt::Debug> fmt::Debug for ConduitM<'a, I, O, A> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ConduitM::Pure(ref a) => write!(f, "Pure({:?})", a),
            &ConduitM::Await(_) => write!(f, "Await(..)"),
            &ConduitM::Yield(_, _) => write!(f, "Yield(..)")
        }
    }
}

/// Using a value, constructs the empty conduit,
/// i.e. a conduit that directly returns that value.
///
/// Equivalent to the monadic `return`.
pub fn point<'a, I, O, A>(a: A) -> ConduitM<'a, I, O, A> {
    ConduitM::Pure(Box::new(a))
}

/// Wait for a single input value from upstream.
///
/// If no data is available, returns `None`.
/// Once it returns `None`, subsequent calls will also return `None`.
pub fn consume<'a, I, O>() -> ConduitM<'a, I, O, Option<I>> {
    ConduitM::Await(Kleisli::new())
}

/// Send a value downstream to the next component to consume.
///
/// If the downstream component terminates, this call will never return control.
pub fn produce<'a, I, O>(o: O) -> ConduitM<'a, I, O, ()> {
    ConduitM::Yield(Box::new(o), Kleisli::new())
}

/// Pulls data from the source and pushes it into the sink.
///
/// # Example
///
/// ```rust
/// use plumbum::{Source, Sink, consume, produce, connect};
///
/// let src = produce(42);
///
/// let sink = consume().map(|x| 1 + x.unwrap_or(0));
///
/// assert_eq!(connect(src, sink), 43);
/// ```
pub fn connect<A, B>(mut src: Source<A>, mut sink: Sink<A, B>) -> B {
    loop {
        let (next_src, next_sink) = match sink {
            ConduitM::Pure(b_box) => {
                return *b_box;
            },
            ConduitM::Await(k_sink) => {
                match src {
                    ConduitM::Pure(x) => {
                        (ConduitM::Pure(x), k_sink.run(None))
                    },
                    ConduitM::Await(k_src) => {
                        (k_src.run(Some(())), ConduitM::Await(k_sink))
                    },
                    ConduitM::Yield(a_box, k_src) => {
                        (k_src.run(()), k_sink.run(Some(*a_box)))
                    }
                }
            },
            ConduitM::Yield(_, _) => unreachable!()
        };
        src = next_src;
        sink = next_sink;
    }
}
<commit_msg>remove functor import<commit_after>//! The operational library makes it easy to implement monads with tricky control flow.
//!
//! This is very useful for: writing web applications in a sequential style,
//! programming games with a uniform interface for human and AI players and easy replay,
//! implementing fast parser monads, designing monadic DSLs, etc.
//!
//! A thorough introduction to the ideas behind this library is given in
//! ["The Operational Monad Tutorial"](http://apfelmus.nfshost.com/articles/operational-monad.html),
//! published in [Issue 15 of the Monad.Reader](http://themonadreader.wordpress.com/2010/01/26/issue-15/).

use std::fmt;

mod kleisli;
pub use kleisli::Kleisli;

mod pipe;
pub use pipe::*;

enum Void {}

/// Represents a conduit, i.e. a sequence of await/yield actions.
///
/// - `A` is the return type of the conduit.
pub enum ConduitM<'a, I, O, A> {
    /// The case `Pure(a)` means that the conduit contains requires further action and just returns the result `a`.
    Pure(Box<A>),
    /// The case `Await(k)` means that the conduit waits for a value of type `I`, and the remaining (suspended) program is given by the kleisli arrow `k`.
    Await(Kleisli<'a, Option<I>, I, O, A>),
    /// The case `Yield(o, k)` means that the conduit yields a value of type `O`, and the remaining (suspended) program is given by the kleisli arrow `k`.
    Yield(Box<O>, Kleisli<'a, (), I, O, A>)
}

/// Provides a stream of output values,
/// without consuming any input or producing a final result.
pub type Source<'a, O> = ConduitM<'a, (), O, ()>;

/// Consumes a stream of input values and produces a stream of output values,
/// without producing a final result.
pub type Conduit<'a, I, O> = ConduitM<'a, I, O, ()>;

/// Consumes a stream of input values and produces a final result,
/// without producing any output.
pub type Sink<'a, I, A> = ConduitM<'a, I, Void, A>;

impl<'a, I, O, A> ConduitM<'a, I, O, A> {

    fn and_then_boxed<B, F>(self, js: F) -> ConduitM<'a, I, O, B>
        where F: 'a + Fn(Box<A>) -> ConduitM<'a, I, O, B> {
        match self {
            ConduitM::Pure(a) => js(a),
            ConduitM::Await(is) => ConduitM::Await(kleisli::append_boxed(is, js)),
            ConduitM::Yield(o, is) => ConduitM::Yield(o, kleisli::append_boxed(is, js))
        }
    }

    /// Appends a continuation to a conduit. Which means,
    /// given a function from `A` to `ConduitM<I, O, B>`,
    /// passes the return value of the conduit to the function,
    /// and returns the resulting program.
    ///
    /// Equivalent to the monadic `>>=` operator.
    pub fn and_then<B, F>(self, js: F) -> ConduitM<'a, I, O, B>
        where F: 'a + Fn(A) -> ConduitM<'a, I, O, B> {
        match self {
            ConduitM::Pure(a) => js(*a),
            ConduitM::Await(is) => ConduitM::Await(is.append(js)),
            ConduitM::Yield(o, is) => ConduitM::Yield(o, is.append(js))
        }
    }

    /// Modifies the return value of the conduit.
    /// Seen differently, it lifts a function from
    /// `A` to `B` into a function from `ConduitM<I, O, A>`
    /// to `ConduitM<I, O, B>`.
    ///
    /// Equivalent to the monadic `liftM`.
    pub fn map<B, F>(self, f: F) -> ConduitM<'a, I, O, B>
        where F: 'a + Fn(A) -> B {
        self.and_then(move |a| point(f(a)))
    }

}

impl<'a, I, O, A: PartialEq> PartialEq for ConduitM<'a, I, O, A> {
    fn eq(&self, other: &ConduitM<'a, I, O, A>) -> bool {
        match (self, other) {
            (&ConduitM::Pure(ref a), &ConduitM::Pure(ref b)) => a == b,
            _ => false
        }
    }
}

impl<'a, I, O, A: fmt::Debug> fmt::Debug for ConduitM<'a, I, O, A> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ConduitM::Pure(ref a) => write!(f, "Pure({:?})", a),
            &ConduitM::Await(_) => write!(f, "Await(..)"),
            &ConduitM::Yield(_, _) => write!(f, "Yield(..)")
        }
    }
}

/// Using a value, constructs the empty conduit,
/// i.e. a conduit that directly returns that value.
///
/// Equivalent to the monadic `return`.
pub fn point<'a, I, O, A>(a: A) -> ConduitM<'a, I, O, A> {
    ConduitM::Pure(Box::new(a))
}

/// Wait for a single input value from upstream.
///
/// If no data is available, returns `None`.
/// Once it returns `None`, subsequent calls will also return `None`.
pub fn consume<'a, I, O>() -> ConduitM<'a, I, O, Option<I>> {
    ConduitM::Await(Kleisli::new())
}

/// Send a value downstream to the next component to consume.
///
/// If the downstream component terminates, this call will never return control.
pub fn produce<'a, I, O>(o: O) -> ConduitM<'a, I, O, ()> {
    ConduitM::Yield(Box::new(o), Kleisli::new())
}

/// Pulls data from the source and pushes it into the sink.
///
/// # Example
///
/// ```rust
/// use plumbum::{Source, Sink, consume, produce, connect};
///
/// let src = produce(42);
///
/// let sink = consume().map(|x| 1 + x.unwrap_or(0));
///
/// assert_eq!(connect(src, sink), 43);
/// ```
pub fn connect<A, B>(mut src: Source<A>, mut sink: Sink<A, B>) -> B {
    loop {
        let (next_src, next_sink) = match sink {
            ConduitM::Pure(b_box) => {
                return *b_box;
            },
            ConduitM::Await(k_sink) => {
                match src {
                    ConduitM::Pure(x) => {
                        (ConduitM::Pure(x), k_sink.run(None))
                    },
                    ConduitM::Await(k_src) => {
                        (k_src.run(Some(())), ConduitM::Await(k_sink))
                    },
                    ConduitM::Yield(a_box, k_src) => {
                        (k_src.run(()), k_sink.run(Some(*a_box)))
                    }
                }
            },
            ConduitM::Yield(_, _) => unreachable!()
        };
        src = next_src;
        sink = next_sink;
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
extern crate rand;
extern crate time;

use rand::{thread_rng, Rng};
use time::{precise_time_ns};

#[derive(Debug)]
pub struct CohortResult<T: Clone> {
    pub duration: f64,
    pub result: T
}

impl<T: Clone> CohortResult<T> {
    pub fn new(duration: f64, result: &T) -> Self {
        CohortResult {
            duration: duration,
            result: result.clone()
        }
    }
}

#[derive(Debug)]
pub struct ExperimentResult<CurrentT: Clone, NewT: Clone> {
    pub current: CohortResult<CurrentT>,
    pub new: CohortResult<NewT>,
    pub name: &'static str
}

impl<CurrentT: Clone, NewT: Clone> ExperimentResult<CurrentT, NewT> {
    pub fn new(current: CohortResult<CurrentT>, new: CohortResult<NewT>, name: &'static str) -> Self {
        ExperimentResult {
            current: current,
            new: new,
            name: name
        }
    }
}

pub trait Experiment<CurrentResult: Clone, NewResult: Clone> {
    fn publish(_: ExperimentResult<CurrentResult, NewResult>) {}

    fn carry_out<C, N, Param>(name: &'static str, mut current: C, mut new: N, param: Param) -> CurrentResult
        where C: FnMut(Param) -> CurrentResult,
              N: FnMut(Param) -> NewResult,
              Param: Clone {
        let mut rng = thread_rng();
        let mut did_one = false;
        let current_goes_first: bool = rng.gen();
        let mut current_val = None;
        let mut new_val = None;
        let mut current_duration = 0;
        let mut new_duration = 0;
        loop {
            if (current_goes_first || did_one) && !(current_goes_first && did_one) {
                let start = precise_time_ns();
                current_val = Some(current(param.clone()));
                current_duration = precise_time_ns() - start;
                if did_one {
                    break;
                } else {
                    did_one = true;
                }
            }
            if (!current_goes_first || did_one) && !(!current_goes_first && did_one) {
                let start = precise_time_ns();
                new_val = Some(new(param.clone()));
                new_duration = precise_time_ns() - start;
                if did_one {
                    break;
                } else {
                    did_one = true;
                }
            }
        }
        Self::publish(ExperimentResult::new(
            CohortResult::new(current_duration as f64 * 1e-9, &current_val.as_ref().unwrap()),
            CohortResult::new(new_duration as f64 * 1e-9, &new_val.as_ref().unwrap()),
            name
        ));
        current_val.unwrap()
    }
}

#[cfg(test)]
mod test {
    use super::{Experiment, ExperimentResult};
    struct TestExperiment;

    impl Experiment<String, String> for TestExperiment {
        fn publish(result: ExperimentResult<String, String>) {
            println!("{:?}", result);
        }
    }

    #[test]
    fn it_works() {
        let a_str = "bagelman";
        let a = TestExperiment::carry_out(
            "experiment!",
            |_| {
                println!("current went!");
                a_str.to_string()
            },
            |_| {
                println!("new went!");
                a_str.to_string()
            },
            ()
        );
        println!("{}", a);
    }
}

#[doc(hidden)]
pub mod internal {
    pub use rand;
    pub use time;
}
<commit_msg>Added the run_if feature<commit_after>#![allow(dead_code)]
extern crate rand;
extern crate time;

use rand::{thread_rng, Rng};
use time::{precise_time_ns};
use std::marker::PhantomData;

#[derive(Debug)]
pub struct CohortResult<T: Clone> {
    pub duration: f64,
    pub result: T
}

impl<T: Clone> CohortResult<T> {
    pub fn new(duration: f64, result: &T) -> Self {
        CohortResult {
            duration: duration,
            result: result.clone()
        }
    }
}

#[derive(Debug)]
pub struct ExperimentResult<CurrentT: Clone, NewT: Clone> {
    pub current: CohortResult<CurrentT>,
    pub new: CohortResult<NewT>,
    pub name: &'static str
}

impl<CurrentT: Clone, NewT: Clone> ExperimentResult<CurrentT, NewT> {
    pub fn new(current: CohortResult<CurrentT>, new: CohortResult<NewT>, name: &'static str) -> Self {
        ExperimentResult {
            current: current,
            new: new,
            name: name
        }
    }
}

pub struct ExperimentBuilder<'a, CurrentResult: Clone, NewResult: Clone, Param: Clone, E: Experiment<CurrentResult, NewResult, Param> + ?Sized> {
    name: &'static str,
    current: Box<FnMut(Param) -> CurrentResult + 'a>,
    new: Box<FnMut(Param) -> NewResult + 'a>,
    run_if: Option<Box<FnMut(Param) -> bool + 'a>>,
    experiment: PhantomData<E>
}

impl<'a, CurrentResult: Clone, NewResult: Clone, Param: Clone, E: Experiment<CurrentResult, NewResult, Param>> ExperimentBuilder<'a, CurrentResult, NewResult, Param, E> {
    pub fn run_if<R>(mut self, run_if: R) -> Self
            where R: FnMut(Param) -> bool + 'a {
        self.run_if = Some(Box::new(run_if));
        self
    }

    pub fn carry_out(mut self, param: Param) -> CurrentResult {
        match self.run_if {
            Some(mut r) => {
                if !r(param.clone()) {
                    return (self.current)(param.clone());
                }
            }
            _ => {}
        }
        let mut rng = thread_rng();
        let mut did_one = false;
        let current_goes_first: bool = rng.gen();
        let mut current_val = None;
        let mut new_val = None;
        let mut current_duration = 0;
        let mut new_duration = 0;
        loop {
            if (current_goes_first || did_one) && !(current_goes_first && did_one) {
                let start = precise_time_ns();
                current_val = Some((self.current)(param.clone()));
                current_duration = precise_time_ns() - start;
                if did_one {
                    break;
                } else {
                    did_one = true;
                }
            }
            if (!current_goes_first || did_one) && !(!current_goes_first && did_one) {
                let start = precise_time_ns();
                new_val = Some((self.new)(param.clone()));
                new_duration = precise_time_ns() - start;
                if did_one {
                    break;
                } else {
                    did_one = true;
                }
            }
        }
        E::publish(ExperimentResult::new(
            CohortResult::new(current_duration as f64 * 1e-9, &current_val.as_ref().unwrap()),
            CohortResult::new(new_duration as f64 * 1e-9, &new_val.as_ref().unwrap()),
            self.name
        ));
        current_val.unwrap()
    }
}

pub trait Experiment<CurrentResult: Clone, NewResult: Clone, Param: Clone> {
    fn publish(_: ExperimentResult<CurrentResult, NewResult>) {}

    fn new<'a, C, N>(name: &'static str, current: C, new: N) -> ExperimentBuilder<'a, CurrentResult, NewResult, Param, Self>
        where C: FnMut(Param) -> CurrentResult + 'a,
              N: FnMut(Param) -> NewResult + 'a {
        ExperimentBuilder {
            name: name,
            current: Box::new(current),
            new: Box::new(new),
            run_if: None,
            experiment: PhantomData
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Experiment, ExperimentResult};
    struct TestExperiment;

    impl Experiment<String, String, ()> for TestExperiment {
        fn publish(result: ExperimentResult<String, String>) {
            println!("{:#?}", result);
        }
    }

    #[test]
    fn it_works() {
        let a_str = vec!['a', 'b', 'c'];
        let a = TestExperiment::new("experiment!",
            |_| {
                println!("current went!");
                a_str.clone().into_iter().collect()
            },
            |_| {
                println!("new went!");
                a_str.clone().into_iter().collect()
            })
            .run_if(|_| true)
            .carry_out(());
        println!("{}", a);
    }
}
<|endoftext|>


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

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

use std::collections::RingBuf;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex, Condvar, TaskPool};
use std::fmt;

pub use config::{Config, ConfigError};

mod config;
mod task;

/// 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>> {
    fn handle_error(&self, error: E) {
        (**self).handle_error(error)
    }
}

/// An `ErrorHandler` which does nothing.
#[derive(Copy, Clone, Show)]
pub struct NoopErrorHandler;

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

/// An `ErrorHandler` which logs at the error level.
#[derive(Copy, Clone, Show)]
pub struct LoggingErrorHandler;

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

struct PoolInternals<C> {
    conns: RingBuf<C>,
    num_conns: u32,
    task_pool: TaskPool,
}

unsafe impl<C: Send> Send for PoolInternals<C> {}

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>>,
    cond: Condvar,
}

fn add_connection<C, E, M, H>(inner: &Arc<InnerPool<C, E, M, H>>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    let new_inner = inner.clone();
    inner.internals.lock().unwrap().task_pool.execute(move || {
        let inner = new_inner;
        match inner.manager.connect() {
            Ok(conn) => {
                let mut internals = inner.internals.lock().unwrap();
                internals.conns.push_back(conn);
                internals.num_conns += 1;
                inner.cond.notify_one();
            }
            Err(err) => inner.error_handler.handle_error(err),
        }
    });
}

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

impl<C, E, M, H> fmt::Show for Pool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>+fmt::Show, H: ErrorHandler<E> {
    // FIXME there's more we can do here
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Pool {{ config: {:?}, manager: {:?} }}", self.inner.config,
               self.inner.manager)
    }
}

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,
            task_pool: TaskPool::new(config.helper_tasks as usize),
        };

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

        for _ in range(0, config.pool_size) {
            add_connection(&inner);
        }

        Ok(Pool {
            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().unwrap();

        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().unwrap();
                            internals.num_conns -= 1;
                            continue
                        }
                    }

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

    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().unwrap();
        if broken {
            internals.num_conns -= 1;
        } else {
            internals.conns.push_back(conn);
            self.inner.cond.notify_one();
        }
    }
}

/// 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>,
}

impl<'a, C, E, M, H> fmt::Show for PooledConnection<'a, C, E, M, H>
        where C: Send+fmt::Show, E: Send, M: PoolManager<C, E>+fmt::Show, H: ErrorHandler<E> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "PooledConnection {{ pool: {:?}, connection: {:?} }}", self.pool,
               self.conn.as_ref().unwrap())
    }
}

#[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 for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    type Target = C;

    fn deref(&self) -> &C {
        self.conn.as_ref().unwrap()
    }
}

impl<'a, C, E, M, H> DerefMut 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>Switch to using ScheduledThreadPool<commit_after>//! A library providing a generic connection pool.
#![feature(unsafe_destructor)]
#![warn(missing_docs)]
#![allow(unstable)]
#![doc(html_root_url="https://sfackler.github.io/doc")]

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

use std::collections::RingBuf;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex, Condvar};
use std::fmt;

pub use config::{Config, ConfigError};

use task::ScheduledThreadPool;

mod config;
mod task;

/// 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>> {
    fn handle_error(&self, error: E) {
        (**self).handle_error(error)
    }
}

/// An `ErrorHandler` which does nothing.
#[derive(Copy, Clone, Show)]
pub struct NoopErrorHandler;

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

/// An `ErrorHandler` which logs at the error level.
#[derive(Copy, Clone, Show)]
pub struct LoggingErrorHandler;

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

struct PoolInternals<C> {
    conns: RingBuf<C>,
    num_conns: u32,
    thread_pool: ScheduledThreadPool,
}

unsafe impl<C: Send> Send for PoolInternals<C> {}

struct SharedPool<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>>,
    cond: Condvar,
}

fn add_connection<C, E, M, H>(inner: &Arc<SharedPool<C, E, M, H>>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    let new_inner = inner.clone();
    inner.internals.lock().unwrap().thread_pool.run(move || {
        let inner = new_inner;
        match inner.manager.connect() {
            Ok(conn) => {
                let mut internals = inner.internals.lock().unwrap();
                internals.conns.push_back(conn);
                internals.num_conns += 1;
                inner.cond.notify_one();
            }
            Err(err) => inner.error_handler.handle_error(err),
        }
    });
}

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

impl<C, E, M, H> fmt::Show for Pool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>+fmt::Show, H: ErrorHandler<E> {
    // FIXME there's more we can do here
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Pool {{ config: {:?}, manager: {:?} }}", self.inner.config,
               self.inner.manager)
    }
}

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,
            thread_pool: ScheduledThreadPool::new(config.helper_tasks as usize),
        };

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

        for _ in range(0, config.pool_size) {
            add_connection(&inner);
        }

        Ok(Pool {
            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().unwrap();

        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().unwrap();
                            internals.num_conns -= 1;
                            continue
                        }
                    }

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

    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().unwrap();
        if broken {
            internals.num_conns -= 1;
        } else {
            internals.conns.push_back(conn);
            self.inner.cond.notify_one();
        }
    }
}

/// 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>,
}

impl<'a, C, E, M, H> fmt::Show for PooledConnection<'a, C, E, M, H>
        where C: Send+fmt::Show, E: Send, M: PoolManager<C, E>+fmt::Show, H: ErrorHandler<E> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "PooledConnection {{ pool: {:?}, connection: {:?} }}", self.pool,
               self.conn.as_ref().unwrap())
    }
}

#[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 for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    type Target = C;

    fn deref(&self) -> &C {
        self.conn.as_ref().unwrap()
    }
}

impl<'a, C, E, M, H> DerefMut 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>#![deny(trivial_casts, unused_qualifications)]
#[macro_use]
extern crate approx;
#[macro_use]
extern crate bitflags;
extern crate ieee754 as fp;
extern crate image as img;
extern crate itertools as it;
extern crate nalgebra as na;
extern crate num;
extern crate rand;
#[macro_use(o, slog_info, slog_debug, slog_warn, slog_error, slog_trace, slog_log)]
extern crate slog;
#[macro_use]
extern crate slog_scope;
extern crate threadpool as tp;

use std::f32;
use std::ops::{Add, Mul, Sub};

use na::{Vector3, Point2, Point3, Similarity3, BaseNum};
use num::One;

mod blockedarray;
mod block_queue;
mod bounds;
mod bsdf;
mod bvh;
pub mod camera;
pub mod spectrum;
pub mod efloat;
mod filter;
pub mod geometry;
mod film;
pub mod instance;
pub mod integrator;
mod interaction;
mod intersection;
pub mod light;
pub mod material;
pub mod mipmap;
pub mod primitive;
pub mod ray;
pub mod renderer;
pub mod sampling;
pub mod sampler;
pub mod scene;
pub mod shapes;
mod skydome;
mod stats;
pub mod texture;
mod transform;

pub type Dim = (u32, u32);

pub type Vector = Vector3<f32>;
pub type Point = Point3<f32>;
pub type Point2f = Point2<f32>;
pub type Point2i = Point2<u32>;
pub type Transform = Similarity3<f32>;

pub const MACHINE_EPSILON: f32 = f32::EPSILON * 0.5;
pub fn gamma(n: u32) -> f32 {
    (n as f32 * MACHINE_EPSILON) / (1.0 - n as f32 * MACHINE_EPSILON)
}

/// Linear interpolation between 2 values
pub fn lerp<S, T>(t: S, a: T, b: T) -> T
    where S: One,
          S: Sub<S, Output = S>,
          S: Copy,
          T: Add<T, Output = T>,
          T: Mul<S, Output = T>
{
    let one: S = num::one();
    a * (one - t) + b * t
}

#[test]
fn test_gamma() {
    let g5 = gamma(5);
    let p = Point::new(-0.4, 0.9, 0.2);
    let v = g5 * na::abs(&p.to_vector());
    println!("gamma(5) = {}, p={:?}, v={:?}", gamma(5), p, v);
}
<commit_msg>Add Vector2f alias<commit_after>#![deny(trivial_casts, unused_qualifications)]
#[macro_use]
extern crate approx;
#[macro_use]
extern crate bitflags;
extern crate ieee754 as fp;
extern crate image as img;
extern crate itertools as it;
extern crate nalgebra as na;
extern crate num;
extern crate rand;
#[macro_use(o, slog_info, slog_debug, slog_warn, slog_error, slog_trace, slog_log)]
extern crate slog;
#[macro_use]
extern crate slog_scope;
extern crate threadpool as tp;

use std::f32;
use std::ops::{Add, Mul, Sub};

use na::{Vector2, Vector3, Point2, Point3, Similarity3, BaseNum};
use num::One;

mod blockedarray;
mod block_queue;
mod bounds;
mod bsdf;
mod bvh;
pub mod camera;
pub mod spectrum;
pub mod efloat;
mod filter;
pub mod geometry;
mod film;
pub mod instance;
pub mod integrator;
mod interaction;
mod intersection;
pub mod light;
pub mod material;
pub mod mipmap;
pub mod primitive;
pub mod ray;
pub mod renderer;
pub mod sampling;
pub mod sampler;
pub mod scene;
pub mod shapes;
mod skydome;
mod stats;
pub mod texture;
mod transform;

pub type Dim = (u32, u32);

pub type Vector = Vector3<f32>;
pub type Vector2f = Vector2<f32>;
pub type Point = Point3<f32>;
pub type Point2f = Point2<f32>;
pub type Point2i = Point2<u32>;
pub type Transform = Similarity3<f32>;

pub const MACHINE_EPSILON: f32 = f32::EPSILON * 0.5;
pub fn gamma(n: u32) -> f32 {
    (n as f32 * MACHINE_EPSILON) / (1.0 - n as f32 * MACHINE_EPSILON)
}

/// Linear interpolation between 2 values
pub fn lerp<S, T>(t: S, a: T, b: T) -> T
    where S: One,
          S: Sub<S, Output = S>,
          S: Copy,
          T: Add<T, Output = T>,
          T: Mul<S, Output = T>
{
    let one: S = num::one();
    a * (one - t) + b * t
}

#[test]
fn test_gamma() {
    let g5 = gamma(5);
    let p = Point::new(-0.4, 0.9, 0.2);
    let v = g5 * na::abs(&p.to_vector());
    println!("gamma(5) = {}, p={:?}, v={:?}", gamma(5), p, v);
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate energymon_sys;

use libc::{c_int, c_ulonglong, c_char};
use std::mem;
use std::ptr;
use energymon_sys::*;

/// A basic energy monitor.
pub struct EnergyMon {
    /// The native C struct.
    em: em_impl,
}

impl EnergyMon {
    /// Create and initialize an `EnergyMon`.
    pub fn new() -> Result<EnergyMon, &'static str> {
    	unsafe {
            let mut em: em_impl = mem::uninitialized();
            match em_impl_get(&mut em) {
                0 => (),
                _ => return Err("Failed to create em_impl"),
            }
            match (em.finit)(&mut em) {
            	0 => Ok(EnergyMon{ em: em }),
            	_ => Err("Failed to initialize em_impl"),
        	}
        }
    }

    /// Read the total energy from the `EnergyMon`.
    pub fn read(&self) -> u64 {
        (self.em.fread)(&self.em)
    }

    /// Get a human-readable name of the `EnergyMon`'s source.
    pub fn source(&mut self) -> String {
        const BUFSIZE: usize = 100;
        let mut buf: [c_char; BUFSIZE] = [0; BUFSIZE];
        let ret: *mut c_char = (self.em.fsource)(buf.as_mut_ptr());
        if ret.is_null() {
            return "UNKNOWN".to_owned();
        }
        let buf: &[u8] = unsafe {
            mem::transmute::<&[c_char], &[u8]>(&buf)
        };
        String::from_utf8_lossy(buf).into_owned()
    }

    /// Get the refresh interval for the `EnergyMon`.
    pub fn interval(&self) -> u64 {
        (self.em.finterval)(&self.em)
    }

    /// Cleanup the `EnergyMon`.
    fn finish(&mut self) -> i32 {
    	(self.em.ffinish)(&mut self.em)
    }
}

impl Drop for EnergyMon {
    fn drop(&mut self) {
        self.finish();
    }
}

impl Default for EnergyMon {
    /// Returns a dummy `EnergyMon`.
    fn default() -> EnergyMon {
        EnergyMon {
            em: em_impl {
                finit: default_init,
                fread: default_read_total,
                ffinish: default_finish,
                fsource: default_get_source,
                finterval:default_get_interval,
                state: ptr::null_mut(),
            }
        }
    }
}

extern fn default_init(_impl: *mut em_impl) -> c_int {
    0
}

extern fn default_read_total(_impl: *const em_impl) -> c_ulonglong {
    0
}

extern fn default_finish(_impl: *mut em_impl) -> c_int {
    0
}

extern fn default_get_source(_impl: *mut c_char) -> *mut c_char {
    ptr::null_mut()
}

extern fn default_get_interval(_impl: *const em_impl) -> c_ulonglong {
    1
}

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

    #[test]
    fn test_interface() {
        let mut em: EnergyMon = EnergyMon::new().unwrap();
        let val = em.read();
        println!("Read {} from {} with refresh interval {}", val, em.source(), em.interval());
    }

    #[test]
    fn test_default() {
        let mut em: EnergyMon = Default::default();
        assert!(em.read() == 0);
        assert!(em.interval() == 1);
        assert!(em.finish() == 0);
        assert!(em.em.state.is_null())
    }

}
<commit_msg>Restrict scope of default extern functions to default()<commit_after>extern crate libc;
extern crate energymon_sys;

use libc::{c_int, c_ulonglong, c_char};
use std::mem;
use std::ptr;
use energymon_sys::*;

/// A basic energy monitor.
pub struct EnergyMon {
    /// The native C struct.
    em: em_impl,
}

impl EnergyMon {
    /// Create and initialize an `EnergyMon`.
    pub fn new() -> Result<EnergyMon, &'static str> {
    	unsafe {
            let mut em: em_impl = mem::uninitialized();
            match em_impl_get(&mut em) {
                0 => (),
                _ => return Err("Failed to create em_impl"),
            }
            match (em.finit)(&mut em) {
            	0 => Ok(EnergyMon{ em: em }),
            	_ => Err("Failed to initialize em_impl"),
        	}
        }
    }

    /// Read the total energy from the `EnergyMon`.
    pub fn read(&self) -> u64 {
        (self.em.fread)(&self.em)
    }

    /// Get a human-readable name of the `EnergyMon`'s source.
    pub fn source(&mut self) -> String {
        const BUFSIZE: usize = 100;
        let mut buf: [c_char; BUFSIZE] = [0; BUFSIZE];
        let ret: *mut c_char = (self.em.fsource)(buf.as_mut_ptr());
        if ret.is_null() {
            return "UNKNOWN".to_owned();
        }
        let buf: &[u8] = unsafe {
            mem::transmute::<&[c_char], &[u8]>(&buf)
        };
        String::from_utf8_lossy(buf).into_owned()
    }

    /// Get the refresh interval for the `EnergyMon`.
    pub fn interval(&self) -> u64 {
        (self.em.finterval)(&self.em)
    }

    /// Cleanup the `EnergyMon`.
    fn finish(&mut self) -> i32 {
    	(self.em.ffinish)(&mut self.em)
    }
}

impl Drop for EnergyMon {
    fn drop(&mut self) {
        self.finish();
    }
}

impl Default for EnergyMon {
    /// Returns a dummy `EnergyMon`.
    fn default() -> EnergyMon {
        extern fn default_init(_impl: *mut em_impl) -> c_int { 0 };
        extern fn default_read_total(_impl: *const em_impl) -> c_ulonglong { 0 };
        extern fn default_finish(_impl: *mut em_impl) -> c_int { 0 };
        extern fn default_get_source(_impl: *mut c_char) -> *mut c_char { ptr::null_mut() };
        extern fn default_get_interval(_impl: *const em_impl) -> c_ulonglong { 1 };
        EnergyMon {
            em: em_impl {
                finit: default_init,
                fread: default_read_total,
                ffinish: default_finish,
                fsource: default_get_source,
                finterval:default_get_interval,
                state: ptr::null_mut(),
            }
        }
    }
}

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

    #[test]
    fn test_interface() {
        let mut em: EnergyMon = EnergyMon::new().unwrap();
        let val = em.read();
        println!("Read {} from {} with refresh interval {}", val, em.source(), em.interval());
    }

    #[test]
    fn test_default() {
        let mut em: EnergyMon = Default::default();
        assert!(em.read() == 0);
        assert!(em.interval() == 1);
        assert!(em.finish() == 0);
        assert!(em.em.state.is_null())
    }

}
<|endoftext|>


<commit_before>use std::ffi::OsStr;
use std::fs;
use std::path;

use failure::ResultExt;
use liquid;
use serde_json;
use serde_yaml;
use toml;

use crate::error::*;

use super::files;

#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields, default)]
pub struct Site {
    pub title: Option<kstring::KString>,
    pub description: Option<kstring::KString>,
    pub base_url: Option<kstring::KString>,
    pub sitemap: Option<cobalt_config::RelPath>,
    pub data: Option<liquid::Object>,
    pub data_dir: &'static str,
}

impl Site {
    pub fn from_config(config: cobalt_config::Site) -> Self {
        let cobalt_config::Site {
            title,
            description,
            base_url,
            sitemap,
            data,
            data_dir,
        } = config;

        let base_url = base_url.map(|mut l| {
            if l.ends_with('/') {
                let mut other = String::from(l.as_str());
                other.pop();
                l = kstring::KString::from_string(other);
            }
            l
        });

        Self {
            title,
            description,
            base_url,
            sitemap,
            data,
            data_dir,
        }
    }

    pub fn load(&self, source: &std::path::Path) -> Result<liquid::Object> {
        let mut attributes = liquid::Object::new();
        if let Some(title) = self.title.as_ref() {
            attributes.insert(
                "title".into(),
                liquid::model::Value::scalar(kstring::KString::from_ref(title)),
            );
        }
        if let Some(description) = self.description.as_ref() {
            attributes.insert(
                "description".into(),
                liquid::model::Value::scalar(kstring::KString::from_ref(description)),
            );
        }
        if let Some(base_url) = self.base_url.as_ref() {
            attributes.insert(
                "base_url".into(),
                liquid::model::Value::scalar(kstring::KString::from_ref(base_url)),
            );
        }
        let mut data = self.data.clone().unwrap_or_default();
        let data_path = source.join(&self.data_dir);
        insert_data_dir(&mut data, &data_path)?;
        if !data.is_empty() {
            attributes.insert("data".into(), liquid::model::Value::Object(data));
        }

        Ok(attributes)
    }
}

fn deep_insert(
    data_map: &mut liquid::Object,
    file_path: &path::Path,
    target_key: String,
    data: liquid::model::Value,
) -> Result<()> {
    // now find the nested map it is supposed to be in
    let target_map = if let Some(path) = file_path.parent() {
        let mut map = data_map;
        for part in path.iter() {
            let key = part.to_str().ok_or_else(|| {
                failure::format_err!(
                    "The data from {:?} can't be loaded as it contains non utf-8 characters",
                    path
                )
            })?;
            let cur_map = map;
            let key = kstring::KString::from_ref(key);
            map = cur_map
                .entry(key)
                .or_insert_with(|| liquid::model::Value::Object(liquid::Object::new()))
                .as_object_mut()
                .ok_or_else(|| {
                    failure::format_err!(
                        "Aborting: Duplicate in data tree. Would overwrite {:?} ",
                        path
                    )
                })?;
        }
        map
    } else {
        data_map
    };

    match target_map.insert(target_key.into(), data) {
        None => Ok(()),
        _ => Err(failure::format_err!(
            "The data from {:?} can't be loaded: the key already exists",
            file_path
        )),
    }
}

fn load_data(data_path: &path::Path) -> Result<liquid::model::Value> {
    let ext = data_path.extension().unwrap_or_else(|| OsStr::new(""));

    let data: liquid::model::Value;

    if ext == OsStr::new("yml") || ext == OsStr::new("yaml") {
        let reader = fs::File::open(data_path)?;
        data = serde_yaml::from_reader(reader)?;
    } else if ext == OsStr::new("json") {
        let reader = fs::File::open(data_path)?;
        data = serde_json::from_reader(reader)?;
    } else if ext == OsStr::new("toml") {
        let text = files::read_file(data_path)?;
        data = toml::from_str(&text)?;
    } else {
        failure::bail!(
            "Failed to load of data {:?}: unknown file type '{:?}'.\n\
             Supported data files extensions are: yml, yaml, json and toml.",
            data_path,
            ext
        );
    }

    Ok(data)
}

fn insert_data_dir(data: &mut liquid::Object, data_root: &path::Path) -> Result<()> {
    debug!("Loading data from {:?}", data_root);

    let data_files_builder = files::FilesBuilder::new(data_root)?;
    let data_files = data_files_builder.build()?;
    for full_path in data_files.files() {
        let rel_path = full_path
            .strip_prefix(data_root)
            .expect("file was found under the root");

        let file_stem = full_path
            .file_stem()
            .expect("Files will always return with a stem");
        let file_stem = String::from(file_stem.to_str().unwrap());
        let data_fragment = load_data(&full_path)
            .with_context(|_| format!("Loading data from {:?} failed", full_path))?;

        deep_insert(data, rel_path, file_stem, data_fragment)
            .with_context(|_| format!("Merging data into {:?} failed", rel_path))?;
    }

    Ok(())
}
<commit_msg>cobalt_model - Add a `time` to Site<commit_after>use std::ffi::OsStr;
use std::fs;
use std::path;

use cobalt_config::DateTime;
use failure::ResultExt;
use liquid;
use serde_json;
use serde_yaml;
use toml;

use crate::error::*;

use super::files;

#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields, default)]
pub struct Site {
    pub title: Option<kstring::KString>,
    pub description: Option<kstring::KString>,
    pub base_url: Option<kstring::KString>,
    pub sitemap: Option<cobalt_config::RelPath>,
    pub data: Option<liquid::Object>,
    pub data_dir: &'static str,
    /// The time at which the `cobalt` binary built the site
    pub time: DateTime,
}

impl Site {
    pub fn from_config(config: cobalt_config::Site) -> Self {
        let cobalt_config::Site {
            title,
            description,
            base_url,
            sitemap,
            data,
            data_dir,
        } = config;

        let base_url = base_url.map(|mut l| {
            if l.ends_with('/') {
                let mut other = String::from(l.as_str());
                other.pop();
                l = kstring::KString::from_string(other);
            }
            l
        });

        Self {
            title,
            description,
            base_url,
            sitemap,
            data,
            data_dir,
            time: DateTime::now()
        }
    }

    pub fn load(&self, source: &std::path::Path) -> Result<liquid::Object> {
        let mut attributes = liquid::Object::new();
        if let Some(title) = self.title.as_ref() {
            attributes.insert(
                "title".into(),
                liquid::model::Value::scalar(kstring::KString::from_ref(title)),
            );
        }
        if let Some(description) = self.description.as_ref() {
            attributes.insert(
                "description".into(),
                liquid::model::Value::scalar(kstring::KString::from_ref(description)),
            );
        }
        if let Some(base_url) = self.base_url.as_ref() {
            attributes.insert(
                "base_url".into(),
                liquid::model::Value::scalar(kstring::KString::from_ref(base_url)),
            );
        }
        attributes.insert(
            "time".into(),
            liquid::model::Value::scalar(kstring::KString::from_ref(&self.time.to_string())),
        );

        let mut data = self.data.clone().unwrap_or_default();
        let data_path = source.join(&self.data_dir);
        insert_data_dir(&mut data, &data_path)?;
        if !data.is_empty() {
            attributes.insert("data".into(), liquid::model::Value::Object(data));
        }

        Ok(attributes)
    }
}

fn deep_insert(
    data_map: &mut liquid::Object,
    file_path: &path::Path,
    target_key: String,
    data: liquid::model::Value,
) -> Result<()> {
    // now find the nested map it is supposed to be in
    let target_map = if let Some(path) = file_path.parent() {
        let mut map = data_map;
        for part in path.iter() {
            let key = part.to_str().ok_or_else(|| {
                failure::format_err!(
                    "The data from {:?} can't be loaded as it contains non utf-8 characters",
                    path
                )
            })?;
            let cur_map = map;
            let key = kstring::KString::from_ref(key);
            map = cur_map
                .entry(key)
                .or_insert_with(|| liquid::model::Value::Object(liquid::Object::new()))
                .as_object_mut()
                .ok_or_else(|| {
                    failure::format_err!(
                        "Aborting: Duplicate in data tree. Would overwrite {:?} ",
                        path
                    )
                })?;
        }
        map
    } else {
        data_map
    };

    match target_map.insert(target_key.into(), data) {
        None => Ok(()),
        _ => Err(failure::format_err!(
            "The data from {:?} can't be loaded: the key already exists",
            file_path
        )),
    }
}

fn load_data(data_path: &path::Path) -> Result<liquid::model::Value> {
    let ext = data_path.extension().unwrap_or_else(|| OsStr::new(""));

    let data: liquid::model::Value;

    if ext == OsStr::new("yml") || ext == OsStr::new("yaml") {
        let reader = fs::File::open(data_path)?;
        data = serde_yaml::from_reader(reader)?;
    } else if ext == OsStr::new("json") {
        let reader = fs::File::open(data_path)?;
        data = serde_json::from_reader(reader)?;
    } else if ext == OsStr::new("toml") {
        let text = files::read_file(data_path)?;
        data = toml::from_str(&text)?;
    } else {
        failure::bail!(
            "Failed to load of data {:?}: unknown file type '{:?}'.\n\
             Supported data files extensions are: yml, yaml, json and toml.",
            data_path,
            ext
        );
    }

    Ok(data)
}

fn insert_data_dir(data: &mut liquid::Object, data_root: &path::Path) -> Result<()> {
    debug!("Loading data from {:?}", data_root);

    let data_files_builder = files::FilesBuilder::new(data_root)?;
    let data_files = data_files_builder.build()?;
    for full_path in data_files.files() {
        let rel_path = full_path
            .strip_prefix(data_root)
            .expect("file was found under the root");

        let file_stem = full_path
            .file_stem()
            .expect("Files will always return with a stem");
        let file_stem = String::from(file_stem.to_str().unwrap());
        let data_fragment = load_data(&full_path)
            .with_context(|_| format!("Loading data from {:?} failed", full_path))?;

        deep_insert(data, rel_path, file_stem, data_fragment)
            .with_context(|_| format!("Merging data into {:?} failed", rel_path))?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>use libc::{c_int, off_t};
use mio::{Evented, Poll, Token, Ready, PollOpt};
use nix;
use nix::sys::aio;
use nix::sys::signal::SigevNotify;
use std::cell::RefCell;
use std::io;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::RawFd;
use std::rc::Rc;

#[derive(Debug)]
pub struct AioCb<'a> {
    // Must use a RefCell because mio::Evented's methods only take immutable
    // references we must use a RefCell here.  Unlike sockets, registering
    // aiocb's requires modifying the aiocb.
    inner: RefCell<aio::AioCb<'a>>
}

/// Wrapper around nix::sys::aio::AioCb.
///
/// Implements mio::Evented.  After creation, use mio::Evented::register to
/// connect to the event loop
impl<'a> AioCb<'a> {
    /// Wraps nix::sys::aio::AioCb::from_fd.
    pub fn from_fd(fd: RawFd, prio: c_int) -> AioCb<'a> {
        let aiocb = aio::AioCb::from_fd(fd, prio, SigevNotify::SigevNone);
        AioCb { inner: RefCell::new(aiocb) }
    }

    /// Wraps nix::sys::aio::AioCb::from_mut_slice.
    pub fn from_boxed_slice(fd: RawFd, offs: off_t, buf: Rc<Box<[u8]>>,
                          prio: c_int, opcode: aio::LioOpcode) -> AioCb<'a>{
        let aiocb = aio::AioCb::from_boxed_slice(fd, offs, buf, prio,
                                               SigevNotify::SigevNone, opcode);
        AioCb { inner: RefCell::new(aiocb) }
    }

    /// Wraps nix::sys::aio::from_slice
    pub fn from_slice(fd: RawFd, offs: off_t, buf: &'a [u8],
                      prio: c_int, opcode: aio::LioOpcode) -> AioCb {
        let aiocb = aio::AioCb::from_slice(fd, offs, buf, prio,
                                           SigevNotify::SigevNone, opcode);
        AioCb { inner: RefCell::new(aiocb) }
    }

    /// Wrapper for nix::sys::aio::aio_return
    pub fn aio_return(&self) -> nix::Result<isize> {
        self.inner.borrow_mut().aio_return()
    }

    /// Wrapper for nix::sys::aio::AioCb::cancel
    pub fn cancel(&self) -> nix::Result<aio::AioCancelStat> {
        self.inner.borrow_mut().cancel()
    }

    /// Wrapper for nix::sys::aio::AioCb::fsync
    pub fn fsync(&self, mode: aio::AioFsyncMode) -> nix::Result<()> {
        self.inner.borrow_mut().fsync(mode)
    }

    /// Wrapper for nix::sys::aio::AioCb::read
    pub fn read(&self) -> nix::Result<()> {
        self.inner.borrow_mut().read()
    }

    /// Wrapper for nix::sys::aio::AioCb::write
    pub fn write(&self) -> nix::Result<()> {
        self.inner.borrow_mut().write()
    }
}

impl<'a> Evented for AioCb<'a> {
    fn register(&self,
                poll: &Poll,
                token: Token,
                events: Ready,
                _: PollOpt) -> io::Result<()> {
        assert!(events.is_aio());
        let udata = usize::from(token);
        let kq = poll.as_raw_fd();
        let sigev = SigevNotify::SigevKevent{kq: kq, udata: udata as isize};
        self.inner.borrow_mut().set_sigev_notify(sigev);
        Ok(())
    }

    fn reregister(&self,
                  poll: &Poll,
                  token: Token,
                  events: Ready,
                  opts: PollOpt) -> io::Result<()> {
        self.register(poll, token, events, opts)
    }

    fn deregister(&self, _: &Poll) -> io::Result<()> {
        let sigev = SigevNotify::SigevNone;
        self.inner.borrow_mut().set_sigev_notify(sigev);
        Ok(())
    }
}
<commit_msg>AioCb must not be moved after submission to the kernel<commit_after>use libc::{c_int, off_t};
use mio::{Evented, Poll, Token, Ready, PollOpt};
use nix;
use nix::sys::aio;
use nix::sys::signal::SigevNotify;
use std::cell::RefCell;
use std::io;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::RawFd;
use std::rc::Rc;

#[derive(Debug)]
pub struct AioCb<'a> {
    // Must use a RefCell because mio::Evented's methods only take immutable
    // references we must use a RefCell here.  Unlike sockets, registering
    // aiocb's requires modifying the aiocb.
    // Must use Box for the AioCb so its location in memory will be constant.
    // It is an error to move a libc::aiocb after passing it to the kernel.
    inner: RefCell<Box<aio::AioCb<'a>>>
}

/// Wrapper around nix::sys::aio::AioCb.
///
/// Implements mio::Evented.  After creation, use mio::Evented::register to
/// connect to the event loop
impl<'a> AioCb<'a> {
    /// Wraps nix::sys::aio::AioCb::from_fd.
    pub fn from_fd(fd: RawFd, prio: c_int) -> AioCb<'a> {
        let aiocb = aio::AioCb::from_fd(fd, prio, SigevNotify::SigevNone);
        AioCb { inner: RefCell::new(Box::new(aiocb)) }
    }

    /// Wraps nix::sys::aio::AioCb::from_mut_slice.
    pub fn from_boxed_slice(fd: RawFd, offs: off_t, buf: Rc<Box<[u8]>>,
                          prio: c_int, opcode: aio::LioOpcode) -> AioCb<'a>{
        let aiocb = aio::AioCb::from_boxed_slice(fd, offs, buf, prio,
                                               SigevNotify::SigevNone, opcode);
        AioCb { inner: RefCell::new(Box::new(aiocb)) }
    }

    /// Wraps nix::sys::aio::from_slice
    pub fn from_slice(fd: RawFd, offs: off_t, buf: &'a [u8],
                      prio: c_int, opcode: aio::LioOpcode) -> AioCb {
        let aiocb = aio::AioCb::from_slice(fd, offs, buf, prio,
                                           SigevNotify::SigevNone, opcode);
        AioCb { inner: RefCell::new(Box::new(aiocb)) }
    }

    /// Wrapper for nix::sys::aio::aio_return
    pub fn aio_return(&self) -> nix::Result<isize> {
        self.inner.borrow_mut().aio_return()
    }

    /// Wrapper for nix::sys::aio::AioCb::cancel
    pub fn cancel(&self) -> nix::Result<aio::AioCancelStat> {
        self.inner.borrow_mut().cancel()
    }

    /// Wrapper for nix::sys::aio::AioCb::fsync
    pub fn fsync(&self, mode: aio::AioFsyncMode) -> nix::Result<()> {
        self.inner.borrow_mut().fsync(mode)
    }

    /// Wrapper for nix::sys::aio::AioCb::read
    pub fn read(&self) -> nix::Result<()> {
        self.inner.borrow_mut().read()
    }

    /// Wrapper for nix::sys::aio::AioCb::write
    pub fn write(&self) -> nix::Result<()> {
        self.inner.borrow_mut().write()
    }
}

impl<'a> Evented for AioCb<'a> {
    fn register(&self,
                poll: &Poll,
                token: Token,
                events: Ready,
                _: PollOpt) -> io::Result<()> {
        assert!(events.is_aio());
        let udata = usize::from(token);
        let kq = poll.as_raw_fd();
        let sigev = SigevNotify::SigevKevent{kq: kq, udata: udata as isize};
        self.inner.borrow_mut().set_sigev_notify(sigev);
        Ok(())
    }

    fn reregister(&self,
                  poll: &Poll,
                  token: Token,
                  events: Ready,
                  opts: PollOpt) -> io::Result<()> {
        self.register(poll, token, events, opts)
    }

    fn deregister(&self, _: &Poll) -> io::Result<()> {
        let sigev = SigevNotify::SigevNone;
        self.inner.borrow_mut().set_sigev_notify(sigev);
        Ok(())
    }
}
<|endoftext|>


<commit_before>// -*- rust -*-

import front.parser;
import front.token;
import front.eval;
import middle.trans;
import middle.resolve;
import middle.typeck;
import util.common;

import std.option;
import std.option.some;
import std.option.none;
import std._str;
import std._vec;

fn default_environment(session.session sess,
                       str argv0,
                       str input) -> eval.env {

    auto libc = "libc.so";
    alt (sess.get_targ_cfg().os) {
        case (session.os_win32) { libc = "msvcrt.dll"; }
        case (session.os_macos) { libc = "libc.dylib"; }
        case (session.os_linux) { libc = "libc.so.6"; }
    }

    ret
        vec(
            // Target bindings.
            tup("target_os", eval.val_str(std.os.target_os())),
            tup("target_arch", eval.val_str("x86")),
            tup("target_libc", eval.val_str(libc)),

            // Build bindings.
            tup("build_compiler", eval.val_str(argv0)),
            tup("build_input", eval.val_str(input))
            );
}

impure fn parse_input(session.session sess,
                      parser.parser p,
                      str input) -> @front.ast.crate {
    if (_str.ends_with(input, ".rc")) {
        ret parser.parse_crate_from_crate_file(p);
    } else if (_str.ends_with(input, ".rs")) {
        ret parser.parse_crate_from_source_file(p);
    }
    sess.err("unknown unput file type: " + input);
    fail;
}

impure fn compile_input(session.session sess,
                        eval.env env,
                        str input, str output,
                        bool shared) {
    auto p = parser.new_parser(sess, env, 0, input);
    auto crate = parse_input(sess, p, input);
    crate = resolve.resolve_crate(sess, crate);
    crate = typeck.check_crate(sess, crate);
    trans.trans_crate(sess, crate, output, shared);
}

fn warn_wrong_compiler() {
    log "This is the rust 'self-hosted' compiler.";
    log "The one written in rust.";
    log "It is currently incomplete.";
    log "You may want rustboot instead, the compiler next door.";
}

fn usage(session.session sess, str argv0) {
    log #fmt("usage: %s [options] <input>", argv0);
    log "options:";
    log "";
    log "    -o <filename>      write output to <filename>";
    log "    -nowarn            suppress wrong-compiler warning";
    log "    -shared            compile a shared-library crate";
    log "    -h                 display this message";
    log "";
    log "";
}

fn get_os() -> session.os {
    auto s = std.os.target_os();
    if (_str.eq(s, "win32")) { ret session.os_win32; }
    if (_str.eq(s, "macos")) { ret session.os_macos; }
    if (_str.eq(s, "linux")) { ret session.os_linux; }
}

impure fn main(vec[str] args) {

    // FIXME: don't hard-wire this.
    auto target_cfg = rec(os = get_os(),
                          arch = session.arch_x86,
                          int_type = common.ty_i32,
                          uint_type = common.ty_u32,
                          float_type = common.ty_f64 );

    auto sess = session.session(target_cfg);
    let option.t[str] input_file = none[str];
    let option.t[str] output_file = none[str];
    let bool do_warn = true;
    let bool shared = false;

    auto i = 1u;
    auto len = _vec.len[str](args);

    // FIXME: a getopt module would be nice.
    while (i < len) {
        auto arg = args.(i);
        if (_str.byte_len(arg) > 0u && arg.(0) == '-' as u8) {
            if (_str.eq(arg, "-nowarn")) {
                do_warn = false;
            } else if (_str.eq(arg, "-shared")) {
                shared = true;
            } else {
                // FIXME: rust could use an elif construct.
                if (_str.eq(arg, "-o")) {
                    if (i+1u < len) {
                        output_file = some(args.(i+1u));
                        i += 1u;
                    } else {
                        usage(sess, args.(0));
                        sess.err("-o requires an argument");
                    }
                } else {
                    if (_str.eq(arg, "-h")) {
                        usage(sess, args.(0));
                    } else {
                        usage(sess, args.(0));
                        sess.err("unrecognized option: " + arg);
                    }
                }
            }
        } else {
            alt (input_file) {
                case (some[str](_)) {
                    usage(sess, args.(0));
                    sess.err("multiple inputs provided");
                }
                case (none[str]) {
                    input_file = some[str](arg);
                }
            }
            // FIXME: dummy node to work around typestate mis-wiring bug.
            i = i;
        }
        i += 1u;
    }

    if (do_warn) {
        warn_wrong_compiler();
    }

    alt (input_file) {
        case (none[str]) {
            usage(sess, args.(0));
            sess.err("no input filename");
        }
        case (some[str](?ifile)) {

            auto env = default_environment(sess, args.(0), ifile);

            alt (output_file) {
                case (none[str]) {
                    let vec[str] parts = _str.split(ifile, '.' as u8);
                    parts = _vec.pop[str](parts);
                    parts += ".bc";
                    auto ofile = _str.concat(parts);
                    compile_input(sess, env, ifile, ofile, shared);
                }
                case (some[str](?ofile)) {
                    compile_input(sess, env, ifile, ofile, shared);
                }
            }
        }
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Flatten conditionals in rustc.rs. Remove FIXME<commit_after>// -*- rust -*-

import front.parser;
import front.token;
import front.eval;
import middle.trans;
import middle.resolve;
import middle.typeck;
import util.common;

import std.option;
import std.option.some;
import std.option.none;
import std._str;
import std._vec;

fn default_environment(session.session sess,
                       str argv0,
                       str input) -> eval.env {

    auto libc = "libc.so";
    alt (sess.get_targ_cfg().os) {
        case (session.os_win32) { libc = "msvcrt.dll"; }
        case (session.os_macos) { libc = "libc.dylib"; }
        case (session.os_linux) { libc = "libc.so.6"; }
    }

    ret
        vec(
            // Target bindings.
            tup("target_os", eval.val_str(std.os.target_os())),
            tup("target_arch", eval.val_str("x86")),
            tup("target_libc", eval.val_str(libc)),

            // Build bindings.
            tup("build_compiler", eval.val_str(argv0)),
            tup("build_input", eval.val_str(input))
            );
}

impure fn parse_input(session.session sess,
                      parser.parser p,
                      str input) -> @front.ast.crate {
    if (_str.ends_with(input, ".rc")) {
        ret parser.parse_crate_from_crate_file(p);
    } else if (_str.ends_with(input, ".rs")) {
        ret parser.parse_crate_from_source_file(p);
    }
    sess.err("unknown unput file type: " + input);
    fail;
}

impure fn compile_input(session.session sess,
                        eval.env env,
                        str input, str output,
                        bool shared) {
    auto p = parser.new_parser(sess, env, 0, input);
    auto crate = parse_input(sess, p, input);
    crate = resolve.resolve_crate(sess, crate);
    crate = typeck.check_crate(sess, crate);
    trans.trans_crate(sess, crate, output, shared);
}

fn warn_wrong_compiler() {
    log "This is the rust 'self-hosted' compiler.";
    log "The one written in rust.";
    log "It is currently incomplete.";
    log "You may want rustboot instead, the compiler next door.";
}

fn usage(session.session sess, str argv0) {
    log #fmt("usage: %s [options] <input>", argv0);
    log "options:";
    log "";
    log "    -o <filename>      write output to <filename>";
    log "    -nowarn            suppress wrong-compiler warning";
    log "    -shared            compile a shared-library crate";
    log "    -h                 display this message";
    log "";
    log "";
}

fn get_os() -> session.os {
    auto s = std.os.target_os();
    if (_str.eq(s, "win32")) { ret session.os_win32; }
    if (_str.eq(s, "macos")) { ret session.os_macos; }
    if (_str.eq(s, "linux")) { ret session.os_linux; }
}

impure fn main(vec[str] args) {

    // FIXME: don't hard-wire this.
    auto target_cfg = rec(os = get_os(),
                          arch = session.arch_x86,
                          int_type = common.ty_i32,
                          uint_type = common.ty_u32,
                          float_type = common.ty_f64 );

    auto sess = session.session(target_cfg);
    let option.t[str] input_file = none[str];
    let option.t[str] output_file = none[str];
    let bool do_warn = true;
    let bool shared = false;

    auto i = 1u;
    auto len = _vec.len[str](args);

    // FIXME: a getopt module would be nice.
    while (i < len) {
        auto arg = args.(i);
        if (_str.byte_len(arg) > 0u && arg.(0) == '-' as u8) {
            if (_str.eq(arg, "-nowarn")) {
                do_warn = false;
            } else if (_str.eq(arg, "-shared")) {
                shared = true;
            } else if (_str.eq(arg, "-o")) {
                if (i+1u < len) {
                    output_file = some(args.(i+1u));
                    i += 1u;
                } else {
                    usage(sess, args.(0));
                    sess.err("-o requires an argument");
                }
            } else if (_str.eq(arg, "-h")) {
                usage(sess, args.(0));
            } else {
                usage(sess, args.(0));
                sess.err("unrecognized option: " + arg);
            }
        } else {
            alt (input_file) {
                case (some[str](_)) {
                    usage(sess, args.(0));
                    sess.err("multiple inputs provided");
                }
                case (none[str]) {
                    input_file = some[str](arg);
                }
            }
            // FIXME: dummy node to work around typestate mis-wiring bug.
            i = i;
        }
        i += 1u;
    }

    if (do_warn) {
        warn_wrong_compiler();
    }

    alt (input_file) {
        case (none[str]) {
            usage(sess, args.(0));
            sess.err("no input filename");
        }
        case (some[str](?ifile)) {

            auto env = default_environment(sess, args.(0), ifile);

            alt (output_file) {
                case (none[str]) {
                    let vec[str] parts = _str.split(ifile, '.' as u8);
                    parts = _vec.pop[str](parts);
                    parts += ".bc";
                    auto ofile = _str.concat(parts);
                    compile_input(sess, env, ifile, ofile, shared);
                }
                case (some[str](?ofile)) {
                    compile_input(sess, env, ifile, ofile, shared);
                }
            }
        }
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>pub type Map = ~[Block];

pub type Block = ~[Cell];

pub struct Cell {
    graphic: u16,
    altitude: i8,
}

const BLOCK_SIZE: uint = 196;
const OFFSET: uint = 4;

pub struct MapReader {
    data_reader: io::Reader
}

impl MapReader {

    /**
     * Read a specific block from a map
     */
    fn read_block(&self, id: uint) -> Block {
        //Cycle to id * 196 + Offset
        self.data_reader.seek(((id * BLOCK_SIZE) + OFFSET) as int, io::SeekSet);
        let map_reader = self.data_reader as io::ReaderUtil;
        //Read the 64 cells
        let mut block: Block = ~[];
        //Read 64 cells
        for uint::range(0, 64) |_index| {
            block.push(Cell{
                graphic: map_reader.read_le_u16(),
                altitude: map_reader.read_i8()
            });
        }
        block
    }

    /**
     * Read the whole map!
     */
    fn read_map(&self, max_blocks: uint) -> Map {
        let mut map: Map = ~[];
        let mut index = 0;
        while index < max_blocks {
            map.push(self.read_block(index));
            index += 1;
        }
        map
    }
}

/**
 * Create a handle to a mapreader, and read out given blocks as needed
 */
pub fn MapReader(path: ~str) -> result::Result<MapReader, ~str> {
    let mul_path: path::Path = path::Path(path);
    match io::file_reader(&mul_path) {
        result::Ok(data_reader) => {
            result::Ok(MapReader {
                data_reader: data_reader
            })
        },
        result::Err(error_message) => {
            result::Err(error_message)
        }
    }
}
<commit_msg>Started working on Static importation<commit_after>pub type Map = ~[Block];

pub type Block = ~[Cell];

pub struct Cell {
    graphic: u16,
    altitude: i8,
}

pub type Statics = ~[StaticLocation];

pub struct StaticLocation {
    object_id: u16,
    x: u8,
    y: u8,
    altitude: i8,
    remainder: u16
}

const BLOCK_SIZE: uint = 196;
const OFFSET: uint = 4;

pub struct MapReader {
    data_reader: io::Reader
}

impl MapReader {

    /**
     * Read a specific block from a map
     */
    fn read_block(&self, id: uint) -> Block {
        //Cycle to id * 196 + Offset
        self.data_reader.seek(((id * BLOCK_SIZE) + OFFSET) as int, io::SeekSet);
        let map_reader = self.data_reader as io::ReaderUtil;
        //Read the 64 cells
        let mut block: Block = ~[];
        //Read 64 cells
        for uint::range(0, 64) |_index| {
            block.push(Cell{
                graphic: map_reader.read_le_u16(),
                altitude: map_reader.read_i8()
            });
        }
        block
    }

    /**
     * Read the whole map!
     */
    fn read_map(&self, max_blocks: uint) -> Map {
        let mut map: Map = ~[];
        let mut index = 0;
        while index < max_blocks {
            map.push(self.read_block(index));
            index += 1;
        }
        map
    }
}

/**
 * Create a handle to a mapreader, and read out given blocks as needed
 */
pub fn MapReader(path: ~str) -> result::Result<MapReader, ~str> {
    let mul_path: path::Path = path::Path(path);
    match io::file_reader(&mul_path) {
        result::Ok(data_reader) => {
            result::Ok(MapReader {
                data_reader: data_reader
            })
        },
        result::Err(error_message) => {
            result::Err(error_message)
        }
    }
}

pub struct StaticReader {
    mul_reader: mul_reader::MulReader
}

impl StaticReader {
    fn read_block(&self, id: uint) -> option::Option(Statics) {
        match self.mul_reader.read(id) {
            option::Some(record) => {
                assert record.len % 7 == 0;
                //TODO: Read the actual gumpf
            }
            option::None => {
                option::None
            }
        }
    }
}

pub fn StaticReader(index_path: &path::Path, mul_path: &path::Path) -> result::Result<StaticReader, ~str> {
    match mul_reader::MulReader(index_path, mul_path) {
        result::Err(message) => result::Err(message),
        result::Ok(mul_reader) => {
            result::Ok(StaticReader{
                mul_reader: mul_reader
            })
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{Error, ErrorKind};
use std::net::SocketAddr;

use super::router::{Router};

use futures::{Future, Sink};
use futures::stream::{Stream};
use json::{parse as parse_json};
use tokio_core::net::{TcpListener};
use tokio_core::reactor::{Core};
use tokio_tungstenite::{accept_async};
use tungstenite::protocol::{Message};

pub struct Proxy {
    router: Box<Router>,
}

impl Proxy {
    pub fn new(router: Box<Router>) -> Proxy {
        Proxy {
            router: router
        }
    }

    pub fn run(&self, address: SocketAddr) {
        let mut core = Core::new().unwrap();
        let handle = core.handle();
        let socket = TcpListener::bind(&address, &handle).unwrap();
        println!("Listening on: {}", address);

        // The server loop.
        let server = socket.incoming().for_each(|(stream, addr)| {
            let handle_inner = handle.clone();

            // Handler per each connection.
            accept_async(stream)
                .map_err(|err| {
                    println!("Occurred error during the WebSocket handshake: {}", err);
                    Error::new(ErrorKind::Other, err)
                })
                // Check the Auth header
                .and_then(move |ws_stream| {
                    println!("Checking the user's token");
                    Ok(ws_stream)
                })
                // Process the message
                .and_then(move |ws_stream| {
                    ws_stream.for_each(move |message: Message| {
                        // Convert message into text
                        // After it try to parse into JSON
                        // Convert specified API url to a Kafka topic
                        println!("Message: {}", message);
                        Ok(())
                    }).map_err(|err| {
                        println!("Occurred error during the processing a message: {}", err);
                        Error::new(ErrorKind::InvalidData, err)
                    })
                })
        });

        // Run the server
        core.run(server).unwrap();
    }
}
<commit_msg>Implemented parsing message into JSON objects<commit_after>use std::io::{Error, ErrorKind};
use std::net::SocketAddr;
use std::result::{Result as BaseResult};

use super::router::{Router};

use futures::{Future, Sink};
use futures::stream::{Stream};
use json::{parse as parse_json, JsonValue};
use tokio_core::net::{TcpListener};
use tokio_core::reactor::{Core};
use tokio_tungstenite::{accept_async};
use tungstenite::protocol::{Message};

pub struct Proxy {
    router: Box<Router>,
}

impl Proxy {
    pub fn new(router: Box<Router>) -> Proxy {
        Proxy {
            router: router
        }
    }

    pub fn run(&self, address: SocketAddr) {
        let mut core = Core::new().unwrap();
        let handle = core.handle();
        let socket = TcpListener::bind(&address, &handle).unwrap();
        println!("Listening on: {}", address);

        // The server loop.
        let server = socket.incoming().for_each(|(stream, addr)| {
            let proxy_inner = self;

            // Handler per each connection.
            accept_async(stream)
                .map_err(|err| {
                    println!("Occurred error during the WebSocket handshake: {}", err);
                    Error::new(ErrorKind::Other, err)
                })
                // Check the Auth header
                .and_then(move |ws_stream| {
                    println!("Checking the user's token");
                    Ok(ws_stream)
                })
                // Process the messages
                .and_then(move |ws_stream| {
                    // Per each message
                    ws_stream.for_each(move |message: Message| {
                        // Convert an incoming message into JSON
                        let text_message = try!(message.into_text());
                        let json_message = try!(proxy_inner.decode_message(text_message.as_str()));

                        // Convert the specified API url to a Kafka topic
                        println!("Message = {}", json_message);
                        Ok(())
                    })
                    .map_err(|err| {
                        println!("Occurred error during the processing a message: {}", err);
                        Error::new(ErrorKind::Other, err)
                    })
                })
        });

        // Run the server
        core.run(server).unwrap();
    }

    fn decode_message(&self, message: &str) -> BaseResult<JsonValue, Error> {
        match parse_json(message) {
            Ok(message) => Ok(message),
            Err(err) => Err(Error::new(ErrorKind::InvalidData, err))
        }
    }
}
<|endoftext|>


<commit_before>// Example of how to cancel a blocking Context operation from another
// thread.

extern crate pcsc;

use std::sync::Arc;
use std::time::Duration;

use pcsc::*;

fn wait_for_enter_keypress() {
    use std::io::Read;
    let mut stdin = std::io::stdin();
    let _ = stdin.read(&mut [0]).expect("failed to read key");
}

fn main() {
    // Get a context.
    let ctx = Arc::new(Context::establish(Scope::User).expect("failed to establish context"));

    // Spawn a thread which waits for a key-press then cancels the operation.
    // In this case, we could have used a scoped thread instead of Arc.
    {
        let ctx = Arc::downgrade(&ctx);
        std::thread::spawn(move || {
            wait_for_enter_keypress();
            ctx.upgrade().map(|ctx| ctx.cancel().expect("failed to cancel"));
        });
    }

    // Set up the blocking call, and wait for cancel or timeout.
    println!("Entering blocking call; press Enter to cancel");
    let mut reader_states = vec![
        ReaderState::new(PNP_NOTIFICATION(), State::UNAWARE),
    ];
    match ctx.get_status_change(Duration::from_secs(5), &mut reader_states) {
        Ok(()) => {
            println!("Blocking call exited normally");
        }
        Err(Error::Cancelled) => {
            println!("Blocking call canceled");
        }
        Err(Error::Timeout) => {
            println!("Blocking call timed out");
        }
        Err(error) => {
            panic!("failed to get status changes: {:?}", error);
        }
    }
}
<commit_msg>pcsc/examples: simplify cancel example<commit_after>// Example of how to cancel a blocking Context operation from another
// thread.

extern crate pcsc;

use std::time::Duration;

use pcsc::*;

fn wait_for_enter_keypress() {
    use std::io::Read;
    let mut stdin = std::io::stdin();
    let _ = stdin.read(&mut [0]).expect("failed to read key");
}

fn main() {
    // Get a context.
    let ctx = Context::establish(Scope::User).expect("failed to establish context");

    // Spawn a thread which waits for a key-press then cancels the operation.
    {
        let ctx = ctx.clone();
        std::thread::spawn(move || {
            wait_for_enter_keypress();
            ctx.cancel().expect("failed to cancel");
        });
    }

    // Set up the blocking call, and wait for cancel or timeout.
    println!("Entering blocking call; press Enter to cancel");
    let mut reader_states = vec![
        ReaderState::new(PNP_NOTIFICATION(), State::UNAWARE),
    ];
    match ctx.get_status_change(Duration::from_secs(5), &mut reader_states) {
        Ok(()) => {
            println!("Blocking call exited normally");
        }
        Err(Error::Cancelled) => {
            println!("Blocking call canceled");
        }
        Err(Error::Timeout) => {
            println!("Blocking call timed out");
        }
        Err(error) => {
            panic!("failed to get status changes: {:?}", error);
        }
    }
}
<|endoftext|>