<commit_before>/*
 * Copyright (c) 2014, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;

use capnp::capability::{FromServer, Server};
use capnp::list::{PrimitiveList};
use capnp::message::{MallocMessageBuilder, MessageBuilder};

use capnp_rpc::capability::{InitRequest, WaitForContent};
use capnp_rpc::ez_rpc::EzRpcServer;

use calculator_capnp::Calculator;

struct ValueImpl {
    value : f64
}

impl ValueImpl {
    fn new(value : f64) -> ValueImpl {
        ValueImpl { value : value }
    }
}

impl Calculator::Value::Server for ValueImpl {
    fn read(&mut self, mut context : Calculator::Value::ReadContext) {
        let (_, results) = context.get();
        results.set_value(self.value);
        context.done();
    }
}

fn evaluate_impl(
    expression : Calculator::Expression::Reader,
    params : Option<PrimitiveList::Reader<f64>>) -> f64 {

    match expression.which() {
        Some(Calculator::Expression::Literal(v)) => {
            v
        },
        Some(Calculator::Expression::PreviousResult(p)) => {
            p.read_request().send().wait().get_value()
        }
        Some(Calculator::Expression::Parameter(p)) => {
            match params {
                None => {fail!()}
                Some(params) => {
                    params[p as uint]
                }
            }
        }
        Some(Calculator::Expression::Call(call)) => {
            let func = call.get_function();
            let call_params = call.get_params();
            let mut param_values = ~[];
            for ii in range(0, call_params.size()) {
                param_values.push(evaluate_impl(call_params[ii], params));
            }
            let mut request = func.call_request();
            let request_params = request.init().init_params(param_values.len());
            for ii in range(0, param_values.len()) {
                request_params.set(ii, param_values[ii]);
            }
            return request.send().wait().get_value();
        }
        None => fail!("unsupported expression"),
    }
}

struct FunctionImpl {
    param_count : uint,
    body : MallocMessageBuilder,
}

impl FunctionImpl {
    fn new(param_count : uint, body : Calculator::Expression::Reader) -> FunctionImpl {
        let mut result = FunctionImpl { param_count : param_count, body : MallocMessageBuilder::new_default() };
        result.body.set_root(&body.reader);
        result
    }
}

impl Calculator::Function::Server for FunctionImpl {
    fn call(&mut self, mut context : Calculator::Function::CallContext) {
        let (params, results) = context.get();
        assert!(params.get_params().size() == self.param_count,
                "Wrong number of parameters.");

        {
            let expression = self.body.get_root::<Calculator::Expression::Builder>().as_reader();
            results.set_value(evaluate_impl(expression, Some(params.get_params())));
        }
        context.done();
    }
}

pub struct OperatorImpl {
    op : Calculator::Operator::Reader,
}

impl Calculator::Function::Server for OperatorImpl {
    fn call(&mut self, mut context : Calculator::Function::CallContext) {
        let (params, results) = context.get();
        let params = params.get_params();
        assert!(params.size() == 2, "Wrong number of parameters.");

        let result = match self.op {
            Calculator::Operator::Add => params[0] + params[1],
            Calculator::Operator::Subtract => params[0] - params[1],
            Calculator::Operator::Multiply => params[0] * params[1],
            Calculator::Operator::Divide => params[0] / params[1],
        };

        results.set_value(result);
        context.done();
    }
}

struct CalculatorImpl;

impl Calculator::Server for CalculatorImpl {
    fn evaluate(&mut self, mut context : Calculator::EvaluateContext) {
        let (params, results) = context.get();
        results.set_value(
            FromServer::new(
                None::<EzRpcServer>,
                ~ValueImpl::new(evaluate_impl(params.get_expression(), None))));
        context.done();
    }
    fn def_function(&mut self, mut context : Calculator::DefFunctionContext) {
        let (params, results) = context.get();
        results.set_func(
            FromServer::new(
                None::<EzRpcServer>,
                ~FunctionImpl::new(params.get_param_count() as uint, params.get_body())));
    }
    fn get_operator(&mut self, mut context : Calculator::GetOperatorContext) {
        let (params, results) = context.get();
        results.set_func(
            match params.get_op() {
                Some(op) => {
                    FromServer::new(
                        None::<EzRpcServer>,
                        ~OperatorImpl {op : op})
                }
                None => fail!("Unknown operator."),
            });
        context.done();
    }
}

pub fn main() {
    let args = std::os::args();
    if args.len() != 3 {
        println!("usage: {} server ADDRESS[:PORT]", args[0]);
        return;
    }

    let rpc_server = EzRpcServer::new(args[2]).unwrap();

    // There's got to be a better way to do this.
    let calculator = (~Calculator::ServerDispatch { server : ~CalculatorImpl}) as ~Server;
    rpc_server.export_cap("calculator", calculator);

}
<commit_msg>call context.done() in def_function()<commit_after>/*
 * Copyright (c) 2014, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;

use capnp::capability::{FromServer, Server};
use capnp::list::{PrimitiveList};
use capnp::message::{MallocMessageBuilder, MessageBuilder};

use capnp_rpc::capability::{InitRequest, WaitForContent};
use capnp_rpc::ez_rpc::EzRpcServer;

use calculator_capnp::Calculator;

struct ValueImpl {
    value : f64
}

impl ValueImpl {
    fn new(value : f64) -> ValueImpl {
        ValueImpl { value : value }
    }
}

impl Calculator::Value::Server for ValueImpl {
    fn read(&mut self, mut context : Calculator::Value::ReadContext) {
        let (_, results) = context.get();
        results.set_value(self.value);
        context.done();
    }
}

fn evaluate_impl(
    expression : Calculator::Expression::Reader,
    params : Option<PrimitiveList::Reader<f64>>) -> f64 {

    match expression.which() {
        Some(Calculator::Expression::Literal(v)) => {
            v
        },
        Some(Calculator::Expression::PreviousResult(p)) => {
            p.read_request().send().wait().get_value()
        }
        Some(Calculator::Expression::Parameter(p)) => {
            match params {
                None => {fail!()}
                Some(params) => {
                    params[p as uint]
                }
            }
        }
        Some(Calculator::Expression::Call(call)) => {
            let func = call.get_function();
            let call_params = call.get_params();
            let mut param_values = ~[];
            for ii in range(0, call_params.size()) {
                param_values.push(evaluate_impl(call_params[ii], params));
            }
            let mut request = func.call_request();
            let request_params = request.init().init_params(param_values.len());
            for ii in range(0, param_values.len()) {
                request_params.set(ii, param_values[ii]);
            }
            return request.send().wait().get_value();
        }
        None => fail!("unsupported expression"),
    }
}

struct FunctionImpl {
    param_count : uint,
    body : MallocMessageBuilder,
}

impl FunctionImpl {
    fn new(param_count : uint, body : Calculator::Expression::Reader) -> FunctionImpl {
        let mut result = FunctionImpl { param_count : param_count, body : MallocMessageBuilder::new_default() };
        result.body.set_root(&body.reader);
        result
    }
}

impl Calculator::Function::Server for FunctionImpl {
    fn call(&mut self, mut context : Calculator::Function::CallContext) {
        let (params, results) = context.get();
        assert!(params.get_params().size() == self.param_count,
                "Wrong number of parameters.");

        {
            let expression = self.body.get_root::<Calculator::Expression::Builder>().as_reader();
            results.set_value(evaluate_impl(expression, Some(params.get_params())));
        }
        context.done();
    }
}

pub struct OperatorImpl {
    op : Calculator::Operator::Reader,
}

impl Calculator::Function::Server for OperatorImpl {
    fn call(&mut self, mut context : Calculator::Function::CallContext) {
        let (params, results) = context.get();
        let params = params.get_params();
        assert!(params.size() == 2, "Wrong number of parameters.");

        let result = match self.op {
            Calculator::Operator::Add => params[0] + params[1],
            Calculator::Operator::Subtract => params[0] - params[1],
            Calculator::Operator::Multiply => params[0] * params[1],
            Calculator::Operator::Divide => params[0] / params[1],
        };

        results.set_value(result);
        context.done();
    }
}

struct CalculatorImpl;

impl Calculator::Server for CalculatorImpl {
    fn evaluate(&mut self, mut context : Calculator::EvaluateContext) {
        let (params, results) = context.get();
        results.set_value(
            FromServer::new(
                None::<EzRpcServer>,
                ~ValueImpl::new(evaluate_impl(params.get_expression(), None))));
        context.done();
    }
    fn def_function(&mut self, mut context : Calculator::DefFunctionContext) {
        let (params, results) = context.get();
        results.set_func(
            FromServer::new(
                None::<EzRpcServer>,
                ~FunctionImpl::new(params.get_param_count() as uint, params.get_body())));
        context.done();
    }
    fn get_operator(&mut self, mut context : Calculator::GetOperatorContext) {
        let (params, results) = context.get();
        results.set_func(
            match params.get_op() {
                Some(op) => {
                    FromServer::new(
                        None::<EzRpcServer>,
                        ~OperatorImpl {op : op})
                }
                None => fail!("Unknown operator."),
            });
        context.done();
    }
}

pub fn main() {
    let args = std::os::args();
    if args.len() != 3 {
        println!("usage: {} server ADDRESS[:PORT]", args[0]);
        return;
    }

    let rpc_server = EzRpcServer::new(args[2]).unwrap();

    // There's got to be a better way to do this.
    let calculator = (~Calculator::ServerDispatch { server : ~CalculatorImpl}) as ~Server;
    rpc_server.export_cap("calculator", calculator);

}
<|endoftext|>


<commit_before>//! A simplified implementation of the `bytes` crate, with different features, less safety.
//!
//! #Examples
//!
//! ```
//! use timely_bytes::rc::Bytes;
//!
//! let bytes = vec![0u8; 1024];
//! let mut shared1 = Bytes::from(bytes);
//! let mut shared2 = shared1.extract_to(100);
//! let mut shared3 = shared1.extract_to(100);
//! let mut shared4 = shared2.extract_to(60);
//!
//! assert_eq!(shared1.len(), 824);
//! assert_eq!(shared2.len(), 40);
//! assert_eq!(shared3.len(), 100);
//! assert_eq!(shared4.len(), 60);
//!
//! for byte in shared1.iter_mut() { *byte = 1u8; }
//! for byte in shared2.iter_mut() { *byte = 2u8; }
//! for byte in shared3.iter_mut() { *byte = 3u8; }
//! for byte in shared4.iter_mut() { *byte = 4u8; }
//!
//! drop(shared1);
//! drop(shared2);
//! drop(shared3);
//!
//! if let Ok(bytes) = shared4.try_recover::<Vec<u8>>() {
//!     assert_eq!(bytes[200..1024].to_vec(), [1u8;824].to_vec());
//!     assert_eq!(bytes[60..100].to_vec(),   [2u8;40].to_vec());
//!     assert_eq!(bytes[100..200].to_vec(),  [3u8;100].to_vec());
//!     assert_eq!(bytes[0..60].to_vec(),     [4u8;60].to_vec());
//! }
//! else {
//!     panic!("unrecoverable!");
//! }
//! ```
#![forbid(missing_docs)]

/// An `Rc`-backed mutable byte slice backed by a common allocation.
pub mod rc {

    use std::ops::{Deref, DerefMut};
    use std::rc::Rc;
    use std::any::Any;

    /// A thread-local byte buffer backed by a shared allocation.
    pub struct Bytes {
        /// Pointer to the start of this slice (not the allocation).
        ptr: *mut u8,
        /// Length of this slice.
        len: usize,
        /// Shared access to underlying resources.
        ///
        /// Importantly, this is unavailable for as long as the struct exists, which may
        /// prevent shared access to ptr[0 .. len]. I'm not sure I understand Rust's rules
        /// enough to make a strong statement about this.
        sequestered: Rc<Box<Any>>,
    }

    impl Bytes {

        /// Create a new instance from a byte allocation.
        pub fn from<B>(bytes: B) -> Bytes where B: DerefMut<Target=[u8]>+'static {

            let mut boxed = Box::new(bytes) as Box<Any>;

            let ptr = boxed.downcast_mut::<B>().unwrap().as_mut_ptr();
            let len = boxed.downcast_ref::<B>().unwrap().len();
            let sequestered = Rc::new(boxed);

            Bytes {
                ptr,
                len,
                sequestered,
            }
        }

        /// Extracts [0, index) into a new `Bytes` which is returned, updating `self`.
        ///
        /// #Safety
        ///
        /// This method uses an `unsafe` region to advance the pointer by `index`. It first
        /// tests `index` against `self.len`, which should ensure that the offset is in-bounds.
        pub fn extract_to(&mut self, index: usize) -> Bytes {

            assert!(index <= self.len);

            let result = Bytes {
                ptr: self.ptr,
                len: index,
                sequestered: self.sequestered.clone(),
            };

            unsafe { self.ptr = self.ptr.offset(index as isize); }
            self.len -= index;

            result
        }

        /// Recover the underlying storage.
        ///
        /// This method either results in the underlying storage if it is uniquely held, or the
        /// input `Bytes` if it is not uniquely held.
        pub fn try_recover<B>(self) -> Result<B, Bytes> where B: DerefMut<Target=[u8]>+'static {
            match Rc::try_unwrap(self.sequestered) {
                Ok(bytes) => Ok(*bytes.downcast::<B>().unwrap()),
                Err(rc) => Err(Bytes {
                    ptr: self.ptr,
                    len: self.len,
                    sequestered: rc,
                }),
            }
        }
    }

    impl Deref for Bytes {
        type Target = [u8];
        fn deref(&self) -> &[u8] {
            unsafe { ::std::slice::from_raw_parts(self.ptr, self.len) }
        }
    }

    impl DerefMut for Bytes {
        fn deref_mut(&mut self) -> &mut [u8] {
            unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.len) }
        }
    }
}

/// An `Arc`-backed mutable byte slice backed by a common allocation.
pub mod arc {

    use std::ops::{Deref, DerefMut};
    use std::sync::Arc;
    use std::any::Any;

    /// A thread-safe byte buffer backed by a shared allocation.
    pub struct Bytes {
        /// Pointer to the start of this slice (not the allocation).
        ptr: *mut u8,
        /// Length of this slice.
        len: usize,
        /// Shared access to underlying resources.
        ///
        /// Importantly, this is unavailable for as long as the struct exists, which may
        /// prevent shared access to ptr[0 .. len]. I'm not sure I understand Rust's rules
        /// enough to make a strong statement about this.
        sequestered: Arc<Box<Any>>,
    }

    unsafe impl Send for Bytes { }

    impl Bytes {

        /// Create a new instance from a byte allocation.
        pub fn from<B>(bytes: B) -> Bytes where B : DerefMut<Target=[u8]>+'static {

            let mut boxed = Box::new(bytes) as Box<Any>;

            let ptr = boxed.downcast_mut::<B>().unwrap().as_mut_ptr();
            let len = boxed.downcast_ref::<B>().unwrap().len();
            let sequestered = Arc::new(boxed);

            Bytes {
                ptr,
                len,
                sequestered,
            }
        }

        /// Extracts [0, index) into a new `Bytes` which is returned, updating `self`.
        ///
        /// #Safety
        ///
        /// This method uses an `unsafe` region to advance the pointer by `index`. It first
        /// tests `index` against `self.len`, which should ensure that the offset is in-bounds.
        pub fn extract_to(&mut self, index: usize) -> Bytes {

            assert!(index <= self.len);

            let result = Bytes {
                ptr: self.ptr,
                len: index,
                sequestered: self.sequestered.clone(),
            };

            unsafe { self.ptr = self.ptr.offset(index as isize); }
            self.len -= index;

            result
        }

        /// Recover the underlying storage.
        ///
        /// This method either results in the underlying storage if it is uniquely held, or the
        /// input `Bytes` if it is not uniquely held.
        ///
        /// #Examples
        ///
        /// ```
        /// use timely_bytes::arc::Bytes;
        ///
        /// let bytes = vec![0u8; 1024];
        /// let mut shared1 = Bytes::from(bytes);
        /// let mut shared2 = shared1.extract_to(100);
        /// let mut shared3 = shared1.extract_to(100);
        /// let mut shared4 = shared2.extract_to(60);
        ///
        /// drop(shared1);
        /// drop(shared2);
        /// drop(shared4);
        /// let recovered = shared3.try_recover::<Vec<u8>>().ok().expect("recovery failed");
        /// assert!(recovered.len() == 1024);
        /// ```
        pub fn try_recover<B>(self) -> Result<B, Bytes> where B: DerefMut<Target=[u8]>+'static {
            // println!("Trying recovery; strong count: {:?}", Arc::strong_count(&self.sequestered));
            match Arc::try_unwrap(self.sequestered) {
                Ok(bytes) => Ok(*bytes.downcast::<B>().unwrap()),
                Err(arc) => Err(Bytes {
                    ptr: self.ptr,
                    len: self.len,
                    sequestered: arc,
                }),
            }
        }

        /// Regenerates the Bytes if it is uniquely held.
        ///
        /// If uniquely held, this method recovers the initial pointer and length
        /// of the sequestered allocation and re-initialized the Bytes. The return
        /// value indicates whether this occurred.
        ///
        /// #Examples
        ///
        /// ```
        /// use timely_bytes::arc::Bytes;
        ///
        /// let bytes = vec![0u8; 1024];
        /// let mut shared1 = Bytes::from(bytes);
        /// let mut shared2 = shared1.extract_to(100);
        /// let mut shared3 = shared1.extract_to(100);
        /// let mut shared4 = shared2.extract_to(60);
        ///
        /// drop(shared1);
        /// drop(shared2);
        /// drop(shared4);
        /// assert!(shared3.try_regenerate::<Vec<u8>>());
        /// assert!(shared3.len() == 1024);
        /// ```
        pub fn try_regenerate<B>(&mut self) -> bool where B: DerefMut<Target=[u8]>+'static {
            if let Some(boxed) = Arc::get_mut(&mut self.sequestered) {
                let downcast = boxed.downcast_mut::<B>().expect("Downcast failed");
                self.ptr = downcast.as_mut_ptr();
                self.len = downcast.len();
                true
            }
            else {
                false
            }
        }

        /// Attempts to merge adjacent slices from the same allocation.
        ///
        /// If the merge succeeds then `other.len` is added to `self` and the result is `Ok(())`.
        /// If the merge fails self is unmodified and the result is `Err(other)`, returning the
        /// bytes supplied as input.
        ///
        /// #Examples
        ///
        /// ```
        /// use timely_bytes::arc::Bytes;
        ///
        /// let bytes = vec![0u8; 1024];
        /// let mut shared1 = Bytes::from(bytes);
        /// let mut shared2 = shared1.extract_to(100);
        /// let mut shared3 = shared1.extract_to(100);
        /// let mut shared4 = shared2.extract_to(60);
        ///
        /// // memory in slabs [4, 2, 3, 1]: merge back in arbitrary order.
        /// shared2.try_merge(shared3).ok().expect("Failed to merge 2 and 3");
        /// shared2.try_merge(shared1).ok().expect("Failed to merge 23 and 1");
        /// shared4.try_merge(shared2).ok().expect("Failed to merge 4 and 231");
        /// ```
        pub fn try_merge(&mut self, other: Bytes) -> Result<(), Bytes> {
            use ::std::sync::Arc;
            if Arc::ptr_eq(&self.sequestered, &other.sequestered) && ::std::ptr::eq(unsafe { self.ptr.offset(self.len as isize) }, other.ptr) {
                self.len += other.len;
                Ok(())
            }
            else {
                Err(other)
            }
        }
    }

    impl Deref for Bytes {
        type Target = [u8];
        fn deref(&self) -> &[u8] {
            unsafe { ::std::slice::from_raw_parts(self.ptr, self.len) }
        }
    }

    impl DerefMut for Bytes {
        fn deref_mut(&mut self) -> &mut [u8] {
            unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.len) }
        }
    }
}
<commit_msg>tidy using<commit_after>//! A simplified implementation of the `bytes` crate, with different features, less safety.
//!
//! #Examples
//!
//! ```
//! use timely_bytes::rc::Bytes;
//!
//! let bytes = vec![0u8; 1024];
//! let mut shared1 = Bytes::from(bytes);
//! let mut shared2 = shared1.extract_to(100);
//! let mut shared3 = shared1.extract_to(100);
//! let mut shared4 = shared2.extract_to(60);
//!
//! assert_eq!(shared1.len(), 824);
//! assert_eq!(shared2.len(), 40);
//! assert_eq!(shared3.len(), 100);
//! assert_eq!(shared4.len(), 60);
//!
//! for byte in shared1.iter_mut() { *byte = 1u8; }
//! for byte in shared2.iter_mut() { *byte = 2u8; }
//! for byte in shared3.iter_mut() { *byte = 3u8; }
//! for byte in shared4.iter_mut() { *byte = 4u8; }
//!
//! drop(shared1);
//! drop(shared2);
//! drop(shared3);
//!
//! if let Ok(bytes) = shared4.try_recover::<Vec<u8>>() {
//!     assert_eq!(bytes[200..1024].to_vec(), [1u8;824].to_vec());
//!     assert_eq!(bytes[60..100].to_vec(),   [2u8;40].to_vec());
//!     assert_eq!(bytes[100..200].to_vec(),  [3u8;100].to_vec());
//!     assert_eq!(bytes[0..60].to_vec(),     [4u8;60].to_vec());
//! }
//! else {
//!     panic!("unrecoverable!");
//! }
//! ```
#![forbid(missing_docs)]

/// An `Rc`-backed mutable byte slice backed by a common allocation.
pub mod rc {

    use std::ops::{Deref, DerefMut};
    use std::rc::Rc;
    use std::any::Any;

    /// A thread-local byte buffer backed by a shared allocation.
    pub struct Bytes {
        /// Pointer to the start of this slice (not the allocation).
        ptr: *mut u8,
        /// Length of this slice.
        len: usize,
        /// Shared access to underlying resources.
        ///
        /// Importantly, this is unavailable for as long as the struct exists, which may
        /// prevent shared access to ptr[0 .. len]. I'm not sure I understand Rust's rules
        /// enough to make a strong statement about this.
        sequestered: Rc<Box<Any>>,
    }

    impl Bytes {

        /// Create a new instance from a byte allocation.
        pub fn from<B>(bytes: B) -> Bytes where B: DerefMut<Target=[u8]>+'static {

            let mut boxed = Box::new(bytes) as Box<Any>;

            let ptr = boxed.downcast_mut::<B>().unwrap().as_mut_ptr();
            let len = boxed.downcast_ref::<B>().unwrap().len();
            let sequestered = Rc::new(boxed);

            Bytes {
                ptr,
                len,
                sequestered,
            }
        }

        /// Extracts [0, index) into a new `Bytes` which is returned, updating `self`.
        ///
        /// #Safety
        ///
        /// This method uses an `unsafe` region to advance the pointer by `index`. It first
        /// tests `index` against `self.len`, which should ensure that the offset is in-bounds.
        pub fn extract_to(&mut self, index: usize) -> Bytes {

            assert!(index <= self.len);

            let result = Bytes {
                ptr: self.ptr,
                len: index,
                sequestered: self.sequestered.clone(),
            };

            unsafe { self.ptr = self.ptr.offset(index as isize); }
            self.len -= index;

            result
        }

        /// Recover the underlying storage.
        ///
        /// This method either results in the underlying storage if it is uniquely held, or the
        /// input `Bytes` if it is not uniquely held.
        pub fn try_recover<B>(self) -> Result<B, Bytes> where B: DerefMut<Target=[u8]>+'static {
            match Rc::try_unwrap(self.sequestered) {
                Ok(bytes) => Ok(*bytes.downcast::<B>().unwrap()),
                Err(rc) => Err(Bytes {
                    ptr: self.ptr,
                    len: self.len,
                    sequestered: rc,
                }),
            }
        }
    }

    impl Deref for Bytes {
        type Target = [u8];
        fn deref(&self) -> &[u8] {
            unsafe { ::std::slice::from_raw_parts(self.ptr, self.len) }
        }
    }

    impl DerefMut for Bytes {
        fn deref_mut(&mut self) -> &mut [u8] {
            unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.len) }
        }
    }
}

/// An `Arc`-backed mutable byte slice backed by a common allocation.
pub mod arc {

    use std::ops::{Deref, DerefMut};
    use std::sync::Arc;
    use std::any::Any;

    /// A thread-safe byte buffer backed by a shared allocation.
    pub struct Bytes {
        /// Pointer to the start of this slice (not the allocation).
        ptr: *mut u8,
        /// Length of this slice.
        len: usize,
        /// Shared access to underlying resources.
        ///
        /// Importantly, this is unavailable for as long as the struct exists, which may
        /// prevent shared access to ptr[0 .. len]. I'm not sure I understand Rust's rules
        /// enough to make a strong statement about this.
        sequestered: Arc<Box<Any>>,
    }

    unsafe impl Send for Bytes { }

    impl Bytes {

        /// Create a new instance from a byte allocation.
        pub fn from<B>(bytes: B) -> Bytes where B : DerefMut<Target=[u8]>+'static {

            let mut boxed = Box::new(bytes) as Box<Any>;

            let ptr = boxed.downcast_mut::<B>().unwrap().as_mut_ptr();
            let len = boxed.downcast_ref::<B>().unwrap().len();
            let sequestered = Arc::new(boxed);

            Bytes {
                ptr,
                len,
                sequestered,
            }
        }

        /// Extracts [0, index) into a new `Bytes` which is returned, updating `self`.
        ///
        /// #Safety
        ///
        /// This method uses an `unsafe` region to advance the pointer by `index`. It first
        /// tests `index` against `self.len`, which should ensure that the offset is in-bounds.
        pub fn extract_to(&mut self, index: usize) -> Bytes {

            assert!(index <= self.len);

            let result = Bytes {
                ptr: self.ptr,
                len: index,
                sequestered: self.sequestered.clone(),
            };

            unsafe { self.ptr = self.ptr.offset(index as isize); }
            self.len -= index;

            result
        }

        /// Recover the underlying storage.
        ///
        /// This method either results in the underlying storage if it is uniquely held, or the
        /// input `Bytes` if it is not uniquely held.
        ///
        /// #Examples
        ///
        /// ```
        /// use timely_bytes::arc::Bytes;
        ///
        /// let bytes = vec![0u8; 1024];
        /// let mut shared1 = Bytes::from(bytes);
        /// let mut shared2 = shared1.extract_to(100);
        /// let mut shared3 = shared1.extract_to(100);
        /// let mut shared4 = shared2.extract_to(60);
        ///
        /// drop(shared1);
        /// drop(shared2);
        /// drop(shared4);
        /// let recovered = shared3.try_recover::<Vec<u8>>().ok().expect("recovery failed");
        /// assert!(recovered.len() == 1024);
        /// ```
        pub fn try_recover<B>(self) -> Result<B, Bytes> where B: DerefMut<Target=[u8]>+'static {
            // println!("Trying recovery; strong count: {:?}", Arc::strong_count(&self.sequestered));
            match Arc::try_unwrap(self.sequestered) {
                Ok(bytes) => Ok(*bytes.downcast::<B>().unwrap()),
                Err(arc) => Err(Bytes {
                    ptr: self.ptr,
                    len: self.len,
                    sequestered: arc,
                }),
            }
        }

        /// Regenerates the Bytes if it is uniquely held.
        ///
        /// If uniquely held, this method recovers the initial pointer and length
        /// of the sequestered allocation and re-initialized the Bytes. The return
        /// value indicates whether this occurred.
        ///
        /// #Examples
        ///
        /// ```
        /// use timely_bytes::arc::Bytes;
        ///
        /// let bytes = vec![0u8; 1024];
        /// let mut shared1 = Bytes::from(bytes);
        /// let mut shared2 = shared1.extract_to(100);
        /// let mut shared3 = shared1.extract_to(100);
        /// let mut shared4 = shared2.extract_to(60);
        ///
        /// drop(shared1);
        /// drop(shared2);
        /// drop(shared4);
        /// assert!(shared3.try_regenerate::<Vec<u8>>());
        /// assert!(shared3.len() == 1024);
        /// ```
        pub fn try_regenerate<B>(&mut self) -> bool where B: DerefMut<Target=[u8]>+'static {
            if let Some(boxed) = Arc::get_mut(&mut self.sequestered) {
                let downcast = boxed.downcast_mut::<B>().expect("Downcast failed");
                self.ptr = downcast.as_mut_ptr();
                self.len = downcast.len();
                true
            }
            else {
                false
            }
        }

        /// Attempts to merge adjacent slices from the same allocation.
        ///
        /// If the merge succeeds then `other.len` is added to `self` and the result is `Ok(())`.
        /// If the merge fails self is unmodified and the result is `Err(other)`, returning the
        /// bytes supplied as input.
        ///
        /// #Examples
        ///
        /// ```
        /// use timely_bytes::arc::Bytes;
        ///
        /// let bytes = vec![0u8; 1024];
        /// let mut shared1 = Bytes::from(bytes);
        /// let mut shared2 = shared1.extract_to(100);
        /// let mut shared3 = shared1.extract_to(100);
        /// let mut shared4 = shared2.extract_to(60);
        ///
        /// // memory in slabs [4, 2, 3, 1]: merge back in arbitrary order.
        /// shared2.try_merge(shared3).ok().expect("Failed to merge 2 and 3");
        /// shared2.try_merge(shared1).ok().expect("Failed to merge 23 and 1");
        /// shared4.try_merge(shared2).ok().expect("Failed to merge 4 and 231");
        /// ```
        pub fn try_merge(&mut self, other: Bytes) -> Result<(), Bytes> {
            if Arc::ptr_eq(&self.sequestered, &other.sequestered) && ::std::ptr::eq(unsafe { self.ptr.offset(self.len as isize) }, other.ptr) {
                self.len += other.len;
                Ok(())
            }
            else {
                Err(other)
            }
        }
    }

    impl Deref for Bytes {
        type Target = [u8];
        fn deref(&self) -> &[u8] {
            unsafe { ::std::slice::from_raw_parts(self.ptr, self.len) }
        }
    }

    impl DerefMut for Bytes {
        fn deref_mut(&mut self) -> &mut [u8] {
            unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.len) }
        }
    }
}
<|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.

//! Shader parameter handling.

use std::cell::Cell;
use std::rc::Rc;
use device::shade as s;
use device::{RawBufferHandle, ProgramHandle, SamplerHandle, TextureHandle};

/// Helper trait to transform base types into their corresponding uniforms
pub trait ToUniform {
    /// Create a `UniformValue` representing this value.
    fn to_uniform(&self) -> s::UniformValue;
}

macro_rules! impl_ToUniform(
    ($srcty:ty, $dstty:expr) => (
        impl ToUniform for $srcty {
            fn to_uniform(&self) -> s::UniformValue {
                $dstty(*self)
            }
        }
    );
)

impl_ToUniform!(i32, s::ValueI32)
impl_ToUniform!(f32, s::ValueF32)

impl_ToUniform!([i32, ..2], s::ValueI32Vector2)
impl_ToUniform!([i32, ..3], s::ValueI32Vector3)
impl_ToUniform!([i32, ..4], s::ValueI32Vector4)

impl_ToUniform!([f32, ..2], s::ValueF32Vector2)
impl_ToUniform!([f32, ..3], s::ValueF32Vector3)
impl_ToUniform!([f32, ..4], s::ValueF32Vector4)

impl_ToUniform!([[f32, ..2], ..2], s::ValueF32Matrix2)
impl_ToUniform!([[f32, ..3], ..3], s::ValueF32Matrix3)
impl_ToUniform!([[f32, ..4], ..4], s::ValueF32Matrix4)

/// Variable index of a uniform.
pub type VarUniform = u16;

/// Variable index of a uniform block.
pub type VarBlock = u8;

/// Variable index of a texture.
pub type VarTexture = u8;

/// A texture parameter: consists of a texture handle with an optional sampler.
pub type TextureParam = (TextureHandle, Option<SamplerHandle>);

/// A borrowed mutable storage for shader parameter values.
// Not sure if it's the best data structure to represent it.
pub struct ParamValues<'a> {
    /// uniform values to be provided
    pub uniforms: &'a mut [Option<s::UniformValue>],
    /// uniform buffers to be provided
    pub blocks  : &'a mut [Option<RawBufferHandle>],
    /// textures to be provided
    pub textures: &'a mut [Option<TextureParam>],
}

/// Encloses a shader program handle with its parameter
pub trait Program {
    /// Get the contained program handle
    fn get_handle(&self) -> &ProgramHandle;
    /// Get all the contained parameter values
    fn fill_params(&self, ParamValues);
}

/// An error type on either the parameter storage or the program side
#[deriving(Clone, PartialEq, Show)]
pub enum ParameterError {
    /// Internal error
    ErrorInternal,
    /// Error with the named uniform
    ErrorUniform(String),
    /// Error with the named uniform block
    ErrorBlock(String),
    /// Error with the named texture.
    ErrorTexture(String),
}

/// Abstracts the shader parameter structure, generated by the `shader_param` attribute
pub trait ShaderParam<L> {
    /// Creates a new link, self is passed as a workaround for Rust to not be lost in generics
    fn create_link(Option<Self>, &s::ProgramInfo) -> Result<L, ParameterError>;
    /// Get all the contained parameter values, using a given link.
    fn fill_params(&self, &L, ParamValues);
}

impl ShaderParam<()> for () {
    fn create_link(_: Option<()>, info: &s::ProgramInfo) -> Result<(), ParameterError> {
        match info.uniforms.as_slice().head() {
            Some(u) => return Err(ErrorUniform(u.name.clone())),
            None => (),
        }
        match info.blocks.as_slice().head() {
            Some(b) => return Err(ErrorBlock(b.name.clone())),
            None => (),
        }
        match info.textures.as_slice().head() {
            Some(t) => return Err(ErrorTexture(t.name.clone())),
            None => (),
        }
        Ok(())
    }

    fn fill_params(&self, _: &(), _: ParamValues) {
        //empty
    }
}

/// A bundle that encapsulates a program and a custom user-provided
/// structure containing the program parameters.
/// # Type parameters:
///
/// * `L` - auto-generated structure that has a variable index for every field of T
/// * `T` - user-provided structure containing actual parameter values
pub struct UserProgram<L, T> {
    /// Shader program handle
    program: ProgramHandle,
    /// Hidden link that provides parameter indices for user data
    link: L,
}

impl<L: Copy, T> Clone for UserProgram<L, T> {
    fn clone(&self) -> UserProgram<L, T> {
        UserProgram {
            program: self.program.clone(),
            link: self.link,
        }
    }
}

impl<L, T: ShaderParam<L>> UserProgram<L, T> {
    /// Connect a shader program with a parameter structure
    pub fn connect(prog: ProgramHandle) ->
                   Result<UserProgram<L, T>, ParameterError> {
        ShaderParam::create_link(None::<T>, prog.get_info())
            .map(|link| UserProgram {
                program: prog.clone(),
                link: link,
        })
    }
}

// Tuple of references `(&MyProgram, &Data)` is the standard way of providing
// a program with its parameters for the draw call.

impl<'a, L, T: ShaderParam<L>> Program for (&'a UserProgram<L, T>, &'a T) {
    fn get_handle(&self) -> &ProgramHandle {
        &self.val0().program
    }

    fn fill_params(&self, params: ParamValues) {
        self.val1().fill_params(&self.val0().link, params);
    }
}

pub type EmptyProgram = UserProgram<(), ()>;

impl<'a> Program for &'a EmptyProgram {
    fn get_handle(&self) -> &ProgramHandle {
        &self.program
    }

    fn fill_params(&self, params: ParamValues) {
        debug_assert!(
            params.uniforms.is_empty() &&
            params.blocks.is_empty() &&
            params.textures.is_empty(),
            "trying to bind a program handle that has uniforms;\n
            please link with `DeviceHelper::link_program` instead,\n
            or connect with `UserProgram::connect` after construction"
        );
    }
}

/// A named cell containing arbitrary value
pub struct NamedCell<T> {
    /// Name
    pub name: String,
    /// Value
    pub value: Cell<T>,
}

/// A dictionary of parameters, meant to be shared between different programs
pub struct ParamDictionary {
    /// Uniform dictionary
    pub uniforms: Vec<NamedCell<s::UniformValue>>,
    /// Block dictionary
    pub blocks: Vec<NamedCell<RawBufferHandle>>,
    /// Texture dictionary
    pub textures: Vec<NamedCell<TextureParam>>,
}

/// An associated link structure for `ParamDictionary` that redirects program
/// input to the relevant dictionary cell.
pub struct ParamDictionaryLink {
    uniforms: Vec<uint>,
    blocks: Vec<uint>,
    textures: Vec<uint>,
}

/// A shader program with dictionary of parameters
pub struct DictionaryProgram {
    program: ProgramHandle,
    link: ParamDictionaryLink,
    data: Rc<ParamDictionary>,
}

impl DictionaryProgram {
    /// Connect a shader program with a parameter structure
    pub fn connect(prog: ProgramHandle, data: Rc<ParamDictionary>)
                   -> Result<DictionaryProgram, ParameterError> {
        //TODO: proper error checks
        let link = ParamDictionaryLink {
            uniforms: prog.get_info().uniforms.iter().map(|var|
                data.uniforms.iter().position(|c| c.name == var.name).unwrap()
            ).collect(),
            blocks: prog.get_info().blocks.iter().map(|var|
                data.blocks  .iter().position(|c| c.name == var.name).unwrap()
            ).collect(),
            textures: prog.get_info().textures.iter().map(|var|
                data.textures.iter().position(|c| c.name == var.name).unwrap()
            ).collect(),
        };
        Ok(DictionaryProgram {
            program: prog,
            link: link,
            data: data,
        })
    }
}

impl<'a> Program for &'a DictionaryProgram {
    fn get_handle(&self) -> &ProgramHandle {
        &self.program
    }

    fn fill_params(&self, params: ParamValues) {
        for (&id, var) in self.link.uniforms.iter().zip(params.uniforms.mut_iter()) {
            *var = Some(self.data.uniforms[id].value.get());
        }
        for (&id, var) in self.link.blocks.iter().zip(params.blocks.mut_iter()) {
            *var = Some(self.data.blocks[id].value.get());
        }
        for (&id, var) in self.link.textures.iter().zip(params.textures.mut_iter()) {
            *var = Some(self.data.textures[id].value.get());
        }
    }
}
<commit_msg>Improve error messages for parameter errors<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.

//! Shader parameter handling.

use std::cell::Cell;
use std::fmt;
use std::rc::Rc;
use device::shade as s;
use device::{RawBufferHandle, ProgramHandle, SamplerHandle, TextureHandle};

/// Helper trait to transform base types into their corresponding uniforms
pub trait ToUniform {
    /// Create a `UniformValue` representing this value.
    fn to_uniform(&self) -> s::UniformValue;
}

macro_rules! impl_ToUniform(
    ($srcty:ty, $dstty:expr) => (
        impl ToUniform for $srcty {
            fn to_uniform(&self) -> s::UniformValue {
                $dstty(*self)
            }
        }
    );
)

impl_ToUniform!(i32, s::ValueI32)
impl_ToUniform!(f32, s::ValueF32)

impl_ToUniform!([i32, ..2], s::ValueI32Vector2)
impl_ToUniform!([i32, ..3], s::ValueI32Vector3)
impl_ToUniform!([i32, ..4], s::ValueI32Vector4)

impl_ToUniform!([f32, ..2], s::ValueF32Vector2)
impl_ToUniform!([f32, ..3], s::ValueF32Vector3)
impl_ToUniform!([f32, ..4], s::ValueF32Vector4)

impl_ToUniform!([[f32, ..2], ..2], s::ValueF32Matrix2)
impl_ToUniform!([[f32, ..3], ..3], s::ValueF32Matrix3)
impl_ToUniform!([[f32, ..4], ..4], s::ValueF32Matrix4)

/// Variable index of a uniform.
pub type VarUniform = u16;

/// Variable index of a uniform block.
pub type VarBlock = u8;

/// Variable index of a texture.
pub type VarTexture = u8;

/// A texture parameter: consists of a texture handle with an optional sampler.
pub type TextureParam = (TextureHandle, Option<SamplerHandle>);

/// A borrowed mutable storage for shader parameter values.
// Not sure if it's the best data structure to represent it.
pub struct ParamValues<'a> {
    /// uniform values to be provided
    pub uniforms: &'a mut [Option<s::UniformValue>],
    /// uniform buffers to be provided
    pub blocks  : &'a mut [Option<RawBufferHandle>],
    /// textures to be provided
    pub textures: &'a mut [Option<TextureParam>],
}

/// Encloses a shader program handle with its parameter
pub trait Program {
    /// Get the contained program handle
    fn get_handle(&self) -> &ProgramHandle;
    /// Get all the contained parameter values
    fn fill_params(&self, ParamValues);
}

/// An error type on either the parameter storage or the program side
#[deriving(Clone, PartialEq)]
pub enum ParameterError {
    /// Internal error
    ErrorInternal,
    /// Error with the named uniform
    ErrorUniform(String),
    /// Error with the named uniform block
    ErrorBlock(String),
    /// Error with the named texture.
    ErrorTexture(String),
}

impl fmt::Show for ParameterError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ErrorInternal          => write!(f, "Internal error"),
            &ErrorUniform(ref name) => write!(
                f,
                "Uniform error: Please make sure the uniform \"{0}\" is used \
                by the shader. Note: Specifying the uniform in the shader like \
                \"uniform <type> {0};\"  is not enough. It must actively be \
                used by the shader code.",
                name),
            &ErrorBlock(ref name)   => write!(f, "Block error: {}", name),
            &ErrorTexture(ref name) => write!(
                f,
                "Texture error: Please make sure the texture \"{0}\" is used \
                by the shader. Note: Specifying the texture in the shader like \
                \"uniform sampler2D {0};\"  is not enough. It must actively be \
                used by the shader code.",
                name),
        }
    }
}

/// Abstracts the shader parameter structure, generated by the `shader_param` attribute
pub trait ShaderParam<L> {
    /// Creates a new link, self is passed as a workaround for Rust to not be lost in generics
    fn create_link(Option<Self>, &s::ProgramInfo) -> Result<L, ParameterError>;
    /// Get all the contained parameter values, using a given link.
    fn fill_params(&self, &L, ParamValues);
}

impl ShaderParam<()> for () {
    fn create_link(_: Option<()>, info: &s::ProgramInfo) -> Result<(), ParameterError> {
        match info.uniforms.as_slice().head() {
            Some(u) => return Err(ErrorUniform(u.name.clone())),
            None => (),
        }
        match info.blocks.as_slice().head() {
            Some(b) => return Err(ErrorBlock(b.name.clone())),
            None => (),
        }
        match info.textures.as_slice().head() {
            Some(t) => return Err(ErrorTexture(t.name.clone())),
            None => (),
        }
        Ok(())
    }

    fn fill_params(&self, _: &(), _: ParamValues) {
        //empty
    }
}

/// A bundle that encapsulates a program and a custom user-provided
/// structure containing the program parameters.
/// # Type parameters:
///
/// * `L` - auto-generated structure that has a variable index for every field of T
/// * `T` - user-provided structure containing actual parameter values
pub struct UserProgram<L, T> {
    /// Shader program handle
    program: ProgramHandle,
    /// Hidden link that provides parameter indices for user data
    link: L,
}

impl<L: Copy, T> Clone for UserProgram<L, T> {
    fn clone(&self) -> UserProgram<L, T> {
        UserProgram {
            program: self.program.clone(),
            link: self.link,
        }
    }
}

impl<L, T: ShaderParam<L>> UserProgram<L, T> {
    /// Connect a shader program with a parameter structure
    pub fn connect(prog: ProgramHandle) ->
                   Result<UserProgram<L, T>, ParameterError> {
        ShaderParam::create_link(None::<T>, prog.get_info())
            .map(|link| UserProgram {
                program: prog.clone(),
                link: link,
        })
    }
}

// Tuple of references `(&MyProgram, &Data)` is the standard way of providing
// a program with its parameters for the draw call.

impl<'a, L, T: ShaderParam<L>> Program for (&'a UserProgram<L, T>, &'a T) {
    fn get_handle(&self) -> &ProgramHandle {
        &self.val0().program
    }

    fn fill_params(&self, params: ParamValues) {
        self.val1().fill_params(&self.val0().link, params);
    }
}

pub type EmptyProgram = UserProgram<(), ()>;

impl<'a> Program for &'a EmptyProgram {
    fn get_handle(&self) -> &ProgramHandle {
        &self.program
    }

    fn fill_params(&self, params: ParamValues) {
        debug_assert!(
            params.uniforms.is_empty() &&
            params.blocks.is_empty() &&
            params.textures.is_empty(),
            "trying to bind a program handle that has uniforms;\n
            please link with `DeviceHelper::link_program` instead,\n
            or connect with `UserProgram::connect` after construction"
        );
    }
}

/// A named cell containing arbitrary value
pub struct NamedCell<T> {
    /// Name
    pub name: String,
    /// Value
    pub value: Cell<T>,
}

/// A dictionary of parameters, meant to be shared between different programs
pub struct ParamDictionary {
    /// Uniform dictionary
    pub uniforms: Vec<NamedCell<s::UniformValue>>,
    /// Block dictionary
    pub blocks: Vec<NamedCell<RawBufferHandle>>,
    /// Texture dictionary
    pub textures: Vec<NamedCell<TextureParam>>,
}

/// An associated link structure for `ParamDictionary` that redirects program
/// input to the relevant dictionary cell.
pub struct ParamDictionaryLink {
    uniforms: Vec<uint>,
    blocks: Vec<uint>,
    textures: Vec<uint>,
}

/// A shader program with dictionary of parameters
pub struct DictionaryProgram {
    program: ProgramHandle,
    link: ParamDictionaryLink,
    data: Rc<ParamDictionary>,
}

impl DictionaryProgram {
    /// Connect a shader program with a parameter structure
    pub fn connect(prog: ProgramHandle, data: Rc<ParamDictionary>)
                   -> Result<DictionaryProgram, ParameterError> {
        //TODO: proper error checks
        let link = ParamDictionaryLink {
            uniforms: prog.get_info().uniforms.iter().map(|var|
                data.uniforms.iter().position(|c| c.name == var.name).unwrap()
            ).collect(),
            blocks: prog.get_info().blocks.iter().map(|var|
                data.blocks  .iter().position(|c| c.name == var.name).unwrap()
            ).collect(),
            textures: prog.get_info().textures.iter().map(|var|
                data.textures.iter().position(|c| c.name == var.name).unwrap()
            ).collect(),
        };
        Ok(DictionaryProgram {
            program: prog,
            link: link,
            data: data,
        })
    }
}

impl<'a> Program for &'a DictionaryProgram {
    fn get_handle(&self) -> &ProgramHandle {
        &self.program
    }

    fn fill_params(&self, params: ParamValues) {
        for (&id, var) in self.link.uniforms.iter().zip(params.uniforms.mut_iter()) {
            *var = Some(self.data.uniforms[id].value.get());
        }
        for (&id, var) in self.link.blocks.iter().zip(params.blocks.mut_iter()) {
            *var = Some(self.data.blocks[id].value.get());
        }
        for (&id, var) in self.link.textures.iter().zip(params.textures.mut_iter()) {
            *var = Some(self.data.textures[id].value.get());
        }
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::{AContext, ContextOf};
use image_data::{RenderbufferFormat};
use types::GLError;

pub struct Renderbuffer {
    gl_id: GLuint
}

impl Renderbuffer {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Renderbuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteRenderbuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

pub struct RenderbufferBuilder<C>
    where C: RenderbufferContext
{
    gl: C,
    storage_params: Option<(RenderbufferFormat, u32, u32)>
}

impl<C> RenderbufferBuilder<C>
    where C: RenderbufferContext
{
    fn new(gl: C) -> Self {
        RenderbufferBuilder {
            gl: gl,
            storage_params: None
        }
    }

    pub fn storage(mut self,
                   format: RenderbufferFormat,
                   width: u32,
                   height: u32)
        -> Self
    {
        self.storage_params = Some((format, width, height));
        self
    }

    pub fn try_unwrap(self) -> Result<Renderbuffer, GLError> {
        let gl = self.gl;
        let mut rbo = unsafe { gl.gen_renderbuffer() };

        match self.storage_params {
            Some((format, width, height)) => {
                {
                    let (mut gl_rbo, gl) = gl.bind_renderbuffer(&mut rbo);
                    gl.storage(&mut gl_rbo, format, width, height);
                }

                Ok(rbo)
            },
            None => {
                let msg = "Error building renderbuffer: no format or dimensions provided";
                Err(GLError::Message(msg.to_owned()))
            }
        }
    }

    pub fn unwrap(self) -> Renderbuffer {
        self.try_unwrap().unwrap()
    }
}

pub trait ContextRenderbufferBuilderExt: RenderbufferContext + Sized {
    fn build_renderbuffer(self) -> RenderbufferBuilder<Self>;
}

impl<'a, C: 'a> ContextRenderbufferBuilderExt for &'a mut C
    where &'a mut C: RenderbufferContext
{
    fn build_renderbuffer(self) -> RenderbufferBuilder<&'a mut C> {
        RenderbufferBuilder::new(self)
    }
}

pub unsafe trait ContextRenderbufferExt {
    unsafe fn gen_renderbuffer(&self) -> Renderbuffer {
        let mut id : GLuint = 0;

        gl::GenRenderbuffers(1, &mut id as *mut GLuint);
        dbg_gl_sanity_check! {
            GLError::InvalidValue => "`n` is negative",
            _ => "Unknown error"
        }

        Renderbuffer {
            gl_id: id
        }
    }

    fn storage(&self,
               gl_rbo: &mut RenderbufferBinding,
               format: RenderbufferFormat,
               width: u32,
               height: u32)
    {
        unsafe {
            gl::RenderbufferStorage(gl_rbo.target().gl_enum(),
                                    format.gl_enum(),
                                    width as GLint,
                                    height as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_RENDERBUFFER` or `internalformat` is not an accepted format",
                GLError::InvalidValue => "`width` or `height` is less than zero or greater than `GL_MAX_RENDERBUFFER_SIZE`",
                GLError::OutOfMemory => "Unable to allocate enough memory for requested size",
                GLError::InvalidOperation => "Renderbuffer object 0 is bound",
                _ => "Unknown error"
            }
        }
    }
}

unsafe impl<B, F, P, R, T> ContextRenderbufferExt for ContextOf<B, F, P, R, T> {

}

unsafe impl<'a, B, F, P, R, T> ContextRenderbufferExt
    for &'a mut ContextOf<B, F, P, R, T>
{

}

pub trait RenderbufferContext: AContext {
    type Binder: BorrowMut<RenderbufferBinder>;
    type Rest: AContext;

    fn split_renderbuffer(self) -> (Self::Binder, Self::Rest);

    fn bind_renderbuffer<'a>(self, rbo: &'a mut Renderbuffer)
        -> (RenderbufferBinding<'a>, Self::Rest)
        where Self: Sized
    {
        let (mut binder, rest) = self.split_renderbuffer();
        (binder.borrow_mut().bind(rbo), rest)
    }
}

impl<B, F, P, R, T> RenderbufferContext for ContextOf<B, F, P, R, T>
    where R: BorrowMut<RenderbufferBinder>
{
    type Binder = R;
    type Rest = ContextOf<B, F, P, (), T>;

    fn split_renderbuffer(self) -> (Self::Binder, Self::Rest) {
        self.swap_renderbuffer(())
    }
}

impl<'a, B, F, P, R, T> RenderbufferContext
    for &'a mut ContextOf<B, F, P, R, T>
    where R: BorrowMut<RenderbufferBinder>
{
    type Binder = &'a mut RenderbufferBinder;
    type Rest = ContextOf<&'a mut B, &'a mut F, &'a mut P, (), &'a mut T>;

    fn split_renderbuffer(self) -> (Self::Binder, Self::Rest) {
        let gl = self.borrowed_mut();
        gl.swap_renderbuffer(())
    }
}

gl_enum! {
    pub gl_enum RenderbufferTarget {
        Renderbuffer as RENDERBUFFER = gl::RENDERBUFFER
    }
}

pub struct RenderbufferBinding<'a> {
    phantom: PhantomData<&'a mut Renderbuffer>
}

impl<'a> RenderbufferBinding<'a> {
    fn target(&self) -> RenderbufferTarget {
        RenderbufferTarget::Renderbuffer
    }
}

pub struct RenderbufferBinder;
impl RenderbufferBinder {
    pub fn bind<'a>(&mut self, renderbuffer: &'a mut Renderbuffer)
        -> RenderbufferBinding<'a>
    {
        let binding = RenderbufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindRenderbuffer(binding.target().gl_enum(),
                                 renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_RENDERBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<commit_msg>Add `GLObject` impl for `Renderbuffer`<commit_after>use std::marker::PhantomData;
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::{AContext, ContextOf};
use image_data::{RenderbufferFormat};
use types::{GLObject, GLError};

pub struct Renderbuffer {
    gl_id: GLuint
}

impl Renderbuffer {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Renderbuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteRenderbuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

impl GLObject for Renderbuffer {
    type Id = GLuint;

    unsafe fn from_raw(id: Self::Id) -> Self {
        Renderbuffer { gl_id: id }
    }

    fn id(&self) -> Self::Id {
        self.gl_id
    }
}

pub struct RenderbufferBuilder<C>
    where C: RenderbufferContext
{
    gl: C,
    storage_params: Option<(RenderbufferFormat, u32, u32)>
}

impl<C> RenderbufferBuilder<C>
    where C: RenderbufferContext
{
    fn new(gl: C) -> Self {
        RenderbufferBuilder {
            gl: gl,
            storage_params: None
        }
    }

    pub fn storage(mut self,
                   format: RenderbufferFormat,
                   width: u32,
                   height: u32)
        -> Self
    {
        self.storage_params = Some((format, width, height));
        self
    }

    pub fn try_unwrap(self) -> Result<Renderbuffer, GLError> {
        let gl = self.gl;
        let mut rbo = unsafe { gl.gen_renderbuffer() };

        match self.storage_params {
            Some((format, width, height)) => {
                {
                    let (mut gl_rbo, gl) = gl.bind_renderbuffer(&mut rbo);
                    gl.storage(&mut gl_rbo, format, width, height);
                }

                Ok(rbo)
            },
            None => {
                let msg = "Error building renderbuffer: no format or dimensions provided";
                Err(GLError::Message(msg.to_owned()))
            }
        }
    }

    pub fn unwrap(self) -> Renderbuffer {
        self.try_unwrap().unwrap()
    }
}

pub trait ContextRenderbufferBuilderExt: RenderbufferContext + Sized {
    fn build_renderbuffer(self) -> RenderbufferBuilder<Self>;
}

impl<'a, C: 'a> ContextRenderbufferBuilderExt for &'a mut C
    where &'a mut C: RenderbufferContext
{
    fn build_renderbuffer(self) -> RenderbufferBuilder<&'a mut C> {
        RenderbufferBuilder::new(self)
    }
}

pub unsafe trait ContextRenderbufferExt {
    unsafe fn gen_renderbuffer(&self) -> Renderbuffer {
        let mut id : GLuint = 0;

        gl::GenRenderbuffers(1, &mut id as *mut GLuint);
        dbg_gl_sanity_check! {
            GLError::InvalidValue => "`n` is negative",
            _ => "Unknown error"
        }

        Renderbuffer {
            gl_id: id
        }
    }

    fn storage(&self,
               gl_rbo: &mut RenderbufferBinding,
               format: RenderbufferFormat,
               width: u32,
               height: u32)
    {
        unsafe {
            gl::RenderbufferStorage(gl_rbo.target().gl_enum(),
                                    format.gl_enum(),
                                    width as GLint,
                                    height as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_RENDERBUFFER` or `internalformat` is not an accepted format",
                GLError::InvalidValue => "`width` or `height` is less than zero or greater than `GL_MAX_RENDERBUFFER_SIZE`",
                GLError::OutOfMemory => "Unable to allocate enough memory for requested size",
                GLError::InvalidOperation => "Renderbuffer object 0 is bound",
                _ => "Unknown error"
            }
        }
    }
}

unsafe impl<B, F, P, R, T> ContextRenderbufferExt for ContextOf<B, F, P, R, T> {

}

unsafe impl<'a, B, F, P, R, T> ContextRenderbufferExt
    for &'a mut ContextOf<B, F, P, R, T>
{

}

pub trait RenderbufferContext: AContext {
    type Binder: BorrowMut<RenderbufferBinder>;
    type Rest: AContext;

    fn split_renderbuffer(self) -> (Self::Binder, Self::Rest);

    fn bind_renderbuffer<'a>(self, rbo: &'a mut Renderbuffer)
        -> (RenderbufferBinding<'a>, Self::Rest)
        where Self: Sized
    {
        let (mut binder, rest) = self.split_renderbuffer();
        (binder.borrow_mut().bind(rbo), rest)
    }
}

impl<B, F, P, R, T> RenderbufferContext for ContextOf<B, F, P, R, T>
    where R: BorrowMut<RenderbufferBinder>
{
    type Binder = R;
    type Rest = ContextOf<B, F, P, (), T>;

    fn split_renderbuffer(self) -> (Self::Binder, Self::Rest) {
        self.swap_renderbuffer(())
    }
}

impl<'a, B, F, P, R, T> RenderbufferContext
    for &'a mut ContextOf<B, F, P, R, T>
    where R: BorrowMut<RenderbufferBinder>
{
    type Binder = &'a mut RenderbufferBinder;
    type Rest = ContextOf<&'a mut B, &'a mut F, &'a mut P, (), &'a mut T>;

    fn split_renderbuffer(self) -> (Self::Binder, Self::Rest) {
        let gl = self.borrowed_mut();
        gl.swap_renderbuffer(())
    }
}

gl_enum! {
    pub gl_enum RenderbufferTarget {
        Renderbuffer as RENDERBUFFER = gl::RENDERBUFFER
    }
}

pub struct RenderbufferBinding<'a> {
    phantom: PhantomData<&'a mut Renderbuffer>
}

impl<'a> RenderbufferBinding<'a> {
    fn target(&self) -> RenderbufferTarget {
        RenderbufferTarget::Renderbuffer
    }
}

pub struct RenderbufferBinder;
impl RenderbufferBinder {
    pub fn bind<'a>(&mut self, renderbuffer: &'a mut Renderbuffer)
        -> RenderbufferBinding<'a>
    {
        let binding = RenderbufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindRenderbuffer(binding.target().gl_enum(),
                                 renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_RENDERBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<|endoftext|>


<commit_before>pub fn add(num_l: &str, num_r: &str) -> String {
    let mut sum: Vec<u8> = denormalize(num_l).into();
    sum.extend(denormalize(num_r).bytes());

    sum.sort();
    sum.reverse();

    normalize(&String::from_utf8(sum).unwrap())
}

pub fn denormalize(num: &str) -> String {
    match num {
        "IV" => "IIII",
        "IX" => "VIIII",
        _ => num,
    }.to_string()
}

fn _factor_out(num: &str, before: &str, after: &str) -> String {
    let parts: Vec<&str> = num.split(before).collect();
    parts.join(after)
}

pub fn normalize(num: &str) -> String {
    let num = _factor_out(num, "IIIII", "V");
    let num = _factor_out(num.as_ref(), "IIII", "IV");
    let num = _factor_out(num.as_ref(), "VIV", "IX");
    match num.as_ref() {
        "VIIII" => "IX".to_string(),
        "VIIIII" => "X".to_string(),
        "VV" => "X".to_string(),
        _ => num,
    }
}

#[cfg(test)]
mod tests {
    use super::add;
    use super::normalize;
    use super::denormalize;

    #[test]
    fn add_i_i() {
        assert_eq!("II", add("I", "I"));
    }

    #[test]
    fn add_i_ii() {
        assert_eq!("III", add("I", "II"));
    }

    #[test]
    fn add_ii_iii_requires_normalization_to_v() {
        assert_eq!("V", add("II", "III"));

    }

    #[test]
    fn add_v_i() {
        assert_eq!("VI", add("V", "I"));
    }

    #[test]
    fn add_i_v_understands_the_relative_order_of_v_and_i() {
        assert_eq!("VI", add("I", "V"));
    }

    #[test]
    fn add_i_iv_denormalizes_before_adding() {
        assert_eq!("V", add("I", "IV"));
    }

    #[test]
    fn denormalize_iv() {
        assert_eq!("IIII", denormalize("IV"));
    }

    #[test]
    fn denormalize_ix() {
        assert_eq!("VIIII", denormalize("IX"));
    }

    #[test]
    fn normalize_iiiii() {
        assert_eq!("V", normalize("IIIII"));
    }

    #[test]
    fn normalize_iiii() {
        assert_eq!("IV", normalize("IIII"));
    }

    #[test]
    fn normalize_vv() {
        assert_eq!("X", normalize("VV"));
    }

    #[test]
    fn normalize_viiii() {
        assert_eq!("IX", normalize("VIIII"));
    }

    #[test]
    fn normalize_viiiii() {
        assert_eq!("X", normalize("VIIIII"));
    }

}
<commit_msg>Refactor to clean up rust normalize method<commit_after>pub fn add(num_l: &str, num_r: &str) -> String {
    let mut sum: Vec<u8> = denormalize(num_l).into();
    sum.extend(denormalize(num_r).bytes());

    sum.sort();
    sum.reverse();

    normalize(&String::from_utf8(sum).unwrap())
}

pub fn denormalize(num: &str) -> String {
    match num {
        "IV" => "IIII",
        "IX" => "VIIII",
        _ => num,
    }.to_string()
}

fn _factor_out(num: &str, before: &str, after: &str) -> String {
    let parts: Vec<&str> = num.split(before).collect();
    parts.join(after)
}

pub fn normalize(num: &str) -> String {
    let num = _factor_out(num, "IIIII", "V");
    let num = _factor_out(num.as_ref(), "IIII", "IV");
    let num = _factor_out(num.as_ref(), "VIV", "IX");
    let num = _factor_out(num.as_ref(), "VV", "X");
    num
}

#[cfg(test)]
mod tests {
    use super::add;
    use super::normalize;
    use super::denormalize;

    #[test]
    fn add_i_i() {
        assert_eq!("II", add("I", "I"));
    }

    #[test]
    fn add_i_ii() {
        assert_eq!("III", add("I", "II"));
    }

    #[test]
    fn add_ii_iii_requires_normalization_to_v() {
        assert_eq!("V", add("II", "III"));

    }

    #[test]
    fn add_v_i() {
        assert_eq!("VI", add("V", "I"));
    }

    #[test]
    fn add_i_v_understands_the_relative_order_of_v_and_i() {
        assert_eq!("VI", add("I", "V"));
    }

    #[test]
    fn add_i_iv_denormalizes_before_adding() {
        assert_eq!("V", add("I", "IV"));
    }

    #[test]
    fn denormalize_iv() {
        assert_eq!("IIII", denormalize("IV"));
    }

    #[test]
    fn denormalize_ix() {
        assert_eq!("VIIII", denormalize("IX"));
    }

    #[test]
    fn normalize_iiiii() {
        assert_eq!("V", normalize("IIIII"));
    }

    #[test]
    fn normalize_iiii() {
        assert_eq!("IV", normalize("IIII"));
    }

    #[test]
    fn normalize_vv() {
        assert_eq!("X", normalize("VV"));
    }

    #[test]
    fn normalize_viiii() {
        assert_eq!("IX", normalize("VIIII"));
    }

    #[test]
    fn normalize_viiiii() {
        assert_eq!("X", normalize("VIIIII"));
    }

}
<|endoftext|>


<commit_before>use borrow;
use denormalize;
use normalize;

pub fn sub(num_l: &str, num_r: &str) -> Result<String, &'static str> {
    let from = denormalize(num_l);
    match from.find(num_r) {
        Some(begin) => {
            let end = begin + num_r.len();
            Ok(from[end..from.len()].to_string())
        },
        None => {
            let from = borrow(from.as_ref(), 'I').unwrap();
            match from.find(num_r) {
                Some(begin) => {
                    let end = begin + num_r.len();
                    Ok(normalize(from[end..from.len()].as_ref()))
                },
                None => {
                    Err("Romans don't know negative numbers")
                }
            }
        }
    }
}

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

    #[test]
    fn sub_ii_i() {
        assert_eq!("I", sub("II", "I").unwrap());
    }

    #[test]
    fn sub_iii_i() {
        assert_eq!("II", sub("III", "I").unwrap());
    }

    #[test]
    fn sub_v_ii_borrows_i_from_v() {
        assert_eq!("III", sub("V", "II").unwrap());
    }

    #[test]
    fn sub_v_i_normalizes_result() {
        assert_eq!("IV", sub("V", "I").unwrap());
    }

    #[test]
    fn sub_iv_i_denormalizes_before_subtracting() {
        assert_eq!("III", sub("IV", "I").unwrap());
    }
}
<commit_msg>Denormalize right side before subtracting in Rust<commit_after>use borrow;
use denormalize;
use normalize;

pub fn sub(num_l: &str, num_r: &str) -> Result<String, &'static str> {
    let lhs = denormalize(num_l);
    let rhs = denormalize(num_r);

    match lhs.find(&rhs) {
        Some(begin) => {
            let end = begin + rhs.len();
            Ok(lhs[end..lhs.len()].to_string())
        },
        None => {
            let lhs = borrow(lhs.as_ref(), 'I').unwrap();
            match lhs.find(&rhs) {
                Some(begin) => {
                    let end = begin + rhs.len();
                    Ok(normalize(lhs[end..lhs.len()].as_ref()))
                },
                None => {
                    Err("Romans don't know negative numbers")
                }
            }
        }
    }
}

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

    #[test]
    fn sub_ii_i() {
        assert_eq!("I", sub("II", "I").unwrap());
    }

    #[test]
    fn sub_iii_i() {
        assert_eq!("II", sub("III", "I").unwrap());
    }

    #[test]
    fn sub_v_ii_borrows_i_from_v() {
        assert_eq!("III", sub("V", "II").unwrap());
    }

    #[test]
    fn sub_v_i_normalizes_result() {
        assert_eq!("IV", sub("V", "I").unwrap());
    }

    #[test]
    fn sub_iv_i_denormalizes_rhs_before_subtracting() {
        assert_eq!("III", sub("IV", "I").unwrap());
    }

    #[test]
    fn sub_v_iv_denormalizes_rhs_before_subtracting() {
        assert_eq!("I", sub("V", "IV").unwrap());
    }
}
<|endoftext|>


<commit_before>use std::vec::Vec;
use tokens::*;

pub fn slice_of(string: &str, range: (usize, usize)) -> String
{
    let native_slice = &string[range.0..range.1];
    let mut slice = String::new();
    slice.push_str(native_slice);
    slice
}

/// Identifies the end index of a nestable body given the open and close symbols for the body
/// For instance, an arithmetic expression can have nested parenthesis groups (e.g. (1 + (2*(2+1))) * (2 + 5) )
/// In the example, this method would identify the start and stop as these (> and < respectively):
///     >(1 + (2*(2+1)))< * (2 + 5)
/// If the start_index was specified as the parenthesis surrounding 2 + 5, then this method would select:
///     (1 + (2*(2+1))) * >(2 + 5)<
///
/// The start index passed to this method should be the index AFTER the first open symbol
/// @return the index of the token that closes the specified body or None if the block is not closed or nested properly
pub fn identify_body_bounds(tokens: &Vec<Token>, start: usize, symbols: (&str, &str)) -> Option<usize>
{
    let (open, close) = symbols;
    let mut open_braces = 1;

    for(index, token) in tokens[start..].iter().enumerate()
    {
        if token.value == open
        {
            open_braces += 1;
        }
        else if token.value == close
        {
            open_braces -= 1;
            if open_braces == 0
            {
                return Some(index + start);
            }
        }
    }

    return None;
}

/// Identifies the index of the next token matching the specified symbol
/// @return the index of the specified token (after the specified start index) or None if no such symbol exists
pub fn find_next(tokens: &Vec<Token>, start: usize, symbol: &str) -> Option<usize>
{
    for (index, token) in tokens[start..].iter().enumerate()
    {
        if token.value == symbol { return Some(index + start); }
    }

    return None;
}
<commit_msg>Alter string function<commit_after>use std::vec::Vec;
use tokens::*;

pub fn slice_of(string: &str, range: (usize, usize)) -> String
{
    let native_slice = &string[range.0..range.1];
    let mut slice = String::new();
    slice.push_str(native_slice);
    slice
}

/// Identifies the end index of a nestable body given the open and close symbols for the body
/// For instance, an arithmetic expression can have nested parenthesis groups (e.g. (1 + (2*(2+1))) * (2 + 5) )
/// In the example, this method would identify the start and stop as these (> and < respectively):
///     >(1 + (2*(2+1)))< * (2 + 5)
/// If the start_index was specified as the parenthesis surrounding 2 + 5, then this method would select:
///     (1 + (2*(2+1))) * >(2 + 5)<
///
/// The start index passed to this method should be the index AFTER the first open symbol
/// @return the index of the token that closes the specified body or None if the block is not closed or nested properly
pub fn identify_body_bounds(tokens: &Vec<Token>, start: usize, symbols: (&str, &str)) -> Option<usize>
{
    let (open, close) = symbols;
    let mut open_braces = 1;

    for(index, token) in tokens[start..].iter().enumerate()
    {
        if token.value == open
        {
            open_braces += 1;
        }
        else if token.value == close
        {
            open_braces -= 1;
            if open_braces == 0
            {
                return Some(index + start);
            }
        }
    }

    return None;
}

/// Identifies the index of the next token matching the specified symbol
/// @return the index of the specified token (after the specified start index) or None if no such symbol exists
pub fn find_next(tokens: &Vec<Token>, start: usize, symbol: &str) -> Option<usize>
{
    for (index, token) in tokens[start..].iter().enumerate()
    {
        if token.value == symbol { return Some(index + start); }
    }

    return None;
}

pub fn alter_string(original_string: &str, delimiter: &str, join_symbol: &str, string_added: &str, remove: bool) -> String
{
    let mut string: Vec<&str> = original_string.split_terminator(delimiter).collect();
    let mut length = string.len();
    let mut result: String;

    if remove
    {
        string.remove(length - 1);
    }
    else
    {
        string.push(string_added);
    }

    result = string.connect(join_symbol);
    return result;
}
<|endoftext|>


<commit_before>/*!
A binding for SDL2_gfx.
 */

