<commit_before>//! A simple crate for executing work on a thread pool, and getting back a
//! future.
//!
//! This crate provides a simple thread pool abstraction for running work
//! externally from the current thread that's running. An instance of `Future`
//! is handed back to represent that the work may be done later, and further
//! computations can be chained along with it as well.
//!
//! ```rust
//! extern crate futures;
//! extern crate futures_cpupool;
//!
//! use futures::Future;
//! use futures_cpupool::CpuPool;
//!
//! # fn long_running_future(a: u32) -> futures::future::BoxFuture<u32, ()> {
//! #     futures::future::result(Ok(a)).boxed()
//! # }
//! # fn main() {
//!
//! // Create a worker thread pool with four threads
//! let pool = CpuPool::new(4);
//!
//! // Execute some work on the thread pool, optionally closing over data.
//! let a = pool.spawn(long_running_future(2));
//! let b = pool.spawn(long_running_future(100));
//!
//! // Express some further computation once the work is completed on the thread
//! // pool.
//! let c = a.join(b).map(|(a, b)| a + b).wait().unwrap();
//!
//! // Print out the result
//! println!("{:?}", c);
//! # }
//! ```

#![deny(missing_docs)]

extern crate futures;
extern crate num_cpus;

use std::panic::{self, AssertUnwindSafe};
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::mpsc;
use std::thread;

use futures::{IntoFuture, Future, Poll, Async};
use futures::future::lazy;
use futures::sync::oneshot::{channel, Sender, Receiver};
use futures::executor::{self, Run, Executor};

/// A thread pool intended to run CPU intensive work.
///
/// This thread pool will hand out futures representing the completed work
/// that happens on the thread pool itself, and the futures can then be later
/// composed with other work as part of an overall computation.
///
/// The worker threads associated with a thread pool are kept alive so long as
/// there is an open handle to the `CpuPool` or there is work running on them. Once
/// all work has been drained and all references have gone away the worker
/// threads will be shut down.
///
/// Currently `CpuPool` implements `Clone` which just clones a new reference to
/// the underlying thread pool.
///
/// **Note:** if you use CpuPool inside a library it's better accept a
/// `Builder` object for thread configuration rather than configuring just
/// pool size.  This not only future proof for other settings but also allows
/// user to attach monitoring tools to lifecycle hooks.
pub struct CpuPool {
    inner: Arc<Inner>,
}

/// Thread pool configuration object
///
/// Builder starts with a number of workers equal to the number
/// of CPUs on the host. But you can change it until you call `create()`.
pub struct Builder {
    pool_size: usize,
    name_prefix: Option<String>,
    after_start: Option<Arc<Fn() + Send + Sync>>,
    before_stop: Option<Arc<Fn() + Send + Sync>>,
}

struct MySender<F, T> {
    fut: F,
    tx: Option<Sender<T>>,
    keep_running_flag: Arc<AtomicBool>,
}

fn _assert() {
    fn _assert_send<T: Send>() {}
    fn _assert_sync<T: Sync>() {}
    _assert_send::<CpuPool>();
    _assert_sync::<CpuPool>();
}

struct Inner {
    tx: Mutex<mpsc::Sender<Message>>,
    rx: Mutex<mpsc::Receiver<Message>>,
    cnt: AtomicUsize,
    size: usize,
    after_start: Option<Arc<Fn() + Send + Sync>>,
    before_stop: Option<Arc<Fn() + Send + Sync>>,
}

/// The type of future returned from the `CpuPool::spawn` function, which
/// proxies the futures running on the thread pool.
///
/// This future will resolve in the same way as the underlying future, and it
/// will propagate panics.
#[must_use]
pub struct CpuFuture<T, E> {
    inner: Receiver<thread::Result<Result<T, E>>>,
    keep_running_flag: Arc<AtomicBool>,
}

enum Message {
    Run(Run),
    Close,
}

impl CpuPool {
    /// Creates a new thread pool with `size` worker threads associated with it.
    ///
    /// The returned handle can use `execute` to run work on this thread pool,
    /// and clones can be made of it to get multiple references to the same
    /// thread pool.
    ///
    /// This is a shortcut for:
    /// ```rust
    /// Builder::new().pool_size(size).create()
    /// ```
    ///
    /// # Panics
    ///
    /// Panics if `size == 0`.
    pub fn new(size: usize) -> CpuPool {
        Builder::new().pool_size(size).create()
    }

    /// Creates a new thread pool with a number of workers equal to the number
    /// of CPUs on the host.
    ///
    /// This is a shortcut for:
    /// ```rust
    /// Builder::new().create()
    /// ```
    pub fn new_num_cpus() -> CpuPool {
        Builder::new().create()
    }

    /// Spawns a future to run on this thread pool, returning a future
    /// representing the produced value.
    ///
    /// This function will execute the future `f` on the associated thread
    /// pool, and return a future representing the finished computation. The
    /// returned future serves as a proxy to the computation that `F` is
    /// running.
    ///
    /// To simply run an arbitrary closure on a thread pool and extract the
    /// result, you can use the `future::lazy` combinator to defer work to
    /// executing on the thread pool itself.
    ///
    /// Note that if the future `f` panics it will be caught by default and the
    /// returned future will propagate the panic. That is, panics will not tear
    /// down the thread pool and will be propagated to the returned future's
    /// `poll` method if queried.
    ///
    /// If the returned future is dropped then this `CpuPool` will attempt to
    /// cancel the computation, if possible. That is, if the computation is in
    /// the middle of working, it will be interrupted when possible.
    pub fn spawn<F>(&self, f: F) -> CpuFuture<F::Item, F::Error>
        where F: Future + Send + 'static,
              F::Item: Send + 'static,
              F::Error: Send + 'static,
    {
        let (tx, rx) = channel();
        let keep_running_flag = Arc::new(AtomicBool::new(false));
        // AssertUnwindSafe is used here becuase `Send + 'static` is basically
        // an alias for an implementation of the `UnwindSafe` trait but we can't
        // express that in the standard library right now.
        let sender = MySender {
            fut: AssertUnwindSafe(f).catch_unwind(),
            tx: Some(tx),
            keep_running_flag: keep_running_flag.clone(),
        };
        executor::spawn(sender).execute(self.inner.clone());
        CpuFuture { inner: rx , keep_running_flag: keep_running_flag.clone() }
    }

    /// Spawns a closure on this thread pool.
    ///
    /// This function is a convenience wrapper around the `spawn` function above
    /// for running a closure wrapped in `future::lazy`. It will spawn the
    /// function `f` provided onto the thread pool, and continue to run the
    /// future returned by `f` on the thread pool as well.
    ///
    /// The returned future will be a handle to the result produced by the
    /// future that `f` returns.
    pub fn spawn_fn<F, R>(&self, f: F) -> CpuFuture<R::Item, R::Error>
        where F: FnOnce() -> R + Send + 'static,
              R: IntoFuture + 'static,
              R::Future: Send + 'static,
              R::Item: Send + 'static,
              R::Error: Send + 'static,
    {
        self.spawn(lazy(f))
    }
}

impl Inner {
    fn send(&self, msg: Message) {
        self.tx.lock().unwrap().send(msg).unwrap();
    }

    fn work(&self) {
        self.after_start.as_ref().map(|fun| fun());
        loop {
            let msg = self.rx.lock().unwrap().recv().unwrap();
            match msg {
                Message::Run(r) => r.run(),
                Message::Close => break,
            }
        }
        self.before_stop.as_ref().map(|fun| fun());
    }
}

impl Clone for CpuPool {
    fn clone(&self) -> CpuPool {
        self.inner.cnt.fetch_add(1, Ordering::Relaxed);
        CpuPool { inner: self.inner.clone() }
    }
}

impl Drop for CpuPool {
    fn drop(&mut self) {
        if self.inner.cnt.fetch_sub(1, Ordering::Relaxed) == 1 {
            for _ in 0..self.inner.size {
                self.inner.send(Message::Close);
            }
        }
    }
}

impl Executor for Inner {
    fn execute(&self, run: Run) {
        self.send(Message::Run(run))
    }
}

impl<T, E> CpuFuture<T, E> {
    /// Drop this future without canceling the underlying future.
    ///
    /// When `CpuFuture` is dropped, `CpuPool` will try to abort the underlying
    /// future. This function can be used when user wants to drop but keep
    /// executing the underlying future.
    pub fn forget(self) {
        self.keep_running_flag.store(true, Ordering::SeqCst);
    }
}

impl<T: Send + 'static, E: Send + 'static> Future for CpuFuture<T, E> {
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<T, E> {
        match self.inner.poll().expect("shouldn't be canceled") {
            Async::Ready(Ok(Ok(e))) => Ok(e.into()),
            Async::Ready(Ok(Err(e))) => Err(e),
            Async::Ready(Err(e)) => panic::resume_unwind(e),
            Async::NotReady => Ok(Async::NotReady),
        }
    }
}

impl<F: Future> Future for MySender<F, Result<F::Item, F::Error>> {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        if let Ok(Async::Ready(_)) = self.tx.as_mut().unwrap().poll_cancel() {
            if !self.keep_running_flag.load(Ordering::SeqCst) {
                // Cancelled, bail out
                return Ok(().into())
            }
        }

        let res = match self.fut.poll() {
            Ok(Async::Ready(e)) => Ok(e),
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            Err(e) => Err(e),
        };

        // if the receiving end has gone away then that's ok, we just ignore the
        // send error here.
        drop(self.tx.take().unwrap().send(res));
        Ok(Async::Ready(()))
    }
}

impl Builder {
    /// Create a builder a number of workers equal to the number
    /// of CPUs on the host.
    pub fn new() -> Builder {
        Builder {
            pool_size: num_cpus::get(),
            name_prefix: None,
            after_start: None,
            before_stop: None,
        }
    }

    /// Set size of a future CpuPool
    ///
    /// The size of a thread pool is the number of worker threads spawned
    pub fn pool_size(&mut self, size: usize) -> &mut Self {
        self.pool_size = size;
        self
    }

    /// Set thread name prefix of a future CpuPool
    ///
    /// Thread name prefix is used for generating thread names. For example, if prefix is
    /// `my-pool-`, then threads in the pool will get names like `my-pool-1` etc.
    pub fn name_prefix<S: Into<String>>(&mut self, name_prefix: S) -> &mut Self {
        self.name_prefix = Some(name_prefix.into());
        self
    }

    /// Execute function `f` right after each thread is started but before
    /// running any jobs on it
    ///
    /// This is initially intended for bookkeeping and monitoring uses
    pub fn after_start<F>(&mut self, f: F) -> &mut Self
        where F: Fn() + Send + Sync + 'static
    {
        self.after_start = Some(Arc::new(f));
        self
    }

    /// Execute function `f` before each worker thread stops
    ///
    /// This is initially intended for bookkeeping and monitoring uses
    pub fn before_stop<F>(&mut self, f: F) -> &mut Self
        where F: Fn() + Send + Sync + 'static
    {
        self.before_stop = Some(Arc::new(f));
        self
    }

