<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::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(),
    })
}
<commit_msg>Refactor wait/cancel logic into RawRequest<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 registered to some pre-existing
//! [`Scope`](trait.Scope.html).  At the end of a `Scope`, all its remaining requests will be waited
//! for until completion.  Scopes can be created using either [`scope`](fn.scope.html) or
//! [`StaticScope`](struct.StaticScope.html).
//!
//! 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 unregistered 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 registered with a `Scope`.
#[must_use]
#[derive(Debug)]
struct RawRequest<'a, S> {
    request: MPI_Request,
    scope: S,
    phantom: PhantomData<Cell<&'a ()>>,
}

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

impl<'a, S> RawRequest<'a, S> {
    /// Mark the request for cancellation.
    fn cancel(&self) {
        let mut request = self.as_raw();
        unsafe {
            ffi::MPI_Cancel(&mut request);
        }
    }
}

impl<'a, S: Scope<'a>> RawRequest<'a, S> {
    /// Construct a scoped request from the raw MPI type and register it with the given scope.
    ///
    /// # 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();
        Self {
            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(self) -> (MPI_Request, S) {
        self.scope.unregister();
        (self.request, self.scope)
    }

    /// Wait for the request to finish and unregister the request object from its scope.
    ///
    /// This is unsafe because afterward the request is left in an unspecified but droppable state.
    unsafe fn 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));
        self.scope.unregister();
    }
}

/// A request object for a non-blocking operation registered with a `Scope` of 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>(RawRequest<'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<Request<'a, S>> for RawRequest<'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>> From<WaitGuard<'a, S>> for Request<'a, S> {
    fn from(guard: WaitGuard<'a, S>) -> Self {
        Request(RawRequest::from(guard))
    }
}

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

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(RawRequest::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) {
        RawRequest::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.wait(Some(&mut status));
            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.wait(None);
        }
    }

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

    /// Initiate cancellation of the request.
    ///
    /// 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>(RawRequest<'a, S>);

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

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

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

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

impl<'a, S: Scope<'a>> WaitGuard<'a, S> {
    fn cancel(&self) {
        self.0.cancel();
    }
}

