<commit_before>//! Request objects for non-blocking operations
//!
//! Non-blocking operations such as `immediate_send()` return request objects that borrow any
//! buffers involved in the operation so as to ensure proper access restrictions. In order to
//! release the borrowed buffers from the request objects, a completion operation such as
//! [`wait()`](struct.Request.html#method.wait) or [`test()`](struct.Request.html#method.test) must
//! be used on the request object.
//!
//! **Note:** If the `Request` is dropped (as opposed to calling `wait` or `test` explicitly), the
//! program will panic.
//!
//! To enforce this rule, every request object must be attached to some pre-existing
//! [`Scope`](trait.Scope.html), which is usually created with [`scope`](fn.scope.html).  At the end
//! of a `Scope`, all its remaining requests will be waited for until completion.
//!
//! To handle request completion in an RAII style, a request can be wrapped in either
//! [`WaitGuard`](struct.WaitGuard.html) or [`CancelGuard`](struct.CancelGuard.html), which will
//! follow the respective policy for completing the operation.  When the guard is dropped, the
//! request will be automatically detached from its `Scope`.
//!
//! # Unfinished features
//!
//! - **3.7**: Nonblocking mode:
//!   - Completion, `MPI_Waitany()`, `MPI_Waitall()`, `MPI_Waitsome()`,
//!   `MPI_Testany()`, `MPI_Testall()`, `MPI_Testsome()`, `MPI_Request_get_status()`
//! - **3.8**:
//!   - Cancellation, `MPI_Test_cancelled()`

use std::cell::RefCell;
use std::collections::HashSet;
use std::mem;
use std::marker::PhantomData;
use std::os::raw::c_int;

use ffi;
use ffi::{MPI_Request, MPI_Status};

use point_to_point::Status;
use raw::traits::*;

/// Check if the request is `MPI_REQUEST_NULL`.
fn is_null(request: MPI_Request) -> bool {
    request == unsafe_extern_static!(ffi::RSMPI_REQUEST_NULL)
}

/// A request object for a non-blocking operation attached to a `Scope` with lifetime `'a`
///
/// The `Scope` is needed to ensure that all buffers associated request will outlive the request
/// itself, even if the destructor of the request fails to run.
///
/// # Panics
///
/// Panics if the request object is dropped.  To prevent this, call `wait`, `wait_without_status`,
/// or `test`.  Alternatively, wrap the request inside a `WaitGuard` or `CancelGuard`.
///
/// # Examples
///
/// See `examples/immediate.rs`
///
/// # Standard section(s)
///
/// 3.7.1
#[must_use]
#[derive(Debug)]
pub struct Request<'a, S: Scope<'a> = StaticScope>(WaitGuard<'a, S>);

unsafe impl<'a, S: Scope<'a>> AsRaw for Request<'a, S> {
    type Raw = MPI_Request;
    fn as_raw(&self) -> Self::Raw {
        self.0.as_raw()
    }
}

impl<'a, S: Scope<'a>> Drop for Request<'a, S> {
    fn drop(&mut self) {
        panic!("request was dropped without being completed");
    }
}

impl<'a, S: Scope<'a>> From<WaitGuard<'a, S>> for Request<'a, S> {
    fn from(guard: WaitGuard<'a, S>) -> Self {
        Request(guard)
    }
}

impl<'a, S: Scope<'a>> From<CancelGuard<'a, S>> for Request<'a, S> {
    fn from(mut guard: CancelGuard<'a, S>) -> Self {
        // unwrapping an object that implements Drop is tricky
        Request(unsafe {
            let inner = mem::replace(&mut guard.0, mem::uninitialized());
            mem::forget(guard);
            inner
        })
    }
}

impl<'a, S: Scope<'a>> Request<'a, S> {
    /// Construct a request object from the raw MPI type.
    ///
    /// # Requirements
    ///
    /// - The request is a valid, active request.  It must not be `MPI_REQUEST_NULL`.
    /// - The request must not be persistent.
    /// - All buffers associated with the request must outlive `'a`.
    /// - The request must not be registered with the given scope.
    ///
    pub unsafe fn from_raw(request: MPI_Request, scope: S) -> Self {
        Request(WaitGuard::from_raw(request, scope))
    }

    /// Unregister the request object from its scope and deconstruct it into its raw parts.
    ///
    /// This is unsafe because the request may outlive its associated buffers.
    pub unsafe fn into_raw(self) -> (MPI_Request, S) {
        WaitGuard::from(self).into_raw()
    }

    /// Wait for an operation to finish.
    ///
    /// Will block execution of the calling thread until the associated operation has finished.
    ///
    /// # Examples
    ///
    /// See `examples/immediate.rs`
    ///
    /// # Standard section(s)
    ///
    /// 3.7.3
    pub fn wait(self) -> Status {
        unsafe {
            let mut status: MPI_Status = mem::uninitialized();
            self.0.raw_wait(Some(&mut status));
            self.into_raw();
            Status::from_raw(status)
        }
    }

    /// Wait for an operation to finish, but don’t bother retrieving the `Status` information.
    ///
    /// Will block execution of the calling thread until the associated operation has finished.
    ///
    /// # Standard section(s)
    ///
    /// 3.7.3
    pub fn wait_without_status(self) {
        unsafe {
            self.0.raw_wait(None);
            self.into_raw();
        }
    }

    /// Test whether an operation has finished.
    ///
    /// If the operation has finished, `Status` is returned.  Otherwise returns the unfinished
    /// `Request`.
    ///
    /// # Examples
    ///
    /// See `examples/immediate.rs`
    ///
    /// # Standard section(s)
    ///
    /// 3.7.3
    pub fn test(self) -> Result<Status, Self> {
        unsafe {
            let mut status: MPI_Status = mem::uninitialized();
            let mut flag: c_int = mem::uninitialized();
            let mut request = self.as_raw();
            ffi::MPI_Test(&mut request, &mut flag, &mut status);
            if flag != 0 {
                assert!(is_null(request));  // persistent requests are not supported
                self.into_raw();
                Ok(Status::from_raw(status))
            } else {
                Err(self)
            }
        }
    }

    /// Cancel an operation.
    ///
    /// The MPI implementation is not guaranteed to fulfill this operation.  It may not even be
    /// valid for certain types of requests.  In the future, the MPI forum may [deprecate
    /// cancellation of sends][mpi26] entirely.
    ///
    /// [mpi26]: https://github.com/mpi-forum/mpi-issues/issues/26
    ///
    /// # Examples
    ///
    /// See `examples/immediate.rs`
    ///
    /// # Standard section(s)
    ///
    /// 3.8.4
    pub fn cancel(&self) {
        self.0.cancel();
    }

    /// Reduce the scope of a request.
    pub fn shrink_scope_to<'b, S2>(self, scope: S2) -> Request<'b, S2>
        where 'a: 'b, S2: Scope<'b>
    {
        unsafe {
            let (request, _) = self.into_raw();
            Request::from_raw(request, scope)
        }
    }
}

/// Guard object that waits for the completion of an operation when it is dropped
///
/// The guard can be constructed or deconstructed using the `From` and `Into` traits.
///
/// # Examples
///
/// See `examples/immediate.rs`
#[derive(Debug)]
pub struct WaitGuard<'a, S: Scope<'a> = StaticScope> {
    request: MPI_Request,
    scope: S,
    phantom: PhantomData<RefCell<&'a ()>>,
}

impl<'a, S: Scope<'a>> Drop for WaitGuard<'a, S> {
    fn drop(&mut self) {
        unsafe {
            self.raw_wait(None);
            self.scope.unregister(&self.as_raw());
        }
    }
}

unsafe impl<'a, S: Scope<'a>> AsRaw for WaitGuard<'a, S> {
    type Raw = MPI_Request;
    fn as_raw(&self) -> Self::Raw {
        self.request
    }
}

impl<'a, S: Scope<'a>> From<Request<'a, S>> for WaitGuard<'a, S> {
    fn from(mut req: Request<'a, S>) -> Self {
        unsafe {
            let inner = mem::replace(&mut req.0, mem::uninitialized());
            mem::forget(req);
            inner
        }
    }
}

impl<'a, S: Scope<'a>> WaitGuard<'a, S> {
    /// Construct a request object from the raw MPI type.
    ///
    /// # Requirements
    ///
    /// - The request is a valid, active request.  It must not be `MPI_REQUEST_NULL`.
    /// - The request must not be persistent.
    /// - All buffers associated with the request must outlive `'a`.
    /// - The request must not be registered with the given scope.
    ///
    unsafe fn from_raw(request: MPI_Request, scope: S) -> Self {
        debug_assert!(!is_null(request));
        scope.register(request);
        WaitGuard { request: request, scope: scope, phantom: Default::default() }
    }

    /// Unregister the request object from its scope and deconstruct it into its raw parts.
    ///
    /// This is unsafe because the request may outlive its associated buffers.
    unsafe fn into_raw(mut self) -> (MPI_Request, S) {
        let request = self.as_raw();
        let scope = mem::replace(&mut self.scope, mem::uninitialized());
        mem::replace(&mut self.phantom, mem::uninitialized());
        mem::forget(self);
        scope.unregister(&request);
        (request, scope)
    }

    /// Wait for the request to finish.
    ///
    /// This is unsafe because `.request` is no longer valid afterwards.  This function should only
    /// be called if the caller calls `into_raw` afterward and forgets the request.
    unsafe fn raw_wait(&self, status: Option<&mut MPI_Status>) {
        let mut request = self.as_raw();
        let status = match status {
            Some(r) => r,
            None => ffi::RSMPI_STATUS_IGNORE,
        };
        ffi::MPI_Wait(&mut request, status);
        assert!(is_null(request));      // persistent requests are not supported
    }

    fn cancel(&self) {
        let mut request = self.as_raw();
        unsafe {
            ffi::MPI_Cancel(&mut request);
        }
    }
}

/// Guard object that tries to cancel and waits for the completion of an operation when it is
/// dropped
///
/// The guard can be constructed or deconstructed using the `From` and `Into` traits.
///
/// # Examples
///
/// See `examples/immediate.rs`
#[derive(Debug)]
pub struct CancelGuard<'a, S: Scope<'a> = StaticScope>(WaitGuard<'a, S>);

impl<'a, S: Scope<'a>> Drop for CancelGuard<'a, S> {
    fn drop(&mut self) {
        self.0.cancel();
    }
}

impl<'a, S: Scope<'a>> From<Request<'a, S>> for CancelGuard<'a, S> {
    fn from(req: Request<'a, S>) -> Self {
        CancelGuard(WaitGuard::from(req))
    }
}