    /// Create CpuPool with configured parameters
    ///
    /// # Panics
    ///
    /// Panics if `pool_size == 0`.
    pub fn create(&mut self) -> CpuPool {
        let (tx, rx) = mpsc::channel();
        let pool = CpuPool {
            inner: Arc::new(Inner {
                tx: Mutex::new(tx),
                rx: Mutex::new(rx),
                cnt: AtomicUsize::new(1),
                size: self.pool_size,
                after_start: self.after_start.clone(),
                before_stop: self.before_stop.clone(),
            }),
        };
        assert!(self.pool_size > 0);

        for counter in 0..self.pool_size {
            let inner = pool.inner.clone();
            let mut thread_builder = thread::Builder::new();
            if let Some(ref name_prefix) = self.name_prefix {
                thread_builder = thread_builder.name(format!("{}{}", name_prefix, counter));
            }
            thread_builder.spawn(move || inner.work()).unwrap();
        }

        return pool
    }
}
<commit_msg>Add newlines to docs (for correct rendering)<commit_after>//! A simple crate for executing work on a thread pool, and getting back a
//! future.
//!
//! This crate provides a simple thread pool abstraction for running work
//! externally from the current thread that's running. An instance of `Future`
//! is handed back to represent that the work may be done later, and further
//! computations can be chained along with it as well.
//!
//! ```rust
//! extern crate futures;
//! extern crate futures_cpupool;
//!
//! use futures::Future;
//! use futures_cpupool::CpuPool;
//!
//! # fn long_running_future(a: u32) -> futures::future::BoxFuture<u32, ()> {
//! #     futures::future::result(Ok(a)).boxed()
//! # }
//! # fn main() {
//!
//! // Create a worker thread pool with four threads
//! let pool = CpuPool::new(4);
//!
//! // Execute some work on the thread pool, optionally closing over data.
//! let a = pool.spawn(long_running_future(2));
//! let b = pool.spawn(long_running_future(100));
//!
//! // Express some further computation once the work is completed on the thread
//! // pool.
//! let c = a.join(b).map(|(a, b)| a + b).wait().unwrap();
//!
//! // Print out the result
//! println!("{:?}", c);
//! # }
//! ```

#![deny(missing_docs)]

extern crate futures;
extern crate num_cpus;

use std::panic::{self, AssertUnwindSafe};
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::mpsc;
use std::thread;

use futures::{IntoFuture, Future, Poll, Async};
use futures::future::lazy;
use futures::sync::oneshot::{channel, Sender, Receiver};
use futures::executor::{self, Run, Executor};

/// A thread pool intended to run CPU intensive work.
///
/// This thread pool will hand out futures representing the completed work
/// that happens on the thread pool itself, and the futures can then be later
/// composed with other work as part of an overall computation.
///
/// The worker threads associated with a thread pool are kept alive so long as
/// there is an open handle to the `CpuPool` or there is work running on them. Once
/// all work has been drained and all references have gone away the worker
/// threads will be shut down.
///
/// Currently `CpuPool` implements `Clone` which just clones a new reference to
/// the underlying thread pool.
///
/// **Note:** if you use CpuPool inside a library it's better accept a
/// `Builder` object for thread configuration rather than configuring just
/// pool size.  This not only future proof for other settings but also allows
/// user to attach monitoring tools to lifecycle hooks.
pub struct CpuPool {
    inner: Arc<Inner>,
}

/// Thread pool configuration object
///
/// Builder starts with a number of workers equal to the number
/// of CPUs on the host. But you can change it until you call `create()`.
pub struct Builder {
    pool_size: usize,
    name_prefix: Option<String>,
    after_start: Option<Arc<Fn() + Send + Sync>>,
    before_stop: Option<Arc<Fn() + Send + Sync>>,
}

struct MySender<F, T> {
    fut: F,
    tx: Option<Sender<T>>,
    keep_running_flag: Arc<AtomicBool>,
}

fn _assert() {
    fn _assert_send<T: Send>() {}
    fn _assert_sync<T: Sync>() {}
    _assert_send::<CpuPool>();
    _assert_sync::<CpuPool>();
}

struct Inner {
    tx: Mutex<mpsc::Sender<Message>>,
    rx: Mutex<mpsc::Receiver<Message>>,
    cnt: AtomicUsize,
    size: usize,
    after_start: Option<Arc<Fn() + Send + Sync>>,
    before_stop: Option<Arc<Fn() + Send + Sync>>,
}

/// The type of future returned from the `CpuPool::spawn` function, which
/// proxies the futures running on the thread pool.
///
/// This future will resolve in the same way as the underlying future, and it
/// will propagate panics.
#[must_use]
pub struct CpuFuture<T, E> {
    inner: Receiver<thread::Result<Result<T, E>>>,
    keep_running_flag: Arc<AtomicBool>,
}

enum Message {
    Run(Run),
    Close,
}

impl CpuPool {
    /// Creates a new thread pool with `size` worker threads associated with it.
    ///
    /// The returned handle can use `execute` to run work on this thread pool,
    /// and clones can be made of it to get multiple references to the same
    /// thread pool.
    ///
    /// This is a shortcut for:
    ///
    /// ```rust
    /// Builder::new().pool_size(size).create()
    /// ```
    ///
    /// # Panics
    ///
    /// Panics if `size == 0`.
    pub fn new(size: usize) -> CpuPool {
        Builder::new().pool_size(size).create()
    }

    /// Creates a new thread pool with a number of workers equal to the number
    /// of CPUs on the host.
    ///
    /// This is a shortcut for:
    ///
    /// ```rust
    /// Builder::new().create()
    /// ```
    pub fn new_num_cpus() -> CpuPool {
        Builder::new().create()
    }

    /// Spawns a future to run on this thread pool, returning a future
    /// representing the produced value.
    ///
    /// This function will execute the future `f` on the associated thread
    /// pool, and return a future representing the finished computation. The
    /// returned future serves as a proxy to the computation that `F` is
    /// running.
    ///
    /// To simply run an arbitrary closure on a thread pool and extract the
    /// result, you can use the `future::lazy` combinator to defer work to
    /// executing on the thread pool itself.
    ///
    /// Note that if the future `f` panics it will be caught by default and the
    /// returned future will propagate the panic. That is, panics will not tear
    /// down the thread pool and will be propagated to the returned future's
    /// `poll` method if queried.
    ///
    /// If the returned future is dropped then this `CpuPool` will attempt to
    /// cancel the computation, if possible. That is, if the computation is in
    /// the middle of working, it will be interrupted when possible.
    pub fn spawn<F>(&self, f: F) -> CpuFuture<F::Item, F::Error>
        where F: Future + Send + 'static,
              F::Item: Send + 'static,
              F::Error: Send + 'static,
    {
        let (tx, rx) = channel();
        let keep_running_flag = Arc::new(AtomicBool::new(false));
        // AssertUnwindSafe is used here becuase `Send + 'static` is basically
        // an alias for an implementation of the `UnwindSafe` trait but we can't
        // express that in the standard library right now.
        let sender = MySender {
            fut: AssertUnwindSafe(f).catch_unwind(),
            tx: Some(tx),
            keep_running_flag: keep_running_flag.clone(),
        };
        executor::spawn(sender).execute(self.inner.clone());
        CpuFuture { inner: rx , keep_running_flag: keep_running_flag.clone() }
    }

    /// Spawns a closure on this thread pool.
    ///
    /// This function is a convenience wrapper around the `spawn` function above
    /// for running a closure wrapped in `future::lazy`. It will spawn the
    /// function `f` provided onto the thread pool, and continue to run the
    /// future returned by `f` on the thread pool as well.
    ///
    /// The returned future will be a handle to the result produced by the
    /// future that `f` returns.
    pub fn spawn_fn<F, R>(&self, f: F) -> CpuFuture<R::Item, R::Error>
        where F: FnOnce() -> R + Send + 'static,
              R: IntoFuture + 'static,
              R::Future: Send + 'static,
              R::Item: Send + 'static,
              R::Error: Send + 'static,
    {
        self.spawn(lazy(f))
    }
}

impl Inner {
    fn send(&self, msg: Message) {
        self.tx.lock().unwrap().send(msg).unwrap();
    }

    fn work(&self) {
        self.after_start.as_ref().map(|fun| fun());
        loop {
            let msg = self.rx.lock().unwrap().recv().unwrap();
            match msg {
                Message::Run(r) => r.run(),
                Message::Close => break,
            }
        }
        self.before_stop.as_ref().map(|fun| fun());
    }
}

impl Clone for CpuPool {
    fn clone(&self) -> CpuPool {
        self.inner.cnt.fetch_add(1, Ordering::Relaxed);
        CpuPool { inner: self.inner.clone() }
    }
}

impl Drop for CpuPool {
    fn drop(&mut self) {
        if self.inner.cnt.fetch_sub(1, Ordering::Relaxed) == 1 {
            for _ in 0..self.inner.size {
                self.inner.send(Message::Close);
            }
        }
    }
}

impl Executor for Inner {
    fn execute(&self, run: Run) {
        self.send(Message::Run(run))
    }
}

impl<T, E> CpuFuture<T, E> {
    /// Drop this future without canceling the underlying future.
    ///
    /// When `CpuFuture` is dropped, `CpuPool` will try to abort the underlying
    /// future. This function can be used when user wants to drop but keep
    /// executing the underlying future.
    pub fn forget(self) {
        self.keep_running_flag.store(true, Ordering::SeqCst);
    }
}

impl<T: Send + 'static, E: Send + 'static> Future for CpuFuture<T, E> {
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<T, E> {
        match self.inner.poll().expect("shouldn't be canceled") {
            Async::Ready(Ok(Ok(e))) => Ok(e.into()),
            Async::Ready(Ok(Err(e))) => Err(e),
            Async::Ready(Err(e)) => panic::resume_unwind(e),
            Async::NotReady => Ok(Async::NotReady),
        }
    }
}

impl<F: Future> Future for MySender<F, Result<F::Item, F::Error>> {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        if let Ok(Async::Ready(_)) = self.tx.as_mut().unwrap().poll_cancel() {
            if !self.keep_running_flag.load(Ordering::SeqCst) {
                // Cancelled, bail out
                return Ok(().into())
            }
        }

        let res = match self.fut.poll() {
            Ok(Async::Ready(e)) => Ok(e),
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            Err(e) => Err(e),
        };

        // if the receiving end has gone away then that's ok, we just ignore the
        // send error here.
        drop(self.tx.take().unwrap().send(res));
        Ok(Async::Ready(()))
    }
}

impl Builder {
    /// Create a builder a number of workers equal to the number
    /// of CPUs on the host.
    pub fn new() -> Builder {
        Builder {
            pool_size: num_cpus::get(),
            name_prefix: None,
            after_start: None,
            before_stop: None,
        }
    }

    /// Set size of a future CpuPool
    ///
    /// The size of a thread pool is the number of worker threads spawned
    pub fn pool_size(&mut self, size: usize) -> &mut Self {
        self.pool_size = size;
        self
    }

    /// Set thread name prefix of a future CpuPool
    ///
    /// Thread name prefix is used for generating thread names. For example, if prefix is
    /// `my-pool-`, then threads in the pool will get names like `my-pool-1` etc.
    pub fn name_prefix<S: Into<String>>(&mut self, name_prefix: S) -> &mut Self {
        self.name_prefix = Some(name_prefix.into());
        self
    }

    /// Execute function `f` right after each thread is started but before
    /// running any jobs on it
    ///
    /// This is initially intended for bookkeeping and monitoring uses
    pub fn after_start<F>(&mut self, f: F) -> &mut Self
        where F: Fn() + Send + Sync + 'static
    {
        self.after_start = Some(Arc::new(f));
        self
    }

