<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

use {REMOTE, bincode};
use future::server::Response;
use futures::{self, Future, future};
use protocol::Proto;
use serde::Serialize;
use serde::de::DeserializeOwned;
use std::fmt;
use std::io;
use std::net::SocketAddr;
use stream_type::StreamType;
use tokio_core::net::TcpStream;
use tokio_core::reactor;
use tokio_proto::BindClient as ProtoBindClient;
use tokio_proto::multiplex::ClientService;
use tokio_service::Service;

cfg_if! {
    if #[cfg(feature = "tls")] {
        use errors::native_to_io;
        use tls::client::Context;
        use tokio_tls::TlsConnectorExt;
    } else {}
}

/// Additional options to configure how the client connects and operates.
#[derive(Debug)]
pub struct Options {
    /// Max packet size in bytes.
    max_payload_size: u64,
    reactor: Option<Reactor>,
    #[cfg(feature = "tls")]
    tls_ctx: Option<Context>,
}

impl Default for Options {
    #[cfg(feature = "tls")]
    fn default() -> Self {
        Options {
            max_payload_size: 2 << 20,
            reactor: None,
            tls_ctx: None,
        }
    }

    #[cfg(not(feature = "tls"))]
    fn default() -> Self {
        Options {
            max_payload_size: 2 << 20,
            reactor: None,
        }
    }
}

impl Options {
    /// Set the max payload size in bytes. The default is 2 << 20 (2 MiB).
    pub fn max_payload_size(mut self, bytes: u64) -> Self {
        self.max_payload_size = bytes;
        self
    }

    /// Drive using the given reactor handle.
    pub fn handle(mut self, handle: reactor::Handle) -> Self {
        self.reactor = Some(Reactor::Handle(handle));
        self
    }

    /// Drive using the given reactor remote.
    pub fn remote(mut self, remote: reactor::Remote) -> Self {
        self.reactor = Some(Reactor::Remote(remote));
        self
    }

    /// Connect using the given `Context`
    #[cfg(feature = "tls")]
    pub fn tls(mut self, tls_ctx: Context) -> Self {
        self.tls_ctx = Some(tls_ctx);
        self
    }
}

enum Reactor {
    Handle(reactor::Handle),
    Remote(reactor::Remote),
}

impl fmt::Debug for Reactor {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        const HANDLE: &'static &str = &"Reactor::Handle";
        const HANDLE_INNER: &'static &str = &"Handle { .. }";
        const REMOTE: &'static &str = &"Reactor::Remote";
        const REMOTE_INNER: &'static &str = &"Remote { .. }";

        match *self {
            Reactor::Handle(_) => f.debug_tuple(HANDLE).field(HANDLE_INNER).finish(),
            Reactor::Remote(_) => f.debug_tuple(REMOTE).field(REMOTE_INNER).finish(),
        }
    }
}
#[doc(hidden)]
pub struct Client<Req, Resp, E>
where
    Req: Serialize + 'static,
    Resp: DeserializeOwned + 'static,
    E: DeserializeOwned + 'static,
{
    inner: ClientService<StreamType, Proto<Req, Response<Resp, E>>>,
}

impl<Req, Resp, E> Clone for Client<Req, Resp, E>
where
    Req: Serialize + 'static,
    Resp: DeserializeOwned + 'static,
    E: DeserializeOwned + 'static,
{
    fn clone(&self) -> Self {
        Client {
            inner: self.inner.clone(),
        }
    }
}

impl<Req, Resp, E> Service for Client<Req, Resp, E>
where
    Req: Serialize + Send + 'static,
    Resp: DeserializeOwned + Send + 'static,
    E: DeserializeOwned + Send + 'static,
{
    type Request = Req;
    type Response = Resp;
    type Error = ::Error<E>;
    type Future = ResponseFuture<Req, Resp, E>;

    fn call(&self, request: Self::Request) -> Self::Future {
        fn identity<T>(t: T) -> T {
            t
        }
        self.inner
            .call(request)
            .map(Self::map_err as _)
            .map_err(::Error::from as _)
            .and_then(identity as _)
    }
}

impl<Req, Resp, E> Client<Req, Resp, E>
where
    Req: Serialize + 'static,
    Resp: DeserializeOwned + 'static,
    E: DeserializeOwned + 'static,
{
    fn bind(handle: &reactor::Handle, tcp: StreamType, max_payload_size: u64) -> Self
    where
        Req: Serialize + Send + 'static,
        Resp: DeserializeOwned + Send + 'static,
        E: DeserializeOwned + Send + 'static,
    {
        let inner = Proto::new(max_payload_size).bind_client(handle, tcp);
        Client { inner }
    }

    fn map_err(resp: WireResponse<Resp, E>) -> Result<Resp, ::Error<E>> {
        resp.map(|r| r.map_err(::Error::from))
            .map_err(::Error::ResponseDeserialize)
            .and_then(|r| r)
    }
}

impl<Req, Resp, E> fmt::Debug for Client<Req, Resp, E>
where
    Req: Serialize + 'static,
    Resp: DeserializeOwned + 'static,
    E: DeserializeOwned + 'static,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Client {{ .. }}")
    }
}

/// Extension methods for clients.
pub trait ClientExt: Sized {
    /// The type of the future returned when calling `connect`.
    type ConnectFut: Future<Item = Self, Error = io::Error>;

    /// Connects to a server located at the given address, using the given options.
    fn connect(addr: SocketAddr, options: Options) -> Self::ConnectFut;
}

/// A future that resolves to a `Client` or an `io::Error`.
pub type ConnectFuture<Req, Resp, E> = futures::Flatten<
    futures::MapErr<
        futures::Oneshot<io::Result<Client<Req, Resp, E>>>,
        fn(futures::Canceled) -> io::Error,
    >,
>;

impl<Req, Resp, E> ClientExt for Client<Req, Resp, E>
where
    Req: Serialize + Send + 'static,
    Resp: DeserializeOwned + Send + 'static,
    E: DeserializeOwned + Send + 'static,
{
    type ConnectFut = ConnectFuture<Req, Resp, E>;

    fn connect(addr: SocketAddr, options: Options) -> Self::ConnectFut {
        // we need to do this for tls because we need to avoid moving the entire `Options`
        // struct into the `setup` closure, since `Reactor` is not `Send`.
        #[cfg(feature = "tls")]
        let mut options = options;
        #[cfg(feature = "tls")]
        let tls_ctx = options.tls_ctx.take();

        let max_payload_size = options.max_payload_size;

        let connect = move |handle: &reactor::Handle| {
            let handle2 = handle.clone();
            TcpStream::connect(&addr, handle)
                .and_then(move |socket| {
                    // TODO(https://github.com/tokio-rs/tokio-proto/issues/132): move this into the
                    // ServerProto impl
                    #[cfg(feature = "tls")]
                    match tls_ctx {
                        Some(tls_ctx) => {
                            future::Either::A(
                                tls_ctx
                                    .tls_connector
                                    .connect_async(&tls_ctx.domain, socket)
                                    .map(StreamType::Tls)
                                    .map_err(native_to_io),
                            )
                        }
                        None => future::Either::B(future::ok(StreamType::Tcp(socket))),
                    }
                    #[cfg(not(feature = "tls"))] future::ok(StreamType::Tcp(socket))
                })
                .map(move |tcp| Client::bind(&handle2, tcp, max_payload_size))
        };
        let (tx, rx) = futures::oneshot();
        let setup = move |handle: &reactor::Handle| {
            connect(handle).then(move |result| {
                // If send fails it means the client no longer cared about connecting.
                let _ = tx.send(result);
                Ok(())
            })
        };

        match options.reactor {
            Some(Reactor::Handle(handle)) => {
                handle.spawn(setup(&handle));
            }
            Some(Reactor::Remote(remote)) => {
                remote.spawn(setup);
            }
            None => {
                REMOTE.spawn(setup);
            }
        }
        fn panic(canceled: futures::Canceled) -> io::Error {
            unreachable!(canceled)
        }
        rx.map_err(panic as _).flatten()
    }
}

type ResponseFuture<Req, Resp, E> =
    futures::AndThen<futures::MapErr<
    futures::Map<<ClientService<StreamType, Proto<Req, Response<Resp, E>>> as Service>::Future,
                 fn(WireResponse<Resp, E>) -> Result<Resp, ::Error<E>>>,
        fn(io::Error) -> ::Error<E>>,
                 Result<Resp, ::Error<E>>,
                 fn(Result<Resp, ::Error<E>>) -> Result<Resp, ::Error<E>>>;

type WireResponse<R, E> = Result<Response<R, E>, bincode::Error>;
<commit_msg>Drop more 'static lifetimes<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

use {REMOTE, bincode};
use future::server::Response;
use futures::{self, Future, future};
use protocol::Proto;
use serde::Serialize;
use serde::de::DeserializeOwned;
use std::fmt;
use std::io;
use std::net::SocketAddr;
use stream_type::StreamType;
use tokio_core::net::TcpStream;
use tokio_core::reactor;
use tokio_proto::BindClient as ProtoBindClient;
use tokio_proto::multiplex::ClientService;
use tokio_service::Service;

cfg_if! {
    if #[cfg(feature = "tls")] {
        use errors::native_to_io;
        use tls::client::Context;
        use tokio_tls::TlsConnectorExt;
    } else {}
}

/// Additional options to configure how the client connects and operates.
#[derive(Debug)]
pub struct Options {
    /// Max packet size in bytes.
    max_payload_size: u64,
    reactor: Option<Reactor>,
    #[cfg(feature = "tls")]
    tls_ctx: Option<Context>,
}

impl Default for Options {
    #[cfg(feature = "tls")]
    fn default() -> Self {
        Options {
            max_payload_size: 2 << 20,
            reactor: None,
            tls_ctx: None,
        }
    }

    #[cfg(not(feature = "tls"))]
    fn default() -> Self {
        Options {
            max_payload_size: 2 << 20,
            reactor: None,
        }
    }
}

impl Options {
    /// Set the max payload size in bytes. The default is 2 << 20 (2 MiB).
    pub fn max_payload_size(mut self, bytes: u64) -> Self {
        self.max_payload_size = bytes;
        self
    }

    /// Drive using the given reactor handle.
    pub fn handle(mut self, handle: reactor::Handle) -> Self {
        self.reactor = Some(Reactor::Handle(handle));
        self
    }

    /// Drive using the given reactor remote.
    pub fn remote(mut self, remote: reactor::Remote) -> Self {
        self.reactor = Some(Reactor::Remote(remote));
        self
    }

    /// Connect using the given `Context`
    #[cfg(feature = "tls")]
    pub fn tls(mut self, tls_ctx: Context) -> Self {
        self.tls_ctx = Some(tls_ctx);
        self
    }
}

enum Reactor {
    Handle(reactor::Handle),
    Remote(reactor::Remote),
}

impl fmt::Debug for Reactor {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        const HANDLE: &str = "Reactor::Handle";
        const HANDLE_INNER: &str = "Handle { .. }";
        const REMOTE: &str = "Reactor::Remote";
        const REMOTE_INNER: &str = "Remote { .. }";

        match *self {
            Reactor::Handle(_) => f.debug_tuple(HANDLE).field(&HANDLE_INNER).finish(),
            Reactor::Remote(_) => f.debug_tuple(REMOTE).field(&REMOTE_INNER).finish(),
        }
    }
}