/// A common interface for [`LocalScope`](struct.LocalScope.html) and
/// [`StaticScope`](struct.StaticScope.html)
///
/// This trait is an implementation detail.  You shouldn’t have to use or implement this trait.
pub unsafe trait Scope<'a> {
    /// Registers the request with the scope.
    unsafe fn register(&self, request: MPI_Request);

    /// Unregisters the request from the scope.
    unsafe fn unregister(&self, request: &MPI_Request);
}

/// The scope that lasts as long as the entire execution of the program
///
/// Unlike `LocalScope<'a>`, `StaticScope` does not require any bookkeeping on the requests as every
/// request associated with a `StaticScope` can live as long as they please.
///
/// A `StaticScope` can be created simply by calling the `StaticScope` constructor.
///
/// # Invariant
///
/// For any `Request` attached to a `StaticScope`, its associated buffers must be `'static`.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct StaticScope;

unsafe impl Scope<'static> for StaticScope {
    unsafe fn register(&self, _: MPI_Request) {}

    unsafe fn unregister(&self, _: &MPI_Request) {}
}

/// A temporary scope that lasts no more than the lifetime `'a`
///
/// Use `LocalScope` for to perform requests with temporary buffers.
///
/// To obtain a `LocalScope`, use the [`scope`](fn.scope.html) function.
///
/// # Invariant
///
/// For any `Request` attached to a `LocalScope<'a>`, its associated buffers must outlive `'a`.
#[derive(Debug)]
pub struct LocalScope<'a> {
    requests: RefCell<HashSet<MPI_Request>>,
    phantom: PhantomData<RefCell<&'a ()>>, // RefCell needed to ensure 'a is invariant
}

impl<'a> Drop for LocalScope<'a> {
    fn drop(&mut self) {
        for &request in &*self.requests.borrow() {
            unsafe {
                let _ = WaitGuard::from_raw(request, StaticScope);
            }
        }
    }
}

unsafe impl<'a, 'b> Scope<'a> for &'b LocalScope<'a> {
    unsafe fn register(&self, request: MPI_Request) {
        if !self.requests.borrow_mut().insert(request) {
            panic!("request already registered");
        }
    }

    unsafe fn unregister(&self, request: &MPI_Request) {
        if !self.requests.borrow_mut().remove(request) {
            panic!("can't unregister a request that wasn't registered");
        }
    }
}

/// Used to create a [`LocalScope`](struct.LocalScope.html)
///
/// The function creates a `LocalScope` and then passes it into the given
/// closure as an argument.
///
/// For safety reasons, all variables and buffers associated with a request
/// must exist *outside* the scope to which the request is attached.
///
/// It is typically used like this:
///
/// ```
/// /* declare variables and buffers here ... */
/// mpi::request::scope(|scope| {
///     /* perform sends and/or receives using 'scope' */
/// });
/// /* when scope ends, all associated requests are automatically waited for */
/// ```
///
/// # Examples
///
/// See `examples/immediate.rs`
pub fn scope<'a, F, R>(f: F) -> R
    where F: FnOnce(&LocalScope<'a>) -> R {
    f(&LocalScope {
        requests: Default::default(),
        phantom: Default::default(),
    })
}
<commit_msg>Change LocalScope drop behavior to panic<commit_after>//! Request objects for non-blocking operations
//!
//! Non-blocking operations such as `immediate_send()` return request objects that borrow any
//! buffers involved in the operation so as to ensure proper access restrictions. In order to
//! release the borrowed buffers from the request objects, a completion operation such as
//! [`wait()`](struct.Request.html#method.wait) or [`test()`](struct.Request.html#method.test) must
//! be used on the request object.
//!
//! **Note:** If the `Request` is dropped (as opposed to calling `wait` or `test` explicitly), the
//! program will panic.
//!
//! To enforce this rule, every request object must be attached to some pre-existing
//! [`Scope`](trait.Scope.html), which is usually created with [`scope`](fn.scope.html).  At the end
//! of a `Scope`, all its remaining requests will be waited for until completion.
//!
//! To handle request completion in an RAII style, a request can be wrapped in either
//! [`WaitGuard`](struct.WaitGuard.html) or [`CancelGuard`](struct.CancelGuard.html), which will
//! follow the respective policy for completing the operation.  When the guard is dropped, the
//! request will be automatically detached from its `Scope`.
//!
//! # Unfinished features
//!
//! - **3.7**: Nonblocking mode:
//!   - Completion, `MPI_Waitany()`, `MPI_Waitall()`, `MPI_Waitsome()`,
//!   `MPI_Testany()`, `MPI_Testall()`, `MPI_Testsome()`, `MPI_Request_get_status()`
//! - **3.8**:
//!   - Cancellation, `MPI_Test_cancelled()`

use std::cell::Cell;
use std::mem;
use std::marker::PhantomData;
use std::os::raw::c_int;

use ffi;
use ffi::{MPI_Request, MPI_Status};

use point_to_point::Status;
use raw::traits::*;

/// Check if the request is `MPI_REQUEST_NULL`.
fn is_null(request: MPI_Request) -> bool {
    request == unsafe_extern_static!(ffi::RSMPI_REQUEST_NULL)
}

/// A request object for a non-blocking operation attached to a `Scope` with lifetime `'a`
///
/// The `Scope` is needed to ensure that all buffers associated request will outlive the request
/// itself, even if the destructor of the request fails to run.
///
/// # Panics
///
/// Panics if the request object is dropped.  To prevent this, call `wait`, `wait_without_status`,
/// or `test`.  Alternatively, wrap the request inside a `WaitGuard` or `CancelGuard`.
///
/// # Examples
///
/// See `examples/immediate.rs`
///
/// # Standard section(s)
///
/// 3.7.1
#[must_use]
#[derive(Debug)]
pub struct Request<'a, S: Scope<'a> = StaticScope>(WaitGuard<'a, S>);

unsafe impl<'a, S: Scope<'a>> AsRaw for Request<'a, S> {
    type Raw = MPI_Request;
    fn as_raw(&self) -> Self::Raw {
        self.0.as_raw()
    }
}

impl<'a, S: Scope<'a>> Drop for Request<'a, S> {
    fn drop(&mut self) {
        panic!("request was dropped without being completed");
    }
}

impl<'a, S: Scope<'a>> From<WaitGuard<'a, S>> for Request<'a, S> {
    fn from(guard: WaitGuard<'a, S>) -> Self {
        Request(guard)
    }
}

impl<'a, S: Scope<'a>> From<CancelGuard<'a, S>> for Request<'a, S> {
    fn from(mut guard: CancelGuard<'a, S>) -> Self {
        // unwrapping an object that implements Drop is tricky
        Request(unsafe {
            let inner = mem::replace(&mut guard.0, mem::uninitialized());
            mem::forget(guard);
            inner
        })
    }
}

impl<'a, S: Scope<'a>> Request<'a, S> {
    /// Construct a request object from the raw MPI type.
    ///
    /// # Requirements
    ///
    /// - The request is a valid, active request.  It must not be `MPI_REQUEST_NULL`.
    /// - The request must not be persistent.
    /// - All buffers associated with the request must outlive `'a`.
    /// - The request must not be registered with the given scope.
    ///
    pub unsafe fn from_raw(request: MPI_Request, scope: S) -> Self {
        Request(WaitGuard::from_raw(request, scope))
    }

    /// Unregister the request object from its scope and deconstruct it into its raw parts.
    ///
    /// This is unsafe because the request may outlive its associated buffers.
    pub unsafe fn into_raw(self) -> (MPI_Request, S) {
        WaitGuard::from(self).into_raw()
    }

    /// Wait for an operation to finish.
    ///
    /// Will block execution of the calling thread until the associated operation has finished.
    ///
    /// # Examples
    ///
    /// See `examples/immediate.rs`
    ///
    /// # Standard section(s)
    ///
    /// 3.7.3
    pub fn wait(self) -> Status {
        unsafe {
            let mut status: MPI_Status = mem::uninitialized();
            self.0.raw_wait(Some(&mut status));
            self.into_raw();
            Status::from_raw(status)
        }
    }

    /// Wait for an operation to finish, but don’t bother retrieving the `Status` information.
    ///
    /// Will block execution of the calling thread until the associated operation has finished.
    ///
    /// # Standard section(s)
    ///
    /// 3.7.3
    pub fn wait_without_status(self) {
        unsafe {
            self.0.raw_wait(None);
            self.into_raw();
        }
    }

    /// Test whether an operation has finished.
    ///
    /// If the operation has finished, `Status` is returned.  Otherwise returns the unfinished
    /// `Request`.
    ///
    /// # Examples
    ///
    /// See `examples/immediate.rs`
    ///
    /// # Standard section(s)
    ///
    /// 3.7.3
    pub fn test(self) -> Result<Status, Self> {
        unsafe {
            let mut status: MPI_Status = mem::uninitialized();
            let mut flag: c_int = mem::uninitialized();
            let mut request = self.as_raw();
            ffi::MPI_Test(&mut request, &mut flag, &mut status);
            if flag != 0 {
                assert!(is_null(request));  // persistent requests are not supported
                self.into_raw();
                Ok(Status::from_raw(status))
            } else {
                Err(self)
            }
        }
    }

    /// Cancel an operation.
    ///
    /// The MPI implementation is not guaranteed to fulfill this operation.  It may not even be
    /// valid for certain types of requests.  In the future, the MPI forum may [deprecate
    /// cancellation of sends][mpi26] entirely.
    ///
    /// [mpi26]: https://github.com/mpi-forum/mpi-issues/issues/26
    ///
    /// # Examples
    ///
    /// See `examples/immediate.rs`
    ///
    /// # Standard section(s)
    ///
    /// 3.8.4
    pub fn cancel(&self) {
        self.0.cancel();
    }

    /// Reduce the scope of a request.
    pub fn shrink_scope_to<'b, S2>(self, scope: S2) -> Request<'b, S2>
        where 'a: 'b, S2: Scope<'b>
    {
        unsafe {
            let (request, _) = self.into_raw();
            Request::from_raw(request, scope)
        }
    }
}

/// Guard object that waits for the completion of an operation when it is dropped
///
/// The guard can be constructed or deconstructed using the `From` and `Into` traits.
///
/// # Examples
///
/// See `examples/immediate.rs`
#[derive(Debug)]
pub struct WaitGuard<'a, S: Scope<'a> = StaticScope> {
    request: MPI_Request,
    scope: S,
    phantom: PhantomData<Cell<&'a ()>>,
}

impl<'a, S: Scope<'a>> Drop for WaitGuard<'a, S> {
    fn drop(&mut self) {
        unsafe {
            self.raw_wait(None);
            self.scope.unregister();
        }
    }
}

unsafe impl<'a, S: Scope<'a>> AsRaw for WaitGuard<'a, S> {
    type Raw = MPI_Request;
    fn as_raw(&self) -> Self::Raw {
        self.request
    }
}