#![crate_name="sdl2_gfx"]
#![crate_type = "lib"]
#![desc = "SDL2_gfx bindings and wrappers"]
#![comment = "SDL2_gfx bindings and wrappers"]
#![license = "MIT"]

#![feature(globs, macro_rules)]

extern crate libc;
extern crate sdl2;
extern crate "sdl2-sys" as sys;

// Setup linking for all targets.
#[link(name="SDL2_gfx")]
extern {}

pub mod primitives;
pub mod rotozoom;
pub mod framerate;
pub mod imagefilter;
<commit_msg>Remove custom attributes.<commit_after>/*!
A binding for SDL2_gfx.
 */

#![crate_name="sdl2_gfx"]
#![crate_type = "lib"]

#![feature(globs, macro_rules)]

extern crate libc;
extern crate sdl2;
extern crate "sdl2-sys" as sys;

// Setup linking for all targets.
#[link(name="SDL2_gfx")]
extern {}

pub mod primitives;
pub mod rotozoom;
pub mod framerate;
pub mod imagefilter;
<|endoftext|>


<commit_before>#[feature(phase)];
#[phase(syntax, link)] extern crate log;
extern crate collections;
use std::io::{File, Open, Write, TempDir};
use std::os::args;
use std::cast;
use std::from_str::from_str;
use std::raw::Slice;
use collections::priority_queue::PriorityQueue;
#[cfg(test)]
use std::io::{ReadWrite, SeekSet};