/// 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<CancelGuard<'a, S>> for WaitGuard<'a, S> {
    fn from(mut guard: CancelGuard<'a, S>) -> Self {
        unsafe {
            let inner = mem::replace(&mut guard.0, mem::uninitialized());
            mem::forget(guard);
            inner
        }
    }
}

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

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) used internally by the `request` module.
///
/// 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.
    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` registered with 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 {
    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` registered with 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> {
    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 with which the request is registered.
///
/// 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>pub static OBJECT_VERTEX_SRC: &'static str =
   "#version 120
    attribute vec3 position;
    attribute vec3 normal;
    attribute vec3 color;
    attribute vec2 tex_coord_v;
    varying vec3 ws_normal;
    varying vec3 ws_position;
    varying vec2 tex_coord;
    uniform mat4 projection;
    uniform mat4 view;
    uniform mat4 transform;
    uniform mat3 scale;
    uniform mat3 ntransform;
    void main() {
        mat4 scale4 = mat4(scale);
        vec4 pos4   = transform * scale4 * vec4(position, 1.0);
        tex_coord   = tex_coord_v;
        ws_position = pos4.xyz;
        gl_Position = projection * view * transform * scale4 * vec4(position, 1.0);
        ws_normal   = normalize(ntransform * scale * normal);
    }";

// phong lighting (heavily) inspired
// by http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php
pub static OBJECT_FRAGMENT_SRC: &'static str =
   "#version 120
    uniform vec3      color;
    uniform vec3      light_position;
    uniform sampler2D tex;
    varying vec2      tex_coord;
    varying vec3      ws_normal;
    varying vec3      ws_position;
    void main() {
      vec3 L = normalize(light_position - ws_position);
      vec3 E = normalize(-ws_position);

      //calculate Ambient Term:
      vec4 Iamb = vec4(1.0, 1.0, 1.0, 1.0);

      //calculate Diffuse Term:
      vec4 Idiff1 = vec4(1.0, 1.0, 1.0, 1.0) * max(dot(ws_normal,L), 0.0);
      Idiff1 = clamp(Idiff1, 0.0, 1.0);

      // double sided lighting:
      vec4 Idiff2 = vec4(1.0, 1.0, 1.0, 1.0) * max(dot(-ws_normal,L), 0.0);
      Idiff2 = clamp(Idiff2, 0.0, 1.0);

      vec4 tex_color = texture2D(tex, tex_coord);
      gl_FragColor   = tex_color * (vec4(color, 1.0) + Iamb + (Idiff1 + Idiff2) / 2) / 3;
    }";

pub static LINES_VERTEX_SRC: &'static str =
   "#version 120
    attribute vec3 position;
    attribute vec3 color;
    varying   vec3 Color;
    uniform mat4   projection;
    uniform mat4   view;
    void main() {
        gl_Position = projection * view * vec4(position, 1.0);
        Color       = color;
    }";

// phong lighting (heavily) inspired
// by http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php
pub static LINES_FRAGMENT_SRC: &'static str =
   "#version 120
    attribute vec3 Color;
    void main() {
      gl_FragColor = vec4(Color, 1.0);
    }";
<commit_msg>Fix the shader for lines.<commit_after>pub static OBJECT_VERTEX_SRC: &'static str =
   "#version 120
    attribute vec3 position;
    attribute vec3 normal;
    attribute vec3 color;
    attribute vec2 tex_coord_v;
    varying vec3 ws_normal;
    varying vec3 ws_position;
    varying vec2 tex_coord;
    uniform mat4 projection;
    uniform mat4 view;
    uniform mat4 transform;
    uniform mat3 scale;
    uniform mat3 ntransform;
    void main() {
        mat4 scale4 = mat4(scale);
        vec4 pos4   = transform * scale4 * vec4(position, 1.0);
        tex_coord   = tex_coord_v;
        ws_position = pos4.xyz;
        gl_Position = projection * view * transform * scale4 * vec4(position, 1.0);
        ws_normal   = normalize(ntransform * scale * normal);
    }";

// phong lighting (heavily) inspired
// by http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php
pub static OBJECT_FRAGMENT_SRC: &'static str =
   "#version 120
    uniform vec3      color;
    uniform vec3      light_position;
    uniform sampler2D tex;
    varying vec2      tex_coord;
    varying vec3      ws_normal;
    varying vec3      ws_position;
    void main() {
      vec3 L = normalize(light_position - ws_position);
      vec3 E = normalize(-ws_position);

      //calculate Ambient Term:
      vec4 Iamb = vec4(1.0, 1.0, 1.0, 1.0);

      //calculate Diffuse Term:
      vec4 Idiff1 = vec4(1.0, 1.0, 1.0, 1.0) * max(dot(ws_normal,L), 0.0);
      Idiff1 = clamp(Idiff1, 0.0, 1.0);

      // double sided lighting:
      vec4 Idiff2 = vec4(1.0, 1.0, 1.0, 1.0) * max(dot(-ws_normal,L), 0.0);
      Idiff2 = clamp(Idiff2, 0.0, 1.0);

      vec4 tex_color = texture2D(tex, tex_coord);
      gl_FragColor   = tex_color * (vec4(color, 1.0) + Iamb + (Idiff1 + Idiff2) / 2) / 3;
    }";

pub static LINES_VERTEX_SRC: &'static str =
   "#version 120
    attribute vec3 position;
    attribute vec3 color;
    varying   vec3 Color;
    uniform   mat4   projection;
    uniform   mat4   view;
    void main() {
        gl_Position = projection * view * vec4(position, 1.0);
        Color = color;
    }";

// phong lighting (heavily) inspired
// by http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php
pub static LINES_FRAGMENT_SRC: &'static str =
   "#version 120
    varying vec3 Color;
    void main() {
      gl_FragColor = vec4(Color, 1.0);
    }";
<|endoftext|>


<commit_before>//! Time (base unit second, s).

#[cfg(feature = "try-from")]
use lib::time::Duration;
#[cfg(feature = "try-from")]
use num::{FromPrimitive, ToPrimitive, Zero};

quantity! {
    /// Time (base unit second, s).
    quantity: Time; "time";
    /// Dimension of time, T (base unit second, s).
    dimension: ISQ<
        Z0,     // length
        Z0,     // mass
        P1,     // time
        Z0,     // electric current
        Z0,     // thermodynamic temperature
        Z0,     // amount of substance
        Z0>;    // luminous intensity
    units {
        @yottasecond: prefix!(yotta); "Ys", "yottasecond", "yottaseconds";
        @zettasecond: prefix!(zetta); "Zs", "zettasecond", "zettaseconds";
        @exasecond: prefix!(exa); "Es", "exasecond", "exaseconds";
        @petasecond: prefix!(peta); "Ps", "petasecond", "petaseconds";
        @terasecond: prefix!(tera); "Ts", "terasecond", "teraseconds";
        @gigasecond: prefix!(giga); "Gs", "gigasecond", "gigaseconds";
        @megasecond: prefix!(mega); "Ms", "megasecond", "megaseconds";
        @kilosecond: prefix!(kilo); "ks", "kilosecond", "kiloseconds";
        @hectosecond: prefix!(hecto); "hs", "hectosecond", "hectoseconds";
        @decasecond: prefix!(deca); "das", "decasecond", "decaseconds";
        /// The second is the SI unit of time. It is defined by taking the fixed numerical value of
        /// the caesium frequency ∆*ν*Cs, the unperturbed ground-state hyperfine
        /// transition frequency of the caesium 133 atom, to be 9 192 631 770 when expressed in the
        /// unit Hz, which is equal to s⁻¹.
        @second: prefix!(none); "s", "second", "seconds";
        @decisecond: prefix!(deci); "ds", "decisecond", "deciseconds";
        @centisecond: prefix!(centi); "cs", "centisecond", "centiseconds";
        @millisecond: prefix!(milli); "ms", "millisecond", "milliseconds";
        @microsecond: prefix!(micro); "µs", "microsecond", "microseconds";
        @nanosecond: prefix!(nano); "ns", "nanosecond", "nanoseconds";
        @picosecond: prefix!(pico); "ps", "picosecond", "picoseconds";
        @femtosecond: prefix!(femto); "fs", "femtosecond", "femtoseconds";
        @attosecond: prefix!(atto); "as", "attosecond", "attoseconds";
        @zeptosecond: prefix!(zepto); "zs", "zeptosecond", "zeptoseconds";
        @yoctosecond: prefix!(yocto); "ys", "yoctosecond", "yoctoseconds";

        @day: 8.64_E4; "d", "day", "days";
        @hour: 3.6_E3; "h", "hour", "hours";
        @minute: 6.0_E1; "min", "minute", "minutes";
        @shake: 1.0_E-8; "10.0 ns", "shake", "shakes";
        @year: 3.1536_E7; "a", "year", "years";
    }
}

/// An error encountered converting between `Time` and `Duration`.
#[cfg(feature = "try-from")]
#[derive(Debug, Clone, Copy)]
pub enum TryFromError {
    /// The given time interval was negative, making conversion to a duration nonsensical.
    ///
    /// To convert a negative time interval to a duration, first use `abs` to make it positive.
    NegativeDuration,

    /// The given time interval exceeded the maximum size of a `Duration`.
    Overflow,
}

/// Attempt to convert the given `Time` to a `Duration`.
///
/// For possible failure modes see [`TryFromError`][TryFromError].
///
/// ## Notes
///
/// The `Duration` to `Time` conversion is tested to be accurate to within 1 nanosecond (to allow
/// for floating point rounding error). If greater precision is needed, consider using a different
/// underlying storage type or avoiding the conversion altogether.
///
/// [TryFromError]: enum.TryFromError.html
#[cfg(feature = "try-from")]
impl ::lib::convert::TryFrom<Time> for Duration
where
    U: ::si::Units<V> + ?Sized,
    V: ::num::Num + ::Conversion<V> + ::lib::cmp::PartialOrd + ToPrimitive,
    second: ::Conversion<V, T = V::T>,
    nanosecond: ::Conversion<V, T = V::T>,
{
    type Error = TryFromError;

    fn try_from(time: Time) -> Result<Self, Self::Error> {
        if time < Time::::zero() {
            return Err(TryFromError::NegativeDuration);
        }

        let secs = time.get::<second>().to_u64();
        let nanos = (time % Time::::new::<second>(V::one())).get::<nanosecond>().to_u32();

        match (secs, nanos) {
            (Some(secs), Some(nanos)) => Ok(Duration::new(secs, nanos)),
            _ => Err(TryFromError::Overflow),
        }
    }
}

/// Attempt to convert the given `Duration` to a `Time`.
///
/// For possible failure modes, see [`TryFromError`][TryFromError].
///
/// ## Notes
///
/// The `Duration` to `Time` conversion is tested to be accurate to within 100 nanoseconds (to
/// allow for floating point rounding error). If greater precision is needed, consider using a
/// different underlying storage type or avoiding the conversion altogether.
///
/// [TryFromError]: enum.TryFromError.html
#[cfg(feature = "try-from")]
impl ::lib::convert::TryFrom<Duration> for Time
where
    U: ::si::Units<V> + ?Sized,
    V: ::num::Num + ::Conversion<V> + FromPrimitive,
    second: ::Conversion<V, T = V::T>,
    nanosecond: ::Conversion<V, T = V::T>,
{
    type Error = TryFromError;

    fn try_from(duration: Duration) -> Result<Self, Self::Error> {
        let secs = V::from_u64(duration.as_secs());
        let nanos = V::from_u32(duration.subsec_micros());

        match (secs, nanos) {
            (Some(secs), Some(nanos)) => {
                Ok(Time::::new::<second>(secs) + Time::::new::<nanosecond>(nanos))
            }
            _ => Err(TryFromError::Overflow),
        }
    }
}

#[cfg(all(test, feature = "try-from"))]
mod tests {
    storage_types! {
        types: PrimInt, BigInt, BigUint, Float;

        use lib::convert::{TryFrom, TryInto};
        use lib::time::Duration;
        use num::{FromPrimitive, ToPrimitive, Zero};
        use tests::*;
        use si::quantities::*;
        use si::time::{TryFromError, nanosecond};
        use quickcheck::TestResult;

        quickcheck! {
            fn duration_try_from(v: A<V>) -> TestResult {
                test_try_from(Duration::try_from(Time::new::<nanosecond>((*v).clone())), v)
            }

            fn time_try_into(v: A<V>) -> TestResult {
                test_try_from(Time::new::<nanosecond>((*v).clone()).try_into(), v)
            }

            fn time_try_from(v: A<V>) -> TestResult {
                match v.to_u64() {
                    Some(u) => test_try_into(Time::try_from(Duration::from_nanos(u)), v),
                    None => TestResult::discard(),
                }
            }

            fn duration_try_into(v: A<V>) -> TestResult {
                match v.to_u64() {
                    Some(u) => test_try_into(Duration::from_nanos(u).try_into(), v),
                    None => TestResult::discard(),
                }
            }
        }

        fn test_try_from(t: Result<Duration, TryFromError>, v: A<V>) -> TestResult {
            if *v < V::zero() {
                return TestResult::discard();
            }

            let ok = match (t, v.to_u64()) {
                (Ok(t), Some(u)) => {
                    let d = Duration::from_nanos(u);
                    let r = if d > t { d - t } else { t - d };

                    Duration::from_nanos(1) >= r
                },
                (Err(_), None) => true,
                _ => false,
            };

            TestResult::from_bool(ok)
        }

        fn test_try_into(t: Result<Time<V>, TryFromError>, v: A<V>) -> TestResult {
            if *v < V::zero() {
                return TestResult::discard();
            }

            let ok = match t {
                Ok(t) => {
                    let b = Time::new::<nanosecond>((*v).clone());
                    let d = if t > b { t - b } else { b - t };

                    d <= Time::new::<nanosecond>(V::from_u8(100).unwrap())
                },
                _ => false,
            };

            TestResult::from_bool(ok)
        }
    }
}
<commit_msg>Add tropical and sidereal times<commit_after>//! Time (base unit second, s).

#[cfg(feature = "try-from")]
use lib::time::Duration;
#[cfg(feature = "try-from")]
use num::{FromPrimitive, ToPrimitive, Zero};

quantity! {
    /// Time (base unit second, s).
    quantity: Time; "time";
    /// Dimension of time, T (base unit second, s).
    dimension: ISQ<
        Z0,     // length
        Z0,     // mass
        P1,     // time
        Z0,     // electric current
        Z0,     // thermodynamic temperature
        Z0,     // amount of substance
        Z0>;    // luminous intensity
    units {
        @yottasecond: prefix!(yotta); "Ys", "yottasecond", "yottaseconds";
        @zettasecond: prefix!(zetta); "Zs", "zettasecond", "zettaseconds";
        @exasecond: prefix!(exa); "Es", "exasecond", "exaseconds";
        @petasecond: prefix!(peta); "Ps", "petasecond", "petaseconds";
        @terasecond: prefix!(tera); "Ts", "terasecond", "teraseconds";
        @gigasecond: prefix!(giga); "Gs", "gigasecond", "gigaseconds";
        @megasecond: prefix!(mega); "Ms", "megasecond", "megaseconds";
        @kilosecond: prefix!(kilo); "ks", "kilosecond", "kiloseconds";
        @hectosecond: prefix!(hecto); "hs", "hectosecond", "hectoseconds";
        @decasecond: prefix!(deca); "das", "decasecond", "decaseconds";
        /// The second is the SI unit of time. It is defined by taking the fixed numerical value of
        /// the caesium frequency ∆*ν*Cs, the unperturbed ground-state hyperfine
        /// transition frequency of the caesium 133 atom, to be 9 192 631 770 when expressed in the
        /// unit Hz, which is equal to s⁻¹.
        @second: prefix!(none); "s", "second", "seconds";
        @decisecond: prefix!(deci); "ds", "decisecond", "deciseconds";
        @centisecond: prefix!(centi); "cs", "centisecond", "centiseconds";
        @millisecond: prefix!(milli); "ms", "millisecond", "milliseconds";
        @microsecond: prefix!(micro); "µs", "microsecond", "microseconds";
        @nanosecond: prefix!(nano); "ns", "nanosecond", "nanoseconds";
        @picosecond: prefix!(pico); "ps", "picosecond", "picoseconds";
        @femtosecond: prefix!(femto); "fs", "femtosecond", "femtoseconds";
        @attosecond: prefix!(atto); "as", "attosecond", "attoseconds";
        @zeptosecond: prefix!(zepto); "zs", "zeptosecond", "zeptoseconds";
        @yoctosecond: prefix!(yocto); "ys", "yoctosecond", "yoctoseconds";

        @second_sidereal: 9.972_696_E-1; "s (sidereal)", "second (sidereal)", "seconds (sidereal)";
        @day: 8.64_E4; "d", "day", "days";
        @day_sidereal: 8.616_409_E4; "d (sidereal)", "day (sidereal)", "days (sidereal)";
        @hour: 3.6_E3; "h", "hour", "hours";
        @hour_sidereal: 3.590_170_E3; "h (sidereal)", "hour (sidereal)", "hours (sidereal)";
        @minute: 6.0_E1; "min", "minute", "minutes";
        @shake: 1.0_E-8; "10.0 ns", "shake", "shakes";
        @year: 3.1536_E7; "a", "year", "years";
        @year_sidereal: 3.155_815_E7; "a (sidereal)", "year (sidereal)", "years (sidereal)";
        @year_tropical: 3.155_693_E7; "a (tropical)", "year (tropical)", "years (tropical)";
    }
}

/// An error encountered converting between `Time` and `Duration`.
#[cfg(feature = "try-from")]
#[derive(Debug, Clone, Copy)]
pub enum TryFromError {
    /// The given time interval was negative, making conversion to a duration nonsensical.
    ///
    /// To convert a negative time interval to a duration, first use `abs` to make it positive.
    NegativeDuration,

    /// The given time interval exceeded the maximum size of a `Duration`.
    Overflow,
}

/// Attempt to convert the given `Time` to a `Duration`.
///
/// For possible failure modes see [`TryFromError`][TryFromError].
///
/// ## Notes
///
/// The `Duration` to `Time` conversion is tested to be accurate to within 1 nanosecond (to allow
/// for floating point rounding error). If greater precision is needed, consider using a different
/// underlying storage type or avoiding the conversion altogether.
///
/// [TryFromError]: enum.TryFromError.html
#[cfg(feature = "try-from")]
impl ::lib::convert::TryFrom<Time> for Duration
where
    U: ::si::Units<V> + ?Sized,
    V: ::num::Num + ::Conversion<V> + ::lib::cmp::PartialOrd + ToPrimitive,
    second: ::Conversion<V, T = V::T>,
    nanosecond: ::Conversion<V, T = V::T>,
{
    type Error = TryFromError;

    fn try_from(time: Time) -> Result<Self, Self::Error> {
        if time < Time::::zero() {
            return Err(TryFromError::NegativeDuration);
        }

        let secs = time.get::<second>().to_u64();
        let nanos = (time % Time::::new::<second>(V::one())).get::<nanosecond>().to_u32();

        match (secs, nanos) {
            (Some(secs), Some(nanos)) => Ok(Duration::new(secs, nanos)),
            _ => Err(TryFromError::Overflow),
        }
    }
}

/// Attempt to convert the given `Duration` to a `Time`.
///
/// For possible failure modes, see [`TryFromError`][TryFromError].
///
/// ## Notes
///
/// The `Duration` to `Time` conversion is tested to be accurate to within 100 nanoseconds (to
/// allow for floating point rounding error). If greater precision is needed, consider using a
/// different underlying storage type or avoiding the conversion altogether.
///
/// [TryFromError]: enum.TryFromError.html
#[cfg(feature = "try-from")]
impl ::lib::convert::TryFrom<Duration> for Time
where
    U: ::si::Units<V> + ?Sized,
    V: ::num::Num + ::Conversion<V> + FromPrimitive,
    second: ::Conversion<V, T = V::T>,
    nanosecond: ::Conversion<V, T = V::T>,
{
    type Error = TryFromError;

    fn try_from(duration: Duration) -> Result<Self, Self::Error> {
        let secs = V::from_u64(duration.as_secs());
        let nanos = V::from_u32(duration.subsec_micros());

        match (secs, nanos) {
            (Some(secs), Some(nanos)) => {
                Ok(Time::::new::<second>(secs) + Time::::new::<nanosecond>(nanos))
            }
            _ => Err(TryFromError::Overflow),
        }
    }
}

#[cfg(all(test, feature = "try-from"))]
mod tests {
    storage_types! {
        types: PrimInt, BigInt, BigUint, Float;

        use lib::convert::{TryFrom, TryInto};
        use lib::time::Duration;
        use num::{FromPrimitive, ToPrimitive, Zero};
        use tests::*;
        use si::quantities::*;
        use si::time::{TryFromError, nanosecond};
        use quickcheck::TestResult;

        quickcheck! {
            fn duration_try_from(v: A<V>) -> TestResult {
                test_try_from(Duration::try_from(Time::new::<nanosecond>((*v).clone())), v)
            }

            fn time_try_into(v: A<V>) -> TestResult {
                test_try_from(Time::new::<nanosecond>((*v).clone()).try_into(), v)
            }

            fn time_try_from(v: A<V>) -> TestResult {
                match v.to_u64() {
                    Some(u) => test_try_into(Time::try_from(Duration::from_nanos(u)), v),
                    None => TestResult::discard(),
                }
            }

            fn duration_try_into(v: A<V>) -> TestResult {
                match v.to_u64() {
                    Some(u) => test_try_into(Duration::from_nanos(u).try_into(), v),
                    None => TestResult::discard(),
                }
            }
        }

        fn test_try_from(t: Result<Duration, TryFromError>, v: A<V>) -> TestResult {
            if *v < V::zero() {
                return TestResult::discard();
            }

            let ok = match (t, v.to_u64()) {
                (Ok(t), Some(u)) => {
                    let d = Duration::from_nanos(u);
                    let r = if d > t { d - t } else { t - d };

                    Duration::from_nanos(1) >= r
                },
                (Err(_), None) => true,
                _ => false,
            };

            TestResult::from_bool(ok)
        }

        fn test_try_into(t: Result<Time<V>, TryFromError>, v: A<V>) -> TestResult {
            if *v < V::zero() {
                return TestResult::discard();
            }

            let ok = match t {
                Ok(t) => {
                    let b = Time::new::<nanosecond>((*v).clone());
                    let d = if t > b { t - b } else { b - t };

                    d <= Time::new::<nanosecond>(V::from_u8(100).unwrap())
                },
                _ => false,
            };

            TestResult::from_bool(ok)
        }
    }
}
<|endoftext|>


<commit_before>use rocket::http::uri::Origin;
use rocket::response::NamedFile;
use rocket::response::Redirect;
use rocket::State;
use std::io;
use std::path::PathBuf;
use std::sync::Arc;

use crate::server::StaticDirs;

pub fn get_routes() -> Vec<rocket::Route> {
	routes![
		index,
		files,
	]
}

#[get("/", rank = 9)]
fn index(origin: &Origin) -> Redirect {
	let redirect = Redirect::permanent(origin.path().to_owned() + "index.html");
	return redirect;
}

#[get("/<file..>", rank = 9)]
fn files(static_dirs: State<Arc<StaticDirs>>, file: PathBuf) -> Option<NamedFile> {
	let path = static_dirs.swagger_dir_path.clone().join(file.clone());
    NamedFile::open(path).ok()
}

#[test]
fn test_index_redirect() {
	use rocket::http::Status;
	use crate::test::get_test_environment;

	let env = get_test_environment("swagger_index_redirect.sqlite");
	let client = &env.client;
	let response = client.get("/swagger").dispatch();
	assert_eq!(response.status(), Status::PermanentRedirect);
}

#[test]
fn test_index() {
	use rocket::http::Status;
	use crate::test::get_test_environment;

	let env = get_test_environment("swagger_index.sqlite");
	let client = &env.client;
	let response = client.get("/swagger/index.html").dispatch();
	assert_eq!(response.status(), Status::Ok);
}
<commit_msg>Removed unused import<commit_after>use rocket::http::uri::Origin;
use rocket::response::NamedFile;
use rocket::response::Redirect;
use rocket::State;
use std::path::PathBuf;
use std::sync::Arc;

use crate::server::StaticDirs;

pub fn get_routes() -> Vec<rocket::Route> {
	routes![
		index,
		files,
	]
}

#[get("/", rank = 9)]
fn index(origin: &Origin) -> Redirect {
	let redirect = Redirect::permanent(origin.path().to_owned() + "index.html");
	return redirect;
}

#[get("/<file..>", rank = 9)]
fn files(static_dirs: State<Arc<StaticDirs>>, file: PathBuf) -> Option<NamedFile> {
	let path = static_dirs.swagger_dir_path.clone().join(file.clone());
    NamedFile::open(path).ok()
}

#[test]
fn test_index_redirect() {
	use rocket::http::Status;
	use crate::test::get_test_environment;

	let env = get_test_environment("swagger_index_redirect.sqlite");
	let client = &env.client;
	let response = client.get("/swagger").dispatch();
	assert_eq!(response.status(), Status::PermanentRedirect);
}

#[test]
fn test_index() {
	use rocket::http::Status;
	use crate::test::get_test_environment;

	let env = get_test_environment("swagger_index.sqlite");
	let client = &env.client;
	let response = client.get("/swagger/index.html").dispatch();
	assert_eq!(response.status(), Status::Ok);
}
<|endoftext|>


<commit_before>use std::ptr;

use exception::DoraToNativeInfo;
use gc::{Address, Region};

pub struct ThreadLocalData {
    d2n: *const DoraToNativeInfo,
    tlab_top: Address,
    tlab_end: Address,
}

impl ThreadLocalData {
    pub fn new() -> ThreadLocalData {
        ThreadLocalData {
            d2n: ptr::null(),
            tlab_top: Address::null(),
            tlab_end: Address::null(),
        }
    }

    pub fn tlab_initialize(&mut self, start: Address, end: Address) {
        self.tlab_top = start;
        self.tlab_end = end;
    }

    pub fn tlab_rest(&self) -> usize {
        self.tlab_end.offset_from(self.tlab_top)
    }

    pub fn tlab_region(&self) -> Region {
        Region::new(self.tlab_top, self.tlab_end)
    }

    pub fn tlab_top_offset() -> i32 {
        offset_of!(ThreadLocalData, tlab_top) as i32
    }

    pub fn tlab_end_offset() -> i32 {
        offset_of!(ThreadLocalData, tlab_end) as i32
    }
}
<commit_msg>start implementing concurrent marking<commit_after>use std::ptr;

use exception::DoraToNativeInfo;
use gc::{Address, Region};

pub struct ThreadLocalData {
    d2n: *const DoraToNativeInfo,
    tlab_top: Address,
    tlab_end: Address,
    concurrent_marking: bool,
}

impl ThreadLocalData {
    pub fn new() -> ThreadLocalData {
        ThreadLocalData {
            d2n: ptr::null(),
            tlab_top: Address::null(),
            tlab_end: Address::null(),
            concurrent_marking: false,
        }
    }

    pub fn tlab_initialize(&mut self, start: Address, end: Address) {
        self.tlab_top = start;
        self.tlab_end = end;
    }

    pub fn tlab_rest(&self) -> usize {
        self.tlab_end.offset_from(self.tlab_top)
    }

    pub fn tlab_region(&self) -> Region {
        Region::new(self.tlab_top, self.tlab_end)
    }

    pub fn tlab_top_offset() -> i32 {
        offset_of!(ThreadLocalData, tlab_top) as i32
    }

    pub fn tlab_end_offset() -> i32 {
        offset_of!(ThreadLocalData, tlab_end) as i32
    }

    pub fn concurrent_marking_offset() -> i32 {
        offset_of!(ThreadLocalData, concurrent_marking) as i32
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use extra::json;
use serialize::Decodable;
use glfw;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use camera::Camera;
use map::TileIterator;
use geom::Geom;
use tile_picker::TilePicker;
use obj;
use mesh::Mesh;
use misc::read_file;

fn build_hex_mesh(&geom: &Geom) -> ~[Vec3<GLfloat>] {
  let mut vertex_data = ~[];
  for tile_pos in TileIterator::new() {
    let pos3d = geom.map_pos_to_world_pos(tile_pos);
    for num in range(0, 6) {
      let vertex = geom.index_to_hex_vertex(num);
      let next_vertex = geom.index_to_hex_vertex(num + 1);
      let data = &mut vertex_data;
      data.push(pos3d + vertex);
      data.push(pos3d + next_vertex);
      data.push(pos3d + Vec3::zero());
    }
  }
  vertex_data
}

pub struct Visualizer {
  program: GLuint,
  map_mesh: Mesh,
  unit_mesh: Mesh,
  mat_id: GLint,
  win: Option<glfw::Window>,
  mouse_pos: Vec2<f32>,
  camera: Camera,
  picker: TilePicker,
  selected_tile_pos: Option<Vec2<i32>>,
  geom: Geom,
}

fn init_win(win_size: Vec2<int>) -> glfw::Window {
  glfw::set_error_callback(~glfw::LogErrorHandler);
  let init_status = glfw::init();
  if !init_status.is_ok() {
    fail!("Failed to initialize GLFW");
  }
  let win = glfw::Window::create(
    win_size.x as u32,
    win_size.y as u32,
    "OpenGL",
    glfw::Windowed,
  ).unwrap();
  win.make_context_current();
  win.set_all_polling(true);
  win
}

#[deriving(Decodable)]
struct Size2<T> {
  x: T,
  y: T,
}

fn read_win_size(config_path: &str) -> Vec2<int> {
  let path = Path::new(config_path);
  let json = json::from_str(read_file(&path)).unwrap();
  let mut decoder = json::Decoder::new(json);
  let size: Size2<int> = Decodable::decode(&mut decoder);
  Vec2{x: size.x, y: size.y}
}

impl Visualizer {
  pub fn new() -> ~Visualizer {
    let win_size = read_win_size("config.json");
    let win = init_win(win_size);
    let geom = Geom::new();
    let mut vis = ~Visualizer {
      program: 0,
      map_mesh: Mesh::new(),
      unit_mesh: Mesh::new(),
      mat_id: 0,
      win: Some(win),
      mouse_pos: Vec2::zero(),
      camera: Camera::new(),
      picker: TilePicker::new(),
      selected_tile_pos: None,
      geom: geom,
    };
    vis.init_opengl();
    vis.picker.init(&geom);
    vis.init_models();
    vis
  }

  fn win<'a>(&'a self) -> &'a glfw::Window {
    self.win.get_ref()
  }

  fn init_models(&mut self) {
    self.program = glh::compile_program(
      read_file(&Path::new("normal.vs.glsl")),
      read_file(&Path::new("normal.fs.glsl")),
    );
    gl::UseProgram(self.program);
    self.mat_id = glh::get_uniform(self.program, "mvp_mat");
    let pos_attr = glh::get_attr(self.program, "position");
    glh::vertex_attrib_pointer(pos_attr);
    let map_vertex_data = build_hex_mesh(&self.geom);
    self.map_mesh.init(map_vertex_data);
    let unit_obj = obj::Model::new("data/tank.obj");
    self.unit_mesh.init(unit_obj.build());
  }

  fn init_opengl(&mut self) {
    gl::load_with(glfw::get_proc_address);
  }

  fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
  }

  fn draw_unit_at(&self, pos: Vec2<i32>) {
    let world_pos = self.geom.map_pos_to_world_pos(pos);
    let m = glh::tr(self.camera.mat(), world_pos);
    glh::uniform_mat4f(self.mat_id, &m);
    self.unit_mesh.draw(self.program);
  }

  fn draw(&self) {
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::UseProgram(self.program);
    self.draw_unit_at(Vec2{x: 0, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 0});
    self.draw_unit_at(Vec2{x: 2, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 1});
    if !self.selected_tile_pos.is_none() {
      let p = self.selected_tile_pos.unwrap();
      self.draw_unit_at(p);
    }
    glh::uniform_mat4f(self.mat_id, &self.camera.mat());
    self.map_mesh.draw(self.program);
    self.win().swap_buffers();
  }

  pub fn is_running(&self) -> bool {
    return !self.win().should_close()
  }

  fn handle_key_event(&mut self, key: glfw::Key) {
    match key {
      glfw::KeyEscape | glfw::KeyQ => {
        self.win().set_should_close(true);
      },
      glfw::KeySpace => println!("space"),
      glfw::KeyUp => self.camera.move(270.0),
      glfw::KeyDown => self.camera.move(90.0),
      glfw::KeyRight => self.camera.move(0.0),
      glfw::KeyLeft => self.camera.move(180.0),
      _ => {},
    }
  }

  fn handle_cursor_pos_event(&mut self, pos: Vec2<f32>) {
    let button = self.win().get_mouse_button(glfw::MouseButtonRight);
    if button == glfw::Press {
      self.camera.z_angle += self.mouse_pos.x - pos.x;
      self.camera.x_angle += self.mouse_pos.y - pos.y;
    }
    self.mouse_pos = pos;
  }

  fn get_events(&mut self) -> ~[glfw::WindowEvent]{
    glfw::poll_events();
    let mut events = ~[];
    for (_, event) in self.win().flush_events() {
      events.push(event);
    }
    events
  }

  fn handle_event(&mut self, event: glfw::WindowEvent) {
    match event {
      glfw::KeyEvent(key, _, glfw::Press, _) => {
        self.handle_key_event(key);
      },
      glfw::CursorPosEvent(x, y) => {
        let p = Vec2{x: x as f32, y: y as f32};
        self.handle_cursor_pos_event(p);
      },
      _ => {},
    }
  }

  fn handle_events(&mut self) {
    for event in self.get_events().iter() {
      self.handle_event(*event);
    }
  }

  fn close_window(&mut self) {
    // destroy glfw::Window before terminating glfw
    self.win = None;
  }

  fn pick_tile(&mut self) {
    let mouse_pos = Vec2 {
      x: self.mouse_pos.x as i32,
      y: self.mouse_pos.y as i32,
    };
    let win_size = self.win().get_size();
    self.selected_tile_pos = self.picker.pick_tile(
      win_size, &self.camera, mouse_pos);
    println!("selected: {:?}", self.selected_tile_pos);
  }

  pub fn tick(&mut self) {
    self.handle_events();
    self.pick_tile();
    self.draw();
  }
}