impl<'a, S: Scope<'a>> From<Request<'a, S>> for WaitGuard<'a, S> {
    fn from(mut req: Request<'a, S>) -> Self {
        unsafe {
            let inner = mem::replace(&mut req.0, mem::uninitialized());
            mem::forget(req);
            inner
        }
    }
}

impl<'a, S: Scope<'a>> WaitGuard<'a, S> {
    /// Construct a request object from the raw MPI type.
    ///
    /// # Requirements
    ///
    /// - The request is a valid, active request.  It must not be `MPI_REQUEST_NULL`.
    /// - The request must not be persistent.
    /// - All buffers associated with the request must outlive `'a`.
    /// - The request must not be registered with the given scope.
    ///
    unsafe fn from_raw(request: MPI_Request, scope: S) -> Self {
        debug_assert!(!is_null(request));
        scope.register();
        WaitGuard { request: request, scope: scope, phantom: Default::default() }
    }

    /// Unregister the request object from its scope and deconstruct it into its raw parts.
    ///
    /// This is unsafe because the request may outlive its associated buffers.
    unsafe fn into_raw(mut self) -> (MPI_Request, S) {
        let request = self.as_raw();
        let scope = mem::replace(&mut self.scope, mem::uninitialized());
        mem::replace(&mut self.phantom, mem::uninitialized());
        mem::forget(self);
        scope.unregister();
        (request, scope)
    }

    /// Wait for the request to finish.
    ///
    /// This is unsafe because `.request` is no longer valid afterwards.  This function should only
    /// be called if the caller calls `into_raw` afterward and forgets the request.
    unsafe fn raw_wait(&self, status: Option<&mut MPI_Status>) {
        let mut request = self.as_raw();
        let status = match status {
            Some(r) => r,
            None => ffi::RSMPI_STATUS_IGNORE,
        };
        ffi::MPI_Wait(&mut request, status);
        assert!(is_null(request));      // persistent requests are not supported
    }

    fn cancel(&self) {
        let mut request = self.as_raw();
        unsafe {
            ffi::MPI_Cancel(&mut request);
        }
    }
}

/// Guard object that tries to cancel and waits for the completion of an operation when it is
/// dropped
///
/// The guard can be constructed or deconstructed using the `From` and `Into` traits.
///
/// # Examples
///
/// See `examples/immediate.rs`
#[derive(Debug)]
pub struct CancelGuard<'a, S: Scope<'a> = StaticScope>(WaitGuard<'a, S>);

impl<'a, S: Scope<'a>> Drop for CancelGuard<'a, S> {
    fn drop(&mut self) {
        self.0.cancel();
    }
}

impl<'a, S: Scope<'a>> From<Request<'a, S>> for CancelGuard<'a, S> {
    fn from(req: Request<'a, S>) -> Self {
        CancelGuard(WaitGuard::from(req))
    }
}

/// A common interface for [`LocalScope`](struct.LocalScope.html) and
/// [`StaticScope`](struct.StaticScope.html)
///
/// This trait is an implementation detail.  You shouldn’t have to use or implement this trait.
pub unsafe trait Scope<'a> {
    /// Registers a request with the scope.
    unsafe fn register(&self);

    /// Unregisters a request from the scope.
    unsafe fn unregister(&self);
}

/// The scope that lasts as long as the entire execution of the program
///
/// Unlike `LocalScope<'a>`, `StaticScope` does not require any bookkeeping on the requests as every
/// request associated with a `StaticScope` can live as long as they please.
///
/// A `StaticScope` can be created simply by calling the `StaticScope` constructor.
///
/// # Invariant
///
/// For any `Request` attached to a `StaticScope`, its associated buffers must be `'static`.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct StaticScope;

unsafe impl Scope<'static> for StaticScope {
    unsafe fn register(&self) {}

    unsafe fn unregister(&self) {}
}

/// A temporary scope that lasts no more than the lifetime `'a`
///
/// Use `LocalScope` for to perform requests with temporary buffers.
///
/// To obtain a `LocalScope`, use the [`scope`](fn.scope.html) function.
///
/// # Invariant
///
/// For any `Request` attached to a `LocalScope<'a>`, its associated buffers must outlive `'a`.
///
/// # Panics
///
/// When `LocalScope` is dropped, it will panic if there are any lingering `Requests` that have not
/// yet been completed.
#[derive(Debug)]
pub struct LocalScope<'a> {
    num_requests: Cell<usize>,
    phantom: PhantomData<Cell<&'a ()>>, // Cell needed to ensure 'a is invariant
}

impl<'a> Drop for LocalScope<'a> {
    fn drop(&mut self) {
        if self.num_requests.get() != 0 {
            panic!("at least one request was dropped without being completed");
        }
    }
}

unsafe impl<'a, 'b> Scope<'a> for &'b LocalScope<'a> {
    unsafe fn register(&self) {
        self.num_requests.set(self.num_requests.get() + 1)
    }

    unsafe fn unregister(&self) {
        self.num_requests.set(self.num_requests.get().checked_sub(1)
                              .expect("unregister has been called more times than register"))
    }
}

/// Used to create a [`LocalScope`](struct.LocalScope.html)
///
/// The function creates a `LocalScope` and then passes it into the given
/// closure as an argument.
///
/// For safety reasons, all variables and buffers associated with a request
/// must exist *outside* the scope to which the request is attached.
///
/// It is typically used like this:
///
/// ```
/// /* declare variables and buffers here ... */
/// mpi::request::scope(|scope| {
///     /* perform sends and/or receives using 'scope' */
/// });
/// /* at end of scope, panic if there are requests that have not yet completed */
/// ```
///
/// # Examples
///
/// See `examples/immediate.rs`
pub fn scope<'a, F, R>(f: F) -> R
    where F: FnOnce(&LocalScope<'a>) -> R {
    f(&LocalScope {
        num_requests: Default::default(),
        phantom: Default::default(),
    })
}
<|endoftext|>


<commit_before>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

use std::collections::HashMap;
use rustc_serialize::{json, Decodable};

/// This enum represents the various types of HTTP requests.
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
pub enum Method {
    Get,
    Put,
    Post,
    Delete,
    NoImpl,
}

/// A trait that allows for extracting variables from URIs.
pub trait FromUri {
    /// A function to parse a string into the correct type.
    fn from_uri(data: &str) -> Self;
}

impl FromUri for String {
    fn from_uri(data: &str) -> String {
        String::from(data)
    }
}

impl FromUri for i32 {
    fn from_uri(data: &str) -> i32 {
        match data.parse::<i32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched integer can't be parsed: {:?}", e),
        }
    }
}

impl FromUri for u32 {
    fn from_uri(data: &str) -> u32 {
        match data.parse::<u32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched integer can't be parsed: {:?}", e),
        }
    }
}

impl FromUri for f32 {
    fn from_uri(data: &str) -> f32 {
        match data.parse::<f32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched float can't be parsed: {:?}", e),
        }
    }
}

/// This struct represents a request from an HTTP client.
#[derive(Debug)]
pub struct Request {
    pub method:  Method,
    pub path:    String,
    pub payload: Vec<u8>,
    pub params:  HashMap<String, String>,
    headers:     HashMap<String, String>,
}

impl Request {
    /// Create a new, empty Request.
    pub fn new() -> Request {
        Request {
            method:  Method::NoImpl,
            path:    String::new(),
            headers: HashMap::new(),
            params:  HashMap::new(),
            payload: Vec::with_capacity(2048),
        }
    }

    /// Create a Request from an HTTP request string.
    pub fn from_str(rqstr: &str) -> Request {
        let mut req = Request::new();
        req.parse(rqstr);
        req
    }

    /// Get a variable from the URI.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the route "/hello/<str:name>"
    /// fn handler(req: &Request) -> Response {
    ///     let name: String = req.get("name");
    ///     utils::make_response(format!("<b>Hello, {}!</b>", name), "text/html", 200)
    /// }
    /// ```
    pub fn get<T: FromUri>(&self, name: &str) -> T {
        if !self.params.contains_key(name) {
            panic!("invalid route parameter {:?}", name);
        }

        FromUri::from_uri(&self.params[name])
    }

    /// Get a raw JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data = req.get_json();
    ///
    ///     match data {
    ///         Some(val) => utils::make_response(format!("We got: {}", val), "text/plain", 200),
    ///         None      => utils::make_response("We got nothing :(", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_json(&self) -> Option<json::Json> {
        match String::from_utf8(self.payload.clone()) {
            Err(_)      => None,
            Ok(payload) => {
                match json::Json::from_str(&payload) {
                    Ok(data)    => Some(data),
                    Err(_)      => None,
                }
            }
        }
    }

    /// Get a composed JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// use canteen::{Request, Response};
    ///
    /// #[derive(RustcDecodable)]
    /// struct Foo {
    ///     item: i32,
    /// }
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data: Foo = req.get_json_obj();
    ///     utils::make_response(format!("We got: {}!", data.item), "text/html", 200)
    /// }
    /// ```
    pub fn get_json_obj<T: Decodable>(&self) -> Result<T, json::DecoderError> {
        let data = String::from_utf8(self.payload.clone()).unwrap();
        json::decode(&data)
    }

    fn parse(&mut self, rqstr: &str) {
        let mut buf: Vec<&str> = rqstr.splitn(2, "\r\n").collect();
        let ask: Vec<&str> = buf[0].splitn(3, ' ').collect();

        self.method = match ask[0] {
            "GET"           => Method::Get,
            "PUT" | "PATCH" => Method::Put,
            "POST"          => Method::Post,
            "DELETE"        => Method::Delete,
            _               => Method::NoImpl,
        };
        self.path = String::from(ask[1]);

        loop {
            buf = buf[1].splitn(2, "\r\n").collect();

            if buf[0] == "" {
                if buf.len() == 1 || buf[1] == "" {
                    // no payload
                    break;
                }

                self.payload.extend(buf[1].as_bytes());
                break;
            }

            let hdr: Vec<&str> = buf[0].splitn(2, ": ").collect();

            if hdr.len() == 2 {
                self.headers.insert(String::from(hdr[0]), String::from(hdr[1]));
            }
        }
    }
}

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

    #[derive(RustcDecodable)]
    struct Foo {
        item: i32,
    }

    #[test]
    fn test_fromuri_trait_i32() {
        let pos = String::from("1234");
        assert_eq!(1234, FromUri::from_uri(&pos));

        let neg = String::from("-4321");
        assert_eq!(-4321, FromUri::from_uri(&neg));
    }

    #[test]
    fn test_fromuri_trait_u32() {
        let orig = String::from("1234");
        assert_eq!(1234, FromUri::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_string() {
        let orig = String::from("foobar");
        assert_eq!("foobar", <String as FromUri>::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_float() {
        let pos = String::from("123.45");
        assert_eq!(123.45f32, FromUri::from_uri(&pos));

        let neg = String::from("-54.321");
        assert_eq!(-54.321f32, FromUri::from_uri(&neg));
    }

    #[test]
    fn test_get_fromuri_i32() {
        let mut req = Request::new();
        req.params.insert(String::from("test"), String::from("1234"));

        assert_eq!(1234, req.get("test"));
    }

    #[test]
    fn test_get_json() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data = req.get_json().unwrap();

        assert_eq!(true, data.is_object());

        let obj = data.as_object().unwrap();
        let val = obj.get("item").unwrap();

        assert_eq!(true, val.is_u64());
        assert_eq!(123u64, val.as_u64().unwrap());
    }

    #[test]
    fn test_get_json_obj() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data: Foo = req.get_json_obj().unwrap();

        assert_eq!(123, data.item);
    }
}
<commit_msg>show the correct documentation for get_json_obj<commit_after>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

use std::collections::HashMap;
use rustc_serialize::{json, Decodable};

/// This enum represents the various types of HTTP requests.
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
pub enum Method {
    Get,
    Put,
    Post,
    Delete,
    NoImpl,
}

/// A trait that allows for extracting variables from URIs.
pub trait FromUri {
    /// A function to parse a string into the correct type.
    fn from_uri(data: &str) -> Self;
}

impl FromUri for String {
    fn from_uri(data: &str) -> String {
        String::from(data)
    }
}

impl FromUri for i32 {
    fn from_uri(data: &str) -> i32 {
        match data.parse::<i32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched integer can't be parsed: {:?}", e),
        }
    }
}