/*
 * an entry is the number that we read and the file it came from, so after we took
 * out one Entry from the priority queue, we need to know where to take the next number
 * from.
 */
struct Entry {
	value: u64,
	source: File,
}

/* The priority queue depends on the ordering relation and always returns the biggest */
impl Ord for Entry {
	// lesser than implementation
	fn lt(&self, other: &Entry) -> bool {
		// we invert: for us the smallest will have the highest priority
		!(self.value < other.value)
	}
}

/* ordering needs equality for some reason, so there */
impl Eq for Entry {
	fn eq(&self, other: &Entry) -> bool {
		self.value == other.value
	}
}

/* A struct to hold our queue */
struct PriorityFile {
	queue: PriorityQueue<Entry>,
}

/*
 * 'Class' that takes a list of files and does a k-way merge of the smallest values
 * from the files
 */
impl PriorityFile {
	pub fn new(files: Vec<File>) -> PriorityFile {
		let mut queue: PriorityQueue<Entry> = PriorityQueue::new();
		// now that we got the queue, populate it with initial values

		// move_iter is required to get the values themselves, not borrowed pointers to them
		for mut f in files.move_iter() {
			// read from file, append to queue
			let number = match f.read_le_u64() {
				Ok(num) => num,
				Err(e) => fail!("failed to read u64 from file: {}", e),
			};
			queue.push(Entry {value: number, source: f});
		};
		PriorityFile {queue: queue}
	}