#[doc(hidden)]
pub struct Client<Req, Resp, E>
where
    Req: Serialize + 'static,
    Resp: DeserializeOwned + 'static,
    E: DeserializeOwned + 'static,
{
    inner: ClientService<StreamType, Proto<Req, Response<Resp, E>>>,
}

impl<Req, Resp, E> Clone for Client<Req, Resp, E>
where
    Req: Serialize + 'static,
    Resp: DeserializeOwned + 'static,
    E: DeserializeOwned + 'static,
{
    fn clone(&self) -> Self {
        Client {
            inner: self.inner.clone(),
        }
    }
}

impl<Req, Resp, E> Service for Client<Req, Resp, E>
where
    Req: Serialize + Send + 'static,
    Resp: DeserializeOwned + Send + 'static,
    E: DeserializeOwned + Send + 'static,
{
    type Request = Req;
    type Response = Resp;
    type Error = ::Error<E>;
    type Future = ResponseFuture<Req, Resp, E>;

    fn call(&self, request: Self::Request) -> Self::Future {
        fn identity<T>(t: T) -> T {
            t
        }
        self.inner
            .call(request)
            .map(Self::map_err as _)
            .map_err(::Error::from as _)
            .and_then(identity as _)
    }
}

impl<Req, Resp, E> Client<Req, Resp, E>
where
    Req: Serialize + 'static,
    Resp: DeserializeOwned + 'static,
    E: DeserializeOwned + 'static,
{
    fn bind(handle: &reactor::Handle, tcp: StreamType, max_payload_size: u64) -> Self
    where
        Req: Serialize + Send + 'static,
        Resp: DeserializeOwned + Send + 'static,
        E: DeserializeOwned + Send + 'static,
    {
        let inner = Proto::new(max_payload_size).bind_client(handle, tcp);
        Client { inner }
    }

    fn map_err(resp: WireResponse<Resp, E>) -> Result<Resp, ::Error<E>> {
        resp.map(|r| r.map_err(::Error::from))
            .map_err(::Error::ResponseDeserialize)
            .and_then(|r| r)
    }
}

impl<Req, Resp, E> fmt::Debug for Client<Req, Resp, E>
where
    Req: Serialize + 'static,
    Resp: DeserializeOwned + 'static,
    E: DeserializeOwned + 'static,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Client {{ .. }}")
    }
}

/// Extension methods for clients.
pub trait ClientExt: Sized {
    /// The type of the future returned when calling `connect`.
    type ConnectFut: Future<Item = Self, Error = io::Error>;

    /// Connects to a server located at the given address, using the given options.
    fn connect(addr: SocketAddr, options: Options) -> Self::ConnectFut;
}

/// A future that resolves to a `Client` or an `io::Error`.
pub type ConnectFuture<Req, Resp, E> = futures::Flatten<
    futures::MapErr<
        futures::Oneshot<io::Result<Client<Req, Resp, E>>>,
        fn(futures::Canceled) -> io::Error,
    >,
>;

impl<Req, Resp, E> ClientExt for Client<Req, Resp, E>
where
    Req: Serialize + Send + 'static,
    Resp: DeserializeOwned + Send + 'static,
    E: DeserializeOwned + Send + 'static,
{
    type ConnectFut = ConnectFuture<Req, Resp, E>;

    fn connect(addr: SocketAddr, options: Options) -> Self::ConnectFut {
        // we need to do this for tls because we need to avoid moving the entire `Options`
        // struct into the `setup` closure, since `Reactor` is not `Send`.
        #[cfg(feature = "tls")]
        let mut options = options;
        #[cfg(feature = "tls")]
        let tls_ctx = options.tls_ctx.take();

        let max_payload_size = options.max_payload_size;

        let connect = move |handle: &reactor::Handle| {
            let handle2 = handle.clone();
            TcpStream::connect(&addr, handle)
                .and_then(move |socket| {
                    // TODO(https://github.com/tokio-rs/tokio-proto/issues/132): move this into the
                    // ServerProto impl
                    #[cfg(feature = "tls")]
                    match tls_ctx {
                        Some(tls_ctx) => {
                            future::Either::A(
                                tls_ctx
                                    .tls_connector
                                    .connect_async(&tls_ctx.domain, socket)
                                    .map(StreamType::Tls)
                                    .map_err(native_to_io),
                            )
                        }
                        None => future::Either::B(future::ok(StreamType::Tcp(socket))),
                    }
                    #[cfg(not(feature = "tls"))] future::ok(StreamType::Tcp(socket))
                })
                .map(move |tcp| Client::bind(&handle2, tcp, max_payload_size))
        };
        let (tx, rx) = futures::oneshot();
        let setup = move |handle: &reactor::Handle| {
            connect(handle).then(move |result| {
                // If send fails it means the client no longer cared about connecting.
                let _ = tx.send(result);
                Ok(())
            })
        };

        match options.reactor {
            Some(Reactor::Handle(handle)) => {
                handle.spawn(setup(&handle));
            }
            Some(Reactor::Remote(remote)) => {
                remote.spawn(setup);
            }
            None => {
                REMOTE.spawn(setup);
            }
        }
        fn panic(canceled: futures::Canceled) -> io::Error {
            unreachable!(canceled)
        }
        rx.map_err(panic as _).flatten()
    }
}

type ResponseFuture<Req, Resp, E> =
    futures::AndThen<futures::MapErr<
    futures::Map<<ClientService<StreamType, Proto<Req, Response<Resp, E>>> as Service>::Future,
                 fn(WireResponse<Resp, E>) -> Result<Resp, ::Error<E>>>,
        fn(io::Error) -> ::Error<E>>,
                 Result<Resp, ::Error<E>>,
                 fn(Result<Resp, ::Error<E>>) -> Result<Resp, ::Error<E>>>;

type WireResponse<R, E> = Result<Response<R, E>, bincode::Error>;
<|endoftext|>


<commit_before>use alloc::arc::{Arc, Weak};
use collections::{BTreeMap, VecDeque};
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};

use sync::WaitCondition;
use syscall::error::{Error, Result, EBADF, EPIPE};
use syscall::scheme::Scheme;

/// Pipes list
pub static PIPE_SCHEME_ID: AtomicUsize = ATOMIC_USIZE_INIT;
static PIPE_NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
static PIPES: Once<RwLock<(BTreeMap<usize, PipeRead>, BTreeMap<usize, PipeWrite>)>> = Once::new();

/// Initialize pipes, called if needed
fn init_pipes() -> RwLock<(BTreeMap<usize, PipeRead>, BTreeMap<usize, PipeWrite>)> {
    RwLock::new((BTreeMap::new(), BTreeMap::new()))
}

/// Get the global pipes list, const
fn pipes() -> RwLockReadGuard<'static, (BTreeMap<usize, PipeRead>, BTreeMap<usize, PipeWrite>)> {
    PIPES.call_once(init_pipes).read()
}

/// Get the global schemes list, mutable
fn pipes_mut() -> RwLockWriteGuard<'static, (BTreeMap<usize, PipeRead>, BTreeMap<usize, PipeWrite>)> {
    PIPES.call_once(init_pipes).write()
}

pub fn pipe(_flags: usize) -> (usize, usize) {
    let mut pipes = pipes_mut();
    let read_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
    let write_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
    let read = PipeRead::new();
    let write = PipeWrite::new(&read);
    pipes.0.insert(read_id, read);
    pipes.1.insert(write_id, write);
    (read_id, write_id)
}

pub struct PipeScheme;

impl Scheme for PipeScheme {
    fn dup(&self, id: usize) -> Result<usize> {
        let mut pipes = pipes_mut();

        let read_option = pipes.0.get(&id).map(|pipe| pipe.clone());
        if let Some(pipe) = read_option {
            let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
            pipes.0.insert(pipe_id, pipe);
            return Ok(pipe_id);
        }

        let write_option = pipes.1.get(&id).map(|pipe| pipe.clone());
        if let Some(pipe) = write_option {
            let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
            pipes.1.insert(pipe_id, pipe);
            return Ok(pipe_id);
        }

        Err(Error::new(EBADF))
    }

    fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
        let pipe_option = {
            let pipes = pipes();
            pipes.0.get(&id).map(|pipe| pipe.clone())
        };

        if let Some(pipe) = pipe_option {
            pipe.read(buf)
        } else {
            Err(Error::new(EBADF))
        }
    }

    fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
        let pipe_option = {
            let pipes = pipes();
            pipes.1.get(&id).map(|pipe| pipe.clone())
        };

        if let Some(pipe) = pipe_option {
            pipe.write(buf)
        } else {
            Err(Error::new(EBADF))
        }
    }

    fn fsync(&self, _id: usize) -> Result<usize> {
        Ok(0)
    }

    fn close(&self, id: usize) -> Result<usize> {
        let mut pipes = pipes_mut();

        drop(pipes.0.remove(&id));
        drop(pipes.1.remove(&id));

        Ok(0)
    }
}

/// Read side of a pipe
#[derive(Clone)]
pub struct PipeRead {
    condition: Arc<WaitCondition>,
    vec: Arc<Mutex<VecDeque<u8>>>
}

impl PipeRead {
    pub fn new() -> Self {
        PipeRead {
            condition: Arc::new(WaitCondition::new()),
            vec: Arc::new(Mutex::new(VecDeque::new())),
        }
    }

    fn read(&self, buf: &mut [u8]) -> Result<usize> {
        loop {
            {
                let mut vec = self.vec.lock();

                let mut i = 0;
                while i < buf.len() {
                    if let Some(b) = vec.pop_front() {
                        buf[i] = b;
                        i += 1;
                    } else {
                        break;
                    }
                }

                if i > 0 {
                    return Ok(i);
                }
            }

            if Arc::weak_count(&self.vec) == 0 {
                return Ok(0);
            } else {
                self.condition.wait();
            }
        }
    }
}

/// Read side of a pipe
#[derive(Clone)]
pub struct PipeWrite {
    condition: Arc<WaitCondition>,
    vec: Weak<Mutex<VecDeque<u8>>>
}

impl PipeWrite {
    pub fn new(read: &PipeRead) -> Self {
        PipeWrite {
            condition: read.condition.clone(),
            vec: Arc::downgrade(&read.vec),
        }
    }

    fn write(&self, buf: &[u8]) -> Result<usize> {
        if let Some(vec_lock) = self.vec.upgrade() {
            let mut vec = vec_lock.lock();

            for &b in buf.iter() {
                vec.push_back(b);
            }

            self.condition.notify();

            Ok(buf.len())
        } else {
            Err(Error::new(EPIPE))
        }
    }
}

impl Drop for PipeWrite {
    fn drop(&mut self) {
        self.condition.notify();
    }
}
<commit_msg>Allow O_NONBLOCK to be passed to pipe<commit_after>use alloc::arc::{Arc, Weak};
use collections::{BTreeMap, VecDeque};
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};

use sync::WaitCondition;
use syscall::error::{Error, Result, EBADF, EPIPE};
use syscall::flag::O_NONBLOCK;
use syscall::scheme::Scheme;

/// Pipes list
pub static PIPE_SCHEME_ID: AtomicUsize = ATOMIC_USIZE_INIT;
static PIPE_NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
static PIPES: Once<RwLock<(BTreeMap<usize, PipeRead>, BTreeMap<usize, PipeWrite>)>> = Once::new();