impl FromUri for u32 {
    fn from_uri(data: &str) -> u32 {
        match data.parse::<u32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched integer can't be parsed: {:?}", e),
        }
    }
}

impl FromUri for f32 {
    fn from_uri(data: &str) -> f32 {
        match data.parse::<f32>() {
            Ok(v)  => v,
            Err(e) => panic!("matched float can't be parsed: {:?}", e),
        }
    }
}

/// This struct represents a request from an HTTP client.
#[derive(Debug)]
pub struct Request {
    pub method:  Method,
    pub path:    String,
    pub payload: Vec<u8>,
    pub params:  HashMap<String, String>,
    headers:     HashMap<String, String>,
}

impl Request {
    /// Create a new, empty Request.
    pub fn new() -> Request {
        Request {
            method:  Method::NoImpl,
            path:    String::new(),
            headers: HashMap::new(),
            params:  HashMap::new(),
            payload: Vec::with_capacity(2048),
        }
    }

    /// Create a Request from an HTTP request string.
    pub fn from_str(rqstr: &str) -> Request {
        let mut req = Request::new();
        req.parse(rqstr);
        req
    }

    /// Get a variable from the URI.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the route "/hello/<str:name>"
    /// fn handler(req: &Request) -> Response {
    ///     let name: String = req.get("name");
    ///     utils::make_response(format!("<b>Hello, {}!</b>", name), "text/html", 200)
    /// }
    /// ```
    pub fn get<T: FromUri>(&self, name: &str) -> T {
        if !self.params.contains_key(name) {
            panic!("invalid route parameter {:?}", name);
        }

        FromUri::from_uri(&self.params[name])
    }