	/* Returns the next smallest number from the list of files or None if exhausted */
	pub fn next(&mut self) -> Option<u64> {
		match self.queue.maybe_pop() {
			Some(mut res) => {
				let v = res.value;
				match res.source.read_le_u64() {
					Ok(num) => self.queue.push(Entry {value: num, source: res.source}),
					Err(_) => (),
				};
				Some(v)
			},
			None => None,
		}
	}
}

fn read_u64(from: &mut File, n: uint) -> Vec<u64> {
	// rust post 0.10 will directly return a Vec<u8> here
	let buf = match from.read_exact(n*8) {
		Ok(b) => b,
		Err(e) => fail!("reading failed {}", e),
	};
	//let u = buf.as_ptr();
	let u = buf.as_slice();

	let mut r: Slice<u64> = unsafe { cast::transmute(u) };
	assert_eq!(r.len % 8, 0);
	r.len /= 8;
	Vec::from_slice(unsafe { cast::transmute(r) })
}

fn write_u64(to: &mut File, items: &Vec<u64>) {
	let s = items.as_slice();
	let mut r: Slice<u8> = unsafe { cast::transmute(s) };
	r.len *= 8;
	let buf: &[u8] = unsafe { cast::transmute(r) };

	match to.write(buf) {
		Ok(_) => (),
		Err(e) => fail!("writing failed: {}", e),
	};
}