impl Drop for Visualizer {
  fn drop(&mut self) {
    self.cleanup_opengl();
    self.close_window();
    glfw::terminate();
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>Visualizer: draw_map, draw_units<commit_after>// See LICENSE file for copyright and license details.

use extra::json;
use serialize::Decodable;
use glfw;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use camera::Camera;
use map::TileIterator;
use geom::Geom;
use tile_picker::TilePicker;
use obj;
use mesh::Mesh;
use misc::read_file;

fn build_hex_mesh(&geom: &Geom) -> ~[Vec3<GLfloat>] {
  let mut vertex_data = ~[];
  for tile_pos in TileIterator::new() {
    let pos3d = geom.map_pos_to_world_pos(tile_pos);
    for num in range(0, 6) {
      let vertex = geom.index_to_hex_vertex(num);
      let next_vertex = geom.index_to_hex_vertex(num + 1);
      let data = &mut vertex_data;
      data.push(pos3d + vertex);
      data.push(pos3d + next_vertex);
      data.push(pos3d + Vec3::zero());
    }
  }
  vertex_data
}

pub struct Visualizer {
  program: GLuint,
  map_mesh: Mesh,
  unit_mesh: Mesh,
  mat_id: GLint,
  win: Option<glfw::Window>,
  mouse_pos: Vec2<f32>,
  camera: Camera,
  picker: TilePicker,
  selected_tile_pos: Option<Vec2<i32>>,
  geom: Geom,
}

fn init_win(win_size: Vec2<int>) -> glfw::Window {
  glfw::set_error_callback(~glfw::LogErrorHandler);
  let init_status = glfw::init();
  if !init_status.is_ok() {
    fail!("Failed to initialize GLFW");
  }
  let win = glfw::Window::create(
    win_size.x as u32,
    win_size.y as u32,
    "OpenGL",
    glfw::Windowed,
  ).unwrap();
  win.make_context_current();
  win.set_all_polling(true);
  win
}

#[deriving(Decodable)]
struct Size2<T> {
  x: T,
  y: T,
}

fn read_win_size(config_path: &str) -> Vec2<int> {
  let path = Path::new(config_path);
  let json = json::from_str(read_file(&path)).unwrap();
  let mut decoder = json::Decoder::new(json);
  let size: Size2<int> = Decodable::decode(&mut decoder);
  Vec2{x: size.x, y: size.y}
}

impl Visualizer {
  pub fn new() -> ~Visualizer {
    let win_size = read_win_size("config.json");
    let win = init_win(win_size);
    let geom = Geom::new();
    let mut vis = ~Visualizer {
      program: 0,
      map_mesh: Mesh::new(),
      unit_mesh: Mesh::new(),
      mat_id: 0,
      win: Some(win),
      mouse_pos: Vec2::zero(),
      camera: Camera::new(),
      picker: TilePicker::new(),
      selected_tile_pos: None,
      geom: geom,
    };
    vis.init_opengl();
    vis.picker.init(&geom);
    vis.init_models();
    vis
  }

  fn win<'a>(&'a self) -> &'a glfw::Window {
    self.win.get_ref()
  }