    /// Get a raw JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data = req.get_json();
    ///
    ///     match data {
    ///         Some(val) => utils::make_response(format!("We got: {}", val), "text/plain", 200),
    ///         None      => utils::make_response("We got nothing :(", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_json(&self) -> Option<json::Json> {
        match String::from_utf8(self.payload.clone()) {
            Err(_)      => None,
            Ok(payload) => {
                match json::Json::from_str(&payload) {
                    Ok(data)    => Some(data),
                    Err(_)      => None,
                }
            }
        }
    }

    /// Get a composed JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// use canteen::{Request, Response};
    ///
    /// #[derive(RustcDecodable)]
    /// struct Foo {
    ///     item: i32,
    /// }
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data: Foo = req.get_json_obj();
    ///
    ///     match data {
    ///         Ok(foo) => utils::make_response(format!("We got: {}!", data.item), "text/plain", 200),
    ///         Err(_)  => utils::make_response("We got nothing :(", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_json_obj<T: Decodable>(&self) -> Result<T, json::DecoderError> {
        let data = String::from_utf8(self.payload.clone()).unwrap();
        json::decode(&data)
    }

    fn parse(&mut self, rqstr: &str) {
        let mut buf: Vec<&str> = rqstr.splitn(2, "\r\n").collect();
        let ask: Vec<&str> = buf[0].splitn(3, ' ').collect();

        self.method = match ask[0] {
            "GET"           => Method::Get,
            "PUT" | "PATCH" => Method::Put,
            "POST"          => Method::Post,
            "DELETE"        => Method::Delete,
            _               => Method::NoImpl,
        };
        self.path = String::from(ask[1]);

        loop {
            buf = buf[1].splitn(2, "\r\n").collect();

            if buf[0] == "" {
                if buf.len() == 1 || buf[1] == "" {
                    // no payload
                    break;
                }

                self.payload.extend(buf[1].as_bytes());
                break;
            }

            let hdr: Vec<&str> = buf[0].splitn(2, ": ").collect();

            if hdr.len() == 2 {
                self.headers.insert(String::from(hdr[0]), String::from(hdr[1]));
            }
        }
    }
}

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

    #[derive(RustcDecodable)]
    struct Foo {
        item: i32,
    }

    #[test]
    fn test_fromuri_trait_i32() {
        let pos = String::from("1234");
        assert_eq!(1234, FromUri::from_uri(&pos));

        let neg = String::from("-4321");
        assert_eq!(-4321, FromUri::from_uri(&neg));
    }

    #[test]
    fn test_fromuri_trait_u32() {
        let orig = String::from("1234");
        assert_eq!(1234, FromUri::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_string() {
        let orig = String::from("foobar");
        assert_eq!("foobar", <String as FromUri>::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_float() {
        let pos = String::from("123.45");
        assert_eq!(123.45f32, FromUri::from_uri(&pos));

        let neg = String::from("-54.321");
        assert_eq!(-54.321f32, FromUri::from_uri(&neg));
    }

    #[test]
    fn test_get_fromuri_i32() {
        let mut req = Request::new();
        req.params.insert(String::from("test"), String::from("1234"));

        assert_eq!(1234, req.get("test"));
    }

    #[test]
    fn test_get_json() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data = req.get_json().unwrap();

        assert_eq!(true, data.is_object());

        let obj = data.as_object().unwrap();
        let val = obj.get("item").unwrap();

        assert_eq!(true, val.is_u64());
        assert_eq!(123u64, val.as_u64().unwrap());
    }

    #[test]
    fn test_get_json_obj() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data: Foo = req.get_json_obj().unwrap();

        assert_eq!(123, data.item);
    }
}
<|endoftext|>


<commit_before>
use token::{Token, TokenKind};
use error::{NcclError, ErrorKind};

// ranked worst to least
enum Indent {
    Neither,
    Tabs,
    Spaces(u8),
}

pub struct Scanner {
    source: Vec<u8>,
    tokens: Vec<Token>,
    start: usize,
    current: usize,
    line: u64,
    indent: Indent,
}

impl Scanner {
    pub fn new(source: String) -> Self {
        Scanner {
            source: source.into_bytes(),
            tokens: Vec::new(),
            start: 0,
            current: 0,
            line: 1,
            indent: Indent::Neither,
        }
    }

    pub fn scan_tokens(&mut self) -> Result<Vec<Token>, NcclError> {
        while !self.is_at_end() {
            self.start = self.current;
            match self.scan_token() {
                Ok(_) => {},
                Err(e) => return Err(e)
            }
        }

        self.tokens.push(Token::new(TokenKind::EOF, "".into(), self.line));
        Ok(self.tokens.clone())
    }

    fn scan_token(&mut self) -> Result<(), NcclError> {
        let mut error = Ok(());
        match self.advance() {
            b':' => {
                self.add_token(TokenKind::Colon);
                while self.peek() == b' ' && !self.is_at_end() {
                    self.advance();
                }
                if self.is_at_end() {
                    error = Err(NcclError::new(ErrorKind::ParseError, "Expected schema name, found EOF", self.line));
                }
            },

            b'#' => {
                while self.peek() != b'\n' && !self.is_at_end() {
                    self.advance();
                }
            },

            b' ' => {
                match self.indent {
                    Indent::Neither => {
                        let mut spaces = 0;
                        while self.peek() == b' ' && !self.is_at_end() {
                            self.advance();
                            spaces += 1;
                        }
                        if self.is_at_end() {
                            error = Err(NcclError::new(ErrorKind::ParseError, "Expected value, found EOF", self.line));
                        }
                        self.indent = Indent::Spaces(spaces);
                        self.add_token(TokenKind::Indent);
                    }
                    Indent::Spaces(s) => {
                        let mut spaces = 0;
                        while spaces < s  && !self.is_at_end() {
                            if self.peek() != b' ' {
                                error = Err(NcclError::new(ErrorKind::IndentationError, &format!("Incorrect number of spaces: found {}, expected {}", spaces, s), self.line));
                            }
                            self.advance();
                            spaces += 1;
                        }
                        if self.is_at_end() {
                            error = Err(NcclError::new(ErrorKind::ParseError, "Expected value, found EOF", self.line));
                        }
                        self.add_token(TokenKind::Indent);
                    },
                    Indent::Tabs => { error = Err(NcclError::new(ErrorKind::IndentationError, "Expected tabs, found spaces", self.line)); }
                }
            },

            b'\t' => {
                match self.indent {
                    Indent::Neither => {
                        self.add_token(TokenKind::Indent);
                        self.indent = Indent::Tabs;
                    },
                    Indent::Tabs => {
                        self.add_token(TokenKind::Indent);
                    },
                    Indent::Spaces(_) => { error = Err(NcclError::new(ErrorKind::IndentationError, "Expected spaces, found tabs", self.line)); }
                }
            },

            b'\n' => {
                self.add_token(TokenKind::Newline);
                self.line += 1;
            },

            b'"' => if let Err(e) = self.string() { error = Err(e); },

            _ => if let Err(e) = self.identifier() { error = Err(e); },
        }

        error
    }

    fn identifier(&mut self) -> Result<(), NcclError> {
        while self.peek() != b'\n' && !self.is_at_end() {
            self.advance();
        }

        let value = String::from_utf8(self.source[self.start..self.current].to_vec()).unwrap();
        self.add_token_string(TokenKind::Name, value);

        Ok(())
    }

    fn string(&mut self) -> Result<(), NcclError> {
        while self.peek() != b'"' && !self.is_at_end() {
            if self.peek() == b'\n' {
                self.line += 1;
            }
            self.advance();
        }

        if self.is_at_end() {
            return Err(NcclError::new(ErrorKind::ParseError, "Unterminated string", self.line));
        }

        self.advance();

        let value = String::from_utf8(self.source[self.start + 1..self.current - 1].to_vec()).unwrap();
        self.add_token_string(TokenKind::Name, value);

        Ok(())
    }

    fn is_at_end(&mut self) -> bool {
        self.current >= self.source.len()
    }

    fn advance(&mut self) -> u8 {
        self.current += 1;
        self.source[self.current - 1]
    }

    fn add_token(&mut self, kind: TokenKind) {
        let text = String::from_utf8(self.source[self.start..self.current].to_vec()).unwrap();
        self.tokens.push(Token::new(kind, text, self.line));
    }

    fn add_token_string(&mut self, kind: TokenKind, value: String) {
        self.tokens.push(Token::new(kind, value, self.line));
    }

    fn peek(&mut self) -> u8 {
        if self.current >= self.source.len() {
            b'\0'
        } else {
            self.source[self.current]
        }
    }
}

<commit_msg>fix false positive with schema<commit_after>
use token::{Token, TokenKind};
use error::{NcclError, ErrorKind};

// ranked worst to least
enum Indent {
    Neither,
    Tabs,
    Spaces(u8),
}

pub struct Scanner {
    source: Vec<u8>,
    tokens: Vec<Token>,
    start: usize,
    current: usize,
    line: u64,
    indent: Indent,
}

impl Scanner {
    pub fn new(source: String) -> Self {
        Scanner {
            source: source.into_bytes(),
            tokens: Vec::new(),
            start: 0,
            current: 0,
            line: 1,
            indent: Indent::Neither,
        }
    }

    pub fn scan_tokens(&mut self) -> Result<Vec<Token>, NcclError> {
        while !self.is_at_end() {
            self.start = self.current;
            match self.scan_token() {
                Ok(_) => {},
                Err(e) => return Err(e)
            }
        }

        self.tokens.push(Token::new(TokenKind::EOF, "".into(), self.line));
        Ok(self.tokens.clone())
    }

    fn scan_token(&mut self) -> Result<(), NcclError> {
        let mut error = Ok(());
        match self.advance() {
            b':' => {
                self.add_token(TokenKind::Colon);
                while self.peek() == b' ' && !self.is_at_end() {
                    self.advance();
                }
                if self.is_at_end() || self.peek() == b'\n' {
                    error = Err(NcclError::new(ErrorKind::ParseError, "Expected schema name, found EOF", self.line));
                }
            },

            b'#' => {
                while self.peek() != b'\n' && !self.is_at_end() {
                    self.advance();
                }
            },

            b' ' => {
                match self.indent {
                    Indent::Neither => {
                        let mut spaces = 0;
                        while self.peek() == b' ' && !self.is_at_end() {
                            self.advance();
                            spaces += 1;
                        }
                        if self.is_at_end() {
                            error = Err(NcclError::new(ErrorKind::ParseError, "Expected value, found EOF", self.line));
                        }
                        self.indent = Indent::Spaces(spaces);
                        self.add_token(TokenKind::Indent);
                    }
                    Indent::Spaces(s) => {
                        let mut spaces = 0;
                        while spaces < s  && !self.is_at_end() {
                            if self.peek() != b' ' {
                                error = Err(NcclError::new(ErrorKind::IndentationError, &format!("Incorrect number of spaces: found {}, expected {}", spaces, s), self.line));
                            }
                            self.advance();
                            spaces += 1;
                        }
                        if self.is_at_end() {
                            error = Err(NcclError::new(ErrorKind::ParseError, "Expected value, found EOF", self.line));
                        }
                        self.add_token(TokenKind::Indent);
                    },
                    Indent::Tabs => { error = Err(NcclError::new(ErrorKind::IndentationError, "Expected tabs, found spaces", self.line)); }
                }
            },

            b'\t' => {
                match self.indent {
                    Indent::Neither => {
                        self.add_token(TokenKind::Indent);
                        self.indent = Indent::Tabs;
                    },
                    Indent::Tabs => {
                        self.add_token(TokenKind::Indent);
                    },
                    Indent::Spaces(_) => { error = Err(NcclError::new(ErrorKind::IndentationError, "Expected spaces, found tabs", self.line)); }
                }
            },

            b'\n' => {
                self.add_token(TokenKind::Newline);
                self.line += 1;
            },

            b'"' => if let Err(e) = self.string() { error = Err(e); },

            _ => if let Err(e) = self.identifier() { error = Err(e); },
        }

        error
    }

    fn identifier(&mut self) -> Result<(), NcclError> {
        while self.peek() != b'\n' && self.peek() != b':' && !self.is_at_end() {
            self.advance();
        }

        let value = String::from_utf8(self.source[self.start..self.current].to_vec()).unwrap();
        self.add_token_string(TokenKind::Name, value);

        Ok(())
    }

    fn string(&mut self) -> Result<(), NcclError> {
        while self.peek() != b'"' && !self.is_at_end() {
            if self.peek() == b'\n' {
                self.line += 1;
            }
            self.advance();
        }

        if self.is_at_end() {
            return Err(NcclError::new(ErrorKind::ParseError, "Unterminated string", self.line));
        }

        self.advance();

        let value = String::from_utf8(self.source[self.start + 1..self.current - 1].to_vec()).unwrap();
        self.add_token_string(TokenKind::Name, value);

        Ok(())
    }

    fn is_at_end(&mut self) -> bool {
        self.current >= self.source.len()
    }

    fn advance(&mut self) -> u8 {
        self.current += 1;
        self.source[self.current - 1]
    }

    fn add_token(&mut self, kind: TokenKind) {
        let text = String::from_utf8(self.source[self.start..self.current].to_vec()).unwrap();
        self.tokens.push(Token::new(kind, text, self.line));
    }

    fn add_token_string(&mut self, kind: TokenKind, value: String) {
        self.tokens.push(Token::new(kind, value, self.line));
    }

    fn peek(&mut self) -> u8 {
        if self.current >= self.source.len() {
            b'\0'
        } else {
            self.source[self.current]
        }
    }
}

<|endoftext|>


<commit_before>use clap::{App, Arg};

pub struct Config {
	pub address: String,
	pub port: String,
	pub n_bytes: usize,
	pub n_rounds: usize,
	pub no_delay: bool,
	pub non_blocking: bool,
	pub p_id: i8,
}

impl Config {
	pub fn address_and_port(&self) -> String {
		format!("{}:{}", &self.address, &self.port)
	}
}
/// Extract the configuration from Command line
pub fn parse_config() -> Config {
	let matches = App::new("Config")
		.arg(
			Arg::with_name("address")
				.short("a")
				.long("address")
				.value_name("address")
				.help("IP4 address to connect to")
				.takes_value(true)
				.default_value("127.0.0.1"),
		)
		.arg(
			Arg::with_name("port")
				.short("p")
				.long("port")
				.value_name("port")
				.help("port to connect to, like port 7878 if you wanna connect to 127.0.0.1:7878")
				.takes_value(true)
				.default_value("7878"),
		)
		.arg(
			Arg::with_name("n_bytes")
				.short("k")
				.long("bytes")
				.value_name("n_bytes")
				.help("number of bytes to transfer every round")
				.takes_value(true)
				.default_value("1"),
		)
		.arg(
			Arg::with_name("rounds")
				.short("r")
				.long("rounds")
				.value_name("rounds")
				.help("number of rounds of transfer to perform")
				.takes_value(true)
				.default_value("1000000"),
		)
		.arg(
			Arg::with_name("nodelay")
				.short("d")
				.long("nodelay")
				.value_name("nodelay")
				.help("sets TCP in no-delay mode. Any int > 0 for true, 0 for false")
				.takes_value(true)
				.default_value("1"),
		)
		.arg(
			Arg::with_name("nonblocking")
				.short("b")
				.long("nonblocking")
				.value_name("nonblocking")
				.help("sets TCP in non-blocking mode. Any int > 0 for true, 0 for false")
				.takes_value(true)
				.default_value("1"),
		)
		.arg(
			Arg::with_name("thread")
				.short("t")
				.long("thread")
				.value_name("thread")
				.help("id of process to pin thread to, -1 for no pinning")
				.takes_value(true)
				.default_value("-1"),
		)
		.get_matches();

	// Gets a value for config if supplied by user, or defaults to "default.conf"
	let address = String::from(matches.value_of("address").unwrap());
	let port = String::from(matches.value_of("port").unwrap());
	let n_bytes = matches
		.value_of("n_bytes")
		.unwrap()
		.parse::<usize>()
		.unwrap();
	let n_rounds = matches
		.value_of("rounds")
		.unwrap()
		.parse::<usize>()
		.unwrap();
	let no_delay = matches
		.value_of("nodelay")
		.unwrap()
		.parse::<usize>()
		.unwrap()
		> 0;
	let non_blocking = matches
		.value_of("nonblocking")
		.unwrap()
		.parse::<usize>()
		.unwrap()
		> 0;
	let p_id = matches.value_of("thread").unwrap().parse::<i8>().unwrap();

	// Don't kill machines
	if n_bytes > 100_000_000 {
		panic!(
			"More than 100 MB per round is probably too much data you wanna send, \
        you may kill one of the machines. Try with maybe 100MB but more rounds"
		)
	}

	// Very improbable case error handling
	if (n_bytes * 1000000) as u128 * n_rounds as u128 > u64::max_value().into() {
		panic!("There's gonna be too much data. Make sure n_bytes * n_rounds is < u128::MAX")
	}

	Config {
		address,
		port,
		n_bytes,
		n_rounds,
		no_delay,
		non_blocking,
		p_id,
	}
}
<commit_msg>reduce the default round number to 1000<commit_after>use clap::{App, Arg};

pub struct Config {
	pub address: String,
	pub port: String,
	pub n_bytes: usize,
	pub n_rounds: usize,
	pub no_delay: bool,
	pub non_blocking: bool,
	pub p_id: i8,
}

impl Config {
	pub fn address_and_port(&self) -> String {
		format!("{}:{}", &self.address, &self.port)
	}
}
/// Extract the configuration from Command line
pub fn parse_config() -> Config {
	let matches = App::new("Config")
		.arg(
			Arg::with_name("address")
				.short("a")
				.long("address")
				.value_name("address")
				.help("IP4 address to connect to")
				.takes_value(true)
				.default_value("127.0.0.1"),
		)
		.arg(
			Arg::with_name("port")
				.short("p")
				.long("port")
				.value_name("port")
				.help("port to connect to, like port 7878 if you wanna connect to 127.0.0.1:7878")
				.takes_value(true)
				.default_value("7878"),
		)
		.arg(
			Arg::with_name("n_bytes")
				.short("k")
				.long("bytes")
				.value_name("n_bytes")
				.help("number of bytes to transfer every round")
				.takes_value(true)
				.default_value("1"),
		)
		.arg(
			Arg::with_name("rounds")
				.short("r")
				.long("rounds")
				.value_name("rounds")
				.help("number of rounds of transfer to perform")
				.takes_value(true)
				.default_value("1000"),
		)
		.arg(
			Arg::with_name("nodelay")
				.short("d")
				.long("nodelay")
				.value_name("nodelay")
				.help("sets TCP in no-delay mode. Any int > 0 for true, 0 for false")
				.takes_value(true)
				.default_value("1"),
		)
		.arg(
			Arg::with_name("nonblocking")
				.short("b")
				.long("nonblocking")
				.value_name("nonblocking")
				.help("sets TCP in non-blocking mode. Any int > 0 for true, 0 for false")
				.takes_value(true)
				.default_value("1"),
		)
		.arg(
			Arg::with_name("thread")
				.short("t")
				.long("thread")
				.value_name("thread")
				.help("id of process to pin thread to, -1 for no pinning")
				.takes_value(true)
				.default_value("-1"),
		)
		.get_matches();

	// Gets a value for config if supplied by user, or defaults to "default.conf"
	let address = String::from(matches.value_of("address").unwrap());
	let port = String::from(matches.value_of("port").unwrap());
	let n_bytes = matches
		.value_of("n_bytes")
		.unwrap()
		.parse::<usize>()
		.unwrap();
	let n_rounds = matches
		.value_of("rounds")
		.unwrap()
		.parse::<usize>()
		.unwrap();
	let no_delay = matches
		.value_of("nodelay")
		.unwrap()
		.parse::<usize>()
		.unwrap()
		> 0;
	let non_blocking = matches
		.value_of("nonblocking")
		.unwrap()
		.parse::<usize>()
		.unwrap()
		> 0;
	let p_id = matches.value_of("thread").unwrap().parse::<i8>().unwrap();

	// Don't kill machines
	if n_bytes > 100_000_000 {
		panic!(
			"More than 100 MB per round is probably too much data you wanna send, \
        you may kill one of the machines. Try with maybe 100MB but more rounds"
		)
	}

	// Very improbable case error handling
	if (n_bytes * 1000000) as u128 * n_rounds as u128 > u64::max_value().into() {
		panic!("There's gonna be too much data. Make sure n_bytes * n_rounds is < u128::MAX")
	}

	Config {
		address,
		port,
		n_bytes,
		n_rounds,
		no_delay,
		non_blocking,
		p_id,
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Kyle Mayes
//
// 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.

//! Provides helper functionality.

use std::env;
use std::process::{Command};
use std::path::{Path, PathBuf};

use glob;

use libc::{c_int};

use super::{CXVersion};

//================================================
// Structs
//================================================

// try_opt! ______________________________________

macro_rules! try_opt {
    ($option:expr) => ({
        match $option {
            Some(some) => some,
            None => return None,
        }
    });
}

//================================================
// Structs
//================================================

/// A `clang` executable.
#[derive(Clone, Debug)]
pub struct Clang {
    /// The path to this `clang` executable.
    pub path: PathBuf,
    /// The version of this `clang` executable if it could be parsed.
    pub version: Option<CXVersion>,
    /// The directories searched by this `clang` executable for C headers.
    pub c_search_paths: Vec<PathBuf>,
    /// The directories searched by this `clang` executable for C++ headers.
    pub cpp_search_paths: Vec<PathBuf>,
}

impl Clang {
    //- Constructors -----------------------------

    fn new(path: PathBuf) -> Clang {
        let version = parse_version(&path);
        let c_search_paths = parse_search_paths(&path, "c");
        let cpp_search_paths = parse_search_paths(&path, "c++");
        Clang {
            path: path,
            version: version,
            c_search_paths: c_search_paths,
            cpp_search_paths: cpp_search_paths,
        }
    }

    /// Returns a `clang` executable if one can be found.
    ///
    /// If a path is supplied, that is the first directory searched. Otherwise, the directories in
    /// the system's `PATH` are searched.
    pub fn find(path: Option<&Path>) -> Option<Clang> {
        let default = format!("clang{}", env::consts::EXE_SUFFIX);
        let versioned = format!("clang-[0-9]*{}", env::consts::EXE_SUFFIX);
        let patterns = &[&default[..], &versioned[..]];
        if let Some(path) = path.and_then(|p| find(p, patterns)) {
            return Some(Clang::new(path));
        }
        for path in env::split_paths(&env::var("PATH").unwrap()) {
            if let Some(path) = find(&path, patterns) {
                return Some(Clang::new(path));
            }
        }
        None
    }
}

//================================================
// Functions
//================================================

/// Returns the first match to the supplied glob patterns in the supplied directory if there are any
/// matches.
fn find(directory: &Path, patterns: &[&str]) -> Option<PathBuf> {
    for pattern in patterns {
        let pattern = directory.join(pattern).to_string_lossy().into_owned();
        if let Some(path) = try_opt!(glob::glob(&pattern).ok()).filter_map(|p| p.ok()).next() {
            return Some(path);
        }
    }
    None
}

/// Runs a `clang` executable, returning the output.
fn run_clang(path: &Path, arguments: &[&str], stdout: bool) -> String {
    Command::new(path.to_string_lossy().into_owned()).args(arguments).output().map(|o| {
        let output = if stdout {
            &o.stdout
        } else {
            &o.stderr
        };
        String::from_utf8_lossy(output).into_owned()
    }).unwrap()
}

/// Parses a version number if possible, ignoring trailing non-digit characters.
fn parse_version_number(number: &str) -> Option<c_int> {
    number.chars().take_while(|c| c.is_digit(10)).collect::<String>().parse().ok()
}

/// Parses the version from the output of a `clang` executable if possible.
fn parse_version(path: &Path) -> Option<CXVersion> {
    let output = run_clang(path, &["--version"], true);
    let start = try_opt!(output.find("version ")) + 8;
    let mut numbers = try_opt!(output[start..].split_whitespace().nth(0)).split('.');
    let major = try_opt!(numbers.next().and_then(parse_version_number));
    let minor = try_opt!(numbers.next().and_then(parse_version_number));
    let subminor = numbers.next().and_then(parse_version_number).unwrap_or(0);
    Some(CXVersion { Major: major, Minor: minor, Subminor: subminor })
}

/// Parses the search paths from the output of a `clang` executable.
fn parse_search_paths(path: &Path, language: &str) -> Vec<PathBuf> {
    let output = run_clang(path, &["-E", "-x", language, "-", "-v"], false);
    let include_start = "#include <...> search starts here:";
    let start = output.find(include_start).expect(include_start) + include_start.len();
    let end = output.find("End of search list.").expect("End of search list");
    output[start..end].split_whitespace().map(|l| Path::new(l.trim()).into()).collect()
}
<commit_msg>Fix Xcode search path parsing (#32)<commit_after>// Copyright 2016 Kyle Mayes
//
// 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.

//! Provides helper functionality.

use std::env;
use std::process::{Command};
use std::path::{Path, PathBuf};

use glob;

use libc::{c_int};

use super::{CXVersion};

//================================================
// Structs
//================================================

// try_opt! ______________________________________

macro_rules! try_opt {
    ($option:expr) => ({
        match $option {
            Some(some) => some,
            None => return None,
        }
    });
}

//================================================
// Structs
//================================================

/// A `clang` executable.
#[derive(Clone, Debug)]
pub struct Clang {
    /// The path to this `clang` executable.
    pub path: PathBuf,
    /// The version of this `clang` executable if it could be parsed.
    pub version: Option<CXVersion>,
    /// The directories searched by this `clang` executable for C headers.
    pub c_search_paths: Vec<PathBuf>,
    /// The directories searched by this `clang` executable for C++ headers.
    pub cpp_search_paths: Vec<PathBuf>,
}

impl Clang {
    //- Constructors -----------------------------

    fn new(path: PathBuf) -> Clang {
        let version = parse_version(&path);
        let c_search_paths = parse_search_paths(&path, "c");
        let cpp_search_paths = parse_search_paths(&path, "c++");
        Clang {
            path: path,
            version: version,
            c_search_paths: c_search_paths,
            cpp_search_paths: cpp_search_paths,
        }
    }

    /// Returns a `clang` executable if one can be found.
    ///
    /// If a path is supplied, that is the first directory searched. Otherwise, the directories in
    /// the system's `PATH` are searched.
    pub fn find(path: Option<&Path>) -> Option<Clang> {
        let default = format!("clang{}", env::consts::EXE_SUFFIX);
        let versioned = format!("clang-[0-9]*{}", env::consts::EXE_SUFFIX);
        let patterns = &[&default[..], &versioned[..]];
        if let Some(path) = path.and_then(|p| find(p, patterns)) {
            return Some(Clang::new(path));
        }
        for path in env::split_paths(&env::var("PATH").unwrap()) {
            if let Some(path) = find(&path, patterns) {
                return Some(Clang::new(path));
            }
        }
        None
    }
}

//================================================
// Functions
//================================================

/// Returns the first match to the supplied glob patterns in the supplied directory if there are any
/// matches.
fn find(directory: &Path, patterns: &[&str]) -> Option<PathBuf> {
    for pattern in patterns {
        let pattern = directory.join(pattern).to_string_lossy().into_owned();
        if let Some(path) = try_opt!(glob::glob(&pattern).ok()).filter_map(|p| p.ok()).next() {
            return Some(path);
        }
    }
    None
}

/// Runs a `clang` executable, returning the output.
fn run_clang(path: &Path, arguments: &[&str], stdout: bool) -> String {
    Command::new(path.to_string_lossy().into_owned()).args(arguments).output().map(|o| {
        let output = if stdout {
            &o.stdout
        } else {
            &o.stderr
        };
        String::from_utf8_lossy(output).into_owned()
    }).unwrap()
}

/// Parses a version number if possible, ignoring trailing non-digit characters.
fn parse_version_number(number: &str) -> Option<c_int> {
    number.chars().take_while(|c| c.is_digit(10)).collect::<String>().parse().ok()
}

/// Parses the version from the output of a `clang` executable if possible.
fn parse_version(path: &Path) -> Option<CXVersion> {
    let output = run_clang(path, &["--version"], true);
    let start = try_opt!(output.find("version ")) + 8;
    let mut numbers = try_opt!(output[start..].split_whitespace().nth(0)).split('.');
    let major = try_opt!(numbers.next().and_then(parse_version_number));
    let minor = try_opt!(numbers.next().and_then(parse_version_number));
    let subminor = numbers.next().and_then(parse_version_number).unwrap_or(0);
    Some(CXVersion { Major: major, Minor: minor, Subminor: subminor })
}

/// Parses the search paths from the output of a `clang` executable.
fn parse_search_paths(path: &Path, language: &str) -> Vec<PathBuf> {
    let output = run_clang(path, &["-E", "-x", language, "-", "-v"], false);
    let include_start = "#include <...> search starts here:";
    let start = output.find(include_start).expect(include_start) + include_start.len();
    let end = output.find("End of search list.").expect("End of search list");
    let paths = output[start..end].replace("(framework directory)", "");
    paths.split_whitespace().map(|l| Path::new(l.trim()).into()).collect()
}
<|endoftext|>


<commit_before>use gfx;
use image;
use image::{
    GenericImage,
    ImageBuf,
    Rgba,
};
use graphics::{
    ImageSize
};

/// Represents a texture.
pub struct Texture {
    /// A handle to the Gfx texture.
    pub handle: gfx::TextureHandle,
}

impl Texture {
    /// Creates a texture from path.
    pub fn from_path<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(device: &mut D, path: &Path) -> Result<Texture, String> {
        let img = match image::open(path) {
            Ok(img) => img,
            Err(e)  => return Err(format!("Could not load '{}': {}",
                path.filename_str().unwrap(), e)),
        };

        match img.color() {
            image::RGBA(8) => {},
            c => fail!("Unsupported color type {} in png", c),
        };

        let (width, height) = img.dimensions();
        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            img.raw_pixels().as_slice())
        .unwrap();

        Ok(Texture {
            handle: texture
        })
    }

    /// Creates a texture from image.
    pub fn from_image<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(device: &mut D, image: &ImageBuf<Rgba<u8>>) -> Texture {
        let (width, height) = image.dimensions();
        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            image.pixelbuf().as_slice())
        .unwrap();

        Texture {
            handle: texture
        }
    }

    /// Updates the texture with an image.
    pub fn update<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(&mut self, device: &mut D, image: &ImageBuf<Rgba<u8>>) {
        device.update_texture(&self.handle,
            &self.handle.get_info().to_image_info(),
            image.pixelbuf().as_slice()
        ).unwrap();
    }
}

impl ImageSize for Texture {
    fn get_size(&self) -> (u32, u32) {
        let info = self.handle.get_info();
        (info.width as u32, info.height as u32)
    }
}
<commit_msg>Replaced fail with return Err<commit_after>use gfx;
use image;
use image::{
    GenericImage,
    ImageBuf,
    Rgba,
};
use graphics::{
    ImageSize
};

/// Represents a texture.
pub struct Texture {
    /// A handle to the Gfx texture.
    pub handle: gfx::TextureHandle,
}

impl Texture {
    /// Creates a texture from path.
    pub fn from_path<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(device: &mut D, path: &Path) -> Result<Texture, String> {
        let img = match image::open(path) {
            Ok(img) => img,
            Err(e)  => return Err(format!("Could not load '{}': {}",
                path.filename_str().unwrap(), e)),
        };

        match img.color() {
            image::RGBA(8) => {},
            c => return Err(format!("Unsupported color type {}", c)),
        };

        let (width, height) = img.dimensions();
        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            img.raw_pixels().as_slice())
        .unwrap();

        Ok(Texture {
            handle: texture
        })
    }

    /// Creates a texture from image.
    pub fn from_image<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(device: &mut D, image: &ImageBuf<Rgba<u8>>) -> Texture {
        let (width, height) = image.dimensions();
        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            image.pixelbuf().as_slice())
        .unwrap();

        Texture {
            handle: texture
        }
    }

    /// Updates the texture with an image.
    pub fn update<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(&mut self, device: &mut D, image: &ImageBuf<Rgba<u8>>) {
        device.update_texture(&self.handle,
            &self.handle.get_info().to_image_info(),
            image.pixelbuf().as_slice()
        ).unwrap();
    }
}