    /// Execute function `f` before each worker thread stops
    ///
    /// This is initially intended for bookkeeping and monitoring uses
    pub fn before_stop<F>(&mut self, f: F) -> &mut Self
        where F: Fn() + Send + Sync + 'static
    {
        self.before_stop = Some(Arc::new(f));
        self
    }

    /// Create CpuPool with configured parameters
    ///
    /// # Panics
    ///
    /// Panics if `pool_size == 0`.
    pub fn create(&mut self) -> CpuPool {
        let (tx, rx) = mpsc::channel();
        let pool = CpuPool {
            inner: Arc::new(Inner {
                tx: Mutex::new(tx),
                rx: Mutex::new(rx),
                cnt: AtomicUsize::new(1),
                size: self.pool_size,
                after_start: self.after_start.clone(),
                before_stop: self.before_stop.clone(),
            }),
        };
        assert!(self.pool_size > 0);

        for counter in 0..self.pool_size {
            let inner = pool.inner.clone();
            let mut thread_builder = thread::Builder::new();
            if let Some(ref name_prefix) = self.name_prefix {
                thread_builder = thread_builder.name(format!("{}{}", name_prefix, counter));
            }
            thread_builder.spawn(move || inner.work()).unwrap();
        }

        return pool
    }
}
<|endoftext|>


<commit_before>use env::{Environment, Point};
use loans_in_scope::{Loan, LoansInScope};
use nll_repr::repr;
use std::error::Error;
use std::fmt;

pub fn borrow_check(env: &Environment, loans_in_scope: &LoansInScope) -> Result<(), Box<Error>> {
    let mut result: Result<(), Box<Error>> = Ok(());
    loans_in_scope.walk(env, |point, opt_action, loans| {
        let borrowck = BorrowCheck { env, point, loans };
        if let Some(action) = opt_action {
            if let Err(e) = borrowck.check_action(action) {
                if !action.should_have_error {
                    result = Err(e);
                }
            } else if action.should_have_error {
                result = Err(Box::new(BorrowError::no_error(point)));
            }
        }
    });

    result
}

struct BorrowCheck<'cx> {
    env: &'cx Environment<'cx>,
    point: Point,
    loans: &'cx [&'cx Loan<'cx>],
}

impl<'cx> BorrowCheck<'cx> {
    fn check_action(&self, action: &repr::Action) -> Result<(), Box<Error>> {
        log!("check_action({:?}) at {:?}", action, self.point);
        match action.kind {
            repr::ActionKind::Init(ref a, ref bs) => {
                self.check_write(a)?;
                for b in bs {
                    self.check_read(b)?;
                }
            }
            repr::ActionKind::Assign(ref a, ref b) => {
                self.check_write(a)?;
                self.check_read(b)?;
            }
            repr::ActionKind::Borrow(ref a, _, repr::BorrowKind::Shared, ref b) => {
                self.check_write(a)?;
                self.check_read(b)?;
            }
            repr::ActionKind::Borrow(ref a, _, repr::BorrowKind::Mut, ref b) => {
                self.check_write(a)?;
                self.check_write(b)?;
            }
            repr::ActionKind::Constraint(_) => {}
            repr::ActionKind::Use(ref p) => {
                self.check_read(p)?;
            }
            repr::ActionKind::Drop(ref p) => {
                self.check_move(p)?;
            }
            repr::ActionKind::StorageDead(p) => {
                self.check_storage_dead(p)?;
            }
            repr::ActionKind::Noop => {}
        }

        Ok(())
    }

    /// Cannot write to a path `p` if:
    /// - the path `p` is frozen by one of the loans
    ///   - see `frozen_by_borrow_of()`
    ///   - this covers writing to `a` (or `a.b`) when `a.b` is borrowed
    /// - some prefix of `p` is borrowed.
    ///   - this covers writing to `a.b.c` when `a.b` is borrowed
    fn check_write(&self, path: &repr::Path) -> Result<(), Box<Error>> {
        log!(
            "check_write of {:?} at {:?} with loans={:#?}",
            path,
            self.point,
            self.loans
        );
        let prefixes = path.prefixes();
        for loan in self.loans {
            // If you have borrowed `a.b`, this prevents writes to `a`
            // or `a.b`:
            let frozen_paths = self.frozen_by_borrow_of(&loan.path);
            if frozen_paths.contains(&path) {
                return Err(Box::new(BorrowError::for_write(
                    self.point,
                    path,
                    &loan.path,
                    loan.point,
                )));
            }

            // If you have borrowed `a.b`, this prevents writes to
            // `a.b.c`:
            if prefixes.contains(&loan.path) {
                return Err(Box::new(BorrowError::for_write(
                    self.point,
                    path,
                    &loan.path,
                    loan.point,
                )));
            }
        }
        Ok(())
    }

    /// Cannot read from a path `p` if:
    /// - `p` is borrowed mutably;
    /// - some subpath `p.foo` is borrowed mutably;
    /// - some prefix of `p` is borrowed mutably.
    fn check_read(&self, path: &repr::Path) -> Result<(), Box<Error>> {
        log!(
            "check_read of {:?} at {:?} with loans={:#?}",
            path,
            self.point,
            self.loans
        );
        let prefixes = path.prefixes();
        for loan in self.loans {
            match loan.kind {
                repr::BorrowKind::Shared => continue,
                repr::BorrowKind::Mut => {}
            }

            for loan_prefix in loan.path.prefixes() {
                if prefixes.contains(&loan_prefix) {
                    return Err(Box::new(BorrowError::for_read(
                        self.point,
                        path,
                        &loan.path,
                        loan.point,
                    )));
                }
            }
        }
        Ok(())
    }

    /// Cannot move from a path `p` if:
    /// - `p` is borrowed;
    /// - some subpath `p.foo` is borrowed;
    /// - some prefix of `p` is borrowed.
    ///
    /// XXX counterexample?
    ///
    /// ```
    /// let p: &i32;
    /// let q = &*p;
    /// move(p); // but this is not actually a *move*, is the point
    /// ```
    fn check_move(&self, path: &repr::Path) -> Result<(), Box<Error>> {
        log!(
            "check_move of {:?} at {:?} with loans={:#?}",
            path,
            self.point,
            self.loans
        );
        let prefixes = path.prefixes();
        for loan in self.loans {
            for loan_prefix in loan.path.prefixes() {
                if prefixes.contains(&loan_prefix) {
                    return Err(Box::new(BorrowError::for_move(
                        self.point,
                        path,
                        &loan.path,
                        loan.point,
                    )));
                }
            }
        }
        Ok(())
    }

    /// Cannot free a local variable `var` if:
    /// - data interior to `var` is borrowed.
    ///
    /// In particular, having something like `*var` borrowed is ok.
    fn check_storage_dead(&self, var: repr::Variable) -> Result<(), Box<Error>> {
        log!(
            "check_storage_dead of {:?} at {:?} with loans={:#?}",
            var,
            self.point,
            self.loans
        );
        for loan in self.loans {
            if let Some(loan_var) = self.invalidated_by_dead_storage(&loan.path) {
                if var == loan_var {
                    return Err(Box::new(BorrowError::for_storage_dead(
                        self.point,
                        var,
                        &loan.path,
                        loan.point,
                    )));
                }
            }
        }
        Ok(())
    }

    /// If `path` is borrowed, returns a vector of paths which -- if
    /// moved or if the storage went away -- would invalidate this
    /// reference.
    fn invalidated_by_dead_storage(&self, mut path: &repr::Path) -> Option<repr::Variable> {
        loop {
            match *path {
                repr::Path::Base(v) => return Some(v),
                repr::Path::Extension(ref base_path, field_name) => {
                    match *self.env.path_ty(base_path) {
                        // If you borrow `*r`, you can drop the
                        // reference `r` without invalidating that
                        // memory.
                        repr::Ty::Ref(_, _, _) => {
                            assert_eq!(field_name, repr::FieldName::star());
                            return None;
                        }

                        repr::Ty::Unit |
                        repr::Ty::Struct(..) => {
                            path = base_path;
                        }

                        repr::Ty::Bound(..) => panic!("unexpected bound type"),
                    }
                }
            }
        }
    }

    /// If `path` is mutably borrowed, returns a vector of paths which -- if
    /// moved or if the storage went away -- would invalidate this
    /// reference.
    fn frozen_by_borrow_of<'a>(&self, mut path: &'a repr::Path) -> Vec<&'a repr::Path> {
        let mut result = vec![];
        loop {
            result.push(path);
            match *path {
                repr::Path::Base(_) => return result,
                repr::Path::Extension(ref base_path, field_name) => {
                    match *self.env.path_ty(base_path) {
                        // If you borrowed `*r`, writing to `r` does
                        // not actually affect the memory at `*r`, so
                        // we can stop iterating backwards now.
                        repr::Ty::Ref(_, _, _) => {
                            assert_eq!(field_name, repr::FieldName::star());
                            return result;
                        }

                        // If you have borrowed `a.b`, then writing to
                        // `a` would overwrite `a.b`, which is
                        // disallowed.
                        repr::Ty::Struct(..) => {
                            path = base_path;
                        }

                        repr::Ty::Unit => panic!("unit has no fields"),
                        repr::Ty::Bound(..) => panic!("unexpected bound type"),
                    }
                }
            }
        }
    }
}

#[derive(Debug)]
pub struct BorrowError {
    description: String,
}

impl BorrowError {
    fn no_error(point: Point) -> Self {
        BorrowError {
            description: format!("point {:?} had no error, but should have", point),
        }
    }

    fn for_move(
        point: Point,
        path: &repr::Path,
        loan_path: &repr::Path,
        loan_point: Point,
    ) -> Self {
        BorrowError {
            description: format!(
                "point {:?} cannot move {:?} because {:?} is borrowed (at point `{:?}`)",
                point,
                path,
                loan_path,
                loan_point
            ),
        }
    }

    fn for_read(
        point: Point,
        path: &repr::Path,
        loan_path: &repr::Path,
        loan_point: Point,
    ) -> Self {
        BorrowError {
            description: format!(
                "point {:?} cannot read {:?} because {:?} is mutably borrowed (at point `{:?}`)",
                point,
                path,
                loan_path,
                loan_point
            ),
        }
    }

    fn for_write(
        point: Point,
        path: &repr::Path,
        loan_path: &repr::Path,
        loan_point: Point,
    ) -> Self {
        BorrowError {
            description: format!(
                "point {:?} cannot write {:?} because {:?} is borrowed (at point `{:?}`)",
                point,
                path,
                loan_path,
                loan_point
            ),
        }
    }

    fn for_storage_dead(
        point: Point,
        var: repr::Variable,
        loan_path: &repr::Path,
        loan_point: Point,
    ) -> Self {
        BorrowError {
            description: format!(
                "point {:?} cannot kill storage for {:?} \
                 because {:?} is borrowed (at point `{:?}`)",
                point,
                var,
                loan_path,
                loan_point
            ),
        }
    }
}

impl Error for BorrowError {
    fn description(&self) -> &str {
        &self.description
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl fmt::Display for BorrowError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.description)
    }
}
<commit_msg>rewrite for clarity<commit_after>use env::{Environment, Point};
use loans_in_scope::{Loan, LoansInScope};
use nll_repr::repr;
use std::error::Error;
use std::fmt;