  fn init_models(&mut self) {
    self.program = glh::compile_program(
      read_file(&Path::new("normal.vs.glsl")),
      read_file(&Path::new("normal.fs.glsl")),
    );
    gl::UseProgram(self.program);
    self.mat_id = glh::get_uniform(self.program, "mvp_mat");
    let pos_attr = glh::get_attr(self.program, "position");
    glh::vertex_attrib_pointer(pos_attr);
    let map_vertex_data = build_hex_mesh(&self.geom);
    self.map_mesh.init(map_vertex_data);
    let unit_obj = obj::Model::new("data/tank.obj");
    self.unit_mesh.init(unit_obj.build());
  }

  fn init_opengl(&mut self) {
    gl::load_with(glfw::get_proc_address);
  }

  fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
  }

  fn draw_unit_at(&self, pos: Vec2<i32>) {
    let world_pos = self.geom.map_pos_to_world_pos(pos);
    let m = glh::tr(self.camera.mat(), world_pos);
    glh::uniform_mat4f(self.mat_id, &m);
    self.unit_mesh.draw(self.program);
  }

  fn draw_units(&self) {
    self.draw_unit_at(Vec2{x: 0, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 0});
    self.draw_unit_at(Vec2{x: 2, y: 0});
    self.draw_unit_at(Vec2{x: 1, y: 1});
    if !self.selected_tile_pos.is_none() {
      let p = self.selected_tile_pos.unwrap();
      self.draw_unit_at(p);
    }
  }

  fn draw_map(&self) {
    glh::uniform_mat4f(self.mat_id, &self.camera.mat());
    self.map_mesh.draw(self.program);
  }

  fn draw(&self) {
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
    gl::UseProgram(self.program);
    self.draw_units();
    self.draw_map();
    self.win().swap_buffers();
  }

  pub fn is_running(&self) -> bool {
    return !self.win().should_close()
  }

  fn handle_key_event(&mut self, key: glfw::Key) {
    match key {
      glfw::KeyEscape | glfw::KeyQ => {
        self.win().set_should_close(true);
      },
      glfw::KeySpace => println!("space"),
      glfw::KeyUp => self.camera.move(270.0),
      glfw::KeyDown => self.camera.move(90.0),
      glfw::KeyRight => self.camera.move(0.0),
      glfw::KeyLeft => self.camera.move(180.0),
      _ => {},
    }
  }

  fn handle_cursor_pos_event(&mut self, pos: Vec2<f32>) {
    let button = self.win().get_mouse_button(glfw::MouseButtonRight);
    if button == glfw::Press {
      self.camera.z_angle += self.mouse_pos.x - pos.x;
      self.camera.x_angle += self.mouse_pos.y - pos.y;
    }
    self.mouse_pos = pos;
  }

  fn get_events(&mut self) -> ~[glfw::WindowEvent]{
    glfw::poll_events();
    let mut events = ~[];
    for (_, event) in self.win().flush_events() {
      events.push(event);
    }
    events
  }

  fn handle_event(&mut self, event: glfw::WindowEvent) {
    match event {
      glfw::KeyEvent(key, _, glfw::Press, _) => {
        self.handle_key_event(key);
      },
      glfw::CursorPosEvent(x, y) => {
        let p = Vec2{x: x as f32, y: y as f32};
        self.handle_cursor_pos_event(p);
      },
      _ => {},
    }
  }

  fn handle_events(&mut self) {
    for event in self.get_events().iter() {
      self.handle_event(*event);
    }
  }

  fn close_window(&mut self) {
    // destroy glfw::Window before terminating glfw
    self.win = None;
  }

  fn pick_tile(&mut self) {
    let mouse_pos = Vec2 {
      x: self.mouse_pos.x as i32,
      y: self.mouse_pos.y as i32,
    };
    let win_size = self.win().get_size();
    self.selected_tile_pos = self.picker.pick_tile(
      win_size, &self.camera, mouse_pos);
    println!("selected: {:?}", self.selected_tile_pos);
  }

  pub fn tick(&mut self) {
    self.handle_events();
    self.pick_tile();
    self.draw();
  }
}