impl ImageSize for Texture {
    fn get_size(&self) -> (u32, u32) {
        let info = self.handle.get_info();
        (info.width as u32, info.height as u32)
    }
}
<|endoftext|>


<commit_before>extern crate tetrahedrane;

use tetrahedrane::vid::*;
use tetrahedrane::start;
use tetrahedrane::shaders;
use tetrahedrane::texture;

fn main() {
    let mut window = start::Window::new(640, 480, "Hello World!", 1 as usize);

    let mut shaders: Vec<Shader> = Vec::new();

    let triangle = Triangle::new(DepthPoint::new(0.0, -0.5, 3.0),
                                 DepthPoint::new(0.5, 0.5, 3.0),
                                 DepthPoint::new(-0.5, 0.5, 3.0),
                                 0.0, 0.0, 0.0,
                                 Color::new(200, 200, 200));

    let mut triangle_group = TriangleGroup::square(-0.5, -0.5, 3.0, 1.0, 1.0);

    //let mut triangle_group = TriangleGroup::new(vec![triangle]);

    let texture = texture::UVTexture::path(&"bmp/crate.bmp");
    shaders.push(shaders::filled_texture(1, texture, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0));

    let texture = texture::UVTexture::path(&"bmp/crate.bmp");
    shaders.push(shaders::filled_texture(2, texture, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0));
    //shaders.push(shaders::filled_triangle_color(1));
    //shaders.push(shaders::wireframe(1));

    //triangle_group.triangles[0].shader_ids[0] = 1;

    loop {
        window.window.set(Color::new(20, 40, 60).orb_color());
        window.window.set(Color::new(20, 40, 60).orb_color());

        for triangle in &mut triangle_group.triangles {
            triangle.coord_rotate_x_y(0.5, 0.5, 0.01);
            triangle.coord_rotate_x_z(0.5, 0.0, 0.02);
            triangle.coord_rotate_y_z(0.5, 0.0, 0.03);
        }

        window.render_addon_shader(triangle_group.triangles[0], &shaders, [1, 0, 0, 0, 0, 0, 0, 0]);
        window.render_addon_shader(triangle_group.triangles[1], &shaders, [2, 0, 0, 0, 0, 0, 0, 0]);

        window.window.sync();

        //std::thread::sleep(std::time::Duration::from_millis(33));
    }
}<commit_msg>Added framerate counter<commit_after>extern crate tetrahedrane;