fn externalSort(mut fdInput: File, size: u64, mut fdOutput: File, memSize: u64) {
	let mut runs = size / memSize;
	let items_per_run = (memSize / 8) as uint;
	let over = ((size / 8) - (items_per_run as u64 * runs)) as uint;

	info!("There will be {} runs with {} elements each.", runs, items_per_run);
	if over > 0 {
		info!("And one additional run with {} items.", over);
	}

	// let's create a temporary directory to store the sorted chunks
	// neat: TempDir deletes the directory and its contents when it goes out of
	// scope
	let overflow_dir = match TempDir::new("externalsort") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let overflow_path = overflow_dir.path();
	info!("temp dir:\ncd {}", overflow_path.display());

	// start the sorting runs
	for n in range(0, runs) {
		// iterate over our 'run' buffer and read from the input file
		// I suppose the values are little endian, which considering we are most
		// likely on x86, is a reasonable assumption
		info!("Run {}, starting read", n);
		let mut run = read_u64(&mut fdInput, items_per_run);
		info!("Run {}, read finished", n);
		// O(n log n) sort from the stdlib, hopefully more or less equivalent to
		// C++ std::sort
		info!("Run {}, starting sort", n);
		run.sort();
		info!("Run {}, sort finished", n);

		// now write out the results into numbered files
		let file_path = overflow_path.join(n.to_str());
		let mut file_file = match File::open_mode(&file_path, Open, Write) {
			Ok(f) => f,
			Err(e) => fail!("overflow file failed opening for write: {}", e),
		};

		info!("Run {}, starting write", n);
		write_u64(&mut file_file, &run);
		info!("Run {}, write finished", n);
	};

	/* additional run to catch remaining objects */
	if over > 0 {
		info!("overrun starting read");
		let mut run = read_u64(&mut fdInput, over);
		info!("overrun read finished");
		info!("overrun starting sort");
		run.sort();
		info!("overrun sort finished");

		let file_path = overflow_path.join(runs.to_str());
		let mut file_file = match File::open_mode(&file_path, Open, Write) {
			Ok(f) => f,
			Err(e) => fail!("overflow file failed opening for write: {}", e),
		};
		info!("overrun starting write");
		write_u64(&mut file_file, &run);
		info!("overrun finished write");

		runs += 1;
	};

	/* sorting done, now merging */
	info!("Pre-sorting done, now k-way merge")

	// collect all file handles. Hopefully less than 4096
	let mut files = Vec::with_capacity(runs as uint);
	for n in range(0, runs) {
		let file_path = overflow_path.join(n.to_str());
		let fd = match File::open(&file_path) {
			Ok(f) => f,
			Err(e) => fail!("overflow file opening error {}", e),
		};
		files.push(fd);
	}

	// we got a nice class here that spits out sorted numbers until exhausted
	let mut pf = PriorityFile::new(files);
	// put the sorted numbers in a cache first, so they can all be written in bulk
	let mut write_cache = Vec::with_capacity(items_per_run);
	loop {
		match pf.next() {
			Some (number) => {
				// a new number was found, add it to the cache
				// and if the cache is full, write that to disk
				write_cache.push(number);
				debug!("Gathered element {}", number);
				if write_cache.len() >= items_per_run {
					info!("Writing out {} elements from cache", write_cache.len());
					write_u64(&mut fdOutput, &write_cache);
					write_cache.clear();
				};
			},
			None => {
				info!("Ending, writing out remaining {} elements from cache", write_cache.len());
				// we finished, write remaining cache to disk
				write_u64(&mut fdOutput, &write_cache);
				break;
			},
		};
	};
}

