<commit_before>// Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use futures::Future;

use std::cell::{Cell, RefCell};
use std::rc::{Rc};

struct ForkedPromiseInner<F> where F: Future {
    next_clone_id: Cell<u64>,
    poller: Cell<Option<u64>>,
    original_future: RefCell<F>,
    state: RefCell<ForkedPromiseState<F::Item, F::Error>>,
}

enum ForkedPromiseState<T, E> {
    Waiting(::std::collections::BTreeMap<u64, ::futures::task::Task>),
    Done(Result<T, E>),
}

pub struct ForkedPromise<F> where F: Future {
    id: u64,
    inner: Rc<ForkedPromiseInner<F>>,
}

impl <F> Clone for ForkedPromise<F> where F: Future {
    fn clone(&self) -> ForkedPromise<F> {
        let clone_id = self.inner.next_clone_id.get();
        self.inner.next_clone_id.set(clone_id + 1);
        ForkedPromise {
            id: clone_id,
            inner: self.inner.clone(),
        }
    }
}

impl <F> ForkedPromise<F> where F: Future {
    pub fn new(f: F) -> ForkedPromise<F> {
        ForkedPromise {
            id: 0,
            inner: Rc::new(ForkedPromiseInner {
                next_clone_id: Cell::new(1),
                poller: Cell::new(None),
                original_future: RefCell::new(f),
                state: RefCell::new(ForkedPromiseState::Waiting(::std::collections::BTreeMap::new())),
            })
        }
    }
}

impl<F> Drop for ForkedPromise<F> where F: Future {
    fn drop(&mut self) {
        match *self.inner.state.borrow_mut() {
            ForkedPromiseState::Waiting(ref mut waiters) => {
                match self.inner.poller.get() {
                    Some(id) => {
                        if id == self.id {
                            for (_id, waiter) in waiters {
                                waiter.unpark();
                            }
                            self.inner.poller.set(None);
                        } else {
                            waiters.remove(&self.id);
                        }
                    }
                    None => (),
                }
            }
            ForkedPromiseState::Done(_) => (),
        }
    }
}

impl <F> Future for ForkedPromise<F>
    where F: Future, F::Item: Clone, F::Error: Clone,
{
    type Item = F::Item;
    type Error = F::Error;

    fn poll(&mut self) -> ::futures::Poll<Self::Item, Self::Error> {
        match *self.inner.state.borrow_mut() {
            ForkedPromiseState::Waiting(ref mut waiters) => {
                match self.inner.poller.get() {
                    Some(id) if self.id == id => (),
                    None => self.inner.poller.set(Some(self.id)),
                    _ => {
                        waiters.insert(self.id, ::futures::task::park());
                        return Ok(::futures::Async::NotReady)
                    }
                }
            }
            ForkedPromiseState::Done(ref r) => {
                match *r {
                    Ok(ref v) => return Ok(::futures::Async::Ready(v.clone())),
                    Err(ref e) => return Err(e.clone()),
                }
            }
        };

        let done_val = match self.inner.original_future.borrow_mut().poll() {
            Ok(::futures::Async::NotReady) => {
                return Ok(::futures::Async::NotReady)
            }
            Ok(::futures::Async::Ready(v)) => Ok(v),
            Err(e) => Err(e),
        };

        match ::std::mem::replace(&mut *self.inner.state.borrow_mut(),
                                  ForkedPromiseState::Done(done_val.clone())) {
            ForkedPromiseState::Waiting(ref mut waiters) => {
                for (_id, waiter) in waiters {
                    waiter.unpark();
                }
            }
            _ => unreachable!(),
        }
        match done_val {
            Ok(v) => Ok(::futures::Async::Ready(v)),
            Err(e) => Err(e),
        }
    }
}

#[cfg(test)]
mod test {
    use futures::{Future, Poll};
    use futures::sync::oneshot;
    use std::rc::Rc;
    use std::sync::Arc;
    use std::cell::RefCell;
    use super::ForkedPromise;

    enum Mode { Left, Right }

    struct ModedFutureInner<F> where F: Future {
        mode: Mode,
        left: F,
        right: F,
        task: Option<::futures::task::Task>,
    }

    struct ModedFuture<F> where F: Future {
        inner: Rc<RefCell<ModedFutureInner<F>>>,
    }

    struct ModedFutureHandle<F> where F: Future {
        inner: Rc<RefCell<ModedFutureInner<F>>>,
    }

    impl <F> ModedFuture<F> where F: Future {
        pub fn new(left: F, right: F, mode: Mode) -> (ModedFutureHandle<F>, ModedFuture<F>) {
            let inner = Rc::new(RefCell::new(ModedFutureInner {
                left: left, right: right, mode: mode, task: None,
            }));
            (ModedFutureHandle { inner: inner.clone() }, ModedFuture { inner: inner })
        }
    }

    impl <F> ModedFutureHandle<F> where F: Future {
        pub fn switch_mode(&mut self, mode: Mode) {
            self.inner.borrow_mut().mode = mode;
            if let Some(t) = self.inner.borrow_mut().task.take() {
                // The other future may have become ready while we were ignoring it.
                t.unpark();
            }
        }
    }

    impl <F> Future for ModedFuture<F> where F: Future {
        type Item = F::Item;
        type Error = F::Error;
        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            let ModedFutureInner { ref mut mode, ref mut left, ref mut right, ref mut task } =
                *self.inner.borrow_mut();
            *task = Some(::futures::task::park());
            match *mode {
                Mode::Left => left.poll(),
                Mode::Right => right.poll(),
            }
        }
    }

    struct Reaper;
    impl ::task_set::TaskReaper<(), ()> for Reaper {
        fn task_failed(&mut self, _err: ()) {}
    }

    struct Unpark;
    impl ::futures::executor::Unpark for Unpark {
        fn unpark(&self) {}
    }

    fn forked_propagates_unpark_helper(spawn_moded_first: bool) {
        let (handle, tasks) = ::task_set::TaskSet::<(), ()>::new(Box::new(Reaper));

        let mut spawn = ::futures::executor::spawn(tasks);
        let unpark: Arc<::futures::executor::Unpark> = Arc::new(Unpark);

        let (tx, rx) = oneshot::channel::<u32>();
        let f1 = ForkedPromise::new(rx);
        let f2 = f1.clone();

        let (mut mfh, mf) = ModedFuture::new(
            Box::new(f1.map_err(|_| ())) as Box<Future<Item=u32, Error=()>>,
            Box::new(::futures::future::empty()) as Box<Future<Item=u32, Error=()>>,
            Mode::Left);

        let mut handle0 = handle.clone();
        let spawn_mf = move || {
            handle0.add(mf.map(|_| ()));
        };

        let mut handle0 = handle.clone();
        let spawn_f2 = move || {
            let mut handle1 = handle0.clone();
            handle0.add(f2.map(move |_| handle1.terminate(Ok(()))).map_err(|_|()));

        };

        if spawn_moded_first {
            (spawn_mf)();
            match spawn.poll_future(unpark.clone()) {
                Ok(::futures::Async::NotReady) => (),
                _ => panic!("should not be ready yet."),
            }
            (spawn_f2)();
        } else {
            (spawn_f2)();
            match spawn.poll_future(unpark.clone()) {
                Ok(::futures::Async::NotReady) => (),
                _ => panic!("should not be ready yet."),
            }
            (spawn_mf)();
        }

        match spawn.poll_future(unpark.clone()) {
            Ok(::futures::Async::NotReady) => (),
            _ => panic!("should not be ready yet."),
        }

        mfh.switch_mode(Mode::Right);

        tx.complete(11); // It seems like this ought to cause f2 and then rx3 to get resolved.

        loop {
            match spawn.poll_future(unpark.clone()) {
                Ok(::futures::Async::NotReady) => (),
                Ok(::futures::Async::Ready(_)) => break,
                Err(e) => panic!("error: {:?}", e),
            }
        }
    }

    #[test]
    fn forked_propagates_unpark() {
        // This currenty hangs forever. See https://github.com/alexcrichton/futures-rs/issues/330.
        // forked_propagates_unpark_helper(true);

        forked_propagates_unpark_helper(false);
    }
}
<commit_msg>Prevent ForkedPromise from getting stuck.<commit_after>// Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use futures::{task, Future};