pub fn borrow_check(env: &Environment, loans_in_scope: &LoansInScope) -> Result<(), Box<Error>> {
    let mut result: Result<(), Box<Error>> = Ok(());
    loans_in_scope.walk(env, |point, opt_action, loans| {
        let borrowck = BorrowCheck { env, point, loans };
        if let Some(action) = opt_action {
            if let Err(e) = borrowck.check_action(action) {
                if !action.should_have_error {
                    result = Err(e);
                }
            } else if action.should_have_error {
                result = Err(Box::new(BorrowError::no_error(point)));
            }
        }
    });

    result
}

struct BorrowCheck<'cx> {
    env: &'cx Environment<'cx>,
    point: Point,
    loans: &'cx [&'cx Loan<'cx>],
}

impl<'cx> BorrowCheck<'cx> {
    fn check_action(&self, action: &repr::Action) -> Result<(), Box<Error>> {
        log!("check_action({:?}) at {:?}", action, self.point);
        match action.kind {
            repr::ActionKind::Init(ref a, ref bs) => {
                self.check_write(a)?;
                for b in bs {
                    self.check_read(b)?;
                }
            }
            repr::ActionKind::Assign(ref a, ref b) => {
                self.check_write(a)?;
                self.check_read(b)?;
            }
            repr::ActionKind::Borrow(ref a, _, repr::BorrowKind::Shared, ref b) => {
                self.check_write(a)?;
                self.check_read(b)?;
            }
            repr::ActionKind::Borrow(ref a, _, repr::BorrowKind::Mut, ref b) => {
                self.check_write(a)?;
                self.check_write(b)?;
            }
            repr::ActionKind::Constraint(_) => {}
            repr::ActionKind::Use(ref p) => {
                self.check_read(p)?;
            }
            repr::ActionKind::Drop(ref p) => {
                self.check_move(p)?;
            }
            repr::ActionKind::StorageDead(p) => {
                self.check_storage_dead(p)?;
            }
            repr::ActionKind::Noop => {}
        }

        Ok(())
    }

    /// Cannot write to a path `p` if:
    /// - the path `p` is frozen by one of the loans
    ///   - see `frozen_by_borrow_of()`
    ///   - this covers writing to `a` (or `a.b`) when `a.b` is borrowed
    /// - some prefix of `p` is borrowed.
    ///   - this covers writing to `a.b.c` when `a.b` is borrowed
    fn check_write(&self, path: &repr::Path) -> Result<(), Box<Error>> {
        log!(
            "check_write of {:?} at {:?} with loans={:#?}",
            path,
            self.point,
            self.loans
        );
        let prefixes = path.prefixes();
        for loan in self.loans {
            // If you have borrowed `a.b`, this prevents writes to `a`
            // or `a.b`:
            let frozen_paths = self.frozen_by_borrow_of(&loan.path);
            if frozen_paths.contains(&path) {
                return Err(Box::new(BorrowError::for_write(
                    self.point,
                    path,
                    &loan.path,
                    loan.point,
                )));
            }

            // If you have borrowed `a.b`, this prevents writes to
            // `a.b.c`:
            if prefixes.contains(&loan.path) {
                return Err(Box::new(BorrowError::for_write(
                    self.point,
                    path,
                    &loan.path,
                    loan.point,
                )));
            }
        }
        Ok(())
    }

    /// Cannot read from a path `a.b.c` if:
    /// - the exact path `a.b.c` is borrowed mutably;
    /// - some subpath `a.b.c.d` is borrowed mutably;
    /// - some prefix of `a.b` is borrowed mutably.
    fn check_read(&self, path: &repr::Path) -> Result<(), Box<Error>> {
        log!(
            "check_read of {:?} at {:?} with loans={:#?}",
            path,
            self.point,
            self.loans
        );
        let path_prefixes = path.prefixes();
        for loan in self.loans {
            match loan.kind {
                repr::BorrowKind::Shared => continue,
                repr::BorrowKind::Mut => {}
            }

            if {
                // `a.b.c` or `a.b` is borrowed
                path_prefixes.contains(&loan.path) ||

                    // `a.b.c.d` is borrowed
                    loan.path.prefixes().contains(&path)
            } {
                return Err(Box::new(BorrowError::for_read(
                    self.point,
                    path,
                    &loan.path,
                    loan.point,
                )));
            }
        }
        Ok(())
    }

    /// Cannot move from a path `p` if:
    /// - `p` is borrowed;
    /// - some subpath `p.foo` is borrowed;
    /// - some prefix of `p` is borrowed.
    ///
    /// XXX counterexample?
    ///
    /// ```
    /// let p: &i32;
    /// let q = &*p;
    /// move(p); // but this is not actually a *move*, is the point
    /// ```
    fn check_move(&self, path: &repr::Path) -> Result<(), Box<Error>> {
        log!(
            "check_move of {:?} at {:?} with loans={:#?}",
            path,
            self.point,
            self.loans
        );
        let path_prefixes = path.prefixes();
        for loan in self.loans {
            if {
                // accessing `a.b.c` is illegal if `a.b.c` or `a.b` is
                // borrowed...
                path_prefixes.contains(&loan.path) ||

                    // ...or `a.b.c.d` is borrowed
                    loan.path.prefixes().contains(&path)
            } {
                return Err(Box::new(BorrowError::for_move(
                    self.point,
                    path,
                    &loan.path,
                    loan.point,
                )));
            }
        }
        Ok(())
    }

    /// Cannot free a local variable `var` if:
    /// - data interior to `var` is borrowed.
    ///
    /// In particular, having something like `*var` borrowed is ok.
    fn check_storage_dead(&self, var: repr::Variable) -> Result<(), Box<Error>> {
        log!(
            "check_storage_dead of {:?} at {:?} with loans={:#?}",
            var,
            self.point,
            self.loans
        );
        for loan in self.loans {
            if let Some(loan_var) = self.invalidated_by_dead_storage(&loan.path) {
                if var == loan_var {
                    return Err(Box::new(BorrowError::for_storage_dead(
                        self.point,
                        var,
                        &loan.path,
                        loan.point,
                    )));
                }
            }
        }
        Ok(())
    }

    /// If `path` is borrowed, returns a vector of paths which -- if
    /// moved or if the storage went away -- would invalidate this
    /// reference.
    fn invalidated_by_dead_storage(&self, mut path: &repr::Path) -> Option<repr::Variable> {
        loop {
            match *path {
                repr::Path::Base(v) => return Some(v),
                repr::Path::Extension(ref base_path, field_name) => {
                    match *self.env.path_ty(base_path) {
                        // If you borrow `*r`, you can drop the
                        // reference `r` without invalidating that
                        // memory.
                        repr::Ty::Ref(_, _, _) => {
                            assert_eq!(field_name, repr::FieldName::star());
                            return None;
                        }

                        repr::Ty::Unit |
                        repr::Ty::Struct(..) => {
                            path = base_path;
                        }

                        repr::Ty::Bound(..) => panic!("unexpected bound type"),
                    }
                }
            }
        }
    }

    /// If `path` is mutably borrowed, returns a vector of paths which -- if
    /// moved or if the storage went away -- would invalidate this
    /// reference.
    fn frozen_by_borrow_of<'a>(&self, mut path: &'a repr::Path) -> Vec<&'a repr::Path> {
        let mut result = vec![];
        loop {
            result.push(path);
            match *path {
                repr::Path::Base(_) => return result,
                repr::Path::Extension(ref base_path, field_name) => {
                    match *self.env.path_ty(base_path) {
                        // If you borrowed `*r`, writing to `r` does
                        // not actually affect the memory at `*r`, so
                        // we can stop iterating backwards now.
                        repr::Ty::Ref(_, _, _) => {
                            assert_eq!(field_name, repr::FieldName::star());
                            return result;
                        }

                        // If you have borrowed `a.b`, then writing to
                        // `a` would overwrite `a.b`, which is
                        // disallowed.
                        repr::Ty::Struct(..) => {
                            path = base_path;
                        }

                        repr::Ty::Unit => panic!("unit has no fields"),
                        repr::Ty::Bound(..) => panic!("unexpected bound type"),
                    }
                }
            }
        }
    }
}

#[derive(Debug)]
pub struct BorrowError {
    description: String,
}

impl BorrowError {
    fn no_error(point: Point) -> Self {
        BorrowError {
            description: format!("point {:?} had no error, but should have", point),
        }
    }

    fn for_move(
        point: Point,
        path: &repr::Path,
        loan_path: &repr::Path,
        loan_point: Point,
    ) -> Self {
        BorrowError {
            description: format!(
                "point {:?} cannot move {:?} because {:?} is borrowed (at point `{:?}`)",
                point,
                path,
                loan_path,
                loan_point
            ),
        }
    }

    fn for_read(
        point: Point,
        path: &repr::Path,
        loan_path: &repr::Path,
        loan_point: Point,
    ) -> Self {
        BorrowError {
            description: format!(
                "point {:?} cannot read {:?} because {:?} is mutably borrowed (at point `{:?}`)",
                point,
                path,
                loan_path,
                loan_point
            ),
        }
    }

    fn for_write(
        point: Point,
        path: &repr::Path,
        loan_path: &repr::Path,
        loan_point: Point,
    ) -> Self {
        BorrowError {
            description: format!(
                "point {:?} cannot write {:?} because {:?} is borrowed (at point `{:?}`)",
                point,
                path,
                loan_path,
                loan_point
            ),
        }
    }

    fn for_storage_dead(
        point: Point,
        var: repr::Variable,
        loan_path: &repr::Path,
        loan_point: Point,
    ) -> Self {
        BorrowError {
            description: format!(
                "point {:?} cannot kill storage for {:?} \
                 because {:?} is borrowed (at point `{:?}`)",
                point,
                var,
                loan_path,
                loan_point
            ),
        }
    }
}

impl Error for BorrowError {
    fn description(&self) -> &str {
        &self.description
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl fmt::Display for BorrowError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.description)
    }
}
<|endoftext|>


<commit_before>use decoders::*;
use decoders::tiff::*;
use decoders::ljpeg::*;
use std::f32::NAN;