impl Drop for Visualizer {
  fn drop(&mut self) {
    self.cleanup_opengl();
    self.close_window();
    glfw::terminate();
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::iter::FromIterator;

use url::Url;

use iron::prelude::*;
use router::RouterInner;

/// Generate a URL based off of the currently requested URL.
///
/// The `route_id` used during route registration will be used here again.
///
/// `params` will be inserted as route parameters if fitting, the rest will be appended as query
/// parameters.
pub fn url_for(request: &Request, route_id: &str, params: HashMap<String, String>) -> Url {
    let inner = request.extensions.get::<RouterInner>().expect("Couldn\'t find router set up properly.");
    let glob = inner.route_ids.get(route_id).expect("No route with that ID");

    let mut url = request.url.clone().into_generic_url();
    url_for_impl(&mut url, glob, params);
    url
}

fn url_for_impl(url: &mut Url, glob: &str, mut params: HashMap<String, String>) {
    let mut glob_iter = glob.chars();
    let mut path = String::new();

    while glob_iter.size_hint().1.unwrap() > 0 {
        path.extend(glob_iter.by_ref().take_while(|&x| x != ':' && x != '*'));

        let key = String::from_iter(glob_iter.by_ref().take_while(|&x| x != '/'));
        if key.is_empty() { continue }

        let value = match params.remove(&key) {
            Some(x) => x,
            None => panic!("No value for key {}", key)
        };
        path.push_str(&value);
    }

    url.set_path(&path);

    // Now add on the remaining parameters that had no path match.
    url.set_query(None);
    if !params.is_empty() {
        url.query_pairs_mut()
            .extend_pairs(params.into_iter());
    }

    url.set_fragment(None);
}

#[cfg(test)]
mod test {
    use super::url_for_impl;
    use std::collections::HashMap;

    #[test]
    fn test_no_trailing_slash() {
        let mut url = "http://localhost/foo/bar/baz".parse().unwrap();
        url_for_impl(&mut url, "/foo/:user", {
            let mut rv = HashMap::new();
            rv.insert("user".into(), "bam".into());
            rv
        });
        assert_eq!(url.to_string(), "http://localhost/foo/bam");
    }

    #[test]
    fn test_trailing_slash() {
        let mut url = "http://localhost/foo/bar/baz".parse().unwrap();
        url_for_impl(&mut url, "/foo/:user/", {
            let mut rv = HashMap::new();
            rv.insert("user".into(), "bam".into());
            rv
        });
        assert_eq!(url.to_string(), "http://localhost/foo/bam/");
    }
}
<commit_msg>(fix) bug in url_for with trailing slash<commit_after>use std::collections::HashMap;

use url::Url;

use iron::prelude::*;
use router::RouterInner;

/// Generate a URL based off of the currently requested URL.
///
/// The `route_id` used during route registration will be used here again.
///
/// `params` will be inserted as route parameters if fitting, the rest will be appended as query
/// parameters.
pub fn url_for(request: &Request, route_id: &str, params: HashMap<String, String>) -> Url {
    let inner = request.extensions.get::<RouterInner>().expect("Couldn\'t find router set up properly.");
    let glob = inner.route_ids.get(route_id).expect("No route with that ID");

    let mut url = request.url.clone().into_generic_url();
    url_for_impl(&mut url, glob, params);
    url
}

fn url_for_impl(url: &mut Url, glob: &str, mut params: HashMap<String, String>) {
    {
        let mut url_path_segments = url.path_segments_mut().unwrap();
        url_path_segments.clear();
        for path_segment in glob.split('/') {
            if path_segment.len() > 1 && (path_segment.starts_with(':') || path_segment.starts_with('*')) {
                let key = &path_segment[1..];
                match params.remove(key) {
                    Some(x) => url_path_segments.push(&x),
                    None => panic!("No value for key {}", key)
                };
            } else {
                url_path_segments.push(path_segment);
            }
        }
    }

    // Now add on the remaining parameters that had no path match.
    url.set_query(None);
    if !params.is_empty() {
        url.query_pairs_mut()
            .extend_pairs(params.into_iter());
    }

    url.set_fragment(None);
}

#[cfg(test)]
mod test {
    use super::url_for_impl;
    use std::collections::HashMap;

    #[test]
    fn test_no_trailing_slash() {
        let mut url = "http://localhost/foo/bar/baz".parse().unwrap();
        url_for_impl(&mut url, "/foo/:user", {
            let mut rv = HashMap::new();
            rv.insert("user".into(), "bam".into());
            rv
        });
        assert_eq!(url.to_string(), "http://localhost/foo/bam");
    }

    #[test]
    fn test_trailing_slash() {
        let mut url = "http://localhost/foo/bar/baz".parse().unwrap();
        url_for_impl(&mut url, "/foo/:user/", {
            let mut rv = HashMap::new();
            rv.insert("user".into(), "bam".into());
            rv
        });
        assert_eq!(url.to_string(), "http://localhost/foo/bam/");
    }
}
<|endoftext|>


<commit_before>// Utility functions for libsvm versions

use ffi;

/// Returns the libsvm version as an integer
pub fn version() -> ::libc::c_int {
    ffi::version()
}

#[test]
fn test_version() {
    println!("libsvm version: {}", version());
    // 3.12 will be printed "312"
    assert!(version() >= 312);
}
<commit_msg>Add missing period<commit_after>// Utility functions for libsvm versions

use ffi;

/// Returns the libsvm version as an integer
pub fn version() -> ::libc::c_int {
    ffi::version()
}

#[test]
fn test_version() {
    println!("libsvm version: {}", version());
    // 3.12 will be printed "312".
    assert!(version() >= 312);
}
<|endoftext|>


<commit_before>pub const USAGE: &'static str = "
Waterpark File share platform.

Usage:
  waterpark init [options]
  waterpark config <path> [options]

Options
  --blahblah      blahblah
  --blahblah2     blahblah2
";

#[derive(Debug, RustcDecodable)]
pub struct Args {
  pub cmd_init: bool,
  pub arg_path: Vec<String>,
}<commit_msg>re org cli command<commit_after>pub const USAGE: &'static str = "
Waterpark File share platform.

Usage:
  waterpark
  waterpark init
  waterpark config <path>
  waterpark help
";

#[derive(Debug, RustcDecodable)]
pub struct Args {
  pub cmd_init: bool,
  pub cmd_config: bool,
  pub cmd_help: bool,
  pub arg_path: Vec<String>,
}<|endoftext|>


<commit_before>extern crate polydraw;

use polydraw::Application;
use polydraw::devel::{Scene, Poly, DevelRenderer};
use polydraw::geom::point::Point;
use polydraw::draw::RGB;

type TPoint = (i64, i64);
type TPoly = Vec<Vec<TPoint>>;

#[derive(Debug)]
#[allow(dead_code)]
enum Data {
   None,
   I64(i64),
   F64(f64),
   Point(TPoint),
   Poly(TPoly),
}

trait Node {
   fn new(init1: Data, init2: Data, init3: Data, init4: Data) -> Self;

   fn process(&self, arg1: &Data, arg2: &Data, arg3: &Data, arg4: &Data) -> Data;
}

struct Add {
   init1: Data,
   init2: Data,
}

impl Add {
}

impl Node for Add {
   #[inline]
   fn new(init1: Data, init2: Data, _: Data, _: Data) -> Self {
      Add {
         init1: init1,
         init2: init2,
      }
   }

   #[inline]
   fn process(&self, arg1: &Data, arg2: &Data, _: &Data, _: &Data) -> Data {
      let val1 = actual(arg1, &self.init1);
      let val2 = actual(arg2, &self.init2);

      match val1 {
         &Data::I64(ref left) => match val2 {
            &Data::I64(ref right) => add_i64_i64(left, right),
            &Data::F64(ref right) => Data::F64(*left as f64 + *right),
            &Data::Point(ref right) => add_point_i64(right, left),
            _ => Data::None
         },
         &Data::F64(ref left) => match val2 {
            &Data::I64(ref right) => Data::F64(*left + *right as f64),
            &Data::F64(ref right) => Data::F64(*left + *right),
            _ => Data::None
         },
         &Data::Poly(ref left) => match val2 {
            &Data::Point(ref right) => add_poly_point(left, right),
            _ => Data::None
         },
         &Data::Point(ref left) => match val2 {
            &Data::Poly(ref right) => add_poly_point(right, left),
            _ => Data::None
         },
         _ => Data::None
      }
   }
}

#[inline]
fn add_i64_i64(left: &i64, right: &i64) -> Data {
   Data::I64(*left + *right)
}

#[inline]
fn add_point_i64(left: &TPoint, right: &i64) -> Data {
   Data::Point((left.0 + *right, left.1 + *right))
}

#[inline]
fn add_poly_point(left: &TPoly, right: &TPoint) -> Data {
   let mut group = Vec::with_capacity(left.len());

   let (add_x, add_y) = *right;

   for src in left {
      let mut contour = Vec::with_capacity(src.len());

      for point in src {
         let (x, y) = *point;
         contour.push((x + add_x, y + add_y));
      }

      group.push(contour);
   }

   Data::Poly(group)
}

#[inline]
fn actual<'a>(passed: &'a Data, initial: &'a Data) -> &'a Data {
   match passed {
      &Data::None => initial,
      _ => passed
   }
}

#[inline]
fn _poly_from_data(data: &TPoly) -> Poly {
   let outer = _points_from_coords(&data[0]);

   let mut inner = Vec::new();

   for inner_data in &data[1..] {
      inner.push(
         _points_from_coords(inner_data)
      );
   }

   let poly = Poly::new_with_holes(
      outer, inner, RGB::new(81, 180, 200),
   );

   poly
}

#[inline]
fn _points_from_coords(coords: &[(i64, i64)]) -> Vec<Point> {
   let mut points = Vec::new();

   for &(x, y) in coords.iter() {
      points.push(Point::new(x + 120, y + 120))
   }

   points
}

fn main() {
   let mut scene = Scene::new();

   let source = vec![vec![
      (90, 1200),
      (261, 1735),
      (1443, 410),
      (493, 174),
   ]];

   let add = Add::new(Data::None, Data::None, Data::None, Data::None);

   let destination = add.process(
      &Data::Poly(source), &Data::Point((957, 223)), &Data::None, &Data::None
   );

   match destination {
      Data::Poly(data) => scene.push(_poly_from_data(&data)),
      _ => {}
   }

   let mut renderer = DevelRenderer::new(scene);

   Application::new()
      .renderer(&mut renderer)
      .title("Nodes")
      .size(1200, 800)
      .run();
}

<commit_msg>Using a trait with different impls instead of separate functions for the add functionality<commit_after>extern crate polydraw;

use polydraw::Application;
use polydraw::devel::{Scene, Poly, DevelRenderer};
use polydraw::geom::point::Point;
use polydraw::draw::RGB;

type TPoint = (i64, i64);
type TPoly = Vec<Vec<TPoint>>;

#[derive(Debug)]
#[allow(dead_code)]
enum Data {
   None,
   I64(i64),
   F64(f64),
   Point(TPoint),
   Poly(TPoly),
}

trait Node {
   fn new(init1: Data, init2: Data, init3: Data, init4: Data) -> Self;

   fn process(&self, arg1: &Data, arg2: &Data, arg3: &Data, arg4: &Data) -> Data;
}

struct AddNode {
   init1: Data,
   init2: Data,
}

impl Node for AddNode {
   #[inline]
   fn new(init1: Data, init2: Data, _: Data, _: Data) -> Self {
      AddNode {
         init1: init1,
         init2: init2,
      }
   }

   #[inline]
   fn process(&self, arg1: &Data, arg2: &Data, _: &Data, _: &Data) -> Data {
      let in1 = actual(arg1, &self.init1);
      let in2 = actual(arg2, &self.init2);

      match (in1, in2) {
         (&Data::I64(ref v1), &Data::I64(ref v2)) => <(i64, i64)>::add(v1, v2),

         (&Data::F64(ref v1), &Data::I64(ref v2)) => <(f64, i64)>::add(v1, v2),
         (&Data::I64(ref v1), &Data::F64(ref v2)) => <(f64, i64)>::add(v2, v1),

         (&Data::Point(ref v1), &Data::I64(ref v2)) => <(TPoint, i64)>::add(v1, v2),
         (&Data::I64(ref v1), &Data::Point(ref v2)) => <(TPoint, i64)>::add(v2, v1),

         (&Data::Poly(ref v1), &Data::Point(ref v2)) => <(TPoly, TPoint)>::add(v1, v2),
         (&Data::Point(ref v1), &Data::Poly(ref v2)) => <(TPoly, TPoint)>::add(v2, v1),

         _ => Data::None
      }
   }
}

trait Add<T1, T2> {
   fn add(v1: &T1, v2: &T2) -> Data;
}

impl Add<i64, i64> for (i64, i64) {
   #[inline]
   fn add(v1: &i64, v2: &i64) -> Data {
      Data::I64(*v1 + *v2)
   }
}

impl Add<f64, i64> for (f64, i64) {
   #[inline]
   fn add(v1: &f64, v2: &i64) -> Data {
      Data::F64(*v1 + *v2 as f64)
   }
}

impl Add<TPoint, i64> for (TPoint, i64) {
   #[inline]
   fn add(v1: &TPoint, v2: &i64) -> Data {
      Data::Point((v1.0 + *v2, v1.1 + *v2))
   }
}

impl Add<TPoly, TPoint> for (TPoly, TPoint) {
   #[inline]
   fn add(v1: &TPoly, v2: &TPoint) -> Data {
      let mut outer = Vec::with_capacity(v1.len());

      for src in v1 {
         let mut inner = Vec::with_capacity(src.len());

         for tuple in src {
            inner.push((tuple.0 + v2.0, tuple.1 + v2.1));
         }

         outer.push(inner);
      }

      Data::Poly(outer)
   }
}

#[inline]
fn actual<'a>(passed: &'a Data, initial: &'a Data) -> &'a Data {
   match passed {
      &Data::None => initial,
      _ => passed
   }
}

#[inline]
fn _poly_from_data(data: &TPoly) -> Poly {
   let outer = _points_from_coords(&data[0]);

   let mut inner = Vec::new();

   for inner_data in &data[1..] {
      inner.push(
         _points_from_coords(inner_data)
      );
   }

   let poly = Poly::new_with_holes(
      outer, inner, RGB::new(81, 180, 200),
   );

   poly
}

#[inline]
fn _points_from_coords(coords: &[(i64, i64)]) -> Vec<Point> {
   let mut points = Vec::new();

   for &(x, y) in coords.iter() {
      points.push(Point::new(x + 120, y + 120))
   }

   points
}

fn main() {
   let mut scene = Scene::new();

   let source = vec![vec![
      (90, 1200),
      (261, 1735),
      (1443, 410),
      (493, 174),
   ]];

   let add = AddNode::new(Data::None, Data::None, Data::None, Data::None);

   let destination = add.process(
      &Data::Poly(source), &Data::Point((957, 223)), &Data::None, &Data::None
   );

   match destination {
      Data::Poly(data) => scene.push(_poly_from_data(&data)),
      _ => {}
   }

   let mut renderer = DevelRenderer::new(scene);

   Application::new()
      .renderer(&mut renderer)
      .title("Nodes")
      .size(1200, 800)
      .run();
}

<|endoftext|>


<commit_before>use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};

use common::mutex::Mutex;

use scheduler;
use scheduler::context::{context_switch, Context};

struct RecursiveMutexInner {
    owner: usize,
    count: usize
}

pub struct RecursiveMutex<T> {
    inner: Mutex<RecursiveMutexInner>,
    value: UnsafeCell<T>
}

impl<T> RecursiveMutex<T> {
    /// Create a new mutex with value `value`.
    pub fn new(value: T) -> Self {
        RecursiveMutex {
            inner: Mutex::new(RecursiveMutexInner {
                owner: 0,
                count: 0
            }),
            value: UnsafeCell::new(value),
        }
    }
}

impl<T: ?Sized> RecursiveMutex<T> {
    /// Lock mutex
    pub fn lock(&self) -> RecursiveMutexGuard<T> {
        let pid;
        unsafe {
            let reenable = scheduler::start_no_ints();
            if let Some(current) = Context::current() {
                pid = current.pid;
            }else{
                pid = 0;
            }
            scheduler::end_no_ints(reenable);
        }

        loop {
            {
                let mut inner = self.inner.lock();
                if inner.owner == pid || inner.count == 0 {
                    inner.owner = pid;
                    inner.count += 1;
                    break;
                }
            }
            unsafe { context_switch(false) };
        }

        RecursiveMutexGuard::new(&self.inner, &self.value)
    }
}

unsafe impl<T: ?Sized + Send> Send for RecursiveMutex<T> { }

unsafe impl<T: ?Sized + Send> Sync for RecursiveMutex<T> { }

/// A recursive mutex guard (returned by .lock())
pub struct RecursiveMutexGuard<'a, T: ?Sized + 'a> {
    inner: &'a Mutex<RecursiveMutexInner>,
    data: &'a UnsafeCell<T>,
}

impl<'rmutex, T: ?Sized> RecursiveMutexGuard<'rmutex, T> {
    fn new(inner: &'rmutex Mutex<RecursiveMutexInner>, data: &'rmutex UnsafeCell<T>) -> Self {
        RecursiveMutexGuard {
            inner: inner,
            data: data,
        }
    }
}

impl<'rmutex, T: ?Sized> Deref for RecursiveMutexGuard<'rmutex, T> {
    type Target = T;