use std::cell::{Cell, RefCell};
use std::rc::{Rc};
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::collections::HashMap;

struct Unparker {
    original_needs_poll: Arc<AtomicBool>,

    // It's sad that we need a mutex here, even though we know that the RPC
    // system is restricted to a single thread.
    tasks: Mutex<HashMap<u64, task::Task>>,
}

impl Unparker {
    fn new(original_needs_poll: Arc<AtomicBool>) -> Unparker {
        Unparker {
            original_needs_poll: original_needs_poll,
            tasks: Mutex::new(HashMap::new()),
        }
    }

    fn insert(&self, idx: u64, task: task::Task) {
        self.tasks.lock().unwrap().insert(idx, task);
    }

    fn remove(&self, idx: u64) {
        self.tasks.lock().unwrap().remove(&idx);
    }

    fn unpark(&self) {
        self.original_needs_poll.store(true, Ordering::SeqCst);
        let tasks = ::std::mem::replace(&mut *self.tasks.lock().unwrap(), HashMap::new());
        for (_, task) in tasks {
            task.unpark();
        }
    }
}

impl task::EventSet for Unparker {
    fn insert(&self, _id: usize) {
        self.unpark();
    }
}

struct ForkedPromiseInner<F> where F: Future {
    next_clone_id: Cell<u64>,
    unparker: Arc<Unparker>,
    original_future: RefCell<F>,
    state: RefCell<ForkedPromiseState<F::Item, F::Error>>,
}

enum ForkedPromiseState<T, E> {
    Waiting(Arc<AtomicBool>),
    Done(Result<T, E>),
}

pub struct ForkedPromise<F> where F: Future {
    id: u64,
    inner: Rc<ForkedPromiseInner<F>>,
}

impl <F> Clone for ForkedPromise<F> where F: Future {
    fn clone(&self) -> ForkedPromise<F> {
        let clone_id = self.inner.next_clone_id.get();
        self.inner.next_clone_id.set(clone_id + 1);
        ForkedPromise {
            id: clone_id,
            inner: self.inner.clone(),
        }
    }
}

impl <F> ForkedPromise<F> where F: Future {
    pub fn new(f: F) -> ForkedPromise<F> {
        let original_needs_poll = Arc::new(AtomicBool::new(true));
        ForkedPromise {
            id: 0,
            inner: Rc::new(ForkedPromiseInner {
                next_clone_id: Cell::new(1),
                unparker: Arc::new(Unparker::new(original_needs_poll.clone())),
                original_future: RefCell::new(f),
                state: RefCell::new(ForkedPromiseState::Waiting(original_needs_poll)),
            })
        }
    }
}

impl<F> Drop for ForkedPromise<F> where F: Future {
    fn drop(&mut self) {
        match *self.inner.state.borrow_mut() {
            ForkedPromiseState::Waiting(_) => {
                self.inner.unparker.remove(self.id);
            }
            ForkedPromiseState::Done(_) => (),
        }
    }
}

impl <F> Future for ForkedPromise<F>
    where F: Future, F::Item: Clone, F::Error: Clone,
{
    type Item = F::Item;
    type Error = F::Error;

    fn poll(&mut self) -> ::futures::Poll<Self::Item, Self::Error> {
        match *self.inner.state.borrow_mut() {
            ForkedPromiseState::Waiting(ref original_needs_poll) => {
                if !original_needs_poll.swap(false, Ordering::SeqCst) {
                    self.inner.unparker.insert(self.id, task::park());
                    return Ok(::futures::Async::NotReady)
                }
            }
            ForkedPromiseState::Done(ref r) => {
                match *r {
                    Ok(ref v) => return Ok(::futures::Async::Ready(v.clone())),
                    Err(ref e) => return Err(e.clone()),
                }
            }
        };

        let event = task::UnparkEvent::new(self.inner.unparker.clone(), 0);
        let done_val = match task::with_unpark_event(event, || self.inner.original_future.borrow_mut().poll()) {
            Ok(::futures::Async::NotReady) => {
                return Ok(::futures::Async::NotReady)
            }
            Ok(::futures::Async::Ready(v)) => Ok(v),
            Err(e) => Err(e),
        };

        ::std::mem::replace(
            &mut *self.inner.state.borrow_mut(),
            ForkedPromiseState::Done(done_val.clone()));
        self.inner.unparker.unpark();

        match done_val {
            Ok(v) => Ok(::futures::Async::Ready(v)),
            Err(e) => Err(e),
        }
    }
}

#[cfg(test)]
mod test {
    use futures::{Future, Poll};
    use futures::sync::oneshot;
    use std::rc::Rc;
    use std::sync::Arc;
    use std::cell::RefCell;
    use super::ForkedPromise;

    enum Mode { Left, Right }

    struct ModedFutureInner<F> where F: Future {
        mode: Mode,
        left: F,
        right: F,
        task: Option<::futures::task::Task>,
    }

    struct ModedFuture<F> where F: Future {
        inner: Rc<RefCell<ModedFutureInner<F>>>,
    }

    struct ModedFutureHandle<F> where F: Future {
        inner: Rc<RefCell<ModedFutureInner<F>>>,
    }

    impl <F> ModedFuture<F> where F: Future {
        pub fn new(left: F, right: F, mode: Mode) -> (ModedFutureHandle<F>, ModedFuture<F>) {
            let inner = Rc::new(RefCell::new(ModedFutureInner {
                left: left, right: right, mode: mode, task: None,
            }));
            (ModedFutureHandle { inner: inner.clone() }, ModedFuture { inner: inner })
        }
    }

    impl <F> ModedFutureHandle<F> where F: Future {
        pub fn switch_mode(&mut self, mode: Mode) {
            self.inner.borrow_mut().mode = mode;
            if let Some(t) = self.inner.borrow_mut().task.take() {
                // The other future may have become ready while we were ignoring it.
                t.unpark();
            }
        }
    }

    impl <F> Future for ModedFuture<F> where F: Future {
        type Item = F::Item;
        type Error = F::Error;
        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            let ModedFutureInner { ref mut mode, ref mut left, ref mut right, ref mut task } =
                *self.inner.borrow_mut();
            *task = Some(::futures::task::park());
            match *mode {
                Mode::Left => left.poll(),
                Mode::Right => right.poll(),
            }
        }
    }

    struct Reaper;
    impl ::task_set::TaskReaper<(), ()> for Reaper {
        fn task_failed(&mut self, _err: ()) {}
    }

    struct Unpark;
    impl ::futures::executor::Unpark for Unpark {
        fn unpark(&self) {}
    }

    fn forked_propagates_unpark_helper(spawn_moded_first: bool) {
        let (handle, tasks) = ::task_set::TaskSet::<(), ()>::new(Box::new(Reaper));

        let mut spawn = ::futures::executor::spawn(tasks);
        let unpark: Arc<::futures::executor::Unpark> = Arc::new(Unpark);

        let (tx, rx) = oneshot::channel::<u32>();
        let f1 = ForkedPromise::new(rx);
        let f2 = f1.clone();

        let (mut mfh, mf) = ModedFuture::new(
            Box::new(f1.map_err(|_| ())) as Box<Future<Item=u32, Error=()>>,
            Box::new(::futures::future::empty()) as Box<Future<Item=u32, Error=()>>,
            Mode::Left);

        let mut handle0 = handle.clone();
        let spawn_mf = move || {
            handle0.add(mf.map(|_| ()));
        };

        let mut handle0 = handle.clone();
        let spawn_f2 = move || {
            let mut handle1 = handle0.clone();
            handle0.add(f2.map(move |_| handle1.terminate(Ok(()))).map_err(|_|()));

        };

        if spawn_moded_first {
            (spawn_mf)();
            match spawn.poll_future(unpark.clone()) {
                Ok(::futures::Async::NotReady) => (),
                _ => panic!("should not be ready yet."),
            }
            (spawn_f2)();
        } else {
            (spawn_f2)();
            match spawn.poll_future(unpark.clone()) {
                Ok(::futures::Async::NotReady) => (),
                _ => panic!("should not be ready yet."),
            }
            (spawn_mf)();
        }

        match spawn.poll_future(unpark.clone()) {
            Ok(::futures::Async::NotReady) => (),
            _ => panic!("should not be ready yet."),
        }

        mfh.switch_mode(Mode::Right);

        tx.complete(11); // This should cause `f2` and then eventually `spawn` to resolved.

        loop {
            match spawn.poll_future(unpark.clone()) {
                Ok(::futures::Async::NotReady) => (),
                Ok(::futures::Async::Ready(_)) => break,
                Err(e) => panic!("error: {:?}", e),
            }
        }
    }

    #[test]
    fn forked_propagates_unpark() {
        forked_propagates_unpark_helper(true);
        forked_propagates_unpark_helper(false);
    }
}
<|endoftext|>