#[derive(Debug, Clone)]
pub struct Cr2Decoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> Cr2Decoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> Cr2Decoder<'a> {
    Cr2Decoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for Cr2Decoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.rawloader.check_supported(&self.tiff));
    let (raw, offset) = {
      if let Some(raw) = self.tiff.find_first_ifd(Tag::Cr2Id) {
        (raw, fetch_tag!(raw, Tag::StripOffsets).get_usize(0))
      } else if let Some(raw) = self.tiff.find_first_ifd(Tag::CFAPattern) {
        (raw, fetch_tag!(raw, Tag::StripOffsets).get_usize(0))
      } else if let Some(off) = self.tiff.find_entry(Tag::Cr2OldOffset) {
        (&self.tiff, off.get_usize(0))
      } else {
        return Err("CR2: Couldn't find raw info".to_string())
      }
    };
    let src = &self.buffer[offset..];

    let (width, height, image) = {
      let decompressor = try!(LjpegDecompressor::new(src, true));
      let width = decompressor.width();
      let height = decompressor.height();
      let mut ljpegout = vec![0 as u16; width*height];
      try!(decompressor.decode(&mut ljpegout, 0, width, width, height));

      // Take each of the vertical fields and put them into the right location
      // FIXME: Doing this at the decode would reduce about 5% in runtime but I haven't
      //        been able to do it without hairy code
      if let Some(canoncol) = raw.find_entry(Tag::Cr2StripeWidths) {
        if canoncol.get_usize(0) == 0 {
          (width, height, ljpegout)
        } else {
          let mut out = vec![0 as u16; width*height];
          let mut fieldwidths = Vec::new();
          for _ in 0..canoncol.get_usize(0) {
            fieldwidths.push(canoncol.get_usize(1));
          }
          fieldwidths.push(canoncol.get_usize(2));

          let mut fieldstart = 0;
          let mut fieldpos = 0;
          for fieldwidth in fieldwidths {
            for row in 0..height {
              let outpos = row*width+fieldstart;
              let inpos = fieldpos+row*fieldwidth;
              let outb = &mut out[outpos..outpos+fieldwidth];
              let inb = &ljpegout[inpos..inpos+fieldwidth];
              outb.copy_from_slice(inb);
            }
            fieldstart += fieldwidth;
            fieldpos += fieldwidth*height;
          }

          (width, height, out)
        }
      } else {
        (width, height, ljpegout)
      }
    };
    ok_image(camera, width, height, try!(self.get_wb(camera)), image)
  }
}

impl<'a> Cr2Decoder<'a> {
  fn get_wb(&self, cam: &Camera) -> Result<[f32;4], String> {
    if let Some(levels) = self.tiff.find_entry(Tag::Cr2ColorData) {
      let offset = if cam.wb_offset != 0 {cam.wb_offset} else {63};
      Ok([levels.get_force_u16(offset) as f32, levels.get_force_u16(offset+1) as f32,
          levels.get_force_u16(offset+3) as f32, NAN])
    } else if let Some(levels) = self.tiff.find_entry(Tag::Cr2PowerShotWB) {
      Ok([levels.get_force_u32(3) as f32, levels.get_force_u32(2) as f32,
          levels.get_force_u32(4) as f32, NAN])
    } else {
      Err("CR2: Couldn't find WB".to_string())
    }
  }
}
<commit_msg>CR2: add hint to handle 1D/1Ds double width<commit_after>use decoders::*;
use decoders::tiff::*;
use decoders::ljpeg::*;
use std::f32::NAN;

#[derive(Debug, Clone)]
pub struct Cr2Decoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> Cr2Decoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> Cr2Decoder<'a> {
    Cr2Decoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for Cr2Decoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.rawloader.check_supported(&self.tiff));
    let (raw, offset) = {
      if let Some(raw) = self.tiff.find_first_ifd(Tag::Cr2Id) {
        (raw, fetch_tag!(raw, Tag::StripOffsets).get_usize(0))
      } else if let Some(raw) = self.tiff.find_first_ifd(Tag::CFAPattern) {
        (raw, fetch_tag!(raw, Tag::StripOffsets).get_usize(0))
      } else if let Some(off) = self.tiff.find_entry(Tag::Cr2OldOffset) {
        (&self.tiff, off.get_usize(0))
      } else {
        return Err("CR2: Couldn't find raw info".to_string())
      }
    };
    let src = &self.buffer[offset..];

    let (width, height, image) = {
      let decompressor = try!(LjpegDecompressor::new(src, true));
      let width = decompressor.width();
      let height = decompressor.height();
      let mut ljpegout = vec![0 as u16; width*height];
      try!(decompressor.decode(&mut ljpegout, 0, width, width, height));

      // Take each of the vertical fields and put them into the right location
      // FIXME: Doing this at the decode would reduce about 5% in runtime but I haven't
      //        been able to do it without hairy code
      if let Some(canoncol) = raw.find_entry(Tag::Cr2StripeWidths) {
        if canoncol.get_usize(0) == 0 {
          (width, height, ljpegout)
        } else {
          let mut out = vec![0 as u16; width*height];
          let mut fieldwidths = Vec::new();
          for _ in 0..canoncol.get_usize(0) {
            fieldwidths.push(canoncol.get_usize(1));
          }
          fieldwidths.push(canoncol.get_usize(2));

          let mut fieldstart = 0;
          let mut fieldpos = 0;
          for fieldwidth in fieldwidths {
            for row in 0..height {
              let outpos = row*width+fieldstart;
              let inpos = fieldpos+row*fieldwidth;
              let outb = &mut out[outpos..outpos+fieldwidth];
              let inb = &ljpegout[inpos..inpos+fieldwidth];
              outb.copy_from_slice(inb);
            }
            fieldstart += fieldwidth;
            fieldpos += fieldwidth*height;
          }

          (width, height, out)
        }
      } else if camera.find_hint("double_line") {
        (width/2, height*2, ljpegout)
      } else {
        (width, height, ljpegout)
      }
    };
    ok_image(camera, width, height, try!(self.get_wb(camera)), image)
  }
}

impl<'a> Cr2Decoder<'a> {
  fn get_wb(&self, cam: &Camera) -> Result<[f32;4], String> {
    if let Some(levels) = self.tiff.find_entry(Tag::Cr2ColorData) {
      let offset = if cam.wb_offset != 0 {cam.wb_offset} else {63};
      Ok([levels.get_force_u16(offset) as f32, levels.get_force_u16(offset+1) as f32,
          levels.get_force_u16(offset+3) as f32, NAN])
    } else if let Some(levels) = self.tiff.find_entry(Tag::Cr2PowerShotWB) {
      Ok([levels.get_force_u32(3) as f32, levels.get_force_u32(2) as f32,
          levels.get_force_u32(4) as f32, NAN])
    } else {
      Err("CR2: Couldn't find WB".to_string())
    }
  }
}
<|endoftext|>


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

//! Fixed-function hardware state.
//!
//! Configures the primitive assembly (PA), rasterizer, and output merger (OM) blocks.

use std::default::Default;
use std::fmt;

use target;

/// The winding order of a set of vertices.
#[deriving(Clone, PartialEq, Show)]
pub enum WindingOrder {
    /// Clockwise winding order.
    Clockwise,
    /// Counter-clockwise winding order.
    CounterClockwise,
}

/// Width of a line.
pub type LineWidth = f32;
#[allow(missing_doc)]
pub type OffsetFactor = f32;
#[allow(missing_doc)]
pub type OffsetUnits = u32;

/// How to offset vertices in screen space, if at all.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum OffsetType {
    NoOffset,
    Offset(OffsetFactor, OffsetUnits),
}

/// Which face, if any, to cull.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum CullMode {
    CullNothing,
    CullFront,
    CullBack,
}

/// How to rasterize a primitive.
#[deriving(Clone, PartialEq, Show)]
pub enum RasterMethod {
    /// Rasterize as a point.
    Point,
    /// Rasterize as a line with the given width.
    Line(LineWidth),
    /// Rasterize as a face with a given cull mode.
    Fill(CullMode),
}

/// Primitive rasterization state. Note that GL allows different raster
/// method to be used for front and back, while this abstraction does not.
#[deriving(Clone, PartialEq, Show)]
pub struct Primitive {
    /// Which vertex winding is considered to be the front face for culling.
    pub front_face: WindingOrder,
    /// How to rasterize this primitive.
    pub method: RasterMethod,
    /// Any polygon offset to apply.
    pub offset: OffsetType,
}

impl Primitive {
    /// Get the cull mode, if any, for this primitive state.
    pub fn get_cull_mode(&self) -> CullMode {
        match self.method {
            Fill(mode) => mode,
            _ => CullNothing,
        }
    }
}

impl Default for Primitive {
    fn default() -> Primitive {
        Primitive {
            front_face: CounterClockwise,
            method: Fill(CullNothing),
            offset: NoOffset,
        }
    }
}

/// Multi-sampling rasterization mode
#[deriving(Clone, PartialEq, Show)]
pub struct MultiSample;
    //sample_mask: u16,
    //alpha_to_coverage: bool,

/// A pixel-wise comparison function.
#[deriving(Clone, PartialEq, Show)]
pub enum Comparison {
    /// `false`
    Never,
    /// `x < y`
    Less,
    /// `x <= y`
    LessEqual,
    /// `x == y`
    Equal,
    /// `x >= y`
    GreaterEqual,
    /// `x > y`
    Greater,
    /// `x != y`
    NotEqual,
    /// `true`
    Always,
}

/// Stencil mask operation.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum StencilOp {
    /// Keep the current value in the stencil buffer (no change).
    OpKeep,
    /// Set the value in the stencil buffer to zero.
    OpZero,
    /// Set the stencil buffer value to `value` from `StencilSide`
    OpReplace,
    /// Increment the stencil buffer value, clamping to its maximum value.
    OpIncrementClamp,
    /// Increment the stencil buffer value, wrapping around to 0 on overflow.
    OpIncrementWrap,
    /// Decrement the stencil buffer value, clamping to its minimum value.
    OpDecrementClamp,
    /// Decrement the stencil buffer value, wrapping around to the maximum value on overflow.
    OpDecrementWrap,
    /// Bitwise invert the current value in the stencil buffer.
    OpInvert,
}

/// Complete stencil state for a given side of a face.
#[deriving(Clone, PartialEq, Show)]
pub struct StencilSide {
    /// Comparison function to use to determine if the stencil test passes.
    pub fun: Comparison,
    /// Reference value to compare the value in the stencil buffer with.
    pub value: target::Stencil,
    /// A mask that is ANDd with both the stencil buffer value and the reference value when they
    /// are read before doing the stencil test.
    pub mask_read: target::Stencil,
    /// A mask that is ANDd with the stencil value before writing to the stencil buffer.
    pub mask_write: target::Stencil,
    /// What operation to do if the stencil test fails.
    pub op_fail: StencilOp,
    /// What operation to do if the stenil test passes but the depth test fails.
    pub op_depth_fail: StencilOp,
    /// What operation to do if both the depth and stencil test pass.
    pub op_pass: StencilOp,
}

impl Default for StencilSide {
    fn default() -> StencilSide {
        StencilSide {
            fun: Always,
            value: 0,
            mask_read: -1,
            mask_write: -1,
            op_fail: OpKeep,
            op_depth_fail: OpKeep,
            op_pass: OpKeep,
        }
    }
}

/// Complete stencil state, specifying how to handle the front and back side of a face.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub struct Stencil {
    pub front: StencilSide,
    pub back: StencilSide,
}

/// Depth test state.
#[deriving(Clone, PartialEq, Show)]
pub struct Depth {
    /// Comparison function to use.
    pub fun: Comparison,
    /// Specify whether to write to the depth buffer or not.
    pub write: bool,
}

impl Default for Depth {
    fn default() -> Depth {
        Depth {
            fun: Always,
            write: false,
        }
    }
}

#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum Equation {
    FuncAdd,
    FuncSub,
    FuncRevSub,
    FuncMin,
    FuncMax,
}

#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum InverseFlag {
    Normal,
    Inverse,
}

#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum BlendValue {
    Zero,
    SourceColor,
    SourceAlpha,
    SourceAlphaSaturated,
    DestColor,
    DestAlpha,
    ConstColor,
    ConstAlpha,
}

#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub struct Factor(pub InverseFlag, pub BlendValue);