fn main() {
	if args().len() < 4 {
		fail!("Argument error: <inputFile> <outputFile> <memoryBufferInMB>");
	}
	let input_file_path = &Path::new(args()[1]);
	let size = match input_file_path.stat() {
		Ok(stat) => stat.size,
		Err(e) => fail!("Couldn't read {}", e),
	};
	let fin = match File::open(input_file_path) {
		Ok(f) => f,
		Err(e) => fail!("input file error: {}", e),
	};
	let fout = match File::open_mode(&Path::new(args()[2]), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};
	let buffer_size:u64 = match from_str(args()[3]) {
		Some(num) => num,
		None => fail!("Not numeric input"),
	};
	info!("Input file size {}", size);

	//let values = read_u64(&mut fin, 2);
	//println!("Values: {}", values);
	externalSort(fin, size, fout, buffer_size * 1024 * 1024);
}

#[test]
fn generate_5gb_and_sort() {
	let mut random = match File::open(&Path::new("/dev/urandom")) {
		Ok(f) => f,
		Err(e) => fail!("Error opening urandom: {}", e),
	};

	let test_dir = match TempDir::new("externalsort-test") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let test_path = test_dir.path();

	let mut unordered_nums = match File::open_mode(&test_path.join("input"), Open, ReadWrite) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	let mut buffer = [0, .. 1024*1024];
	let mut left = 1 * 1024;
	while left > 0 {
		random.read(buffer);
		unordered_nums.write(buffer);
		left -= 1;
	}

	unordered_nums.seek(0, SeekSet);
	let ordered_nums = match File::open_mode(&test_path.join("output"), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};
	externalSort(unordered_nums, 1024 * 1024 * 1024 * 1, ordered_nums, 1024 * 1024 * 200);
	let mut ordered_nums = match File::open(&test_path.join("output")) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	let mut last = 0_u64;
	loop {
		let number = match ordered_nums.read_le_u64() {
			Ok(num) => num,
			Err(e) => fail!("failed to read u64 from file: {}", e),
		};
		assert!(number >= last);
		last = number;
	}
}
<commit_msg>Prettified the unit test a bit, no more warnings<commit_after>#![feature(phase)]
#[phase(syntax, link)] extern crate log;
extern crate collections;
use std::io::{File, Open, Write, TempDir};
use std::os::args;
use std::cast;
use std::raw::Slice;
use collections::priority_queue::PriorityQueue;
#[cfg(not(test))]
use std::from_str::from_str;
#[cfg(test)]
use std::io::{ReadWrite, SeekSet};