<commit_before>extern crate phf_codegen;
extern crate unicase;

use phf_codegen::Map as PhfMap;
use phf_codegen::OrderedMap as PhfOrderedMap;

use unicase::UniCase;

use std::fs::File;
use std::io::prelude::*;
use std::io::BufWriter;

use std::collections::BTreeMap;

use mime_types::MIME_TYPES;

const GENERATED_FILE: &'static str = "src/mime_types_generated.rs";

mod mime_types;

fn main() {

    let mut outfile = BufWriter::new(File::create(GENERATED_FILE).unwrap());

    build_forward_map(&mut outfile);

    build_rev_map(&mut outfile);
}

// Build forward mappings (ext -> mime type)
fn build_forward_map<W: Write>(out: &mut W) {
    write!(out, "static MIME_TYPES: phf::Map<UniCase<&'static str>, &'static str> = ").unwrap();
    let mut forward_map = PhfMap::new();

    for &(key, val) in MIME_TYPES {
        forward_map.entry(UniCase(key), &format!("{:?}", val));
    }

    forward_map.build(out).unwrap();

    writeln!(out, ";").unwrap();
}

// Build reverse mappings (mime type -> ext)
fn build_rev_map<W: Write>(out: &mut W) {
    // First, collect all the mime type -> ext mappings)
    let mut dyn_map = BTreeMap::new();

    for &(key, val) in MIME_TYPES {
        let (top, sub) = split_mime(val);
        dyn_map.entry(UniCase(top))
            .or_insert_with(BTreeMap::new)
            .entry(UniCase(sub))
            .or_insert_with(Vec::new)
            .push(key);
    }

    write!(out, "static REV_MAPPINGS: phf::Map<UniCase<&'static str>, TopLevelExts> = ").unwrap();

    let mut rev_map = PhfMap::new();

    let mut exts = Vec::new();

    for (top, subs) in dyn_map {
        let top_start = exts.len();

        let mut sub_map = PhfMap::new();

        for(sub, sub_exts) in subs {
            let sub_start = exts.len();
            exts.extend(sub_exts);
            let sub_end = exts.len();

            sub_map.entry(sub, &format!("({}, {})", sub_start, sub_end));
        }

        let top_end = exts.len();

        let mut subs_bytes = Vec::<u8>::new();
        sub_map.build(&mut subs_bytes).unwrap();

        let subs_str = ::std::str::from_utf8(&subs_bytes).unwrap();

        rev_map.entry(
            top,
            &format!("TopLevelExts {{ start: {}, end: {}, subs: {} }}", top_start, top_end, subs_str)
        );
    }

    rev_map.build(out).unwrap();
    writeln!(out, ";").unwrap();

    writeln!(out, "const EXTS: &'static [&'static str] = &{:?};", exts).unwrap();
}

fn split_mime(mime: &str) -> (&str, &str) {
    let split_idx = mime.find('/').unwrap();
    mime.split_at(split_idx)
}

<commit_msg>Cleanup<commit_after>extern crate phf_codegen;
extern crate unicase;

use phf_codegen::Map as PhfMap;

use unicase::UniCase;

use std::fs::File;
use std::io::prelude::*;
use std::io::BufWriter;

use std::collections::BTreeMap;

use mime_types::MIME_TYPES;

const GENERATED_FILE: &'static str = "src/mime_types_generated.rs";

mod mime_types;

fn main() {

    let mut outfile = BufWriter::new(File::create(GENERATED_FILE).unwrap());

    build_forward_map(&mut outfile);

    build_rev_map(&mut outfile);
}

// Build forward mappings (ext -> mime type)
fn build_forward_map<W: Write>(out: &mut W) {
    write!(out, "static MIME_TYPES: phf::Map<UniCase<&'static str>, &'static str> = ").unwrap();
    let mut forward_map = PhfMap::new();

    for &(key, val) in MIME_TYPES {
        forward_map.entry(UniCase(key), &format!("{:?}", val));
    }

    forward_map.build(out).unwrap();

    writeln!(out, ";").unwrap();
}

// Build reverse mappings (mime type -> ext)
fn build_rev_map<W: Write>(out: &mut W) {
    // First, collect all the mime type -> ext mappings)
    let mut dyn_map = BTreeMap::new();

    for &(key, val) in MIME_TYPES {
        let (top, sub) = split_mime(val);
        dyn_map.entry(UniCase(top))
            .or_insert_with(BTreeMap::new)
            .entry(UniCase(sub))
            .or_insert_with(Vec::new)
            .push(key);
    }

    write!(out, "static REV_MAPPINGS: phf::Map<UniCase<&'static str>, TopLevelExts> = ").unwrap();

    let mut rev_map = PhfMap::new();

    let mut exts = Vec::new();

    for (top, subs) in dyn_map {
        let top_start = exts.len();

        let mut sub_map = PhfMap::new();

        for(sub, sub_exts) in subs {
            let sub_start = exts.len();
            exts.extend(sub_exts);
            let sub_end = exts.len();

            sub_map.entry(sub, &format!("({}, {})", sub_start, sub_end));
        }

        let top_end = exts.len();

        let mut subs_bytes = Vec::<u8>::new();
        sub_map.build(&mut subs_bytes).unwrap();

        let subs_str = ::std::str::from_utf8(&subs_bytes).unwrap();

        rev_map.entry(
            top,
            &format!("TopLevelExts {{ start: {}, end: {}, subs: {} }}", top_start, top_end, subs_str)
        );
    }

    rev_map.build(out).unwrap();
    writeln!(out, ";").unwrap();

    writeln!(out, "const EXTS: &'static [&'static str] = &{:?};", exts).unwrap();
}

fn split_mime(mime: &str) -> (&str, &str) {
    let split_idx = mime.find('/').unwrap();
    mime.split_at(split_idx)
}

<|endoftext|>


<commit_before>use iron::prelude::*;
use iron::{BeforeMiddleware, Error};

use url::{Url, SchemeData};

// Errors for the win!
#[deriving(Show)]
pub struct MalformedRequest;
#[deriving(Show)]
pub struct NotFound;

impl Error for MalformedRequest
{
    fn name(&self) -> &'static str { "MalformedRequest" }
}

impl Error for NotFound
{
    fn name(&self) -> &'static str { "NoRoute" }
}

// The actual URLParser struct
pub struct URLParser;

impl URLParser
{

}

// Make URLParser a BeforeMiddleware
impl BeforeMiddleware for URLParser
{
    fn before(&self, req: &mut Request) -> IronResult<()>
    {
        if(check_url(req))
        {
        	Ok(())
        }
        else
        {
        	Err(box MalformedRequest as IronError)
        }
    }
}

fn check_url(req: &mut Request) -> bool
{
	let parsed = Url::parse(req.url.to_string().as_slice()).ok().unwrap();
	let path = parsed.path();
	println!("{}\n{}", path, path.unwrap().len());
	if(path.unwrap()[0] != "".to_string() || path.unwrap().len() != 1)
	{
		return false;
	}

	let mut found = false;
    // This one returns an Option
    let mut query: Vec<(String, String)>;
    query = match parsed.query_pairs()
    {
        Some(query) => { query },
        None => { vec![("r".to_string(), "".to_string())] },
    };

	let get = String::from_str("r");

    // ToDo: This parses the whole query string, no matter if that is actually necessary. We could
    // change that, or parse the whole query string and save its values so the handler does not
    // have to parse it.
    for x in query.iter()
	{
		match x
		{
			&(ref get, ref value) =>
            {
                found = value.contains("/");
            },
			// &(_, _) => { false },
		};
	}
    return found;
}
<commit_msg>Fixed unexpected behavior with get variables. (Should 400, was 200)<commit_after>use iron::prelude::*;
use iron::{BeforeMiddleware, Error};