#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub struct BlendChannel {
    pub equation: Equation,
    pub source: Factor,
    pub destination: Factor,
}

impl Default for BlendChannel {
    fn default() -> BlendChannel {
        BlendChannel {
            equation: FuncAdd,
            source: Factor(Inverse, Zero),
            destination: Factor(Normal, Zero),
        }
    }
}

#[allow(missing_doc)]
pub struct Blend {
    pub color: BlendChannel,
    pub alpha: BlendChannel,
    pub value: ::target::ColorValue,
}

impl Default for Blend {
    fn default() -> Blend {
        Blend {
            color: Default::default(),
            alpha: Default::default(),
            value: [0.0, 0.0, 0.0, 0.0],
        }
    }
}

impl PartialEq for Blend {
    fn eq(&self, other: &Blend) -> bool {
        self.color == other.color &&
        self.alpha == other.alpha &&
        self.value == other.value
    }
}

impl Clone for Blend {
    fn clone(&self) -> Blend {
        Blend {
            color: self.color.clone(),
            alpha: self.alpha.clone(),
            value: self.value,
        }
    }
}

impl fmt::Show for Blend {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Blend {{ color: {}, alpha: {}, value: {} }}",
               self.color, self.alpha, self.value.as_slice())
    }
}

#[deriving(Clone, PartialEq)]
bitflags!(
    #[allow(missing_doc)]
    flags ColorMask: u32 {  //u8 is preferred, but doesn't seem to work well
        static Red     = 0x1,
        static Green   = 0x2,
        static Blue    = 0x4,
        static Alpha   = 0x8,
        static MaskAll = 0xF
    }
)

impl fmt::Show for ColorMask {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ColorMask({})", *self)
    }
}
<commit_msg>Fix stack overflow when formatting ColorMask<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Fixed-function hardware state.
//!
//! Configures the primitive assembly (PA), rasterizer, and output merger (OM) blocks.

use std::default::Default;
use std::fmt;

use target;

/// The winding order of a set of vertices.
#[deriving(Clone, PartialEq, Show)]
pub enum WindingOrder {
    /// Clockwise winding order.
    Clockwise,
    /// Counter-clockwise winding order.
    CounterClockwise,
}

/// Width of a line.
pub type LineWidth = f32;
#[allow(missing_doc)]
pub type OffsetFactor = f32;
#[allow(missing_doc)]
pub type OffsetUnits = u32;

/// How to offset vertices in screen space, if at all.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum OffsetType {
    NoOffset,
    Offset(OffsetFactor, OffsetUnits),
}

/// Which face, if any, to cull.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum CullMode {
    CullNothing,
    CullFront,
    CullBack,
}

/// How to rasterize a primitive.
#[deriving(Clone, PartialEq, Show)]
pub enum RasterMethod {
    /// Rasterize as a point.
    Point,
    /// Rasterize as a line with the given width.
    Line(LineWidth),
    /// Rasterize as a face with a given cull mode.
    Fill(CullMode),
}

/// Primitive rasterization state. Note that GL allows different raster
/// method to be used for front and back, while this abstraction does not.
#[deriving(Clone, PartialEq, Show)]
pub struct Primitive {
    /// Which vertex winding is considered to be the front face for culling.
    pub front_face: WindingOrder,
    /// How to rasterize this primitive.
    pub method: RasterMethod,
    /// Any polygon offset to apply.
    pub offset: OffsetType,
}

impl Primitive {
    /// Get the cull mode, if any, for this primitive state.
    pub fn get_cull_mode(&self) -> CullMode {
        match self.method {
            Fill(mode) => mode,
            _ => CullNothing,
        }
    }
}

impl Default for Primitive {
    fn default() -> Primitive {
        Primitive {
            front_face: CounterClockwise,
            method: Fill(CullNothing),
            offset: NoOffset,
        }
    }
}

/// Multi-sampling rasterization mode
#[deriving(Clone, PartialEq, Show)]
pub struct MultiSample;
    //sample_mask: u16,
    //alpha_to_coverage: bool,

/// A pixel-wise comparison function.
#[deriving(Clone, PartialEq, Show)]
pub enum Comparison {
    /// `false`
    Never,
    /// `x < y`
    Less,
    /// `x <= y`
    LessEqual,
    /// `x == y`
    Equal,
    /// `x >= y`
    GreaterEqual,
    /// `x > y`
    Greater,
    /// `x != y`
    NotEqual,
    /// `true`
    Always,
}

/// Stencil mask operation.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum StencilOp {
    /// Keep the current value in the stencil buffer (no change).
    OpKeep,
    /// Set the value in the stencil buffer to zero.
    OpZero,
    /// Set the stencil buffer value to `value` from `StencilSide`
    OpReplace,
    /// Increment the stencil buffer value, clamping to its maximum value.
    OpIncrementClamp,
    /// Increment the stencil buffer value, wrapping around to 0 on overflow.
    OpIncrementWrap,
    /// Decrement the stencil buffer value, clamping to its minimum value.
    OpDecrementClamp,
    /// Decrement the stencil buffer value, wrapping around to the maximum value on overflow.
    OpDecrementWrap,
    /// Bitwise invert the current value in the stencil buffer.
    OpInvert,
}

/// Complete stencil state for a given side of a face.
#[deriving(Clone, PartialEq, Show)]
pub struct StencilSide {
    /// Comparison function to use to determine if the stencil test passes.
    pub fun: Comparison,
    /// Reference value to compare the value in the stencil buffer with.
    pub value: target::Stencil,
    /// A mask that is ANDd with both the stencil buffer value and the reference value when they
    /// are read before doing the stencil test.
    pub mask_read: target::Stencil,
    /// A mask that is ANDd with the stencil value before writing to the stencil buffer.
    pub mask_write: target::Stencil,
    /// What operation to do if the stencil test fails.
    pub op_fail: StencilOp,
    /// What operation to do if the stenil test passes but the depth test fails.
    pub op_depth_fail: StencilOp,
    /// What operation to do if both the depth and stencil test pass.
    pub op_pass: StencilOp,
}

impl Default for StencilSide {
    fn default() -> StencilSide {
        StencilSide {
            fun: Always,
            value: 0,
            mask_read: -1,
            mask_write: -1,
            op_fail: OpKeep,
            op_depth_fail: OpKeep,
            op_pass: OpKeep,
        }
    }
}

/// Complete stencil state, specifying how to handle the front and back side of a face.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub struct Stencil {
    pub front: StencilSide,
    pub back: StencilSide,
}

/// Depth test state.
#[deriving(Clone, PartialEq, Show)]
pub struct Depth {
    /// Comparison function to use.
    pub fun: Comparison,
    /// Specify whether to write to the depth buffer or not.
    pub write: bool,
}

impl Default for Depth {
    fn default() -> Depth {
        Depth {
            fun: Always,
            write: false,
        }
    }
}

#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum Equation {
    FuncAdd,
    FuncSub,
    FuncRevSub,
    FuncMin,
    FuncMax,
}

#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum InverseFlag {
    Normal,
    Inverse,
}

#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum BlendValue {
    Zero,
    SourceColor,
    SourceAlpha,
    SourceAlphaSaturated,
    DestColor,
    DestAlpha,
    ConstColor,
    ConstAlpha,
}

#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub struct Factor(pub InverseFlag, pub BlendValue);

#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub struct BlendChannel {
    pub equation: Equation,
    pub source: Factor,
    pub destination: Factor,
}

impl Default for BlendChannel {
    fn default() -> BlendChannel {
        BlendChannel {
            equation: FuncAdd,
            source: Factor(Inverse, Zero),
            destination: Factor(Normal, Zero),
        }
    }
}

#[allow(missing_doc)]
pub struct Blend {
    pub color: BlendChannel,
    pub alpha: BlendChannel,
    pub value: ::target::ColorValue,
}

impl Default for Blend {
    fn default() -> Blend {
        Blend {
            color: Default::default(),
            alpha: Default::default(),
            value: [0.0, 0.0, 0.0, 0.0],
        }
    }
}

impl PartialEq for Blend {
    fn eq(&self, other: &Blend) -> bool {
        self.color == other.color &&
        self.alpha == other.alpha &&
        self.value == other.value
    }
}

impl Clone for Blend {
    fn clone(&self) -> Blend {
        Blend {
            color: self.color.clone(),
            alpha: self.alpha.clone(),
            value: self.value,
        }
    }
}

impl fmt::Show for Blend {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Blend {{ color: {}, alpha: {}, value: {} }}",
               self.color, self.alpha, self.value.as_slice())
    }
}

#[deriving(Clone, PartialEq)]
bitflags!(
    #[allow(missing_doc)]
    flags ColorMask: u32 {  //u8 is preferred, but doesn't seem to work well
        static Red     = 0x1,
        static Green   = 0x2,
        static Blue    = 0x4,
        static Alpha   = 0x8,
        static MaskAll = 0xF
    }
)

impl fmt::Show for ColorMask {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let values = [
            (Red,   "Red"  ),
            (Green, "Green"),
            (Blue,  "Blue" ),
            (Alpha, "Alpha"),
        ];

        try!(write!(f, "ColorMask("));
        for (i, &(_, name)) in values.iter()
            .filter(|&&(flag, _)| self.contains(flag))
            .enumerate()
        {
            if i == 0 {
                try!(write!(f, "{}", name))
            } else {
                try!(write!(f, " | {}", name))
            }
        }
        try!(write!(f, ")"));

        Ok(())
    }
}
<|endoftext|>


<commit_before>mod structs;

pub use self::{generation::gen_frame, parsing::parse_frame, structs::*};

pub use crate::types::{
    generation::{BackToTheBuffer, GenError, GenResult, SerializeFn},
    parsing::{ParserError, ParserResult},
};
pub use cookie_factory::WriteContext;
pub use nom::Offset;

/// Serialization utils
pub mod generation;
/// Parsing utils
pub mod parsing;
<commit_msg>don't reexport Offset<commit_after>mod structs;

pub use self::{generation::gen_frame, parsing::parse_frame, structs::*};

pub use crate::types::{
    generation::{BackToTheBuffer, GenError, GenResult, SerializeFn},
    parsing::{ParserError, ParserResult},
};
pub use cookie_factory::WriteContext;

/// Serialization utils
pub mod generation;
/// Parsing utils
pub mod parsing;
<|endoftext|>


<commit_before>// The size of an ELF header tag, in bytes. This was calculated
// from reading the ELF format specification.
const ELF_SECTION_HEADER_SIZE: u64 = 64;

#[derive(Debug)]
#[repr(C, packed)]
pub struct ElfSectionTag {
    tag_type: u32,
    size: u32,
    num: u32,
    entsize: u32,
    shndx: u16,
    reserved: u16,
    first_section: ElfSectionHeader
}

impl ElfSectionTag {
    pub fn elf_sections(&'static self) -> ElfSectionIter {
        ElfSectionIter {
            current_section: &self.first_section,
            section_index: 0,
            total_sections: self.num as u32,
            entry_size: self.entsize as u64
        }
    }

    pub fn section_count(&self) -> usize {
        self.num as usize
    }

    pub fn size(&self) -> usize {
        self.size as usize
    }

    pub fn entry_size(&self) -> usize {
        self.entsize as usize
    }
}