use tetrahedrane::vid::*;
use tetrahedrane::start;
use tetrahedrane::shaders;
use tetrahedrane::texture;

fn main() {
    let mut window = start::Window::new(640, 480, "Hello World!", 1 as usize);

    let mut shaders: Vec<Shader> = Vec::new();

    let triangle = Triangle::new(DepthPoint::new(0.0, -0.5, 3.0),
                                 DepthPoint::new(0.5, 0.5, 3.0),
                                 DepthPoint::new(-0.5, 0.5, 3.0),
                                 0.0, 0.0, 0.0,
                                 Color::new(200, 200, 200));

    let mut triangle_group = TriangleGroup::square(-0.5, -0.5, 3.0, 1.0, 1.0);

    //let mut triangle_group = TriangleGroup::new(vec![triangle]);

    let texture = texture::UVTexture::path(&"bmp/crate.bmp");
    shaders.push(shaders::filled_texture(1, texture, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0));

    let texture = texture::UVTexture::path(&"bmp/crate.bmp");
    shaders.push(shaders::filled_texture(2, texture, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0));
    //shaders.push(shaders::filled_triangle_color(1));
    //shaders.push(shaders::wireframe(1));

    //triangle_group.triangles[0].shader_ids[0] = 1;

    let mut frames = 0;

    let mut total_duration = std::time::Duration::new(0, 0);

    loop {
        let start_time = std::time::Instant::now();

        window.window.set(Color::new(20, 40, 60).orb_color());
        window.window.set(Color::new(20, 40, 60).orb_color());

        for triangle in &mut triangle_group.triangles {
            triangle.coord_rotate_x_y(0.5, 0.5, 0.01);
            triangle.coord_rotate_x_z(0.5, 0.0, 0.02);
            triangle.coord_rotate_y_z(0.5, 0.0, 0.03);
        }

        window.render_addon_shader(triangle_group.triangles[0], &shaders, [1, 0, 0, 0, 0, 0, 0, 0]);
        window.render_addon_shader(triangle_group.triangles[1], &shaders, [2, 0, 0, 0, 0, 0, 0, 0]);

        window.window.sync();

        let end_time = std::time::Instant::now();

        let duration = end_time.duration_since(start_time);

        if total_duration.as_secs() < 1 {
            frames += 1;
            total_duration += duration;
        } else {
            println!("{:?}", frames);
            frames = 0;
            total_duration = std::time::Duration::new(0, 0);
        }
        //std::thread::sleep(std::time::Duration::from_millis(33));
    }
}<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::error;

use super::row::{Row, RowError, RowBuilder, RowReader};
use super::schema::{Schema, Type};
use super::value::Value;
use super::parser::Expression;

#[derive(Debug)]
pub enum StreamError {
    ValidationError(String),
    FieldNotFound(String),
    MissingRowId
}

impl From<RowError> for StreamError {
    fn from(err: RowError) -> StreamError {
        StreamError::MissingRowId
    }

}

#[derive(Debug)]
pub struct Stream {
    inserts: u64, // total number of inserts this Stream has seen
    lowest_id: Option<u64>,  // lowest id we still have in the Stream
    ttl: Option<u64>,
    rows: HashMap<u64, Row>,
    pub schema: Schema,

}

/**
This is a weird DB.  There's no primary key, since everything is based off append only streaming

*/
impl Stream {
    pub fn new() -> Stream {
        let mut stream = Stream::new_empty();
        stream.schema.add_type("_id", Type::Int);
        stream.schema.add_type("_created", Type::Timestamp);
        stream
    }

    // used in temporary tables
    pub fn new_empty() -> Stream {
        let mut stream = Stream {
            inserts: 0,
            lowest_id: None,
            rows: HashMap::new(),
            schema: Schema::new(),
            ttl: None,
        };
        stream
    }

    /* we take a HashMap of String -> Field here
    * we're going to convert it to HashMap<u8, Field> for the Row struct
    */
    pub fn insert(&mut self, mut row_builder: RowBuilder) -> Result<u64, StreamError> {
        // validate the inserted data
        let mut row_map : HashMap<u16, Value> = HashMap::new();
        for (key, val) in row_builder.data.drain() {
            // get the field from the schema
            // TypeDef
            let tmp = try!(self.schema.get(&key)
                               .ok_or(StreamError::FieldNotFound(key.to_string())));
            row_map.insert(tmp.id, val);

        }
        let row_id = self.inserts;
        let row = try!(Row::new(row_map));
        self.rows.insert(self.inserts, row.clone());
        self.inserts += 1;
        Ok(row_id)
    }