/// Initialize pipes, called if needed
fn init_pipes() -> RwLock<(BTreeMap<usize, PipeRead>, BTreeMap<usize, PipeWrite>)> {
    RwLock::new((BTreeMap::new(), BTreeMap::new()))
}

/// Get the global pipes list, const
fn pipes() -> RwLockReadGuard<'static, (BTreeMap<usize, PipeRead>, BTreeMap<usize, PipeWrite>)> {
    PIPES.call_once(init_pipes).read()
}

/// Get the global schemes list, mutable
fn pipes_mut() -> RwLockWriteGuard<'static, (BTreeMap<usize, PipeRead>, BTreeMap<usize, PipeWrite>)> {
    PIPES.call_once(init_pipes).write()
}

pub fn pipe(flags: usize) -> (usize, usize) {
    let mut pipes = pipes_mut();
    let read_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
    let write_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
    let read = PipeRead::new(flags);
    let write = PipeWrite::new(&read);
    pipes.0.insert(read_id, read);
    pipes.1.insert(write_id, write);
    (read_id, write_id)
}

pub struct PipeScheme;

impl Scheme for PipeScheme {
    fn dup(&self, id: usize) -> Result<usize> {
        let mut pipes = pipes_mut();

        let read_option = pipes.0.get(&id).map(|pipe| pipe.clone());
        if let Some(pipe) = read_option {
            let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
            pipes.0.insert(pipe_id, pipe);
            return Ok(pipe_id);
        }

        let write_option = pipes.1.get(&id).map(|pipe| pipe.clone());
        if let Some(pipe) = write_option {
            let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
            pipes.1.insert(pipe_id, pipe);
            return Ok(pipe_id);
        }

        Err(Error::new(EBADF))
    }

    fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
        let pipe_option = {
            let pipes = pipes();
            pipes.0.get(&id).map(|pipe| pipe.clone())
        };

        if let Some(pipe) = pipe_option {
            pipe.read(buf)
        } else {
            Err(Error::new(EBADF))
        }
    }

    fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
        let pipe_option = {
            let pipes = pipes();
            pipes.1.get(&id).map(|pipe| pipe.clone())
        };

        if let Some(pipe) = pipe_option {
            pipe.write(buf)
        } else {
            Err(Error::new(EBADF))
        }
    }

    fn fsync(&self, _id: usize) -> Result<usize> {
        Ok(0)
    }

    fn close(&self, id: usize) -> Result<usize> {
        let mut pipes = pipes_mut();

        drop(pipes.0.remove(&id));
        drop(pipes.1.remove(&id));

        Ok(0)
    }
}

/// Read side of a pipe
#[derive(Clone)]
pub struct PipeRead {
    flags: usize,
    condition: Arc<WaitCondition>,
    vec: Arc<Mutex<VecDeque<u8>>>
}

impl PipeRead {
    pub fn new(flags: usize) -> Self {
        PipeRead {
            flags: flags,
            condition: Arc::new(WaitCondition::new()),
            vec: Arc::new(Mutex::new(VecDeque::new())),
        }
    }

    fn read(&self, buf: &mut [u8]) -> Result<usize> {
        loop {
            {
                let mut vec = self.vec.lock();

                let mut i = 0;
                while i < buf.len() {
                    if let Some(b) = vec.pop_front() {
                        buf[i] = b;
                        i += 1;
                    } else {
                        break;
                    }
                }

                if i > 0 {
                    return Ok(i);
                }
            }

            if self.flags & O_NONBLOCK == O_NONBLOCK || Arc::weak_count(&self.vec) == 0 {
                return Ok(0);
            } else {
                self.condition.wait();
            }
        }
    }
}

/// Read side of a pipe
#[derive(Clone)]
pub struct PipeWrite {
    condition: Arc<WaitCondition>,
    vec: Weak<Mutex<VecDeque<u8>>>
}

impl PipeWrite {
    pub fn new(read: &PipeRead) -> Self {
        PipeWrite {
            condition: read.condition.clone(),
            vec: Arc::downgrade(&read.vec),
        }
    }

    fn write(&self, buf: &[u8]) -> Result<usize> {
        if let Some(vec_lock) = self.vec.upgrade() {
            let mut vec = vec_lock.lock();

            for &b in buf.iter() {
                vec.push_back(b);
            }

            self.condition.notify();

            Ok(buf.len())
        } else {
            Err(Error::new(EPIPE))
        }
    }
}