#[derive(Debug)]
#[repr(C)]
pub struct ElfSectionHeader {
    sh_name: u32,
    sh_type: u32,
    sh_flags: u64,
    sh_addr: u64,
    sh_offset: u64,
    sh_size: u64,
    sh_link: u32,
    sh_info: u32,
    sh_addralign: u64,
    sh_entsize: u64
}

impl ElfSectionHeader {
    /// The type of an ELF section.
    pub fn section_type(&self) -> usize {
        self.sh_type as usize
    }

    /// The start address of an ELF section.
    pub fn section_start_address(&self) -> usize {
        self.sh_addr as usize
    }

    /// The end address of an ELF section.
    pub fn section_end_address(&self) -> usize {
        (self.sh_addr + self.sh_size) as usize
    }

    /// The size of an ELF section in bytes.
    pub fn size_bytes(&self) -> usize {
        self.sh_size as usize
    }

    /// ELF section flags.
    pub fn flags(&self) -> usize {
        self.sh_flags as usize
    }

    /// The size of an ELF header entry.
    pub fn entry_size(&self) -> usize {
        self.sh_entsize as usize
    }
}

pub struct ElfSectionIter {
    current_section: &'static ElfSectionHeader,
    section_index: u32,
    total_sections: u32,
    entry_size: u64
}

impl Iterator for ElfSectionIter {
    type Item = &'static ElfSectionHeader;

    fn next(&mut self) -> Option<Self::Item> {
        if self.section_index >= self.total_sections {
            return None;
        } else {
            let section = self.current_section;
            let next_section_addr =
                (self.current_section as *const ElfSectionHeader as u64) + self.entry_size;
            let next_section = unsafe {
                &*(next_section_addr as *const ElfSectionHeader)
            };

            self.current_section = next_section;
            self.section_index += 1;

            Some(section)
        }
    }
}

<commit_msg>Implement String table support.<commit_after>use core::{slice, str};

// The size of an ELF header tag, in bytes. This was calculated
// from reading the ELF format specification.
const ELF_SECTION_HEADER_SIZE: u64 = 64;

#[derive(Debug)]
#[repr(C, packed)]
pub struct ElfSectionTag {
    tag_type: u32,
    size: u32,
    num: u32,
    entsize: u32,
    shndx: u16,
    reserved: u16,
    first_section: ElfSectionHeader
}

impl ElfSectionTag {
    pub fn elf_sections(&'static self) -> ElfSectionIter {
        ElfSectionIter {
            current_section: &self.first_section,
            section_index: 0,
            total_sections: self.num as u32,
            entry_size: self.entsize as u64
        }
    }

    pub fn section_count(&self) -> usize {
        self.num as usize
    }

    pub fn size(&self) -> usize {
        self.size as usize
    }

    pub fn entry_size(&self) -> usize {
        self.entsize as usize
    }

    pub fn string_table_index(&self) -> usize {
        self.shndx as usize
    }

    pub fn string_table(&self) -> &'static StringTable {
        let string_table_header = unsafe {
            (&self.first_section as *const ElfSectionHeader).offset(self.shndx as isize)
        };

        let string_table_ptr = unsafe {
            &*((*string_table_header).section_start_address() as *const StringTable)
        };

        string_table_ptr
    }
}

#[derive(Debug)]
#[repr(C)]
pub struct ElfSectionHeader {
    sh_name: u32,
    sh_type: u32,
    sh_flags: u64,
    sh_addr: u64,
    sh_offset: u64,
    sh_size: u64,
    sh_link: u32,
    sh_info: u32,
    sh_addralign: u64,
    sh_entsize: u64
}

impl ElfSectionHeader {
    /// The type of an ELF section.
    pub fn section_type(&self) -> usize {
        self.sh_type as usize
    }

    /// The start address of an ELF section.
    pub fn section_start_address(&self) -> usize {
        self.sh_addr as usize
    }

    /// The end address of an ELF section.
    pub fn section_end_address(&self) -> usize {
        (self.sh_addr + self.sh_size) as usize
    }

    /// The size of an ELF section in bytes.
    pub fn size_bytes(&self) -> usize {
        self.sh_size as usize
    }

    /// ELF section flags.
    pub fn flags(&self) -> usize {
        self.sh_flags as usize
    }

    /// The size of an ELF header entry.
    pub fn entry_size(&self) -> usize {
        self.sh_entsize as usize
    }
}

pub struct ElfSectionIter {
    current_section: &'static ElfSectionHeader,
    section_index: u32,
    total_sections: u32,
    entry_size: u64
}

impl Iterator for ElfSectionIter {
    type Item = &'static ElfSectionHeader;

    fn next(&mut self) -> Option<Self::Item> {
        if self.section_index >= self.total_sections {
            return None;
        } else {
            let section = self.current_section;
            let next_section_addr =
                (self.current_section as *const ElfSectionHeader as u64) + self.entry_size;
            let next_section = unsafe {
                &*(next_section_addr as *const ElfSectionHeader)
            };

            self.current_section = next_section;
            self.section_index += 1;

            Some(section)
        }
    }
}

pub struct StringTable {
    first_char: u8
}

impl StringTable {
    fn section_name(&self, section: &ElfSectionHeader) -> &'static str {
        let string_ptr = unsafe {
            (&self.first_char as *const u8).offset(section.sh_name as isize)
        };

        let string_length = unsafe {
            let mut length = 0;
            let mut current_char = self.first_char;

            while current_char != 0x00 {
                length += 1;
                current_char = *string_ptr.offset(length as isize);
            }

            length
        };

        let string_slice = unsafe {
            slice::from_raw_parts(string_ptr, string_length)
        };