/*
 * an entry is the number that we read and the file it came from, so after we took
 * out one Entry from the priority queue, we need to know where to take the next number
 * from.
 */
struct Entry {
	value: u64,
	source: File,
}

/* The priority queue depends on the ordering relation and always returns the biggest */
impl Ord for Entry {
	// lesser than implementation
	fn lt(&self, other: &Entry) -> bool {
		// we invert: for us the smallest will have the highest priority
		!(self.value < other.value)
	}
}

/* ordering needs equality for some reason, so there */
impl Eq for Entry {
	fn eq(&self, other: &Entry) -> bool {
		self.value == other.value
	}
}

/* A struct to hold our queue */
struct PriorityFile {
	queue: PriorityQueue<Entry>,
}

/*
 * 'Class' that takes a list of files and does a k-way merge of the smallest values
 * from the files
 */
impl PriorityFile {
	pub fn new(files: Vec<File>) -> PriorityFile {
		let mut queue: PriorityQueue<Entry> = PriorityQueue::new();
		// now that we got the queue, populate it with initial values

		// move_iter is required to get the values themselves, not borrowed pointers to them
		for mut f in files.move_iter() {
			// read from file, append to queue
			let number = match f.read_le_u64() {
				Ok(num) => num,
				Err(e) => fail!("failed to read u64 from file: {}", e),
			};
			queue.push(Entry {value: number, source: f});
		};
		PriorityFile {queue: queue}
	}