use url::{Url, SchemeData};

// Errors for the win!
#[deriving(Show)]
pub struct MalformedRequest;
#[deriving(Show)]
pub struct NotFound;

impl Error for MalformedRequest
{
    fn name(&self) -> &'static str { "MalformedRequest" }
}

impl Error for NotFound
{
    fn name(&self) -> &'static str { "NoRoute" }
}

// The actual URLParser struct
pub struct URLParser;

impl URLParser
{

}

// Make URLParser a BeforeMiddleware
impl BeforeMiddleware for URLParser
{
    fn before(&self, req: &mut Request) -> IronResult<()>
    {
        if(check_url(req))
        {
        	Ok(())
        }
        else
        {
        	Err(box MalformedRequest as IronError)
        }
    }
}

fn check_url(req: &mut Request) -> bool
{
	let parsed = Url::parse(req.url.to_string().as_slice()).ok().unwrap();
	let path = parsed.path();
	println!("{}\n{}", path, path.unwrap().len());
	if(path.unwrap()[0] != "".to_string() || path.unwrap().len() != 1)
	{
		return false;
	}

	let mut found = false;
    // This one returns an Option
    let mut query: Vec<(String, String)>;
    query = match parsed.query_pairs()
    {
        Some(query) => { query },
        None => { vec![("r".to_string(), "".to_string())] },
    };

	let get = "r".to_string();

    // ToDo: This parses the whole query string, no matter if that is actually necessary. We could
    // change that, or parse the whole query string and save its values so the handler does not
    // have to parse it.
    for x in query.iter()
	{
		match x
		{
			&(ref get, ref value) if get == &"r".to_string() =>
            {
                found = value.contains("/");
            },
			&(_, _) => { },
		};
	}
    return found;
}
<|endoftext|>


<commit_before>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

use ::constants::K_BOLTZMANN;
use ::types::*;
use ::universe::Universe;

/// The compute trait allow to compute properties of an universe, whithout
/// modifying this universe. The Output type is the type of the computed
/// property.
pub trait Compute {
    type Output;
    /// Compute the property
    fn compute(&self, universe: &Universe) -> Self::Output;
}

/******************************************************************************/
/// Compute all the forces acting on the system, and return a vector of
/// force acting on each particles
pub struct Forces;
impl Compute for Forces {
    type Output = Vec<Vector3D>;
    fn compute(&self, universe: &Universe) -> Vec<Vector3D> {
        let natoms = universe.size();
        let mut res = vec![Vector3D::new(0.0, 0.0, 0.0); natoms];

        for i in 0..universe.size() {
            for j in (i+1)..universe.size() {
                for potential in universe.pair_potentials(i, j) {
                    let d = universe.wrap_vector(i, j);
                    let dn = d.normalized();
                    let f = potential.force(d.norm());
                    res[i] = res[i] + f * dn;
                    res[j] = res[j] - f * dn;
                }
            }
        }
        return res;
    }
}

/******************************************************************************/
/// Compute the potential energy of the system
pub struct PotentialEnergy;
impl Compute for PotentialEnergy {
    type Output = f64;
    fn compute(&self, universe: &Universe) -> f64 {
        let mut res = 0.0;
        for i in 0..universe.size() {
            for j in (i+1)..universe.size() {
                for potential in universe.pair_potentials(i, j) {
                    let d = universe.wrap_vector(i, j);
                    res += potential.energy(d.norm());
                }
            }
        }
        return res;
    }
}

/******************************************************************************/
/// Compute the kinetic energy of the system
pub struct KineticEnergy;
impl Compute for KineticEnergy {
    type Output = f64;
    fn compute(&self, universe: &Universe) -> f64 {
        let mut res = 0.0;
        for particle in universe.iter() {
            res += 0.5 * particle.mass() * particle.velocity().norm2();
        }
        return res;
    }
}

/******************************************************************************/
/// Compute the total energy of the system
pub struct TotalEnergy;
impl Compute for TotalEnergy {
    type Output = f64;
    fn compute(&self, universe: &Universe) -> f64 {
        let kinetic = KineticEnergy.compute(universe);
        let potential = PotentialEnergy.compute(universe);
        return kinetic + potential;
    }
}

/******************************************************************************/
/// Compute the instananeous temperature of the system
pub struct Temperature;
impl Compute for Temperature {
    type Output = f64;
    fn compute(&self, universe: &Universe) -> f64 {
        let kinetic = KineticEnergy.compute(universe);
        let natoms = universe.size() as f64;
        return 1.0/K_BOLTZMANN * 2.0 * kinetic/(3.0 * natoms);
    }
}

/******************************************************************************/
/// Compute the volume of the system
pub struct Volume;
impl Compute for Volume {
    type Output = f64;
    #[inline]
    fn compute(&self, universe: &Universe) -> f64 {
        return universe.cell().volume();
    }
}

/******************************************************************************/
/// Compute the virial tensor of the system
pub struct Virial;
impl Compute for Virial {
    type Output = Matrix3;
    fn compute(&self, universe: &Universe) -> Matrix3 {
        let mut res = Matrix3::zero();
        for i in 0..universe.size() {
            for j in (i+1)..universe.size() {
                for potential in universe.pair_potentials(i, j) {
                    let d = universe.wrap_vector(i, j);
                    res = res + 2.0 * potential.virial(&d);
                }
            }
        }
        return res;
    }
}

/******************************************************************************/
/// Compute the stress tensor of the system
pub struct Stress;
impl Compute for Stress {
    type Output = Matrix3;
    fn compute(&self, universe: &Universe) -> Matrix3 {
        let mut K = Matrix3::zero(); // Kinetic tensor
        for particle in universe.iter() {
            let m = particle.mass();
            let vel = particle.velocity();
            K[(0, 0)] += m * vel.x * vel.x;
            K[(0, 1)] += m * vel.x * vel.y;
            K[(0, 2)] += m * vel.x * vel.z;

            K[(1, 0)] += m * vel.y * vel.x;
            K[(1, 1)] += m * vel.y * vel.y;
            K[(1, 2)] += m * vel.y * vel.z;

            K[(2, 0)] += m * vel.z * vel.x;
            K[(2, 1)] += m * vel.z * vel.y;
            K[(2, 2)] += m * vel.z * vel.z;
        }

        let W = Virial.compute(universe);
        let V = Volume.compute(universe);
        return 1.0 / V * (K - W);
    }
}