    pub fn get(&self, position: u64) -> Option<RowReader> {
        if let Some(tmp) = self.rows.get(&position) {
            return Some(RowReader::new(&self.schema, &tmp));
        }
        None

    }
    pub fn select(&self, predicates: Box<Expression>) {

    }

}

impl<'a> IntoIterator for &'a Stream {
    type Item = RowReader<'a>;
    type IntoIter = StreamIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        // TODO fix the position
        StreamIterator{position:0,
                       stream: self}
    }
}

pub struct StreamIterator<'a> {
    position: u64,
    stream: &'a Stream,
}

impl<'a> StreamIterator<'a> {
    fn offset(&'a mut self, num: u64) -> &'a mut StreamIterator {
        self.position = num;
        self
    }
}

impl<'a> Iterator for StreamIterator<'a> {
    type Item = RowReader<'a>;
    fn next(&mut self) -> Option<RowReader<'a>> {
        let tmp = self.stream.get(self.position);
        self.position = self.position + 1;
        tmp
    }
}

#[cfg(test)]
mod tests {
    #![feature(test)]
    extern crate test;
    use super::{Stream};
    use db::row::RowBuilder;

    use db::schema::{Schema, Type};
    use db::value::{Value, ValueComparator};
    use std::collections::HashMap;
    use self::test::Bencher;

    fn get_stream() -> Stream {
        let mut s = Stream::new();
        s.schema.add_type("name", Type::String);
        s.schema.add_type("age", Type::Int);
        s.schema.add_type("created", Type::Timestamp);
        s
    }

    fn get_stream_with_data() -> Stream {
        let mut s = get_stream();

        let names = vec!["Jon", "Dani", "Pete", "Sammy", "Steph",
                         "Blake", "Mr. Robot", "Ted", "Rachel", "Gloria"];
        let ages = vec![35, 29, 45, 56, 100,
                        35, 78, 32, 32, 67];

        for x in 0..10 {
            let mut row = RowBuilder::new();
            row.set_string("name", names[x]);
            row.set_int("age", ages[x]);
            let result = s.insert(row).unwrap();
        }
        s
    }

    #[test]
    fn test_insert_works_normal_case() {
        let mut s = Stream::new();
        let name_id = s.schema.add_type("name", Type::String);

        let mut row = RowBuilder::new();
        row.set_string("name", "test");
        let result = s.insert(row).unwrap();
        assert_eq!(result, 0);
        assert_eq!(s.inserts, 1);
        let row2 = s.get(result).unwrap();
        let name = row2.get("name").unwrap();
        // was the data inserted?
        assert_eq!(*row2.get("name").unwrap(),
                   Value::from("test"));

    }

    #[test]
    fn test_equality() {
        assert_eq!(Value::from("jon"), Value::from("jon"));
    }

    #[test]
    fn test_builder_insertion() {
        let mut s = get_stream();
        let mut row = RowBuilder::new();

        row.set_string("name", "value")
           .set_int("age", 10);
        s.insert(row);

        let mut c = 0;
        for r in s.into_iter() {
            c += 1;
        }
        assert_eq!(c, 1);
    }

    #[test]
    fn test_iterator_offset() {
        let mut s = get_stream_with_data();
        let mut i = 0;
        for row in s.into_iter().offset(9) {
            i = i + 1;
        }
        assert_eq!(i, 1);
    }

    #[test]
    fn test_chaining() {
        let mut s = get_stream_with_data();
        // SELECT * from X where age > 25
        let c = Value::from(40);
        let mut i = 0;
        for row in s.into_iter().filter(|ref x| ValueComparator::new(x.get("age").unwrap(), Type::Int) >
                                                ValueComparator::new(&c, Type::Int) )  {
            i = i + 1;
        }
        assert_eq!(i, 5);

    }

    #[bench]
    fn bench_add_two(b: &mut Bencher) {
        let mut stream = get_stream();
        // benched original row builder at 318 ns/iter (+/- 52)
        b.iter(|| {
            let mut row = RowBuilder::new();
            row.set_string("name", "Dani");
            row.set_int("num_tacos", 4);
            stream.insert(row);
        });
    }

    #[test]
    fn test_table_scan() {
        let mut stream = get_stream_with_data();

    }

}<commit_msg>added Deref and DerefMut<commit_after>use std::collections::HashMap;
use std::error;

use super::row::{Row, RowError, RowBuilder, RowReader};
use super::schema::{Schema, Type};
use super::value::Value;
use super::parser::Expression;
use std::ops::{Deref, DerefMut};

#[derive(Debug)]
pub enum StreamError {
    ValidationError(String),
    FieldNotFound(String),
    MissingRowId
}

impl From<RowError> for StreamError {
    fn from(err: RowError) -> StreamError {
        StreamError::MissingRowId
    }

}

#[derive(Debug)]
pub struct Stream {
    inserts: u64, // total number of inserts this Stream has seen
    lowest_id: Option<u64>,  // lowest id we still have in the Stream
    ttl: Option<u64>,
    rows: HashMap<u64, Row>,
    pub schema: Schema,

}

// Stream should deref schema since it's going to be used a lot
impl Deref for Stream {
    type Target = Schema;
    fn deref(&self) -> &Schema {
        &self.schema
    }
}
impl DerefMut for Stream {
    fn deref_mut(&mut self) -> &mut Schema {
        &mut self.schema
    }
}

/**
This is a weird DB.  There's no user defined primary key,
since everything is based off append only streaming
*/
impl Stream {
    pub fn new() -> Stream {
        let mut stream = Stream::new_empty();
        stream.schema.add_type("_id", Type::Int);
        stream.schema.add_type("_created", Type::Timestamp);
        stream
    }

    // used in temporary tables
    pub fn new_empty() -> Stream {
        let mut stream = Stream {
            inserts: 0,
            lowest_id: None,
            rows: HashMap::new(),
            schema: Schema::new(),
            ttl: None,
        };
        stream
    }

    /* we take a HashMap of String -> Field here
    * we're going to convert it to HashMap<u8, Field> for the Row struct
    */
    pub fn insert(&mut self, mut row_builder: RowBuilder) -> Result<u64, StreamError> {
        // validate the inserted data
        let mut row_map : HashMap<u16, Value> = HashMap::new();
        for (key, val) in row_builder.data.drain() {
            // get the field from the schema
            // TypeDef
            let tmp = try!(self.schema.get(&key)
                               .ok_or(StreamError::FieldNotFound(key.to_string())));
            row_map.insert(tmp.id, val);

        }
        let row_id = self.inserts;
        let row = try!(Row::new(row_map));
        self.rows.insert(self.inserts, row.clone());
        self.inserts += 1;
        Ok(row_id)
    }

    pub fn get(&self, position: u64) -> Option<RowReader> {
        if let Some(tmp) = self.rows.get(&position) {
            return Some(RowReader::new(&self.schema, &tmp));
        }
        None

    }
    pub fn select(&self, predicates: Box<Expression>) {

    }

}

impl<'a> IntoIterator for &'a Stream {
    type Item = RowReader<'a>;
    type IntoIter = StreamIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        // TODO fix the position
        StreamIterator{position:0,
                       stream: self}
    }
}

pub struct StreamIterator<'a> {
    position: u64,
    stream: &'a Stream,
}

impl<'a> StreamIterator<'a> {
    fn offset(&'a mut self, num: u64) -> &'a mut StreamIterator {
        self.position = num;
        self
    }
}

impl<'a> Iterator for StreamIterator<'a> {
    type Item = RowReader<'a>;
    fn next(&mut self) -> Option<RowReader<'a>> {
        let tmp = self.stream.get(self.position);
        self.position = self.position + 1;
        tmp
    }
}

#[cfg(test)]
mod tests {
    #![feature(test)]
    extern crate test;
    use super::{Stream};
    use db::row::RowBuilder;

    use db::schema::{Schema, Type};
    use db::value::{Value, ValueComparator};
    use std::collections::HashMap;
    use self::test::Bencher;

    fn get_stream() -> Stream {
        let mut s = Stream::new();
        s.schema.add_type("name", Type::String);
        s.schema.add_type("age", Type::Int);
        s.schema.add_type("created", Type::Timestamp);
        s
    }

    fn get_stream_with_data() -> Stream {
        let mut s = get_stream();

        let names = vec!["Jon", "Dani", "Pete", "Sammy", "Steph",
                         "Blake", "Mr. Robot", "Ted", "Rachel", "Gloria"];
        let ages = vec![35, 29, 45, 56, 100,
                        35, 78, 32, 32, 67];

        for x in 0..10 {
            let mut row = RowBuilder::new();
            row.set_string("name", names[x]);
            row.set_int("age", ages[x]);
            let result = s.insert(row).unwrap();
        }
        s
    }

    #[test]
    fn test_insert_works_normal_case() {
        let mut s = Stream::new();
        let name_id = s.schema.add_type("name", Type::String);

        let mut row = RowBuilder::new();
        row.set_string("name", "test");
        let result = s.insert(row).unwrap();
        assert_eq!(result, 0);
        assert_eq!(s.inserts, 1);
        let row2 = s.get(result).unwrap();
        let name = row2.get("name").unwrap();
        // was the data inserted?
        assert_eq!(*row2.get("name").unwrap(),
                   Value::from("test"));

    }

    #[test]
    fn test_equality() {
        assert_eq!(Value::from("jon"), Value::from("jon"));
    }

    #[test]
    fn test_builder_insertion() {
        let mut s = get_stream();
        let mut row = RowBuilder::new();

        row.set_string("name", "value")
           .set_int("age", 10);
        s.insert(row);

        let mut c = 0;
        for r in s.into_iter() {
            c += 1;
        }
        assert_eq!(c, 1);
    }

    #[test]
    fn test_iterator_offset() {
        let mut s = get_stream_with_data();
        let mut i = 0;
        for row in s.into_iter().offset(9) {
            i = i + 1;
        }
        assert_eq!(i, 1);
    }

    #[test]
    fn test_chaining() {
        let mut s = get_stream_with_data();
        // SELECT * from X where age > 25
        let c = Value::from(40);
        let mut i = 0;
        for row in s.into_iter().filter(|ref x| ValueComparator::new(x.get("age").unwrap(), Type::Int) >
                                                ValueComparator::new(&c, Type::Int) )  {
            i = i + 1;
        }
        assert_eq!(i, 5);

    }

    #[bench]
    fn bench_add_two(b: &mut Bencher) {
        let mut stream = get_stream();
        // benched original row builder at 318 ns/iter (+/- 52)
        b.iter(|| {
            let mut row = RowBuilder::new();
            row.set_string("name", "Dani");
            row.set_int("num_tacos", 4);
            stream.insert(row);
        });
    }

    #[test]
    fn test_table_scan() {
        let mut stream = get_stream_with_data();

    }

}<|endoftext|>