	/* Returns the next smallest number from the list of files or None if exhausted */
	pub fn next(&mut self) -> Option<u64> {
		match self.queue.maybe_pop() {
			Some(mut res) => {
				let v = res.value;
				match res.source.read_le_u64() {
					Ok(num) => self.queue.push(Entry {value: num, source: res.source}),
					Err(_) => (),
				};
				Some(v)
			},
			None => None,
		}
	}
}

fn read_u64(from: &mut File, n: uint) -> Vec<u64> {
	// rust post 0.10 will directly return a Vec<u8> here
	let buf = match from.read_exact(n*8) {
		Ok(b) => b,
		Err(e) => fail!("reading failed {}", e),
	};
	//let u = buf.as_ptr();
	let u = buf.as_slice();

	let mut r: Slice<u64> = unsafe { cast::transmute(u) };
	assert_eq!(r.len % 8, 0);
	r.len /= 8;
	Vec::from_slice(unsafe { cast::transmute(r) })
}

fn write_u64(to: &mut File, items: &Vec<u64>) {
	let s = items.as_slice();
	let mut r: Slice<u8> = unsafe { cast::transmute(s) };
	r.len *= 8;
	let buf: &[u8] = unsafe { cast::transmute(r) };

	match to.write(buf) {
		Ok(_) => (),
		Err(e) => fail!("writing failed: {}", e),
	};
}

fn externalSort(mut fdInput: File, size: u64, mut fdOutput: File, memSize: u64) {
	let mut runs = size / memSize;
	let items_per_run = (memSize / 8) as uint;
	let over = ((size / 8) - (items_per_run as u64 * runs)) as uint;

	info!("There will be {} runs with {} elements each.", runs, items_per_run);
	if over > 0 {
		info!("And one additional run with {} items.", over);
	}

	// let's create a temporary directory to store the sorted chunks
	// neat: TempDir deletes the directory and its contents when it goes out of
	// scope
	let overflow_dir = match TempDir::new("externalsort") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let overflow_path = overflow_dir.path();
	info!("temp dir:\ncd {}", overflow_path.display());

	// start the sorting runs
	for n in range(0, runs) {
		// iterate over our 'run' buffer and read from the input file
		// I suppose the values are little endian, which considering we are most
		// likely on x86, is a reasonable assumption
		info!("Run {}, starting read", n);
		let mut run = read_u64(&mut fdInput, items_per_run);
		info!("Run {}, read finished", n);
		// O(n log n) sort from the stdlib, hopefully more or less equivalent to
		// C++ std::sort
		info!("Run {}, starting sort", n);
		run.sort();
		info!("Run {}, sort finished", n);

		// now write out the results into numbered files
		let file_path = overflow_path.join(n.to_str());
		let mut file_file = match File::open_mode(&file_path, Open, Write) {
			Ok(f) => f,
			Err(e) => fail!("overflow file failed opening for write: {}", e),
		};

		info!("Run {}, starting write", n);
		write_u64(&mut file_file, &run);
		info!("Run {}, write finished", n);
	};

	/* additional run to catch remaining objects */
	if over > 0 {
		info!("overrun starting read");
		let mut run = read_u64(&mut fdInput, over);
		info!("overrun read finished");
		info!("overrun starting sort");
		run.sort();
		info!("overrun sort finished");

		let file_path = overflow_path.join(runs.to_str());
		let mut file_file = match File::open_mode(&file_path, Open, Write) {
			Ok(f) => f,
			Err(e) => fail!("overflow file failed opening for write: {}", e),
		};
		info!("overrun starting write");
		write_u64(&mut file_file, &run);
		info!("overrun finished write");

		runs += 1;
	};

	/* sorting done, now merging */
	info!("Pre-sorting done, now k-way merge")

	// collect all file handles. Hopefully less than 4096
	let mut files = Vec::with_capacity(runs as uint);
	for n in range(0, runs) {
		let file_path = overflow_path.join(n.to_str());
		let fd = match File::open(&file_path) {
			Ok(f) => f,
			Err(e) => fail!("overflow file opening error {}", e),
		};
		files.push(fd);
	}

	// we got a nice class here that spits out sorted numbers until exhausted
	let mut pf = PriorityFile::new(files);
	// put the sorted numbers in a cache first, so they can all be written in bulk
	let mut write_cache = Vec::with_capacity(items_per_run);
	loop {
		match pf.next() {
			Some (number) => {
				// a new number was found, add it to the cache
				// and if the cache is full, write that to disk
				write_cache.push(number);
				debug!("Gathered element {}", number);
				if write_cache.len() >= items_per_run {
					info!("Writing out {} elements from cache", write_cache.len());
					write_u64(&mut fdOutput, &write_cache);
					info!("Write done");
					write_cache.clear();
				};
			},
			None => {
				info!("Ending, writing out remaining {} elements from cache", write_cache.len());
				// we finished, write remaining cache to disk
				write_u64(&mut fdOutput, &write_cache);
				info!("Write done");
				break;
			},
		};
	};
}

#[cfg(not(test))]
fn main() {
	if args().len() < 4 {
		fail!("Argument error: <inputFile> <outputFile> <memoryBufferInMB>");
	}
	let input_file_path = &Path::new(args()[1]);
	let size = match input_file_path.stat() {
		Ok(stat) => stat.size,
		Err(e) => fail!("Couldn't read {}", e),
	};
	let fin = match File::open(input_file_path) {
		Ok(f) => f,
		Err(e) => fail!("input file error: {}", e),
	};
	let fout = match File::open_mode(&Path::new(args()[2]), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};
	let buffer_size:u64 = match from_str(args()[3]) {
		Some(num) => num,
		None => fail!("Not numeric input"),
	};
	info!("Input file size {}", size);

	externalSort(fin, size, fout, buffer_size * 1024 * 1024);
}

#[test]
fn generate_5gb_and_sort() {
	let number_gigabytes = 1;

	let mut random = match File::open(&Path::new("/dev/urandom")) {
		Ok(f) => f,
		Err(e) => fail!("Error opening urandom: {}", e),
	};

	let test_dir = match TempDir::new("externalsort-test") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let test_path = test_dir.path();

	let mut unordered_nums = match File::open_mode(&test_path.join("input"), Open, ReadWrite) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	let mut buffer = [0, .. 1024*1024];
	let mut left = number_gigabytes * 1024;
	while left > 0 {
		match random.read(buffer) {
			Ok(_) => match unordered_nums.write(buffer) {
				Ok(_) => (),
				Err(e) => fail!("failed writing random numbers {}", e),
			},
			Err(e) => fail!("failed reading random numbers {}", e),
		};
		left -= 1;
	}

	match unordered_nums.seek(0, SeekSet) {
		Ok(_) => (),
		Err(e) => fail!("Failed to seek: {}", e),
	};

	let ordered_nums = match File::open_mode(&test_path.join("output"), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	externalSort(unordered_nums, 1024 * 1024 * 1024 * number_gigabytes, ordered_nums, 1024 * 1024 * 100);
	let mut ordered_nums = match File::open(&test_path.join("output")) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	let mut last = 0_u64;
	loop {
		let number = match ordered_nums.read_le_u64() {
			Ok(num) => num,
			Err(e) => fail!("failed to read u64 from file: {}", e),
		};
		assert!(number >= last);
		last = number;
	}
}
<|endoftext|>