    fn deref<'a>(&'a self) -> &'a T {
        unsafe { &*self.data.get() }
    }
}

impl<'rmutex, T: ?Sized> DerefMut for RecursiveMutexGuard<'rmutex, T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { &mut *self.data.get() }
    }
}

impl<'a, T: ?Sized> Drop for RecursiveMutexGuard<'a, T> {
    fn drop(&mut self) {
        let mut inner = self.inner.lock();
        inner.count -= 1;
    }
}
<commit_msg>Fixes for recursive mutex<commit_after>use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
use core::usize;

use common::mutex::Mutex;

use scheduler;
use scheduler::context::{context_switch, Context};

struct RecursiveMutexInner {
    owner: usize,
    count: usize
}

pub struct RecursiveMutex<T> {
    inner: Mutex<RecursiveMutexInner>,
    value: UnsafeCell<T>
}

impl<T> RecursiveMutex<T> {
    /// Create a new mutex with value `value`.
    pub fn new(value: T) -> Self {
        RecursiveMutex {
            inner: Mutex::new(RecursiveMutexInner {
                owner: 0,
                count: 0
            }),
            value: UnsafeCell::new(value),
        }
    }
}

impl<T: ?Sized> RecursiveMutex<T> {
    /// Lock mutex
    pub fn lock(&self) -> RecursiveMutexGuard<T> {
        let pid;
        unsafe {
            let reenable = scheduler::start_no_ints();
            if let Some(current) = Context::current() {
                pid = current.pid;
            }else{
                pid = usize::MAX;
            }
            scheduler::end_no_ints(reenable);
        }

        loop {
            {
                let mut inner = self.inner.lock();
                if inner.count == 0 || inner.owner == pid  {
                    inner.owner = pid;
                    inner.count += 1;
                    break;
                }
            }
            unsafe { context_switch(false) };
        }

        RecursiveMutexGuard::new(&self.inner, &self.value)
    }
}