        str::from_utf8(string_slice).unwrap()
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

//! A first person camera.

use input::{ self, Button, GenericEvent };
use vecmath::traits::{ Float, Radians };

use Camera;

bitflags!(flags Keys: u8 {
    const MOVE_FORWARD  = 0b00000001,
    const MOVE_BACKWARD = 0b00000010,
    const STRAFE_LEFT   = 0b00000100,
    const STRAFE_RIGHT  = 0b00001000,
    const FLY_UP        = 0b00010000,
    const FLY_DOWN      = 0b00100000
});

/// First person camera settings.
pub struct FirstPersonSettings<T=f32> {
    /// Which button to press to move forward.
    pub move_forward_button: input::Button,
    /// Which button to press to move backward.
    pub move_backward_button: input::Button,
    /// Which button to press to strafe left.
    pub strafe_left_button: input::Button,
    /// Which button to press to strafe right.
    pub strafe_right_button: input::Button,
    /// Which button to press to fly up.
    pub fly_up_button: input::Button,
    /// Which button to press to fly down.
    pub fly_down_button: input::Button,
    /// Which button to press to move faster.
    pub move_faster_button: input::Button,
    /// The horizontal movement speed.
    ///
    /// This is measured in units per second.
    pub speed_horizontal: T,
    /// The vertical movement speed.
    ///
    /// This is measured in units per second.
    pub speed_vertical: T,
}

impl<T> FirstPersonSettings<T>
    where T: Float
{
    /// Creates new first person camera settings with wasd defaults.
    pub fn keyboard_wasd() -> FirstPersonSettings<T> {
        use input::Button::Keyboard;
        use input::Key;

        FirstPersonSettings {
            move_forward_button: Keyboard(Key::W),
            move_backward_button: Keyboard(Key::S),
            strafe_left_button: Keyboard(Key::A),
            strafe_right_button: Keyboard(Key::D),
            fly_up_button: Keyboard(Key::Space),
            fly_down_button: Keyboard(Key::LShift),
            move_faster_button: Keyboard(Key::LCtrl),
            speed_horizontal: T::one(),
            speed_vertical: T::one(),
        }
    }

    /// Creates a new first person camera settings with esdf defaults.
    pub fn keyboard_esdf() -> FirstPersonSettings<T> {
        use input::Button::Keyboard;
        use input::Key;

        FirstPersonSettings {
            move_forward_button: Keyboard(Key::E),
            move_backward_button: Keyboard(Key::D),
            strafe_left_button: Keyboard(Key::S),
            strafe_right_button: Keyboard(Key::F),
            fly_up_button: Keyboard(Key::Space),
            fly_down_button: Keyboard(Key::Z),
            move_faster_button: Keyboard(Key::LShift),
            speed_horizontal: T::one(),
            speed_vertical: T::one(),
        }
    }
}

/// Models a flying first person camera.
pub struct FirstPerson<T=f32> {
    /// The first person camera settings.
    pub settings: FirstPersonSettings<T>,
    /// The yaw angle (in radians).
    pub yaw: T,
    /// The pitch angle (in radians).
    pub pitch: T,
    /// The direction we are heading.
    pub direction: [T; 3],
    /// The position of the camera.
    pub position: [T; 3],
    /// The velocity we are moving in the direction.
    pub velocity: T,
    /// The keys that are pressed.
    keys: Keys,
}

impl<T> FirstPerson<T>
    where T: Float
{
    /// Creates a new first person camera.
    pub fn new(
        position: [T; 3],
        settings: FirstPersonSettings<T>
    ) -> FirstPerson<T> {
        let _0: T = T::zero();
        FirstPerson {
            settings: settings,
            yaw: _0,
            pitch: _0,
            keys: Keys::empty(),
            direction: [_0, _0, _0],
            position: position,
            velocity: T::one(),
        }
    }

    /// Computes camera.
    pub fn camera(&self, dt: f64) -> Camera<T> {
        let dt = T::from_f64(dt);
        let dh = dt * self.velocity * self.settings.speed_horizontal;
        let (dx, dy, dz) = (self.direction[0], self.direction[1], self.direction[2]);
        let (s, c) = (self.yaw.sin(), self.yaw.cos());
        let mut camera = Camera::new([
            self.position[0] + (s * dx - c * dz) * dh,
            self.position[1] + dy * dt * self.settings.speed_vertical,
            self.position[2] + (s * dz + c * dx) * dh
        ]);
        camera.set_yaw_pitch(self.yaw, self.pitch);
        camera
    }

    /// Handles game event and updates camera.
    pub fn event<E>(&mut self, e: &E) where E: GenericEvent {
        use input::{ MouseRelativeEvent, PressEvent, ReleaseEvent, UpdateEvent };

        e.update(|args| {
            let cam = self.camera(args.dt);
            self.position = cam.position;
        });

        let &mut FirstPerson {
            ref mut yaw,
            ref mut pitch,
            ref mut keys,
            ref mut direction,
            ref mut velocity,
            ref settings,
            ..
        } = self;

        let pi: T = Radians::_180();

        let _0 = T::zero();
        let _1 = T::one();
        let _2 =  _1 + _1;
        let _3 = _2 + _1;
        let _4 = _3 + _1;
        let _360 = T::from_isize(360);
        let sqrt2 = _2.sqrt();

        e.mouse_relative(|dx, dy| {

            let dx = T::from_f64(dx);
            let dy = T::from_f64(dy);

            *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
            *pitch = *pitch + dy / _360 * pi / _4;
            *pitch = (*pitch).min(pi / _2).max(-pi / _2);
        });
        e.press(|button| {
            let (dx, dy, dz) = (direction[0], direction[1], direction[2]);
            let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
            let mut set = |k, x: T, y: T, z: T| {
                let (x, z) = (sgn(x), sgn(z));
                let (x, z) = if x != _0 && z != _0 {
                    (x / sqrt2, z / sqrt2)
                } else {
                    (x, z)
                };
                *direction = [x, y, z];
                keys.insert(k);
            };
            match button {
                x if x == settings.move_forward_button =>
                    set(MOVE_FORWARD, -_1, dy, dz),
                x if x == settings.move_backward_button =>
                    set(MOVE_BACKWARD, _1, dy, dz),
                x if x == settings.strafe_left_button =>
                    set(STRAFE_LEFT, dx, dy, _1),
                x if x == settings.strafe_right_button =>
                    set(STRAFE_RIGHT, dx, dy, -_1),
                x if x == settings.fly_up_button =>
                    set(FLY_UP, dx, _1, dz),
                x if x == settings.fly_down_button =>
                    set(FLY_DOWN, dx, -_1, dz),
                x if x == settings.move_faster_button => *velocity = _2,
                _ => {}
            }
        });
        e.release(|button| {
            let (dx, dy, dz) = (direction[0], direction[1], direction[2]);
            let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
            let mut set = |x: T, y: T, z: T| {
                let (x, z) = (sgn(x), sgn(z));
                let (x, z) = if x != _0 && z != _0 {
                    (x / sqrt2, z / sqrt2)
                } else {
                    (x, z)
                };
                *direction = [x, y, z];
            };
            let mut release = |key, rev_key, rev_val| {
                keys.remove(key);
                if keys.contains(rev_key) { rev_val } else { _0 }
            };
            match button {
                x if x == settings.move_forward_button =>
                    set(release(MOVE_FORWARD, MOVE_BACKWARD, _1), dy, dz),
                x if x == settings.move_backward_button =>
                    set(release(MOVE_BACKWARD, MOVE_FORWARD, -_1), dy, dz),
                x if x == settings.strafe_left_button =>
                    set(dx, dy, release(STRAFE_LEFT, STRAFE_RIGHT, -_1)),
                x if x == settings.strafe_right_button =>
                    set(dx, dy, release(STRAFE_RIGHT, STRAFE_LEFT, _1)),
                x if x == settings.fly_up_button =>
                    set(dx, release(FLY_UP, FLY_DOWN, -_1), dz),
                x if x == settings.fly_down_button =>
                    set(dx, release(FLY_DOWN, FLY_UP, _1), dz),
                x if x == settings.move_faster_button => *velocity = _1,
                _ => {}
            }
        });
    }
}
<commit_msg>Add keyboard_zqsd() for azerty keyboard layout<commit_after>#![allow(dead_code)]

//! A first person camera.

use input::{ self, Button, GenericEvent };
use vecmath::traits::{ Float, Radians };

use Camera;

bitflags!(flags Keys: u8 {
    const MOVE_FORWARD  = 0b00000001,
    const MOVE_BACKWARD = 0b00000010,
    const STRAFE_LEFT   = 0b00000100,
    const STRAFE_RIGHT  = 0b00001000,
    const FLY_UP        = 0b00010000,
    const FLY_DOWN      = 0b00100000
});

/// First person camera settings.
pub struct FirstPersonSettings<T=f32> {
    /// Which button to press to move forward.
    pub move_forward_button: input::Button,
    /// Which button to press to move backward.
    pub move_backward_button: input::Button,
    /// Which button to press to strafe left.
    pub strafe_left_button: input::Button,
    /// Which button to press to strafe right.
    pub strafe_right_button: input::Button,
    /// Which button to press to fly up.
    pub fly_up_button: input::Button,
    /// Which button to press to fly down.
    pub fly_down_button: input::Button,
    /// Which button to press to move faster.
    pub move_faster_button: input::Button,
    /// The horizontal movement speed.
    ///
    /// This is measured in units per second.
    pub speed_horizontal: T,
    /// The vertical movement speed.
    ///
    /// This is measured in units per second.
    pub speed_vertical: T,
}

impl<T> FirstPersonSettings<T>
    where T: Float
{
    /// Creates new first person camera settings with wasd defaults.
    pub fn keyboard_wasd() -> FirstPersonSettings<T> {
        use input::Button::Keyboard;
        use input::Key;

        FirstPersonSettings {
            move_forward_button: Keyboard(Key::W),
            move_backward_button: Keyboard(Key::S),
            strafe_left_button: Keyboard(Key::A),
            strafe_right_button: Keyboard(Key::D),
            fly_up_button: Keyboard(Key::Space),
            fly_down_button: Keyboard(Key::LShift),
            move_faster_button: Keyboard(Key::LCtrl),
            speed_horizontal: T::one(),
            speed_vertical: T::one(),
        }
    }

    /// Creates a new first person camera settings with esdf defaults.
    pub fn keyboard_esdf() -> FirstPersonSettings<T> {
        use input::Button::Keyboard;
        use input::Key;

        FirstPersonSettings {
            move_forward_button: Keyboard(Key::E),
            move_backward_button: Keyboard(Key::D),
            strafe_left_button: Keyboard(Key::S),
            strafe_right_button: Keyboard(Key::F),
            fly_up_button: Keyboard(Key::Space),
            fly_down_button: Keyboard(Key::Z),
            move_faster_button: Keyboard(Key::LShift),
            speed_horizontal: T::one(),
            speed_vertical: T::one(),
        }
    }

    /// Creates new first person camera settings with zqsd defaults (azerty keyboard layout).
    pub fn keyboard_zqsd() -> FirstPersonSettings<T> {
        use input::Button::Keyboard;
        use input::Key;

        FirstPersonSettings {
            move_forward_button: Keyboard(Key::Z),
            move_backward_button: Keyboard(Key::S),
            strafe_left_button: Keyboard(Key::Q),
            strafe_right_button: Keyboard(Key::D),
            fly_up_button: Keyboard(Key::Space),
            fly_down_button: Keyboard(Key::LShift),
            move_faster_button: Keyboard(Key::LCtrl),
            speed_horizontal: T::one(),
            speed_vertical: T::one(),
        }
    }
}

/// Models a flying first person camera.
pub struct FirstPerson<T=f32> {
    /// The first person camera settings.
    pub settings: FirstPersonSettings<T>,
    /// The yaw angle (in radians).
    pub yaw: T,
    /// The pitch angle (in radians).
    pub pitch: T,
    /// The direction we are heading.
    pub direction: [T; 3],
    /// The position of the camera.
    pub position: [T; 3],
    /// The velocity we are moving in the direction.
    pub velocity: T,
    /// The keys that are pressed.
    keys: Keys,
}

impl<T> FirstPerson<T>
    where T: Float
{
    /// Creates a new first person camera.
    pub fn new(
        position: [T; 3],
        settings: FirstPersonSettings<T>
    ) -> FirstPerson<T> {
        let _0: T = T::zero();
        FirstPerson {
            settings: settings,
            yaw: _0,
            pitch: _0,
            keys: Keys::empty(),
            direction: [_0, _0, _0],
            position: position,
            velocity: T::one(),
        }
    }

    /// Computes camera.
    pub fn camera(&self, dt: f64) -> Camera<T> {
        let dt = T::from_f64(dt);
        let dh = dt * self.velocity * self.settings.speed_horizontal;
        let (dx, dy, dz) = (self.direction[0], self.direction[1], self.direction[2]);
        let (s, c) = (self.yaw.sin(), self.yaw.cos());
        let mut camera = Camera::new([
            self.position[0] + (s * dx - c * dz) * dh,
            self.position[1] + dy * dt * self.settings.speed_vertical,
            self.position[2] + (s * dz + c * dx) * dh
        ]);
        camera.set_yaw_pitch(self.yaw, self.pitch);
        camera
    }

    /// Handles game event and updates camera.
    pub fn event<E>(&mut self, e: &E) where E: GenericEvent {
        use input::{ MouseRelativeEvent, PressEvent, ReleaseEvent, UpdateEvent };

        e.update(|args| {
            let cam = self.camera(args.dt);
            self.position = cam.position;
        });

        let &mut FirstPerson {
            ref mut yaw,
            ref mut pitch,
            ref mut keys,
            ref mut direction,
            ref mut velocity,
            ref settings,
            ..
        } = self;

        let pi: T = Radians::_180();

        let _0 = T::zero();
        let _1 = T::one();
        let _2 =  _1 + _1;
        let _3 = _2 + _1;
        let _4 = _3 + _1;
        let _360 = T::from_isize(360);
        let sqrt2 = _2.sqrt();

        e.mouse_relative(|dx, dy| {

            let dx = T::from_f64(dx);
            let dy = T::from_f64(dy);

            *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
            *pitch = *pitch + dy / _360 * pi / _4;
            *pitch = (*pitch).min(pi / _2).max(-pi / _2);
        });
        e.press(|button| {
            let (dx, dy, dz) = (direction[0], direction[1], direction[2]);
            let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
            let mut set = |k, x: T, y: T, z: T| {
                let (x, z) = (sgn(x), sgn(z));
                let (x, z) = if x != _0 && z != _0 {
                    (x / sqrt2, z / sqrt2)
                } else {
                    (x, z)
                };
                *direction = [x, y, z];
                keys.insert(k);
            };
            match button {
                x if x == settings.move_forward_button =>
                    set(MOVE_FORWARD, -_1, dy, dz),
                x if x == settings.move_backward_button =>
                    set(MOVE_BACKWARD, _1, dy, dz),
                x if x == settings.strafe_left_button =>
                    set(STRAFE_LEFT, dx, dy, _1),
                x if x == settings.strafe_right_button =>
                    set(STRAFE_RIGHT, dx, dy, -_1),
                x if x == settings.fly_up_button =>
                    set(FLY_UP, dx, _1, dz),
                x if x == settings.fly_down_button =>
                    set(FLY_DOWN, dx, -_1, dz),
                x if x == settings.move_faster_button => *velocity = _2,
                _ => {}
            }
        });
        e.release(|button| {
            let (dx, dy, dz) = (direction[0], direction[1], direction[2]);
            let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
            let mut set = |x: T, y: T, z: T| {
                let (x, z) = (sgn(x), sgn(z));
                let (x, z) = if x != _0 && z != _0 {
                    (x / sqrt2, z / sqrt2)
                } else {
                    (x, z)
                };
                *direction = [x, y, z];
            };
            let mut release = |key, rev_key, rev_val| {
                keys.remove(key);
                if keys.contains(rev_key) { rev_val } else { _0 }
            };
            match button {
                x if x == settings.move_forward_button =>
                    set(release(MOVE_FORWARD, MOVE_BACKWARD, _1), dy, dz),
                x if x == settings.move_backward_button =>
                    set(release(MOVE_BACKWARD, MOVE_FORWARD, -_1), dy, dz),
                x if x == settings.strafe_left_button =>
                    set(dx, dy, release(STRAFE_LEFT, STRAFE_RIGHT, -_1)),
                x if x == settings.strafe_right_button =>
                    set(dx, dy, release(STRAFE_RIGHT, STRAFE_LEFT, _1)),
                x if x == settings.fly_up_button =>
                    set(dx, release(FLY_UP, FLY_DOWN, -_1), dz),
                x if x == settings.fly_down_button =>
                    set(dx, release(FLY_DOWN, FLY_UP, _1), dz),
                x if x == settings.move_faster_button => *velocity = _1,
                _ => {}
            }
        });
    }
}
<|endoftext|>