impl Drop for PipeWrite {
    fn drop(&mut self) {
        self.condition.notify();
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Local state for keys in the snapshot in progress (the "index").

use std::borrow::Cow;

use diesel;
use diesel::prelude::*;
use diesel::sqlite::SqliteConnection;

use std::sync::mpsc;
use time::Duration;

use blob;
use hash;
use periodic_timer::PeriodicTimer;
use process::{Process, MsgHandler};
use util;

use super::schema;

error_type! {
    #[derive(Debug)]
    pub enum MsgError {
        Recv(mpsc::RecvError) {
            cause;
        },
        Message(Cow<'static, str>) {
            desc (e) &**e;
            from (s: &'static str) s.into();
            from (s: String) s.into();
        }
     }
}

#[derive(Clone, Debug)]
pub struct Entry {
    pub id: Option<u64>,
    pub parent_id: Option<u64>,

    pub name: Vec<u8>,

    pub created: Option<i64>,
    pub modified: Option<i64>,
    pub accessed: Option<i64>,

    pub permissions: Option<u64>,
    pub user_id: Option<u64>,
    pub group_id: Option<u64>,

    pub data_hash: Option<Vec<u8>>,
    pub data_length: Option<u64>,
}

pub type IndexProcess = Process<Msg, Result<Reply, MsgError>>;

pub enum Msg {
    /// Insert an entry in the key index.
    /// Returns `Id` with the new entry ID.
    Insert(Entry),

    /// Lookup an entry in the key index by its parent id and name.
    /// Returns either `Entry` with the found entry or `NotFound`.
    Lookup(Option<u64>, Vec<u8>),

    /// Update the `payload` and `persistent_ref` of an entry.
    /// Returns `UpdateOk`.
    UpdateDataHash(Entry, Option<hash::Hash>, Option<blob::ChunkRef>),

    /// List a directory (aka. `level`) in the index.
    /// Returns `ListResult` with all the entries under the given parent.
    ListDir(Option<u64>),

    /// Flush this key index.
    Flush,
}

pub enum Reply {
    Entry(Entry),
    NotFound,
    UpdateOk,
    ListResult(Vec<(Entry, Option<blob::ChunkRef>)>),
    FlushOk,
}

pub struct Index {
    path: String,
    conn: SqliteConnection,
    flush_timer: PeriodicTimer,
}

fn i64_to_u64_or_panic(x: i64) -> u64 {
    if x < 0 {
        panic!("expected u64, got {:?}", x);
    }
    return x as u64;
}

impl Index {
    pub fn new(path: String) -> Index {
        let conn = SqliteConnection::establish(&path).expect("Could not open SQLite database");

        let ki = Index {
            path: path,
            conn: conn,
            flush_timer: PeriodicTimer::new(Duration::seconds(5)),
        };

        let dir = diesel::migrations::find_migrations_directory().unwrap();
        diesel::migrations::run_pending_migrations_in_directory(&ki.conn,
                                                                &dir,
                                                                &mut util::InfoWriter)
            .unwrap();
        ki.conn.begin_transaction().unwrap();

        ki
    }

    #[cfg(test)]
    pub fn new_for_testing() -> Index {
        Index::new(":memory:".to_string())
    }

    fn last_insert_rowid(&self) -> i64 {
        diesel::select(diesel::expression::sql("last_insert_rowid()"))
            .first::<i64>(&self.conn)
            .unwrap()
    }

    pub fn maybe_flush(&mut self) {
        if self.flush_timer.did_fire() {
            self.flush();
        }
    }

    pub fn flush(&mut self) {
        self.conn.commit_transaction().unwrap();
        self.conn.begin_transaction().unwrap();
    }
}

impl Clone for Index {
    fn clone(&self) -> Index {
        Index::new(self.path.clone())
    }
}

impl MsgHandler<Msg, Result<Reply, MsgError>> for Index {
    type Err = MsgError;

    fn handle(&mut self,
              msg: Msg,
              reply: Box<Fn(Result<Reply, MsgError>)>)
              -> Result<(), MsgError> {
        let reply_ok = |x| {
            reply(Ok(x));
            Ok(())
        };
        match msg {
            Msg::Insert(entry) => {
                use super::schema::keys::dsl::*;

                let entry = match entry.id {
                    Some(id_) => {
                        // Replace existing entry.
                        diesel::update(keys.find(id_ as i64))
                            .set((parent.eq(entry.parent_id.map(|x| x as i64)),
                                  name.eq(&entry.name[..]),
                                  created.eq(entry.created),
                                  modified.eq(entry.modified),
                                  accessed.eq(entry.accessed)))
                            .execute(&self.conn)
                            .expect("Error updating key");
                        entry
                    }
                    None => {
                        // Insert new entry.
                        {
                            let new = schema::NewKey {
                                parent: entry.parent_id.map(|x| x as i64),
                                name: &entry.name[..],
                                created: entry.created,
                                modified: entry.modified,
                                accessed: entry.accessed,
                                permissions: entry.permissions.map(|x| x as i64),
                                group_id: entry.group_id.map(|x| x as i64),
                                user_id: entry.user_id.map(|x| x as i64),
                                hash: None,
                                persistent_ref: None,
                            };

                            diesel::insert(&new)
                                .into(keys)
                                .execute(&self.conn)
                                .expect("Error inserting key");
                        }
                        let mut entry = entry;
                        entry.id = Some(self.last_insert_rowid() as u64);
                        entry
                    }
                };

                return reply_ok(Reply::Entry(entry));
            }

            Msg::Lookup(parent_, name_) => {
                use super::schema::keys::dsl::*;

                let row_opt = match parent_ {
                    Some(p) => {
                        keys.filter(parent.eq(p as i64))
                            .filter(name.eq(&name_[..]))
                            .first::<schema::Key>(&self.conn)
                            .optional()
                            .expect("Error searching keys")
                    }
                    None => {
                        keys.filter(parent.is_null())
                            .filter(name.eq(&name_[..]))
                            .first::<schema::Key>(&self.conn)
                            .optional()
                            .expect("Error searching keys")
                    }
                };

                if let Some(row) = row_opt {
                    return reply_ok(Reply::Entry(Entry {
                        id: Some(row.id as u64),
                        parent_id: parent_,
                        name: name_,
                        created: row.created,
                        modified: row.modified,
                        accessed: row.accessed,
                        permissions: row.permissions.map(|x| x as u64),
                        user_id: row.user_id.map(|x| x as u64),
                        group_id: row.group_id.map(|x| x as u64),
                        data_hash: row.hash,
                        data_length: None,
                    }));
                }
                return reply_ok(Reply::NotFound);
            }

            Msg::UpdateDataHash(entry, hash_opt, persistent_ref_opt) => {
                use super::schema::keys::dsl::*;

                let id_ = entry.id.expect("Tried to update without an id") as i64;
                assert!(hash_opt.is_some() == persistent_ref_opt.is_some());

                let hash_bytes = hash_opt.map(|h| h.bytes);
                let persistent_ref_bytes = persistent_ref_opt.map(|p| p.as_bytes());

                if entry.modified.is_some() {
                    diesel::update(keys.find(id_)
                                       .filter(modified.eq::<Option<i64>>(None)
                                                       .or(modified.le(entry.modified))))
                        .set((hash.eq(hash_bytes), persistent_ref.eq(persistent_ref_bytes)))
                        .execute(&self.conn)
                        .expect("Error updating key");
                } else {
                    diesel::update(keys.find(id_))
                        .set((hash.eq(hash_bytes), persistent_ref.eq(persistent_ref_bytes)))
                        .execute(&self.conn)
                        .expect("Error updating key");
                }

                self.maybe_flush();
                return reply_ok(Reply::UpdateOk);
            }

            Msg::Flush => {
                self.flush();
                return reply_ok(Reply::FlushOk);
            }

            Msg::ListDir(parent_opt) => {
                use super::schema::keys::dsl::*;

                let rows = match parent_opt {
                    Some(p) => {
                        keys.filter(parent.eq(p as i64))
                            .load::<schema::Key>(&self.conn)
                            .expect("Error listing keys")
                    }
                    None => {
                        keys.filter(parent.is_null())
                            .load::<schema::Key>(&self.conn)
                            .expect("Error listing keys")
                    }
                };

                return reply_ok(Reply::ListResult(rows.into_iter()
                                                      .map(|mut r| {
                                                          (Entry {
                                                    id: Some(r.id as u64),
                                                    parent_id: r.parent.map(|x| x as u64),
                                                    name: r.name,
                                                    created: r.created,
                                                    modified: r.modified,
                                                    accessed: r.accessed,
                                                    permissions: r.permissions
                                                                  .map(|x| x as u64),
                                                    user_id: r.user_id.map(|x| x as u64),
                                                    group_id: r.group_id.map(|x| x as u64),
                                                    data_hash: r.hash,
                                                    data_length: None,
                                                },
                                                 r.persistent_ref.as_mut().map(|p| {
                                                    blob::ChunkRef::from_bytes(&mut &p[..]).unwrap()
                                                }))
                                                      })
                                                      .collect()));
            }
        }
    }
}
<commit_msg>Propagate immediate diesel errors.<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Local state for keys in the snapshot in progress (the "index").

use std::borrow::Cow;

use diesel;
use diesel::prelude::*;
use diesel::sqlite::SqliteConnection;

use std::sync::mpsc;
use time::Duration;

use blob;
use hash;
use periodic_timer::PeriodicTimer;
use process::{Process, MsgHandler};
use util;

use super::schema;

error_type! {
    #[derive(Debug)]
    pub enum MsgError {
        Recv(mpsc::RecvError) {
            cause;
        },
        Sql(diesel::result::Error) {
            cause;
        },
        Message(Cow<'static, str>) {
            desc (e) &**e;
            from (s: &'static str) s.into();
            from (s: String) s.into();
        }
     }
}

#[derive(Clone, Debug)]
pub struct Entry {
    pub id: Option<u64>,
    pub parent_id: Option<u64>,

    pub name: Vec<u8>,

    pub created: Option<i64>,
    pub modified: Option<i64>,
    pub accessed: Option<i64>,

    pub permissions: Option<u64>,
    pub user_id: Option<u64>,
    pub group_id: Option<u64>,

    pub data_hash: Option<Vec<u8>>,
    pub data_length: Option<u64>,
}

pub type IndexProcess = Process<Msg, Result<Reply, MsgError>>;

pub enum Msg {
    /// Insert an entry in the key index.
    /// Returns `Id` with the new entry ID.
    Insert(Entry),

    /// Lookup an entry in the key index by its parent id and name.
    /// Returns either `Entry` with the found entry or `NotFound`.
    Lookup(Option<u64>, Vec<u8>),

    /// Update the `payload` and `persistent_ref` of an entry.
    /// Returns `UpdateOk`.
    UpdateDataHash(Entry, Option<hash::Hash>, Option<blob::ChunkRef>),

    /// List a directory (aka. `level`) in the index.
    /// Returns `ListResult` with all the entries under the given parent.
    ListDir(Option<u64>),

    /// Flush this key index.
    Flush,
}

pub enum Reply {
    Entry(Entry),
    NotFound,
    UpdateOk,
    ListResult(Vec<(Entry, Option<blob::ChunkRef>)>),
    FlushOk,
}

pub struct Index {
    path: String,
    conn: SqliteConnection,
    flush_timer: PeriodicTimer,
}

fn i64_to_u64_or_panic(x: i64) -> u64 {
    if x < 0 {
        panic!("expected u64, got {:?}", x);
    }
    return x as u64;
}

impl Index {
    pub fn new(path: String) -> Index {
        let conn = SqliteConnection::establish(&path).expect("Could not open SQLite database");

        let ki = Index {
            path: path,
            conn: conn,
            flush_timer: PeriodicTimer::new(Duration::seconds(5)),
        };

        let dir = diesel::migrations::find_migrations_directory().unwrap();
        diesel::migrations::run_pending_migrations_in_directory(&ki.conn,
                                                                &dir,
                                                                &mut util::InfoWriter)
            .unwrap();
        ki.conn.begin_transaction().unwrap();

        ki
    }

    #[cfg(test)]
    pub fn new_for_testing() -> Index {
        Index::new(":memory:".to_string())
    }

    fn last_insert_rowid(&self) -> i64 {
        diesel::select(diesel::expression::sql("last_insert_rowid()"))
            .first::<i64>(&self.conn)
            .unwrap()
    }

    pub fn maybe_flush(&mut self) -> Result<(), MsgError> {
        if self.flush_timer.did_fire() {
            try!(self.flush());
        }

        Ok(())
    }

    pub fn flush(&mut self) -> Result<(), MsgError> {
        try!(self.conn.commit_transaction());
        try!(self.conn.begin_transaction());

        Ok(())
    }
}

impl Clone for Index {
    fn clone(&self) -> Index {
        Index::new(self.path.clone())
    }
}

impl MsgHandler<Msg, Result<Reply, MsgError>> for Index {
    type Err = MsgError;

    fn handle(&mut self,
              msg: Msg,
              reply: Box<Fn(Result<Reply, MsgError>)>)
              -> Result<(), MsgError> {
        let reply_ok = |x| {
            reply(Ok(x));
            Ok(())
        };
        match msg {
            Msg::Insert(entry) => {
                use super::schema::keys::dsl::*;

                let entry = match entry.id {
                    Some(id_) => {
                        // Replace existing entry.
                        try!(diesel::update(keys.find(id_ as i64))
                                 .set((parent.eq(entry.parent_id.map(|x| x as i64)),
                                       name.eq(&entry.name[..]),
                                       created.eq(entry.created),
                                       modified.eq(entry.modified),
                                       accessed.eq(entry.accessed)))
                                 .execute(&self.conn));
                        entry
                    }
                    None => {
                        // Insert new entry.
                        {
                            let new = schema::NewKey {
                                parent: entry.parent_id.map(|x| x as i64),
                                name: &entry.name[..],
                                created: entry.created,
                                modified: entry.modified,
                                accessed: entry.accessed,
                                permissions: entry.permissions.map(|x| x as i64),
                                group_id: entry.group_id.map(|x| x as i64),
                                user_id: entry.user_id.map(|x| x as i64),
                                hash: None,
                                persistent_ref: None,
                            };

                            try!(diesel::insert(&new)
                                     .into(keys)
                                     .execute(&self.conn));
                        }
                        let mut entry = entry;
                        entry.id = Some(self.last_insert_rowid() as u64);
                        entry
                    }
                };

                return reply_ok(Reply::Entry(entry));
            }

            Msg::Lookup(parent_, name_) => {
                use super::schema::keys::dsl::*;

                let row_opt = match parent_ {
                    Some(p) => {
                        try!(keys.filter(parent.eq(p as i64))
                                 .filter(name.eq(&name_[..]))
                                 .first::<schema::Key>(&self.conn)
                                 .optional())
                    }
                    None => {
                        try!(keys.filter(parent.is_null())
                                 .filter(name.eq(&name_[..]))
                                 .first::<schema::Key>(&self.conn)
                                 .optional())
                    }
                };

                if let Some(row) = row_opt {
                    return reply_ok(Reply::Entry(Entry {
                        id: Some(row.id as u64),
                        parent_id: parent_,
                        name: name_,
                        created: row.created,
                        modified: row.modified,
                        accessed: row.accessed,
                        permissions: row.permissions.map(|x| x as u64),
                        user_id: row.user_id.map(|x| x as u64),
                        group_id: row.group_id.map(|x| x as u64),
                        data_hash: row.hash,
                        data_length: None,
                    }));
                }
                return reply_ok(Reply::NotFound);
            }

            Msg::UpdateDataHash(entry, hash_opt, persistent_ref_opt) => {
                use super::schema::keys::dsl::*;

                let id_ = entry.id.expect("Tried to update without an id") as i64;
                assert!(hash_opt.is_some() == persistent_ref_opt.is_some());

                let hash_bytes = hash_opt.map(|h| h.bytes);
                let persistent_ref_bytes = persistent_ref_opt.map(|p| p.as_bytes());

                if entry.modified.is_some() {
                    try!(diesel::update(keys.find(id_)
                                            .filter(modified.eq::<Option<i64>>(None)
                                                            .or(modified.le(entry.modified))))
                             .set((hash.eq(hash_bytes), persistent_ref.eq(persistent_ref_bytes)))
                             .execute(&self.conn));
                } else {
                    try!(diesel::update(keys.find(id_))
                             .set((hash.eq(hash_bytes), persistent_ref.eq(persistent_ref_bytes)))
                             .execute(&self.conn));
                }

                try!(self.maybe_flush());
                return reply_ok(Reply::UpdateOk);
            }

            Msg::Flush => {
                try!(self.flush());
                return reply_ok(Reply::FlushOk);
            }

            Msg::ListDir(parent_opt) => {
                use super::schema::keys::dsl::*;

                let rows = match parent_opt {
                    Some(p) => {
                        try!(keys.filter(parent.eq(p as i64))
                                 .load::<schema::Key>(&self.conn))
                    }
                    None => {
                        try!(keys.filter(parent.is_null())
                                 .load::<schema::Key>(&self.conn))
                    }
                };

                return reply_ok(Reply::ListResult(rows.into_iter()
                                                      .map(|mut r| {
                                                          (Entry {
                                                    id: Some(r.id as u64),
                                                    parent_id: r.parent.map(|x| x as u64),
                                                    name: r.name,
                                                    created: r.created,
                                                    modified: r.modified,
                                                    accessed: r.accessed,
                                                    permissions: r.permissions
                                                                  .map(|x| x as u64),
                                                    user_id: r.user_id.map(|x| x as u64),
                                                    group_id: r.group_id.map(|x| x as u64),
                                                    data_hash: r.hash,
                                                    data_length: None,
                                                },
                                                 r.persistent_ref.as_mut().map(|p| {
                                                    blob::ChunkRef::from_bytes(&mut &p[..]).unwrap()
                                                }))
                                                      })
                                                      .collect()));
            }
        }
    }
}
<|endoftext|>


<commit_before>/// Asserts approximate equality within a given tolerance of two values with the
/// `ApproxEq` trait.
#[macro_export]
macro_rules! assert_approx_eq_eps(
    ($given: expr, $expected: expr, $eps: expr) => ({
        let eps = &($eps);
        let (given_val, expected_val) = (&($given), &($expected));
        if !ApproxEq::approx_eq_eps(given_val, expected_val, eps) {
            panic!("assertion failed: `left ≈ right` (left: `{}`, right: `{}`, tolerance: `{}`)",
                *given_val, *expected_val, *eps
            )
        }
    })
);

/// Asserts approximate equality within a given tolerance of two values with the
/// `ApproxEq` trait, with tolerance specified in ULPs.
#[macro_export]
macro_rules! assert_approx_eq_ulps(
    ($given: expr, $expected: expr, $ulps: expr) => ({
        let ulps = &($ulps);
        let (given_val, expected_val) = (&($given), &($expected));
        if !ApproxEq::approx_eq_ulps(given_val, expected_val, ulps) {
            panic!("assertion failed: `left ≈ right` (left: `{}`, right: `{}`, tolerance: `{}`)",
                *given_val, *expected_val, *ulps
            )
        }
    })
);

/// Asserts approximate equality of two values with the `ApproxEq` trait.
#[macro_export]
macro_rules! assert_approx_eq(
    ($given: expr, $expected: expr) => ({
        let (given_val, expected_val) = (&($given), &($expected));
        if !ApproxEq::approx_eq(given_val, expected_val) {
            panic!("assertion failed: `left ≈ right` (left: `{}`, right: `{}`, tolerance: `{}`)",
                *given_val, *expected_val,
                ApproxEq::approx_epsilon(Some(*given_val))
            )
        }
    })
);
<commit_msg>fix macro<commit_after>/// Asserts approximate equality within a given tolerance of two values with the
/// `ApproxEq` trait.
#[macro_export]
macro_rules! assert_approx_eq_eps(
    ($given: expr, $expected: expr, $eps: expr) => ({
        let eps = &($eps);
        let (given_val, expected_val) = (&($given), &($expected));
        if !ApproxEq::approx_eq_eps(given_val, expected_val, eps) {
            panic!("assertion failed: `left ≈ right` (left: `{}`, right: `{}`, tolerance: `{}`)",
                *given_val, *expected_val, *eps
            )
        }
    })
);

/// Asserts approximate equality within a given tolerance of two values with the
/// `ApproxEq` trait, with tolerance specified in ULPs.
#[macro_export]
macro_rules! assert_approx_eq_ulps(
    ($given: expr, $expected: expr, $ulps: expr) => ({
        let ulps = $ulps;
        let (given_val, expected_val) = (&($given), &($expected));
        if !ApproxEq::approx_eq_ulps(given_val, expected_val, ulps) {
            panic!("assertion failed: `left ≈ right` (left: `{}`, right: `{}`, tolerance: `{}`)",
                *given_val, *expected_val, ulps
            )
        }
    })
);

/// Asserts approximate equality of two values with the `ApproxEq` trait.
#[macro_export]
macro_rules! assert_approx_eq(
    ($given: expr, $expected: expr) => ({
        let (given_val, expected_val) = (&($given), &($expected));
        if !ApproxEq::approx_eq(given_val, expected_val) {
            panic!("assertion failed: `left ≈ right` (left: `{}`, right: `{}`, tolerance: `{}`)",
                *given_val, *expected_val,
                ApproxEq::approx_epsilon(Some(*given_val))
            )
        }
    })
);
<|endoftext|>


<commit_before>extern crate num;

use num::Num;

#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
pub struct Matrix1x1<N> {
	pub m11:N,
}

#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
pub struct Matrix2x2<N>{
	pub m11:N, pub m21:N,
	pub m12:N, pub m22:N,
}

#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
pub struct Matrix3x3<N> {
	pub m11:N, pub m21:N, pub m31:N,
	pub m12:N, pub m22:N, pub m32:N,
	pub m13:N, pub m23:N, pub m33:N,
}

#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
pub struct Matrix4x4<N> {
	pub m11:N, pub m21:N, pub m31:N, pub m41:N,
	pub m12:N, pub m22:N, pub m32:N, pub m42:N,
	pub m13:N, pub m23:N, pub m33:N, pub m43:N,
	pub m14:N, pub m24:N, pub m34:N, pub m44:N,
}

// TODO: make this into a macro so I can easily generate this for all the matrix types
impl<N: Num> Matrix4x4<N> {
	#[inline]
	pub fn identity() -> Matrix4x4<N> {
		Matrix4x4::<N> {
			m11:num::one(),m21:num::zero(),m31:num::zero(),m41:num::zero(),
			m12:num::zero(),m22:num::one(),m32:num::zero(),m42:num::zero(),
			m13:num::zero(),m23:num::zero(),m33:num::one(),m43:num::zero(),
			m14:num::zero(),m24:num::zero(),m34:num::zero(),m44:num::one(),
		}
	}
}<commit_msg>Using macro's for the implementations of the matrix<commit_after>extern crate num;
use num::Num;

// Some macro's to create the implementations for all the fixed-size matrices

// create matrix with zero values
macro_rules! matrix_new(
	($t: ident, $($index: ident),+) => (
		impl<N: Num> $t<N> {
			#[inline]
			pub fn new() -> $t<N> {
				$t {
					$($index: num::zero()),+
				}
			}
		}
	)
);

// create identity matrix
macro_rules! matrix_identity(
	($t: ident, $($diag_index: ident),+) => (
		impl<N: Num> $t<N> {
			#[inline]
			pub fn identity() -> $t<N> {
				let mut mat: $t<N> = $t::new();
				$(mat.$diag_index = num::one();)+
				mat
			}
		}
	)
);

// 1x1 Matrix

#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
pub struct Matrix1x1<N> {
	pub m11:N,
}

matrix_new!(Matrix1x1,m11);
matrix_identity!(Matrix1x1,m11);

// 2x2 Matrix

#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
pub struct Matrix2x2<N>{
	pub m11:N, pub m21:N,
	pub m12:N, pub m22:N,
}

matrix_new!(Matrix2x2,m11,m12,m21,m22);
matrix_identity!(Matrix2x2,m11,m22);

// 3x3 Matrix

#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
pub struct Matrix3x3<N> {
	pub m11:N, pub m21:N, pub m31:N,
	pub m12:N, pub m22:N, pub m32:N,
	pub m13:N, pub m23:N, pub m33:N,
}

matrix_new!(Matrix3x3,m11,m21,m31,m12,m22,m32,m13,m23,m33);
matrix_identity!(Matrix3x3,m11,m22,m33);

// 4x4 Matrix

#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
pub struct Matrix4x4<N> {
	pub m11:N, pub m21:N, pub m31:N, pub m41:N,
	pub m12:N, pub m22:N, pub m32:N, pub m42:N,
	pub m13:N, pub m23:N, pub m33:N, pub m43:N,
	pub m14:N, pub m24:N, pub m34:N, pub m44:N,
}

matrix_new!(Matrix4x4,m11,m21,m31,m41,m12,m22,m32,m42,m13,m23,m33,m43,m14,m24,m34,m44);
matrix_identity!(Matrix4x4,m11,m22,m33,m44);<|endoftext|>


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

use std::cell::Cell;
use std::sync::Arc;
use time::get_time;

/// Naive implementation of a `Gauge`.
///
/// It might be nice to make one built on atomics.
#[derive(Debug)]
pub struct StdGauge {
    /// The gauge value.
    pub value: Cell<f64>,
}

/// A snapshot of the value of a `Gauge`.
#[derive(Debug)]
pub struct GaugeSnapshot {
    /// The snapshot of the gauge value.
    pub value: f64,
}

/// `Gauge` is a `Metric` that represents a single numerical value that can
/// arbitrarily go up and down.
///
/// A `Gauge` is typically used for measured values like temperatures or current
/// memory usage, but also "counts" that can go up and down.
pub trait Gauge {
    /// Increment the gauge by 1.
    fn inc(&self);
    /// Decrement the gauge by 1.
    fn dec(&self);
    /// Increment the gauge by the given amount.
    fn add(&self, value: f64);
    /// Decrement the gauge by the given amount.
    fn sub(&self, value: f64);
    /// Set the current value of the gauge.
    fn set(&self, value: f64);
    ///  Set the current value to the current timestamp.
    fn set_to_current_time(&self);
    /// Take a snapshot of the current value for use with a `Reporter`.
    fn snapshot(&self) -> GaugeSnapshot;
}

impl Gauge for StdGauge {
    fn inc(&self) {
        self.value.set(self.value.get() + 1.0);
    }

    fn dec(&self) {
        self.value.set(self.value.get() - 1.0);
    }

    fn add(&self, value: f64) {
        self.value.set(self.value.get() + value);
        // TODO check for negative
    }

    fn sub(&self, value: f64) {
        self.value.set(self.value.get() - value);
    }

    fn set(&self, value: f64) {
        self.value.set(value);
    }

    fn set_to_current_time(&self) {
        self.value.set(timestamp());
    }

    fn snapshot(&self) -> GaugeSnapshot {
        GaugeSnapshot { value: self.value.get() }
    }
}

impl StdGauge {
    /// Create a new `StdGauge`.
    pub fn new() -> Arc<Self> {
        Arc::new(StdGauge { value: Cell::new(0.0) })
    }
}

fn timestamp() -> f64 {
    let timespec = get_time();
    // 1459440009.113178
    timespec.sec as f64 + (timespec.nsec as f64 / 1000.0 / 1000.0 / 1000.0)
}

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

    #[test]
    fn create_and_snapshot() {
        let g = StdGauge::new();
        let snapshot_1 = g.snapshot();
        g.set(10.0);
        let snapshot_2 = g.snapshot();

        assert_eq!(g.value.get(), 10.0);
        assert_eq!(snapshot_1.value, 0.0);
        assert_eq!(snapshot_2.value, 10.0);
    }
}
<commit_msg>Remove Gauge::set_to_current_time.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cell::Cell;
use std::sync::Arc;

/// Naive implementation of a `Gauge`.
///
/// It might be nice to make one built on atomics.
#[derive(Debug)]
pub struct StdGauge {
    /// The gauge value.
    pub value: Cell<f64>,
}

/// A snapshot of the value of a `Gauge`.
#[derive(Debug)]
pub struct GaugeSnapshot {
    /// The snapshot of the gauge value.
    pub value: f64,
}

/// `Gauge` is a `Metric` that represents a single numerical value that can
/// arbitrarily go up and down.
///
/// A `Gauge` is typically used for measured values like temperatures or current
/// memory usage, but also "counts" that can go up and down.
pub trait Gauge {
    /// Increment the gauge by 1.
    fn inc(&self);
    /// Decrement the gauge by 1.
    fn dec(&self);
    /// Increment the gauge by the given amount.
    fn add(&self, value: f64);
    /// Decrement the gauge by the given amount.
    fn sub(&self, value: f64);
    /// Set the current value of the gauge.
    fn set(&self, value: f64);
    /// Take a snapshot of the current value for use with a `Reporter`.
    fn snapshot(&self) -> GaugeSnapshot;
}

impl Gauge for StdGauge {
    fn inc(&self) {
        self.value.set(self.value.get() + 1.0);
    }

    fn dec(&self) {
        self.value.set(self.value.get() - 1.0);
    }

    fn add(&self, value: f64) {
        self.value.set(self.value.get() + value);
        // TODO check for negative
    }

    fn sub(&self, value: f64) {
        self.value.set(self.value.get() - value);
    }

    fn set(&self, value: f64) {
        self.value.set(value);
    }

    fn snapshot(&self) -> GaugeSnapshot {
        GaugeSnapshot { value: self.value.get() }
    }
}

impl StdGauge {
    /// Create a new `StdGauge`.
    pub fn new() -> Arc<Self> {
        Arc::new(StdGauge { value: Cell::new(0.0) })
    }
}

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

    #[test]
    fn create_and_snapshot() {
        let g = StdGauge::new();
        let snapshot_1 = g.snapshot();
        g.set(10.0);
        let snapshot_2 = g.snapshot();

        assert_eq!(g.value.get(), 10.0);
        assert_eq!(snapshot_1.value, 0.0);
        assert_eq!(snapshot_2.value, 10.0);
    }
}
<|endoftext|>


<commit_before>use std::sync::mpsc;

use platform::time::sleep_secs;
use platform::time::time_now;
use testlib::cmp::eq_f64;

use super::LiveTimers;
use super::MetricsRecorder;
use super::TimeSeries;
use super::Timer;
use super::Timing;

#[test]
#[should_panic(expected="Tried to stop non-live timer: \"resp\"")]
fn test_live_timers_name_mismatch() {
    let mut lt = LiveTimers::new();

    lt.start("cmd");
    lt.stop("resp"); // panic expected
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_live_timers_ok() {
    let mut lt = LiveTimers::new();

    let t1 = time_now();
    let start_time = lt.start("cmd");
    // start_time is very close to *now*
    assert!(eq_f64(t1, start_time, 0.01));
    // "cmd" -> start_time was added to the map
    assert_eq!(&start_time, lt.get_timers().get("cmd").unwrap());

    sleep_secs(0.25);

    let timing = lt.stop("cmd");
    // the returned start_time matches what we saw before
    assert_eq!(start_time, timing.start_time);
    // the duration is almost exactly the time we slept
    assert!(eq_f64(0.25, timing.duration, 0.01));
    // "cmd" was removed from the map
    assert!(!lt.get_timers().contains_key("cmd"));
}

#[test]
fn test_time_series_updates() {
    let mut ts = TimeSeries::new();

    // add a timer
    ts.add_timing(&Timing::new("cmd", 1.1, 0.25));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // add another timer
    ts.add_timing(&Timing::new("cmd", 1.9, 0.51));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25, 0.51],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // add another timer
    ts.add_timing(&Timing::new("cmd", 2.3, 8.8));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25, 0.51],
            2 => vec![8.8],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // add another timer
    ts.add_timing(&Timing::new("resp", 4.1, 1.0));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25, 0.51],
            2 => vec![8.8],
        },
        "resp".to_string() => hashmap!{
            4 => vec![1.0],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // empty the series
    ts.clear();
    // construct the expected value for comparison
    let expected = hashmap!{};
    // compare
    assert_eq!(&expected, ts.get_timers());
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_timer_correct() {
    let (met_tx, met_rx) = mpsc::channel();
    let mut rec = MetricsRecorder::new(met_tx, true);

    // use Timer to make one timing
    let _rv = {
        let _t = Timer::new(&mut rec, "cmd");
        sleep_secs(0.25);
        ()
    };

    // flush the metrics so we can see them
    rec.flush_metrics();

    // receive the metrics
    let metrics = met_rx.recv().unwrap();
    // verify that the timing is correct
    let dur = metrics.first().get_timing().duration;
    assert!(eq_f64(0.25, dur, 0.01));
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_timer_wrong_binding() {
    let (met_tx, met_rx) = mpsc::channel();
    let mut rec = MetricsRecorder::new(met_tx, true);

    // use Timer to make one timing
    let _rv = {
        // this binding discards the value right away!
        let _ = Timer::new(&mut rec, "cmd");
        sleep_secs(0.25);
        ()
    };

    // flush the metrics so we can see them
    rec.flush_metrics();

    // receive the metrics
    let metrics = met_rx.recv().unwrap();
    // verify that the timing is correct
    let dur = metrics.first().get_timing().duration;
    assert!(eq_f64(0.0, dur, 0.01));
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_timer_no_binding() {
    let (met_tx, met_rx) = mpsc::channel();
    let mut rec = MetricsRecorder::new(met_tx, true);

    // use Timer to make one timing
    let _rv = {
        // no binding means Timer does not live past the first line
        Timer::new(&mut rec, "cmd");
        sleep_secs(0.25);
        ()
    };

    // flush the metrics so we can see them
    rec.flush_metrics();

    // receive the metrics
    let metrics = met_rx.recv().unwrap();
    // verify that the timing is correct
    let dur = metrics.first().get_timing().duration;
    assert!(eq_f64(0.0, dur, 0.01));
}
<commit_msg>relax time based test<commit_after>use std::sync::mpsc;

use platform::time::sleep_secs;
use platform::time::time_now;
use testlib::cmp::eq_f64;

use super::LiveTimers;
use super::MetricsRecorder;
use super::TimeSeries;
use super::Timer;
use super::Timing;

#[test]
#[should_panic(expected="Tried to stop non-live timer: \"resp\"")]
fn test_live_timers_name_mismatch() {
    let mut lt = LiveTimers::new();

    lt.start("cmd");
    lt.stop("resp"); // panic expected
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_live_timers_ok() {
    let mut lt = LiveTimers::new();

    let t1 = time_now();
    let start_time = lt.start("cmd");
    // start_time is very close to *now*
    assert!(eq_f64(t1, start_time, 0.01));
    // "cmd" -> start_time was added to the map
    assert_eq!(&start_time, lt.get_timers().get("cmd").unwrap());

    sleep_secs(0.25);

    let timing = lt.stop("cmd");
    // the returned start_time matches what we saw before
    assert_eq!(start_time, timing.start_time);
    // the duration is almost exactly the time we slept
    assert!(eq_f64(0.25, timing.duration, 0.01));
    // "cmd" was removed from the map
    assert!(!lt.get_timers().contains_key("cmd"));
}

#[test]
fn test_time_series_updates() {
    let mut ts = TimeSeries::new();

    // add a timer
    ts.add_timing(&Timing::new("cmd", 1.1, 0.25));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // add another timer
    ts.add_timing(&Timing::new("cmd", 1.9, 0.51));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25, 0.51],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // add another timer
    ts.add_timing(&Timing::new("cmd", 2.3, 8.8));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25, 0.51],
            2 => vec![8.8],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // add another timer
    ts.add_timing(&Timing::new("resp", 4.1, 1.0));
    // construct the expected value for comparison
    let expected = hashmap!{
        "cmd".to_string() => hashmap!{
            1 => vec![0.25, 0.51],
            2 => vec![8.8],
        },
        "resp".to_string() => hashmap!{
            4 => vec![1.0],
        },
    };
    // compare
    assert_eq!(&expected, ts.get_timers());

    // empty the series
    ts.clear();
    // construct the expected value for comparison
    let expected = hashmap!{};
    // compare
    assert_eq!(&expected, ts.get_timers());
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_timer_correct() {
    let (met_tx, met_rx) = mpsc::channel();
    let mut rec = MetricsRecorder::new(met_tx, true);

    // use Timer to make one timing
    let _rv = {
        let _t = Timer::new(&mut rec, "cmd");
        sleep_secs(0.25);
        ()
    };

    // flush the metrics so we can see them
    rec.flush_metrics();

    // receive the metrics
    let metrics = met_rx.recv().unwrap();
    // verify that the timing is correct
    let dur = metrics.first().get_timing().duration;
    assert!(eq_f64(0.25, dur, 0.03));
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_timer_wrong_binding() {
    let (met_tx, met_rx) = mpsc::channel();
    let mut rec = MetricsRecorder::new(met_tx, true);

    // use Timer to make one timing
    let _rv = {
        // this binding discards the value right away!
        let _ = Timer::new(&mut rec, "cmd");
        sleep_secs(0.25);
        ()
    };

    // flush the metrics so we can see them
    rec.flush_metrics();

    // receive the metrics
    let metrics = met_rx.recv().unwrap();
    // verify that the timing is correct
    let dur = metrics.first().get_timing().duration;
    assert!(eq_f64(0.0, dur, 0.01));
}

// this is a slow test that relies on sleeps
#[ignore]
#[test]
fn test_timer_no_binding() {
    let (met_tx, met_rx) = mpsc::channel();
    let mut rec = MetricsRecorder::new(met_tx, true);

    // use Timer to make one timing
    let _rv = {
        // no binding means Timer does not live past the first line
        Timer::new(&mut rec, "cmd");
        sleep_secs(0.25);
        ()
    };

    // flush the metrics so we can see them
    rec.flush_metrics();

    // receive the metrics
    let metrics = met_rx.recv().unwrap();
    // verify that the timing is correct
    let dur = metrics.first().get_timing().duration;
    assert!(eq_f64(0.0, dur, 0.01));
}
<|endoftext|>


<commit_before>extern crate glfw;
use self::glfw::{ Context, Key, Action };

extern crate gl;

use std::sync::mpsc::Receiver;

// settings
const SCR_WIDTH: u32 = 800;
const SCR_HEIGHT: u32 = 600;

#[allow(dead_code)]
fn main() {
    // glfw: initialize and configure
    // ------------------------------
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
    #[cfg(target_os = "macos")]
    glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));

    // glfw window creation
    // --------------------
    let (mut window, events) = glfw.create_window(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window");

    window.make_current();
    window.set_key_polling(true);
    window.set_framebuffer_size_polling(true);

    // gl: load all OpenGL function pointers
    // ---------------------------------------
    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    // render loop
    // -----------
    while !window.should_close() {
        // events
        // -----
        process_events(&mut window, &events);

        // render
        // ------
        unsafe {
            gl::ClearColor(0.2, 0.3, 0.3, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        window.swap_buffers();
        glfw.poll_events();
    }
}

fn process_events(window: &mut glfw::Window, events: &Receiver<(f64, glfw::WindowEvent)>) {
    for (_, event) in glfw::flush_messages(&events) {
        match event {
            glfw::WindowEvent::FramebufferSize(width, height) => {
                // make sure the viewport matches the new window dimensions; note that width and
                // height will be significantly larger than specified on retina displays.
                unsafe { gl::Viewport(0, 0, width, height) }
            },
            glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
                window.set_should_close(true)
            },
            _ => {},
        }
    }
}
<commit_msg>rustfmt 1.2<commit_after>extern crate glfw;
use self::glfw::{Context, Key, Action};

extern crate gl;

use std::sync::mpsc::Receiver;

// settings
const SCR_WIDTH: u32 = 800;
const SCR_HEIGHT: u32 = 600;

#[allow(dead_code)]
fn main() {
    // glfw: initialize and configure
    // ------------------------------
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
    #[cfg(target_os = "macos")]
    glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));

    // glfw window creation
    // --------------------
    let (mut window, events) = glfw.create_window(SCR_WIDTH,
                                                  SCR_HEIGHT,
                                                  "LearnOpenGL",
                                                  glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window");

    window.make_current();
    window.set_key_polling(true);
    window.set_framebuffer_size_polling(true);

    // gl: load all OpenGL function pointers
    // ---------------------------------------
    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    // render loop
    // -----------
    while !window.should_close() {
        // events
        // -----
        process_events(&mut window, &events);

        // render
        // ------
        unsafe {
            gl::ClearColor(0.2, 0.3, 0.3, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        window.swap_buffers();
        glfw.poll_events();
    }
}

fn process_events(window: &mut glfw::Window, events: &Receiver<(f64, glfw::WindowEvent)>) {
    for (_, event) in glfw::flush_messages(&events) {
        match event {
            glfw::WindowEvent::FramebufferSize(width, height) => {
                // make sure the viewport matches the new window dimensions; note that width and
                // height will be significantly larger than specified on retina displays.
                unsafe { gl::Viewport(0, 0, width, height) }
            }
            glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
                window.set_should_close(true)
            }
            _ => {}
        }
    }
}

<|endoftext|>


<commit_before>use instruction::Instruction::*;
use instructions::Instructions;

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum OptimizationLevel {
    // May be room for more optimizations later
    Off,
    On,
}

pub fn apply_optimizations(instructions: &mut Instructions, level: OptimizationLevel) {
    // Optimizers should be grouped by the number of assumptions
    // the optimizer makes about the code
    // The fewer assumptions, the lower the applicable optimization level
    // Optimizers should be ordered appropriately so that they
    // do not conflict or contradict each other
    let optimizers = match level {
        OptimizationLevel::Off => vec![],
        OptimizationLevel::On => vec![
            remove_opposites,
        ],
    };

    for optimize in optimizers {
        optimize(instructions);
    }
}

fn remove_opposites(instructions: &mut Instructions) {
    let mut i = 1;
    while i < instructions.len() {
        let prev = instructions[i - 1];
        let current = instructions[i];

        // Cancel out opposites
        match (prev, current) {
            (Left, Right) | (Right, Left) |
            (Increment, Decrement) | (Decrement, Increment) => {
                instructions.remove(i);
                instructions.remove(i - 1);
                i -= 1;
            },

            // Otherwise just move on
            _ => i += 1,
        }
    }
}
<commit_msg>Removed old optimizations file that isn't used anymore<commit_after><|endoftext|>


<commit_before>#[phase(plugin)]
extern crate peg_syntax_ext;

use ast::AST;
use runtime::Error;

#[deriving(PartialEq)]
enum IntegerSign {
    Positive,
    Negative,
}

fn parse_decimal(str: &str, sign: &IntegerSign) -> AST {
    let integer: i64 = from_str(str).unwrap();

    AST::Integer(
        if *sign == IntegerSign::Negative {
            -integer
        } else {
            integer
        }
    )
}

fn parse_sign(str: &str) -> IntegerSign {
    match str {
        "-" => IntegerSign::Negative,
        _   => IntegerSign::Positive,
    }
}

fn parse_atom(str: &str) -> AST {
    AST::Atom(str.to_string())
}

fn parse_list(values: Vec<AST>) -> AST {
    AST::List(values)
}

fn parse_dotted_list(mut left: Vec<AST>, right: AST) -> AST {
    match right {
        AST::List(list) => {
            left.push_all(list.as_slice());
            AST::List(left)
        }
        AST::DottedList(list, right) => {
            left.push_all(list.as_slice());
            AST::DottedList(left, right)
        }
        _ => AST::DottedList(left, box right)
    }
}

fn parse_bool(str: &str) -> AST {
    AST::Bool(str == "t" || str == "T")
}

fn parse_quoted(val: AST) -> AST {
    AST::List(vec!(AST::Atom("quote".to_string()), val))
}

peg! ast(r#"

use ast::AST;

#[pub]
grammar -> Vec<AST> =
    expression*

expression -> AST =
    __ ast:value {
        ast
    }

value -> AST =
    integer
    / boolean
    / identifier
    / quoted
    / list

identifier -> AST =
    identifier:(
        initial subsequent*   { match_str }
        / peculiar_identifier { match_str }
    ) __ {
        super::parse_atom(identifier)
    }

initial -> &'input str =
    constituent
    / special_initial

constituent -> &'input str =
    letter

letter -> &'input str =
    [a-zA-Z] { match_str }

special_initial -> &'input str =
    [!$%&*/<=>?^_~] { match_str }

subsequent -> &'input str =
    initial
    / digit
    / special_subsequent

digit -> &'input str =
    [0-9] { match_str }

peculiar_identifier -> &'input str =
    (
        "->" subsequent*
        / "..."
        / "+"
        / "-"
    )
    { match_str }

special_subsequent -> &'input str =
    [+-.@] { match_str }

integer -> AST =
    sign:sign digits:digits __ {
        super::parse_decimal(digits, &sign)
    }

list -> AST =
    "(" values:(value ** __) ")" __ {
        super::parse_list(values)
    }
    / "[" values:(value ** __) "]" __ {
        super::parse_list(values)
    }
    / "(" left:(value ++ __) "." __ right:value ")" __ {
        super::parse_dotted_list(left, right)
    }
    / "[" left:(value ++ __) "." __ right:value "]" __ {
        super::parse_dotted_list(left, right)
    }

boolean -> AST =
    "\#" value:boolean_char __ {
        super::parse_bool(value)
    }

boolean_char -> &'input str =
    [tfTF] { match_str }

digits -> &'input str =
    digit+ { match_str }

sign -> super::IntegerSign =
    [-+]? {
        super::parse_sign(match_str)
    }

quoted -> AST =
    "'" value:value {
        super::parse_quoted(value)
    }

__ = (whitespace)*

whitespace =
    [ \t\r\n]

"#);

pub fn parse(input: &str) -> Result<Vec<AST>, Error> {
    match ast::grammar(input) {
        Ok(exprs)  => Ok(exprs),
        Err(error) => Err(Error::ParseError(error)),
    }
}
<commit_msg>Fixed deprecation notice on num::from_str.<commit_after>#[phase(plugin)]
extern crate peg_syntax_ext;

use ast::AST;
use runtime::Error;

#[deriving(PartialEq)]
enum IntegerSign {
    Positive,
    Negative,
}

fn parse_decimal(str: &str, sign: &IntegerSign) -> AST {
    let integer: i64 = str.parse().unwrap();

    AST::Integer(
        if *sign == IntegerSign::Negative {
            -integer
        } else {
            integer
        }
    )
}

fn parse_sign(str: &str) -> IntegerSign {
    match str {
        "-" => IntegerSign::Negative,
        _   => IntegerSign::Positive,
    }
}

fn parse_atom(str: &str) -> AST {
    AST::Atom(str.to_string())
}

fn parse_list(values: Vec<AST>) -> AST {
    AST::List(values)
}

fn parse_dotted_list(mut left: Vec<AST>, right: AST) -> AST {
    match right {
        AST::List(list) => {
            left.push_all(list.as_slice());
            AST::List(left)
        }
        AST::DottedList(list, right) => {
            left.push_all(list.as_slice());
            AST::DottedList(left, right)
        }
        _ => AST::DottedList(left, box right)
    }
}

fn parse_bool(str: &str) -> AST {
    AST::Bool(str == "t" || str == "T")
}

fn parse_quoted(val: AST) -> AST {
    AST::List(vec!(AST::Atom("quote".to_string()), val))
}

peg! ast(r#"

use ast::AST;

#[pub]
grammar -> Vec<AST> =
    expression*

expression -> AST =
    __ ast:value {
        ast
    }

value -> AST =
    integer
    / boolean
    / identifier
    / quoted
    / list

identifier -> AST =
    identifier:(
        initial subsequent*   { match_str }
        / peculiar_identifier { match_str }
    ) __ {
        super::parse_atom(identifier)
    }

initial -> &'input str =
    constituent
    / special_initial

constituent -> &'input str =
    letter

letter -> &'input str =
    [a-zA-Z] { match_str }

special_initial -> &'input str =
    [!$%&*/<=>?^_~] { match_str }

subsequent -> &'input str =
    initial
    / digit
    / special_subsequent

digit -> &'input str =
    [0-9] { match_str }

peculiar_identifier -> &'input str =
    (
        "->" subsequent*
        / "..."
        / "+"
        / "-"
    )
    { match_str }

special_subsequent -> &'input str =
    [+-.@] { match_str }

integer -> AST =
    sign:sign digits:digits __ {
        super::parse_decimal(digits, &sign)
    }

list -> AST =
    "(" values:(value ** __) ")" __ {
        super::parse_list(values)
    }
    / "[" values:(value ** __) "]" __ {
        super::parse_list(values)
    }
    / "(" left:(value ++ __) "." __ right:value ")" __ {
        super::parse_dotted_list(left, right)
    }
    / "[" left:(value ++ __) "." __ right:value "]" __ {
        super::parse_dotted_list(left, right)
    }

boolean -> AST =
    "\#" value:boolean_char __ {
        super::parse_bool(value)
    }

boolean_char -> &'input str =
    [tfTF] { match_str }

digits -> &'input str =
    digit+ { match_str }

sign -> super::IntegerSign =
    [-+]? {
        super::parse_sign(match_str)
    }

quoted -> AST =
    "'" value:value {
        super::parse_quoted(value)
    }

__ = (whitespace)*

whitespace =
    [ \t\r\n]

"#);

pub fn parse(input: &str) -> Result<Vec<AST>, Error> {
    match ast::grammar(input) {
        Ok(exprs)  => Ok(exprs),
        Err(error) => Err(Error::ParseError(error)),
    }
}
<|endoftext|>


<commit_before>#[phase(plugin)]
extern crate peg_syntax_ext;

#[deriving(Show, PartialEq)]
pub enum AST {
    Integer(i64),
}

#[deriving(PartialEq)]
pub enum IntegerSign {
    Positive,
    Negative,
}

pub mod integer {
    use parser::AST;
    use parser::IntegerSign;

    pub fn parse_decimal(str: &str, sign: &IntegerSign) -> AST {
        let integer: i64 = from_str(str).unwrap();

        AST::Integer(
            if *sign == IntegerSign::Negative {
                -integer
            } else {
                integer
            }
        )
    }

    pub fn parse_sign(str: &str) -> IntegerSign {
        match str {
            "-" => IntegerSign::Negative,
            _   => IntegerSign::Positive,
        }
    }
}

peg! ast(r#"

use parser::*;

#[pub]
value -> AST = integer

integer -> AST = sign:sign digits:digits {
    integer::parse_decimal(digits.as_slice(), &sign)
}

digits -> String = [0-9]+ {
    match_str.to_string()
}

sign -> IntegerSign = [-+]? {
    integer::parse_sign(match_str)
}

"#)

pub fn parse(input: &str) -> Result<AST, String> {
    ast::value(input)
}
<commit_msg>Improved parser syntax style.<commit_after>#[phase(plugin)]
extern crate peg_syntax_ext;

#[deriving(Show, PartialEq)]
pub enum AST {
    Integer(i64),
}

#[deriving(PartialEq)]
pub enum IntegerSign {
    Positive,
    Negative,
}

pub mod integer {
    use parser::AST;
    use parser::IntegerSign;

    pub fn parse_decimal(str: &str, sign: &IntegerSign) -> AST {
        let integer: i64 = from_str(str).unwrap();

        AST::Integer(
            if *sign == IntegerSign::Negative {
                -integer
            } else {
                integer
            }
        )
    }

    pub fn parse_sign(str: &str) -> IntegerSign {
        match str {
            "-" => IntegerSign::Negative,
            _   => IntegerSign::Positive,
        }
    }
}

peg! ast(r#"

use parser::*;

#[pub]
value -> AST =
    integer

integer -> AST =
    sign:sign digits:digits {
        integer::parse_decimal(digits, &sign)
    }

digits -> &'input str =
    [0-9]+ { match_str }

sign -> IntegerSign =
    [-+]? {
        integer::parse_sign(match_str)
    }

"#)

pub fn parse(input: &str) -> Result<AST, String> {
    ast::value(input)
}
<|endoftext|>


<commit_before>use std::collections::hash_set;
use std::collections::HashSet;
use std::hash::Hash;
use std::rc::Rc;

#[derive(Default, Debug, Eq, PartialEq)]
pub struct HashSetShallowClone<T: Hash + Eq + Clone> {
    set: HashSet<T>,
    items: Option<Rc<Vec<T>>>,
}

impl<T: Hash + Eq + Clone> HashSetShallowClone<T> {
    pub fn new() -> Self {
        HashSetShallowClone {
            set: HashSet::new(),
            items: None,
        }
    }

    pub fn items(&mut self) -> Rc<Vec<T>> {
        // TODO: store delta and update shallow map
        if let None = self.items {
            self.items = Some(Rc::new(self.set.iter().cloned().collect()));
        }
        self.items.as_mut().unwrap().clone()
    }

    pub fn get(&self, value: &T) -> Option<&T> {
        self.set.get(value)
    }

    pub fn remove(&mut self, item: &T) -> bool {
        // TODO: do not invalidate if nothing changed
        self.items.take();
        self.set.remove(item)
    }

    pub fn insert(&mut self, value: T) -> bool {
        // TODO: do not invalidate if nothing changed
        self.items.take();
        self.set.insert(value)
    }

    pub fn _iter(&self) -> hash_set::Iter<T> {
        self.set.iter()
    }
}
<commit_msg>Basic tests for HashSetShallowClone<commit_after>use std::collections::hash_set;
use std::collections::HashSet;
use std::hash::Hash;
use std::rc::Rc;

#[derive(Default, Debug, Eq, PartialEq)]
pub struct HashSetShallowClone<T: Hash + Eq + Clone> {
    set: HashSet<T>,
    items: Option<Rc<Vec<T>>>,
}

impl<T: Hash + Eq + Clone> HashSetShallowClone<T> {
    pub fn new() -> Self {
        HashSetShallowClone {
            set: HashSet::new(),
            items: None,
        }
    }

    pub fn items(&mut self) -> Rc<Vec<T>> {
        // TODO: store delta and update shallow map
        if let None = self.items {
            self.items = Some(Rc::new(self.set.iter().cloned().collect()));
        }
        self.items.as_mut().unwrap().clone()
    }

    pub fn get(&self, value: &T) -> Option<&T> {
        self.set.get(value)
    }

    pub fn remove(&mut self, item: &T) -> bool {
        // TODO: do not invalidate if nothing changed
        self.items.take();
        self.set.remove(item)
    }

    pub fn insert(&mut self, value: T) -> bool {
        // TODO: do not invalidate if nothing changed
        self.items.take();
        self.set.insert(value)
    }

    pub fn _iter(&self) -> hash_set::Iter<T> {
        self.set.iter()
    }
}

#[cfg(test)]
mod test {
    use super::HashSetShallowClone;
    use std::ops::Deref;

    #[test]
    fn insert_updates() {
        let mut s = HashSetShallowClone::new();
        s.insert(10);
        let mut items = s.items().deref().clone();
        items.sort();
        assert_eq!(&[10], &items[..]);

        s.insert(20);
        let mut items = s.items().deref().clone();
        items.sort();
        assert_eq!(&[10, 20], &items[..]);
    }

    #[test]
    fn remove_updates() {
        let mut s = HashSetShallowClone::new();
        s.insert(10);
        let mut items = s.items().deref().clone();
        items.sort();
        assert_eq!(&[10], &items[..]);

        s.insert(20);
        let mut items = s.items().deref().clone();
        items.sort();
        assert_eq!(&[10, 20], &items[..]);

        s.remove(&10);
        let mut items = s.items().deref().clone();
        items.sort();
        assert_eq!(&[20], &items[..]);
    }

}
<|endoftext|>


<commit_before>use errors::*;

use std::io::Read;
use xml::reader::XmlEvent;
use geo::Bbox;

use parser::Context;

/// consume consumes an element as a nothing.
pub fn consume<R: Read>(context: &mut Context<R>) -> Result<Bbox<f64>> {
    let mut element: Option<String> = None;
    let mut bounds: Bbox<f64> = Bbox {
        xmin: 0.,
        xmax: 0.,
        ymin: 0.,
        ymax: 0.,
    };
    for event in context.reader() {
        match event.chain_err(|| "error while parsing XML")? {
            XmlEvent::StartElement {
                name, attributes, ..
            } => {
                ensure!(element.is_none(), "cannot start element inside bounds");
                // get required bounds
                let minlat = attributes
                    .iter()
                    .filter(|attr| attr.name.local_name == "minlat")
                    .nth(0)
                    .ok_or("no min latitude attribute on bounds tag".to_owned())?;
                let maxlat = attributes
                    .iter()
                    .filter(|attr| attr.name.local_name == "maxlat")
                    .nth(0)
                    .ok_or("no max latitude attribute on bounds tag".to_owned())?;

                let minlat: f64 = minlat
                    .value
                    .parse()
                    .chain_err(|| "error while casting min latitude to f64")?;
                let maxlat: f64 = maxlat
                    .value
                    .parse()
                    .chain_err(|| "error while casting max latitude to f64")?;

                let minlon = attributes
                    .iter()
                    .filter(|attr| attr.name.local_name == "minlon")
                    .nth(0)
                    .ok_or("no min longitude attribute on bounds tag".to_owned())?;
                let maxlon = attributes
                    .iter()
                    .filter(|attr| attr.name.local_name == "maxlon")
                    .nth(0)
                    .ok_or("no max longitude attribute on bounds tag".to_owned())?;

                let minlon: f64 = minlon
                    .value
                    .parse()
                    .chain_err(|| "error while casting min longitude to f64")?;
                let maxlon: f64 = maxlon
                    .value
                    .parse()
                    .chain_err(|| "error while casting max longitude to f64")?;

                bounds.xmin = minlon;
                bounds.xmax = maxlon;
                bounds.ymin = minlat;
                bounds.ymax = maxlat;

                element = Some(name.local_name);
            }

            XmlEvent::EndElement { .. } => {
                return Ok(bounds);
            }

            _ => {}
        }
    }

    return Err("no end tag for bounds".into());
}

#[cfg(test)]
mod tests {
    use std::io::BufReader;
    use xml::reader::EventReader;

    use GpxVersion;
    use parser::Context;
    use super::consume;

    #[test]
    fn consume_bounds() {
        let bounds = consume!(
            "
<bounds minlat=\"45.487064362\" minlon=\"-74.031837463\" maxlat=\"45.701225281\" maxlon=\"-73.586273193\"/>
            ",
            GpxVersion::Gpx11
        );

        assert!(bounds.is_ok());

        let bounds = bounds.unwrap();
        assert_eq!(bounds.xmin, -74.031837463);
        assert_eq!(bounds.ymin, 45.487064362);
        assert_eq!(bounds.xmax, -73.586273193);
        assert_eq!(bounds.ymax, 45.701225281);
    }

    #[test]
    fn consume_bad_bounds() {
        let bounds = consume!(
            "<bounds minlat=\"32.4\" minlon=\"notanumber\"></wpt>",
            GpxVersion::Gpx11
        );

        assert!(bounds.is_err());
    }
}
<commit_msg>Rewrite bounds::consume cleaner and more strict: - Accept only "bounds" as starting tag, and only "bounds" as closing tag - Use InvalidChildElement, InvalidClosingTag and MissingClosingTag errors - Eliminate mutability and initialisation of bounds variable<commit_after>use errors::*;

use std::io::Read;
use xml::reader::XmlEvent;
use geo::Bbox;

use parser::Context;
use parser::verify_starting_tag;

/// consume consumes a bounds element until it ends.
pub fn consume<R: Read>(context: &mut Context<R>) -> Result<Bbox<f64>> {
    let attributes = verify_starting_tag(context, "bounds")?;
    // get required bounds
    let minlat = attributes
        .iter()
        .filter(|attr| attr.name.local_name == "minlat")
        .nth(0)
        .ok_or(ErrorKind::InvalidElementLacksAttribute("minlat", "bounds"))?;
    let maxlat = attributes
        .iter()
        .filter(|attr| attr.name.local_name == "maxlat")
        .nth(0)
        .ok_or(ErrorKind::InvalidElementLacksAttribute("maxlat", "bounds"))?;

    let minlat: f64 = minlat
        .value
        .parse()
        .chain_err(|| "error while casting min latitude to f64")?;
    let maxlat: f64 = maxlat
        .value
        .parse()
        .chain_err(|| "error while casting max latitude to f64")?;

    let minlon = attributes
        .iter()
        .filter(|attr| attr.name.local_name == "minlon")
        .nth(0)
        .ok_or(ErrorKind::InvalidElementLacksAttribute("minlon", "bounds"))?;
    let maxlon = attributes
        .iter()
        .filter(|attr| attr.name.local_name == "maxlon")
        .nth(0)
        .ok_or(ErrorKind::InvalidElementLacksAttribute("maxlon", "bounds"))?;

    let minlon: f64 = minlon
        .value
        .parse()
        .chain_err(|| "error while casting min longitude to f64")?;
    let maxlon: f64 = maxlon
        .value
        .parse()
        .chain_err(|| "error while casting max longitude to f64")?;

    let bounds: Bbox<f64> = Bbox {
        xmin: minlon,
        xmax: maxlon,
        ymin: minlat,
        ymax: maxlat,
    };

    for event in context.reader() {
        match event.chain_err(|| "error while parsing XML")? {
            XmlEvent::StartElement { name, .. } => {
                bail!(ErrorKind::InvalidChildElement(
                    name.local_name.clone(),
                    "bounds"
                ));
            }
            XmlEvent::EndElement { name } => {
                ensure!(
                    name.local_name == "bounds",
                    ErrorKind::InvalidClosingTag(name.local_name.clone(), "bounds")
                );
                return Ok(bounds);
            }
            _ => {}
        }
    }
    bail!(ErrorKind::MissingClosingTag("bounds"));
}

#[cfg(test)]
mod tests {
    use std::io::BufReader;
    use xml::reader::EventReader;

    use GpxVersion;
    use parser::Context;
    use super::consume;

    #[test]
    fn consume_bounds() {
        let bounds = consume!(
            "
<bounds minlat=\"45.487064362\" minlon=\"-74.031837463\" maxlat=\"45.701225281\" maxlon=\"-73.586273193\"/>
            ",
            GpxVersion::Gpx11
        );

        assert!(bounds.is_ok());

        let bounds = bounds.unwrap();
        assert_eq!(bounds.xmin, -74.031837463);
        assert_eq!(bounds.ymin, 45.487064362);
        assert_eq!(bounds.xmax, -73.586273193);
        assert_eq!(bounds.ymax, 45.701225281);
    }

    #[test]
    fn consume_bad_bounds() {
        let bounds = consume!(
            "<bounds minlat=\"32.4\" minlon=\"notanumber\"></wpt>",
            GpxVersion::Gpx11
        );

        assert!(bounds.is_err());
    }
}
<|endoftext|>