unsafe impl<T: ?Sized + Send> Send for RecursiveMutex<T> { }

unsafe impl<T: ?Sized + Send> Sync for RecursiveMutex<T> { }

/// A recursive mutex guard (returned by .lock())
pub struct RecursiveMutexGuard<'a, T: ?Sized + 'a> {
    inner: &'a Mutex<RecursiveMutexInner>,
    data: &'a UnsafeCell<T>,
}

impl<'rmutex, T: ?Sized> RecursiveMutexGuard<'rmutex, T> {
    fn new(inner: &'rmutex Mutex<RecursiveMutexInner>, data: &'rmutex UnsafeCell<T>) -> Self {
        RecursiveMutexGuard {
            inner: inner,
            data: data,
        }
    }
}

impl<'rmutex, T: ?Sized> Deref for RecursiveMutexGuard<'rmutex, T> {
    type Target = T;

    fn deref<'a>(&'a self) -> &'a T {
        unsafe { &*self.data.get() }
    }
}

impl<'rmutex, T: ?Sized> DerefMut for RecursiveMutexGuard<'rmutex, T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { &mut *self.data.get() }
    }
}

impl<'a, T: ?Sized> Drop for RecursiveMutexGuard<'a, T> {
    fn drop(&mut self) {
        let mut inner = self.inner.lock();
        inner.count -= 1;
        if inner.count == 0 {
            inner.owner = 0;
        }
    }
}
<|endoftext|>