/******************************************************************************/
/// Compute the virial pressure of the system
pub struct Pressure;
impl Compute for Pressure {
    type Output = f64;
    fn compute(&self, universe: &Universe) -> f64 {
        let W = Virial.compute(universe);
        let virial = W[(0, 0)] + W[(1, 1)] + W[(2, 2)];
        let V = Volume.compute(universe);
        let natoms = universe.size() as f64;
        let T = Temperature.compute(universe);
        return natoms * K_BOLTZMANN * T / V - virial / (3.0 * V);
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use ::types::*;
    use ::universe::{Universe, Particle, UnitCell};
    use ::universe::{InitVelocities, BoltzmanVelocities};
    use ::potentials::Harmonic;
    use ::units;

    const EPS : f64 = 1e-8;

    fn testing_universe() -> Universe {
        let mut universe = Universe::from_cell(UnitCell::cubic(10.0));;

        universe.add_particle(Particle::new("F"));
        universe[0].set_position(Vector3D::new(0.0, 0.0, 0.0));

        universe.add_particle(Particle::new("F"));
        universe[1].set_position(Vector3D::new(1.3, 0.0, 0.0));

        let mut velocities = BoltzmanVelocities::new(units::from(300.0, "K").unwrap());
        velocities.init(&mut universe);

        universe.add_pair_interaction("F", "F",
            Harmonic{k: units::from(300.0, "kJ/mol/A^2").unwrap(), x0: units::from(1.2, "A").unwrap()});
        return universe;
    }

    #[test]
    fn forces() {
        let universe = &testing_universe();
        let res = Forces.compute(universe);

        let mut forces_tot = Vector3D::new(0.0, 0.0, 0.0);
        forces_tot.x += res[0].x + res[1].x;
        forces_tot.x += res[0].y + res[1].y;
        forces_tot.x += res[0].z + res[1].z;

        assert_eq!(forces_tot, Vector3D::new(0.0, 0.0, 0.0));

        assert_approx_eq!(res[0].x, 3e-3, EPS);
        assert_approx_eq!(res[0].y, 0.0, EPS);
        assert_approx_eq!(res[0].y, 0.0, EPS);

        assert_approx_eq!(res[1].x, -3e-3, EPS);
        assert_approx_eq!(res[1].y, 0.0, EPS);
        assert_approx_eq!(res[1].y, 0.0, EPS);
    }

    #[test]
    fn energy() {
        let universe = &testing_universe();
        let kinetic = KineticEnergy.compute(universe);
        let potential = PotentialEnergy.compute(universe);
        let total = TotalEnergy.compute(universe);

        assert_eq!(kinetic + potential, total);
        assert_eq!(kinetic, 0.0007483016557453699);
        assert_approx_eq!(potential, 1.5e-4, EPS);

        assert_eq!(kinetic, universe.kinetic_energy());
        assert_eq!(potential, universe.potential_energy());
        assert_eq!(total, universe.total_energy());
    }

    #[test]
    fn temperature() {
        let universe = &testing_universe();
        let T = Temperature.compute(universe);
        assert_approx_eq!(T, 300.0, 1e-9);
        assert_eq!(T, universe.temperature());
    }

    #[test]
    fn volume() {
        let universe = &testing_universe();
        let V = Volume.compute(universe);
        assert_eq!(V, 1000.0);
        assert_eq!(V, universe.volume());
    }

    #[test]
    fn virial() {
        let universe = &testing_universe();
        let virial = Virial.compute(universe);

        let mut res = Matrix3::zero();
        res[(0, 0)] = -0.007800000005461644;

        assert_eq!(virial, res);
        assert_eq!(virial, universe.virial());
    }

    #[test]
    fn stress() {
        let universe = &testing_universe();
        let stress = Stress.compute(universe);
        let P = Pressure.compute(universe);

        let trace = (stress[(0, 0)] + stress[(1, 1)] + stress[(2, 2)]) / 3.0;
        assert_approx_eq!(trace, P, 1e-9);
        assert_eq!(stress, universe.stress());
    }

    #[test]
    fn pressure() {
        let universe = &testing_universe();
        let P = Pressure.compute(universe);
        assert_approx_eq!(P, units::from(514.5790116223092, "bar").unwrap(), 1e-9);
        assert_eq!(P, universe.pressure());
    }
}
<commit_msg>Add molecular potential in force and energy computations<commit_after>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

use ::constants::K_BOLTZMANN;
use ::types::*;
use ::universe::Universe;

/// The compute trait allow to compute properties of an universe, whithout
/// modifying this universe. The Output type is the type of the computed
/// property.
pub trait Compute {
    type Output;
    /// Compute the property
    fn compute(&self, universe: &Universe) -> Self::Output;
}

/******************************************************************************/
/// Compute all the forces acting on the system, and return a vector of
/// force acting on each particles
pub struct Forces;
impl Compute for Forces {
    type Output = Vec<Vector3D>;
    fn compute(&self, universe: &Universe) -> Vec<Vector3D> {
        let natoms = universe.size();
        let mut res = vec![Vector3D::new(0.0, 0.0, 0.0); natoms];

        for i in 0..universe.size() {
            for j in (i+1)..universe.size() {
                let d = universe.wrap_vector(i, j);
                let dn = d.normalized();
                let r = d.norm();
                for potential in universe.pair_potentials(i, j) {
                    let f = potential.force(r);
                    res[i] = res[i] + f * dn;
                    res[j] = res[j] - f * dn;
                }
            }
        }

        let topology = universe.topology();
        for angle in topology.angles().iter() {
            let i = angle.i;
            let j = angle.j;
            let k = angle.k;
            let (theta, d1, d2, d3) = universe.angle_and_derivatives(i, j, k);
            for potential in universe.angle_potentials(i, j, k) {
                let f = potential.force(theta);
                res[i] = res[i] + f * d1;
                res[j] = res[j] + f * d2;
                res[k] = res[k] + f * d3;
            }
        }

        for dihedral in topology.dihedrals().iter() {
            let i = dihedral.i;
            let j = dihedral.j;
            let k = dihedral.k;
            let m = dihedral.m;
            let (phi, d1, d2, d3, d4) = universe.dihedral_and_derivatives(i, j, k, m);
            for potential in universe.dihedral_potentials(i, j, k, m) {
                let f = potential.force(phi);
                res[i] = res[i] + f * d1;
                res[j] = res[j] + f * d2;
                res[k] = res[k] + f * d3;
                res[k] = res[k] + f * d4;
            }
        }
        return res;
    }
}

/******************************************************************************/
/// Compute the potential energy of the system
pub struct PotentialEnergy;
impl Compute for PotentialEnergy {
    type Output = f64;
    fn compute(&self, universe: &Universe) -> f64 {
        let mut res = 0.0;
        for i in 0..universe.size() {
            for j in (i+1)..universe.size() {
                let r = universe.wrap_vector(i, j).norm();
                for potential in universe.pair_potentials(i, j) {
                    res += potential.energy(r);
                }
            }
        }

        let topology = universe.topology();
        for angle in topology.angles().iter() {
            let i = angle.i;
            let j = angle.j;
            let k = angle.k;
            let theta = universe.angle(i, j, k);
            for potential in universe.angle_potentials(i, j, k) {
                res += potential.energy(theta);
            }
        }

        for dihedral in topology.dihedrals().iter() {
            let i = dihedral.i;
            let j = dihedral.j;
            let k = dihedral.k;
            let m = dihedral.m;
            let phi = universe.dihedral(i, j, k, m);
            for potential in universe.dihedral_potentials(i, j, k, m) {
                res += potential.energy(phi);
            }
        }
        return res;
    }
}

/******************************************************************************/
/// Compute the kinetic energy of the system
pub struct KineticEnergy;
impl Compute for KineticEnergy {
    type Output = f64;
    fn compute(&self, universe: &Universe) -> f64 {
        let mut res = 0.0;
        for particle in universe.iter() {
            res += 0.5 * particle.mass() * particle.velocity().norm2();
        }
        return res;
    }
}

/******************************************************************************/
/// Compute the total energy of the system
pub struct TotalEnergy;
impl Compute for TotalEnergy {
    type Output = f64;
    fn compute(&self, universe: &Universe) -> f64 {
        let kinetic = KineticEnergy.compute(universe);
        let potential = PotentialEnergy.compute(universe);
        return kinetic + potential;
    }
}

/******************************************************************************/
/// Compute the instananeous temperature of the system
pub struct Temperature;
impl Compute for Temperature {
    type Output = f64;
    fn compute(&self, universe: &Universe) -> f64 {
        let kinetic = KineticEnergy.compute(universe);
        let natoms = universe.size() as f64;
        return 1.0/K_BOLTZMANN * 2.0 * kinetic/(3.0 * natoms);
    }
}

/******************************************************************************/
/// Compute the volume of the system
pub struct Volume;
impl Compute for Volume {
    type Output = f64;
    #[inline]
    fn compute(&self, universe: &Universe) -> f64 {
        return universe.cell().volume();
    }
}

/******************************************************************************/
/// Compute the virial tensor of the system
pub struct Virial;
impl Compute for Virial {
    type Output = Matrix3;
    fn compute(&self, universe: &Universe) -> Matrix3 {
        let mut res = Matrix3::zero();
        for i in 0..universe.size() {
            for j in (i+1)..universe.size() {
                for potential in universe.pair_potentials(i, j) {
                    let d = universe.wrap_vector(i, j);
                    res = res + 2.0 * potential.virial(&d);
                }
            }
        }

        // FIXME: implement virial computations for molecular potentials
        // (angles & dihedrals)
        return res;
    }
}

/******************************************************************************/
/// Compute the stress tensor of the system
pub struct Stress;
impl Compute for Stress {
    type Output = Matrix3;
    fn compute(&self, universe: &Universe) -> Matrix3 {
        let mut K = Matrix3::zero(); // Kinetic tensor
        for particle in universe.iter() {
            let m = particle.mass();
            let vel = particle.velocity();
            K[(0, 0)] += m * vel.x * vel.x;
            K[(0, 1)] += m * vel.x * vel.y;
            K[(0, 2)] += m * vel.x * vel.z;

            K[(1, 0)] += m * vel.y * vel.x;
            K[(1, 1)] += m * vel.y * vel.y;
            K[(1, 2)] += m * vel.y * vel.z;

            K[(2, 0)] += m * vel.z * vel.x;
            K[(2, 1)] += m * vel.z * vel.y;
            K[(2, 2)] += m * vel.z * vel.z;
        }

        let W = Virial.compute(universe);
        let V = Volume.compute(universe);
        return 1.0 / V * (K - W);
    }
}

/******************************************************************************/
/// Compute the virial pressure of the system
pub struct Pressure;
impl Compute for Pressure {
    type Output = f64;
    fn compute(&self, universe: &Universe) -> f64 {
        let W = Virial.compute(universe);
        let virial = W[(0, 0)] + W[(1, 1)] + W[(2, 2)];
        let V = Volume.compute(universe);
        let natoms = universe.size() as f64;
        let T = Temperature.compute(universe);
        return natoms * K_BOLTZMANN * T / V - virial / (3.0 * V);
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use ::types::*;
    use ::universe::{Universe, Particle, UnitCell};
    use ::universe::{InitVelocities, BoltzmanVelocities};
    use ::potentials::Harmonic;
    use ::units;

    const EPS : f64 = 1e-8;

    fn testing_universe() -> Universe {
        let mut universe = Universe::from_cell(UnitCell::cubic(10.0));;

        universe.add_particle(Particle::new("F"));
        universe[0].set_position(Vector3D::new(0.0, 0.0, 0.0));

        universe.add_particle(Particle::new("F"));
        universe[1].set_position(Vector3D::new(1.3, 0.0, 0.0));

        let mut velocities = BoltzmanVelocities::new(units::from(300.0, "K").unwrap());
        velocities.init(&mut universe);

        universe.add_pair_interaction("F", "F",
            Harmonic{k: units::from(300.0, "kJ/mol/A^2").unwrap(), x0: units::from(1.2, "A").unwrap()});
        return universe;
    }

    #[test]
    fn forces() {
        let universe = &testing_universe();
        let res = Forces.compute(universe);

        let forces_tot = res[0] + res[1];
        assert_eq!(forces_tot, Vector3D::new(0.0, 0.0, 0.0));

        assert_approx_eq!(res[0].x, 3e-3, EPS);
        assert_approx_eq!(res[0].y, 0.0, EPS);
        assert_approx_eq!(res[0].y, 0.0, EPS);

        assert_approx_eq!(res[1].x, -3e-3, EPS);
        assert_approx_eq!(res[1].y, 0.0, EPS);
        assert_approx_eq!(res[1].y, 0.0, EPS);
    }

    #[test]
    fn force_molecular() {
        let mut universe = testing_universe();
        universe.add_particle(Particle::new("F"));
        universe.add_particle(Particle::new("F"));

        universe[0].set_position(Vector3D::new(0.0, 0.0, 0.0));
        universe[1].set_position(Vector3D::new(1.2, 0.0, 0.0));
        universe[2].set_position(Vector3D::new(1.2, 1.2, 0.0));
        universe[3].set_position(Vector3D::new(2.4, 1.2, 0.0));

        {
            let topology = universe.topology_mut();
            topology.add_bond(0, 1);
            topology.add_bond(1, 2);
            topology.add_bond(2, 3);
        }

        universe.add_angle_interaction("F", "F", "F",
            Harmonic{
                k: units::from(100.0, "kJ/mol/A^2").unwrap(),
                x0: units::from(80.0, "deg").unwrap()
        });

        universe.add_dihedral_interaction("F", "F", "F", "F",
            Harmonic{
                k: units::from(100.0, "kJ/mol/A^2").unwrap(),
                x0: units::from(185.0, "deg").unwrap()
        });

        let res = Forces.compute(&universe);
        let forces_tot = res[0] + res[1] + res[2] + res[3];
        assert_approx_eq!(forces_tot.norm2(), 0.0, 1e-12);
    }

    #[test]
    fn energy() {
        let universe = &testing_universe();
        let kinetic = KineticEnergy.compute(universe);
        let potential = PotentialEnergy.compute(universe);
        let total = TotalEnergy.compute(universe);

        assert_eq!(kinetic + potential, total);
        assert_eq!(kinetic, 0.0007483016557453699);
        assert_approx_eq!(potential, 1.5e-4, EPS);

        assert_eq!(kinetic, universe.kinetic_energy());
        assert_eq!(potential, universe.potential_energy());
        assert_eq!(total, universe.total_energy());
    }

    #[test]
    fn energy_molecular() {
        let mut universe = testing_universe();
        universe.add_particle(Particle::new("F"));
        universe.add_particle(Particle::new("F"));

        universe[0].set_position(Vector3D::new(0.0, 0.0, 0.0));
        universe[1].set_position(Vector3D::new(1.2, 0.0, 0.0));
        universe[2].set_position(Vector3D::new(1.2, 1.2, 0.0));
        universe[3].set_position(Vector3D::new(2.4, 1.2, 0.0));

        {
            let topology = universe.topology_mut();
            topology.add_bond(0, 1);
            topology.add_bond(1, 2);
            topology.add_bond(2, 3);
        }

        universe.add_angle_interaction("F", "F", "F",
            Harmonic{
                k: units::from(100.0, "kJ/mol/A^2").unwrap(),
                x0: units::from(80.0, "deg").unwrap()
        });

        universe.add_dihedral_interaction("F", "F", "F", "F",
            Harmonic{
                k: units::from(100.0, "kJ/mol/A^2").unwrap(),
                x0: units::from(185.0, "deg").unwrap()
        });

        assert_approx_eq!(PotentialEnergy.compute(&universe), 0.040756506208, 1e-12);
    }

    #[test]
    fn temperature() {
        let universe = &testing_universe();
        let T = Temperature.compute(universe);
        assert_approx_eq!(T, 300.0, 1e-9);
        assert_eq!(T, universe.temperature());
    }

    #[test]
    fn volume() {
        let universe = &testing_universe();
        let V = Volume.compute(universe);
        assert_eq!(V, 1000.0);
        assert_eq!(V, universe.volume());
    }

    #[test]
    fn virial() {
        let universe = &testing_universe();
        let virial = Virial.compute(universe);

        let mut res = Matrix3::zero();
        res[(0, 0)] = -0.007800000005461644;

        assert_eq!(virial, res);
        assert_eq!(virial, universe.virial());
    }

    #[test]
    fn stress() {
        let universe = &testing_universe();
        let stress = Stress.compute(universe);
        let P = Pressure.compute(universe);

        let trace = (stress[(0, 0)] + stress[(1, 1)] + stress[(2, 2)]) / 3.0;
        assert_approx_eq!(trace, P, 1e-9);
        assert_eq!(stress, universe.stress());
    }

    #[test]
    fn pressure() {
        let universe = &testing_universe();
        let P = Pressure.compute(universe);
        assert_approx_eq!(P, units::from(514.5790116223092, "bar").unwrap(), 1e-9);
        assert_eq!(P, universe.pressure());
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Utilities related to FFI bindings.
//!
//! This module provides utilities to handle data across non-Rust
//! interfaces, like other programming languages and the underlying
//! operating system. It is mainly of use for FFI (Foreign Function
//! Interface) bindings and code that needs to exchange C-like strings
//! with other languages.
//!
//! # Overview
//!
//! Rust represents owned strings with the [`String`] type, and
//! borrowed slices of strings with the [`str`] primitive. Both are
//! always in UTF-8 encoding, and may contain nul bytes in the middle,
//! i.e. if you look at the bytes that make up the string, there may
//! be a `\0` among them. Both `String` and `str` store their length
//! explicitly; there are no nul terminators at the end of strings
//! like in C.
//!
//! C strings are different from Rust strings:
//!
//! * **Encodings** - Rust strings are UTF-8, but C strings may use
//! other encodings. If you are using a string from C, you should
//! check its encoding explicitly, rather than just assuming that it
//! is UTF-8 like you can do in Rust.
//!
//! * **Character size** - C strings may use `char` or `wchar_t`-sized
//! characters; please **note** that C's `char` is different from Rust's.
//! The C standard leaves the actual sizes of those types open to
//! interpretation, but defines different APIs for strings made up of
//! each character type. Rust strings are always UTF-8, so different
//! Unicode characters will be encoded in a variable number of bytes
//! each. The Rust type [`char`] represents a '[Unicode scalar
//! value]', which is similar to, but not the same as, a '[Unicode
//! code point]'.
//!
//! * **Nul terminators and implicit string lengths** - Often, C
//! strings are nul-terminated, i.e. they have a `\0` character at the
//! end. The length of a string buffer is not stored, but has to be
//! calculated; to compute the length of a string, C code must
//! manually call a function like `strlen()` for `char`-based strings,
//! or `wcslen()` for `wchar_t`-based ones. Those functions return
//! the number of characters in the string excluding the nul
//! terminator, so the buffer length is really `len+1` characters.
//! Rust strings don't have a nul terminator; their length is always
//! stored and does not need to be calculated. While in Rust
//! accessing a string's length is a O(1) operation (becasue the
//! length is stored); in C it is an O(length) operation because the
//! length needs to be computed by scanning the string for the nul
//! terminator.
//!
//! * **Internal nul characters** - When C strings have a nul
//! terminator character, this usually means that they cannot have nul
//! characters in the middle — a nul character would essentially
//! truncate the string. Rust strings *can* have nul characters in
//! the middle, because nul does not have to mark the end of the
//! string in Rust.
//!
//! # Representations of non-Rust strings
//!
//! [`CString`] and [`CStr`] are useful when you need to transfer
//! UTF-8 strings to and from languages with a C ABI, like Python.
//!
//! * **From Rust to C:** [`CString`] represents an owned, C-friendly
//! string: it is nul-terminated, and has no internal nul characters.
//! Rust code can create a `CString` out of a normal string (provided
//! that the string doesn't have nul characters in the middle), and
//! then use a variety of methods to obtain a raw `*mut u8` that can
//! then be passed as an argument to functions which use the C
//! conventions for strings.
//!
//! * **From C to Rust:** [`CStr`] represents a borrowed C string; it
//! is what you would use to wrap a raw `*const u8` that you got from
//! a C function. A `CStr` is guaranteed to be a nul-terminated array
//! of bytes. Once you have a `CStr`, you can convert it to a Rust
//! `&str` if it's valid UTF-8, or lossily convert it by adding
//! replacement characters.
//!
//! [`OsString`] and [`OsStr`] are useful when you need to transfer
//! strings to and from the operating system itself, or when capturing
//! the output of external commands. Conversions between `OsString`,
//! `OsStr` and Rust strings work similarly to those for [`CString`]
//! and [`CStr`].
//!
//! * [`OsString`] represents an owned string in whatever
//! representation the operating system prefers. In the Rust standard
//! library, various APIs that transfer strings to/from the operating
//! system use `OsString` instead of plain strings. For example,
//! [`env::var_os()`] is used to query environment variables; it
//! returns an `Option<OsString>`. If the environment variable exists
//! you will get a `Some(os_string)`, which you can *then* try to
//! convert to a Rust string. This yields a [`Result<>`], so that
//! your code can detect errors in case the environment variable did
//! not in fact contain valid Unicode data.
//!
//! * [`OsStr`] represents a borrowed reference to a string in a
//! format that can be passed to the operating system. It can be
//! converted into an UTF-8 Rust string slice in a similar way to
//! `OsString`.
//!
//! # Conversions
//!
//! ## On Unix
//!
//! On Unix, [`OsStr`] implements the
//! `std::os::unix:ffi::`[`OsStrExt`][unix.OsStrExt] trait, which
//! augments it with two methods, [`from_bytes`] and [`as_bytes`].
//! These do inexpensive conversions from and to UTF-8 byte slices.
//!
//! Additionally, on Unix [`OsString`] implements the
//! `std::os::unix:ffi::`[`OsStringExt`][unix.OsStringExt] trait,
//! which provides [`from_vec`] and [`into_vec`] methods that consume
//! their arguments, and take or produce vectors of [`u8`].
//!
//! ## On Windows
//!
//! On Windows, [`OsStr`] implements the
//! `std::os::windows::ffi::`[`OsStrExt`][windows.OsStrExt] trait,
//! which provides an [`encode_wide`] method. This provides an
//! iterator that can be [`collect`]ed into a vector of [`u16`].
//!
//! Additionally, on Windows [`OsString`] implements the
//! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt]
//! trait, which provides a [`from_wide`] method. The result of this
//! method is an `OsString` which can be round-tripped to a Windows
//! string losslessly.
//!
//! [`String`]: ../string/struct.String.html
//! [`str`]: ../primitive.str.html
//! [`char`]: ../primitive.char.html
//! [`u8`]: ../primitive.u8.html
//! [`u16`]: ../primitive.u16.html
//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
//! [`CString`]: struct.CString.html
//! [`CStr`]: struct.CStr.html
//! [`OsString`]: struct.OsString.html
//! [`OsStr`]: struct.OsStr.html
//! [`env::set_var()`]: ../env/fn.set_var.html
//! [`env::var_os()`]: ../env/fn.var_os.html
//! [`Result<>`]: ../result/enum.Result.html
//! [unix.OsStringExt]: ../os/unix/ffi/trait.OsStringExt.html
//! [`from_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.from_vec
//! [`into_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.into_vec
//! [unix.OsStrExt]: ../os/unix/ffi/trait.OsStrExt.html
//! [`from_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.from_bytes
//! [`as_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.as_bytes
//! [`OsStrExt`]: ../os/unix/ffi/trait.OsStrExt.html
//! [windows.OsStrExt]: ../os/windows/ffi/trait.OsStrExt.html
//! [`encode_wide`]: ../os/windows/ffi/trait.OsStrExt.html#tymethod.encode_wide
//! [`collect`]: ../iter/trait.Iterator.html#method.collect
//! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html
//! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide

#![stable(feature = "rust1", since = "1.0.0")]

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::{CString, CStr, NulError, IntoStringError};
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub use self::c_str::{FromBytesWithNulError};

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::os_str::{OsString, OsStr};

mod c_str;
mod os_str;
<commit_msg>Fix typo.<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Utilities related to FFI bindings.
//!
//! This module provides utilities to handle data across non-Rust
//! interfaces, like other programming languages and the underlying
//! operating system. It is mainly of use for FFI (Foreign Function
//! Interface) bindings and code that needs to exchange C-like strings
//! with other languages.
//!
//! # Overview
//!
//! Rust represents owned strings with the [`String`] type, and
//! borrowed slices of strings with the [`str`] primitive. Both are
//! always in UTF-8 encoding, and may contain nul bytes in the middle,
//! i.e. if you look at the bytes that make up the string, there may
//! be a `\0` among them. Both `String` and `str` store their length
//! explicitly; there are no nul terminators at the end of strings
//! like in C.
//!
//! C strings are different from Rust strings:
//!
//! * **Encodings** - Rust strings are UTF-8, but C strings may use
//! other encodings. If you are using a string from C, you should
//! check its encoding explicitly, rather than just assuming that it
//! is UTF-8 like you can do in Rust.
//!
//! * **Character size** - C strings may use `char` or `wchar_t`-sized
//! characters; please **note** that C's `char` is different from Rust's.
//! The C standard leaves the actual sizes of those types open to
//! interpretation, but defines different APIs for strings made up of
//! each character type. Rust strings are always UTF-8, so different
//! Unicode characters will be encoded in a variable number of bytes
//! each. The Rust type [`char`] represents a '[Unicode scalar
//! value]', which is similar to, but not the same as, a '[Unicode
//! code point]'.
//!
//! * **Nul terminators and implicit string lengths** - Often, C
//! strings are nul-terminated, i.e. they have a `\0` character at the
//! end. The length of a string buffer is not stored, but has to be
//! calculated; to compute the length of a string, C code must
//! manually call a function like `strlen()` for `char`-based strings,
//! or `wcslen()` for `wchar_t`-based ones. Those functions return
//! the number of characters in the string excluding the nul
//! terminator, so the buffer length is really `len+1` characters.
//! Rust strings don't have a nul terminator; their length is always
//! stored and does not need to be calculated. While in Rust
//! accessing a string's length is a O(1) operation (because the
//! length is stored); in C it is an O(length) operation because the
//! length needs to be computed by scanning the string for the nul
//! terminator.
//!
//! * **Internal nul characters** - When C strings have a nul
//! terminator character, this usually means that they cannot have nul
//! characters in the middle — a nul character would essentially
//! truncate the string. Rust strings *can* have nul characters in
//! the middle, because nul does not have to mark the end of the
//! string in Rust.
//!
//! # Representations of non-Rust strings
//!
//! [`CString`] and [`CStr`] are useful when you need to transfer
//! UTF-8 strings to and from languages with a C ABI, like Python.
//!
//! * **From Rust to C:** [`CString`] represents an owned, C-friendly
//! string: it is nul-terminated, and has no internal nul characters.
//! Rust code can create a `CString` out of a normal string (provided
//! that the string doesn't have nul characters in the middle), and
//! then use a variety of methods to obtain a raw `*mut u8` that can
//! then be passed as an argument to functions which use the C
//! conventions for strings.
//!
//! * **From C to Rust:** [`CStr`] represents a borrowed C string; it
//! is what you would use to wrap a raw `*const u8` that you got from
//! a C function. A `CStr` is guaranteed to be a nul-terminated array
//! of bytes. Once you have a `CStr`, you can convert it to a Rust
//! `&str` if it's valid UTF-8, or lossily convert it by adding
//! replacement characters.
//!
//! [`OsString`] and [`OsStr`] are useful when you need to transfer
//! strings to and from the operating system itself, or when capturing
//! the output of external commands. Conversions between `OsString`,
//! `OsStr` and Rust strings work similarly to those for [`CString`]
//! and [`CStr`].
//!
//! * [`OsString`] represents an owned string in whatever
//! representation the operating system prefers. In the Rust standard
//! library, various APIs that transfer strings to/from the operating
//! system use `OsString` instead of plain strings. For example,
//! [`env::var_os()`] is used to query environment variables; it
//! returns an `Option<OsString>`. If the environment variable exists
//! you will get a `Some(os_string)`, which you can *then* try to
//! convert to a Rust string. This yields a [`Result<>`], so that
//! your code can detect errors in case the environment variable did
//! not in fact contain valid Unicode data.
//!
//! * [`OsStr`] represents a borrowed reference to a string in a
//! format that can be passed to the operating system. It can be
//! converted into an UTF-8 Rust string slice in a similar way to
//! `OsString`.
//!
//! # Conversions
//!
//! ## On Unix
//!
//! On Unix, [`OsStr`] implements the
//! `std::os::unix:ffi::`[`OsStrExt`][unix.OsStrExt] trait, which
//! augments it with two methods, [`from_bytes`] and [`as_bytes`].
//! These do inexpensive conversions from and to UTF-8 byte slices.
//!
//! Additionally, on Unix [`OsString`] implements the
//! `std::os::unix:ffi::`[`OsStringExt`][unix.OsStringExt] trait,
//! which provides [`from_vec`] and [`into_vec`] methods that consume
//! their arguments, and take or produce vectors of [`u8`].
//!
//! ## On Windows
//!
//! On Windows, [`OsStr`] implements the
//! `std::os::windows::ffi::`[`OsStrExt`][windows.OsStrExt] trait,
//! which provides an [`encode_wide`] method. This provides an
//! iterator that can be [`collect`]ed into a vector of [`u16`].
//!
//! Additionally, on Windows [`OsString`] implements the
//! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt]
//! trait, which provides a [`from_wide`] method. The result of this
//! method is an `OsString` which can be round-tripped to a Windows
//! string losslessly.
//!
//! [`String`]: ../string/struct.String.html
//! [`str`]: ../primitive.str.html
//! [`char`]: ../primitive.char.html
//! [`u8`]: ../primitive.u8.html
//! [`u16`]: ../primitive.u16.html
//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
//! [`CString`]: struct.CString.html
//! [`CStr`]: struct.CStr.html
//! [`OsString`]: struct.OsString.html
//! [`OsStr`]: struct.OsStr.html
//! [`env::set_var()`]: ../env/fn.set_var.html
//! [`env::var_os()`]: ../env/fn.var_os.html
//! [`Result<>`]: ../result/enum.Result.html
//! [unix.OsStringExt]: ../os/unix/ffi/trait.OsStringExt.html
//! [`from_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.from_vec
//! [`into_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.into_vec
//! [unix.OsStrExt]: ../os/unix/ffi/trait.OsStrExt.html
//! [`from_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.from_bytes
//! [`as_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.as_bytes
//! [`OsStrExt`]: ../os/unix/ffi/trait.OsStrExt.html
//! [windows.OsStrExt]: ../os/windows/ffi/trait.OsStrExt.html
//! [`encode_wide`]: ../os/windows/ffi/trait.OsStrExt.html#tymethod.encode_wide
//! [`collect`]: ../iter/trait.Iterator.html#method.collect
//! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html
//! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide

#![stable(feature = "rust1", since = "1.0.0")]

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::{CString, CStr, NulError, IntoStringError};
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub use self::c_str::{FromBytesWithNulError};

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::os_str::{OsString, OsStr};

mod c_str;
mod os_str;
<|endoftext|>


<commit_before>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    extern crate libc;

    use self::OsRngInner::*;

    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::{Ok, Err};
    use slice::SlicePrelude;
    use mem;
    use os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0u)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        let len = v.len();
        while read < len {
            let result = getrandom(v[mut read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as uint;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8, ..4] = [0u8, ..4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8, ..4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8, ..8] = [0u8, ..8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8, ..8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Relaxed};

        static GETRANDOM_CHECKED: AtomicBool = INIT_ATOMIC_BOOL;
        static GETRANDOM_AVAILABLE: AtomicBool = INIT_ATOMIC_BOOL;

        if !GETRANDOM_CHECKED.load(Relaxed) {
            let mut buf: [u8, ..0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = errno() as libc::c_int;
                err != libc::ENOSYS
            } else {
                true
            };
            GETRANDOM_AVAILABLE.store(available, Relaxed);
            GETRANDOM_CHECKED.store(true, Relaxed);
            available
        } else {
            GETRANDOM_AVAILABLE.load(Relaxed)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use io::{IoResult};
    use kinds::marker;
    use mem;
    use os;
    use rand::Rng;
    use result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::{SlicePrelude};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        marker: marker::NoCopy
    }

    #[repr(C)]
    struct SecRandom;

    #[allow(non_upper_case_globals)]
    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng {marker: marker::NoCopy} )
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::{SlicePrelude};

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(&mut v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<commit_msg>iOS: fixed broken build after disallowed coercions<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    extern crate libc;

    use self::OsRngInner::*;

    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::{Ok, Err};
    use slice::SlicePrelude;
    use mem;
    use os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0u)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        let len = v.len();
        while read < len {
            let result = getrandom(v[mut read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as uint;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8, ..4] = [0u8, ..4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8, ..4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8, ..8] = [0u8, ..8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8, ..8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Relaxed};

        static GETRANDOM_CHECKED: AtomicBool = INIT_ATOMIC_BOOL;
        static GETRANDOM_AVAILABLE: AtomicBool = INIT_ATOMIC_BOOL;

        if !GETRANDOM_CHECKED.load(Relaxed) {
            let mut buf: [u8, ..0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = errno() as libc::c_int;
                err != libc::ENOSYS
            } else {
                true
            };
            GETRANDOM_AVAILABLE.store(available, Relaxed);
            GETRANDOM_CHECKED.store(true, Relaxed);
            available
        } else {
            GETRANDOM_AVAILABLE.load(Relaxed)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use io::{IoResult};
    use kinds::marker;
    use mem;
    use os;
    use rand::Rng;
    use result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::{SlicePrelude};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        marker: marker::NoCopy
    }

    #[repr(C)]
    struct SecRandom;

    #[allow(non_upper_case_globals)]
    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng {marker: marker::NoCopy} )
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::{SlicePrelude};

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(&mut v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<|endoftext|>