<commit_before>//! A cell with the ability to mutate the value through an immutable reference when safe
//!
//! # Comparison with `RefCell`
//!
//! `RefCell` goes for completely runtime checking, having `try_borrow`, `try_borrow_mut`,
//! `borrow` and `borrow_mut` all taking `&self` and using custom reference types everywhere.
//!
//! `MuCell` (out of pity and the fact that “non-ascii idents are not fully supported” I did not
//! name it `ΜCell` with the crate named `µcell`) makes much more use of true Rust borrow checking
//! for a result that is more efficient and has no possibility of panicking.
//!
//! However, its purpose is not the same as `RefCell`; it is designed specifically for cases where
//! something only *needs* an immutable reference, but where being able to safely take a mutable
//! reference can improve efficiency. Say, for example, where it’s beneficial to be able to cache
//! the result of a calculation, but you don’t really want to *need* to do that.
//!
//! The purpose of all of this is for an accessor for a `T` that can be made more efficient if it
//! can have `&mut self`, but doesn’t strictly require it. For this reason, it’s often going to be
//! paired with [`std::borrow::Cow`](http://doc.rust-lang.org/std/borrow/enum.Cow.html), e.g.
//! `Cow<String, str>` (a.k.a. `std::str::CowString`) or `Cow<Vec<T>, [T]>` (a.k.a.
//! `std::vec::CowVec`), producing `Borrowed` if you are able to mutate the value or `Owned` of the
//! same data if not.
//!
//! # Examples
//!
//! This example covers most of the surface area of the library:
//!
//! ```rust
//! # use mucell::MuCell;
//! let mut cell = MuCell::new(vec![1i, 2, 3]);
//!
//! // You can borrow from the cell mutably at no cost.
//! cell.borrow_mut().push(4);
//!
//! // You can borrow immutably, too, and it’s very cheap.
//! // (Rust’s standard borrow checking prevents you from doing
//! // this while there’s a mutable reference taken out.)
//! assert_eq!(cell.borrow()[], [1, 2, 3, 4][]);
//!
//! // So long as there are no active borrows,
//! // try_mutate can be used to mutate the value.
//! assert!(cell.try_mutate(|x| x.push(5)));
//! assert_eq!(cell.borrow()[], [1, 2, 3, 4, 5][]);
//!
//! // But when there is an immutable borrow active,
//! // try_mutate says no.
//! let b = cell.borrow();
//! assert!(!cell.try_mutate(|_| unreachable!()));
//! drop(b);
//!
//! // We can have many immutable borrows at a time, too.
//! {
//!     let a = cell.borrow();
//!     let b = cell.borrow();
//!     let c = cell.borrow();
//!     assert_eq!(&*a as *const _, &*b as *const _);
//! }
//!
//! // Once they’re all cleared, try_mutate is happy again.
//! assert!(cell.try_mutate(|x| x.push(6)));
//! assert_eq!(cell.borrow()[], [1, 2, 3, 4, 5, 6][]);
//! ```
//!
//! Look at the examples in the repository for some slightly more practical (though still
//! typically contrived) examples. Also see the mucell_ref_type! docs for an example of that part of the
//! library.

#![unstable = "almost stable, but not the macro parts"]
#![no_std]
#![feature(unsafe_destructor, macro_rules, phase, default_type_params)]
#![warn(bad_style, unused, missing_docs)]

#[phase(plugin, link)] extern crate core;
extern crate serialize;
extern crate rand;
extern crate collections;

#[cfg(test)] extern crate std;

use core::cell::{Cell, UnsafeCell};
use core::default::Default;
use core::fmt;
use core::kinds::marker;
use serialize::{Encoder, Decoder, Encodable, Decodable};
use rand::{Rand, Rng};
use core::hash::{Hash, sip};
use core::prelude::{Option, Clone, Result, PartialEq, Eq, PartialOrd, Ord, Ordering, Deref, Drop};

const MUTATING: uint = -1;

/// A cell with the ability to mutate the value through an immutable reference when safe
#[stable]
pub struct MuCell<T> {
    value: UnsafeCell<T>,
    borrows: Cell<uint>,
    nocopy: marker::NoCopy,
    noshare: marker::NoSync,
}

#[stable]
impl<T> MuCell<T> {
    /// Construct a new cell containing the given value
    #[inline]
    #[stable]
    pub fn new(value: T) -> MuCell<T> {
        MuCell {
            value: UnsafeCell::new(value),
            borrows: Cell::new(0),
            nocopy: marker::NoCopy,
            noshare: marker::NoSync,
        }
    }

    /// Borrow the contained object mutably.
    ///
    /// This is genuinely and completely free.
    #[inline]
    #[stable]
    pub fn borrow_mut(&mut self) -> &mut T {
        unsafe { &mut *self.value.get() }
    }

    /// Borrow the contained object immutably.
    ///
    /// Unlike `borrow_mut`, this isn’t *quite* free, but oh, so all but! It has a smattering of
    /// reference counting. No branches, though, so it’s as fast as is computationally possible.
    #[inline]
    #[stable]
    pub fn borrow(&self) -> Ref<T> {
        let borrows = self.borrows.get();
        debug_assert!(borrows != MUTATING);
        self.borrows.set(borrows + 1);
        Ref { _parent: self }
    }

    /// Mutate the contained object if possible.
    ///
    /// If any immutable references produced by calling `borrow()` are active,
    /// this will return false, not executing the function given.
    ///
    /// If there are no immutable references active,
    /// this will execute the mutator function and return true.
    ///
    /// **Caution:** you should avoid touching `self` inside the mutator (not that it would really
    /// make much sense to be touching it, anyway); most notably, you MUST NOT call `borrow` on
    /// `self` inside the mutator, which includes things like the `==` implementation which borrow
    /// the value briefly; while calling `try_mutate` inside it will just return false, in debug
    /// builds calling `borrow` will panic and in release builds it will break memory safety as you
    /// will have both a mutable and an immutable reference to the same object at the same time
    /// (yep, it’s not quite preventing aliasing). So don’t do it.
    #[inline]
    #[stable]
    pub fn try_mutate(&self, mutator: |&mut T|) -> bool {
        if self.borrows.get() == 0 {
            self.borrows.set(MUTATING);
            mutator(unsafe { &mut *self.value.get() });
            self.borrows.set(0);
            true
        } else {
            false
        }
    }
}

/// An immutable reference to a `MuCell`. Dereference to get at the object.
#[stable]
pub struct Ref<'a, T: 'a> {
    _parent: &'a MuCell<T>,
}

#[unsafe_destructor]
#[unstable = "trait is not stable"]
impl<'a, T: 'a> Drop for Ref<'a, T> {
    fn drop(&mut self) {
        self._parent.borrows.set(self._parent.borrows.get() - 1);
    }
}

#[unstable = "trait is not stable"]
impl<'a, T: 'a> Deref<T> for Ref<'a, T> {
    fn deref(&self) -> &T {
        unsafe { &*self._parent.value.get() }
    }
}

#[unstable = "trait is not stable"]
impl<T: PartialEq> PartialEq for MuCell<T> {
    fn eq(&self, other: &MuCell<T>) -> bool {
        *self.borrow() == *other.borrow()
    }
}

#[unstable = "trait is not stable"]
impl<T: Eq> Eq for MuCell<T> { }

#[unstable = "trait is not stable"]
impl<T: PartialOrd> PartialOrd for MuCell<T> {
    fn partial_cmp(&self, other: &MuCell<T>) -> Option<Ordering> {
        self.borrow().partial_cmp(&*other.borrow())
    }
}

#[unstable = "trait is not stable"]
impl<T: Ord> Ord for MuCell<T> {
    fn cmp(&self, other: &MuCell<T>) -> Ordering {
        self.borrow().cmp(&*other.borrow())
    }
}

#[unstable = "trait is not stable"]
impl<T: Default> Default for MuCell<T> {
    fn default() -> MuCell<T> {
        MuCell::new(Default::default())
    }
}

#[unstable = "trait is not stable"]
impl<T: Clone> Clone for MuCell<T> {
    fn clone(&self) -> MuCell<T> {
        MuCell::new(self.borrow().clone())
    }
}

macro_rules! impl_fmt {
    ($($trait_name:ident)*) => {$(
        #[unstable = "trait is not stable"]
        impl<T: fmt::$trait_name> fmt::$trait_name for MuCell<T> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                self.borrow().fmt(f)
            }
        }
    )*}
}
impl_fmt!(Show Octal Binary LowerHex UpperHex Pointer LowerExp UpperExp);

#[unstable = "trait is not stable"]
impl<S: Encoder<E>, E, T: Encodable<S, E>> Encodable<S, E> for MuCell<T> {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        self.borrow().encode(s)
    }
}

#[unstable = "trait is not stable"]
impl<D: Decoder<E>, E, T: Decodable<D, E>> Decodable<D, E> for MuCell<T> {
    fn decode(d: &mut D) -> Result<MuCell<T>, E> {
        Decodable::decode(d).map(|x| MuCell::new(x))
    }
}

#[unstable = "trait is not stable"]
impl<T: Rand> Rand for MuCell<T> {
    fn rand<R: Rng>(rng: &mut R) -> MuCell<T> {
        MuCell::new(Rand::rand(rng))
    }
}

#[unstable = "trait is not stable"]
impl<T: Hash<S>, S = sip::SipState> Hash<S> for MuCell<T> {
    fn hash(&self, state: &mut S) {
        self.borrow().hash(state)
    }
}

/// Create a new reference type to something inside the cell.
///
/// Why is this necesary? Because of the tracking of immutable references (`Ref<'a, T>` rather than
/// `&'a T`), anything from the object owning the original cell wishing to return a reference to
/// something inside the cell must go producing another such reference type like `Ref`, with its
/// own `Deref` implementation and so forth. (This is the cost of efficient memory safety!)
///
/// Here’s an example of usage:
///
/// ```rust
/// #![feature(phase)]
/// #[phase(plugin, link)] extern crate mucell;
/// use mucell::{MuCell, Ref};
///
/// struct Foo {
///     bar: String,
/// }
///
/// mucell_ref_type! {
///     #[doc = "…"]
///     struct BarRef<'a>(Foo)
///     impl Deref<str>
///     data: &'a str = |x| x.bar.as_slice()
/// }
///
/// fn pull_string_out(foo: &MuCell<Foo>) -> BarRef {
///     // Maybe pretend we did something like `try_mutate` here.
///
///     // We would not be able to return foo.borrow().bar.as_slice()
///     // here because the borrow() lifetime would be too short.
///     // So we use our fancy new ref type!
///     BarRef::from(foo)
/// }
///
/// fn say(s: &str) {
///     println!("The string is “{}”", s);
/// }
///
/// fn demo(foo: &MuCell<Foo>) {
///     say(&*pull_string_out(foo));
/// }
///
/// fn main() {
///     demo(&MuCell::new(Foo { bar: "panic".into_string() }));
/// }
/// ```
///
/// The `vector_munger` example demonstrates a more complex use case.
#[macro_export]
#[experimental]
macro_rules! mucell_ref_type {
    (
        $(#[$attr:meta])*  // suggestions: doc, stability markers
        struct $ref_name:ident<'a>($ty:ty)
        impl Deref<$deref:ty>
        data: $data_ty:ty = |$data_ident:ident| $data_expr:expr
    ) => {
        /// An immutable reference to a `MuCell`. Dereference to get at the object.
        $(#[$attr])*
        pub struct $ref_name<'a> {
            _parent: Ref<'a, $ty>,
            _data: $data_ty,
        }

        #[unstable = "still a little experimental, like the whole macro"]
        impl<'a> $ref_name<'a> {
            /// Construct a reference from the cell.
            #[unstable = "still a little experimental, like the whole macro"]
            fn from(cell: &'a MuCell<$ty>) -> $ref_name<'a> {
                let parent = cell.borrow();
                // This transmutation is to fix the lifetime of the reference so it is 'a rather
                // than the block. Because we keep the parent around in the struct, it’ll be OK;
                // even if the parent destructor is run before any data destructor and it does
                // silly things with any references, because we’re not Sync it doesn’t matter if
                // `borrows` is decremented early. We could just use `transmute(&*parent)` here,
                // but for a macro it’s nice to avoid depending on std or core being in a
                // particular place is of value. (Caring about efficiency? Unoptimised, this way is
                // slightly less efficient, optimised both are noops.)
                let $data_ident: &'a $ty = unsafe { &*(&*parent as *const $ty) };
                let data = $data_expr;
                $ref_name {
                    _parent: parent,
                    _data: data,
                }
            }
        }

        #[unstable = "trait is not stable"]
        impl<'a> Deref<$deref> for $ref_name<'a> {
            fn deref<'b>(&'b self) -> &'b $deref {
                &*self._data
            }
        }
    }
}

#[test]
#[should_fail]
fn test_borrow_in_try_mutate() {
    let a = MuCell::new(());
    a.try_mutate(|_| { let _ = a.borrow(); });
}

#[test]
fn test_try_mutate_in_try_mutate() {
    let a = MuCell::new(());
    assert!(a.try_mutate(|_| assert!(!a.try_mutate(|_| unreachable!()))));
}
<commit_msg>Remove libserialize dependency<commit_after>//! A cell with the ability to mutate the value through an immutable reference when safe
//!
//! # Comparison with `RefCell`
//!
//! `RefCell` goes for completely runtime checking, having `try_borrow`, `try_borrow_mut`,
//! `borrow` and `borrow_mut` all taking `&self` and using custom reference types everywhere.
//!
//! `MuCell` (out of pity and the fact that “non-ascii idents are not fully supported” I did not
//! name it `ΜCell` with the crate named `µcell`) makes much more use of true Rust borrow checking
//! for a result that is more efficient and has no possibility of panicking.
//!
//! However, its purpose is not the same as `RefCell`; it is designed specifically for cases where
//! something only *needs* an immutable reference, but where being able to safely take a mutable
//! reference can improve efficiency. Say, for example, where it’s beneficial to be able to cache
//! the result of a calculation, but you don’t really want to *need* to do that.
//!
//! The purpose of all of this is for an accessor for a `T` that can be made more efficient if it
//! can have `&mut self`, but doesn’t strictly require it. For this reason, it’s often going to be
//! paired with [`std::borrow::Cow`](http://doc.rust-lang.org/std/borrow/enum.Cow.html), e.g.
//! `Cow<String, str>` (a.k.a. `std::str::CowString`) or `Cow<Vec<T>, [T]>` (a.k.a.
//! `std::vec::CowVec`), producing `Borrowed` if you are able to mutate the value or `Owned` of the
//! same data if not.
//!
//! # Examples
//!
//! This example covers most of the surface area of the library:
//!
//! ```rust
//! # use mucell::MuCell;
//! let mut cell = MuCell::new(vec![1i, 2, 3]);
//!
//! // You can borrow from the cell mutably at no cost.
//! cell.borrow_mut().push(4);
//!
//! // You can borrow immutably, too, and it’s very cheap.
//! // (Rust’s standard borrow checking prevents you from doing
//! // this while there’s a mutable reference taken out.)
//! assert_eq!(cell.borrow()[], [1, 2, 3, 4][]);
//!
//! // So long as there are no active borrows,
//! // try_mutate can be used to mutate the value.
//! assert!(cell.try_mutate(|x| x.push(5)));
//! assert_eq!(cell.borrow()[], [1, 2, 3, 4, 5][]);
//!
//! // But when there is an immutable borrow active,
//! // try_mutate says no.
//! let b = cell.borrow();
//! assert!(!cell.try_mutate(|_| unreachable!()));
//! drop(b);
//!
//! // We can have many immutable borrows at a time, too.
//! {
//!     let a = cell.borrow();
//!     let b = cell.borrow();
//!     let c = cell.borrow();
//!     assert_eq!(&*a as *const _, &*b as *const _);
//! }
//!
//! // Once they’re all cleared, try_mutate is happy again.
//! assert!(cell.try_mutate(|x| x.push(6)));
//! assert_eq!(cell.borrow()[], [1, 2, 3, 4, 5, 6][]);
//! ```
//!
//! Look at the examples in the repository for some slightly more practical (though still
//! typically contrived) examples. Also see the mucell_ref_type! docs for an example of that part of the
//! library.

#![unstable = "almost stable, but not the macro parts"]
#![no_std]
#![feature(unsafe_destructor, macro_rules, phase, default_type_params)]
#![warn(bad_style, unused, missing_docs)]

#[phase(plugin, link)] extern crate core;
extern crate rand;
extern crate collections;

#[cfg(test)] extern crate std;

use core::cell::{Cell, UnsafeCell};
use core::default::Default;
use core::fmt;
use core::kinds::marker;
use rand::{Rand, Rng};
use core::hash::{Hash, sip};
use core::prelude::{Option, Clone, Result, PartialEq, Eq, PartialOrd, Ord, Ordering, Deref, Drop};

const MUTATING: uint = -1;

/// A cell with the ability to mutate the value through an immutable reference when safe
#[stable]
pub struct MuCell<T> {
    value: UnsafeCell<T>,
    borrows: Cell<uint>,
    nocopy: marker::NoCopy,
    noshare: marker::NoSync,
}

#[stable]
impl<T> MuCell<T> {
    /// Construct a new cell containing the given value
    #[inline]
    #[stable]
    pub fn new(value: T) -> MuCell<T> {
        MuCell {
            value: UnsafeCell::new(value),
            borrows: Cell::new(0),
            nocopy: marker::NoCopy,
            noshare: marker::NoSync,
        }
    }

    /// Borrow the contained object mutably.
    ///
    /// This is genuinely and completely free.
    #[inline]
    #[stable]
    pub fn borrow_mut(&mut self) -> &mut T {
        unsafe { &mut *self.value.get() }
    }

    /// Borrow the contained object immutably.
    ///
    /// Unlike `borrow_mut`, this isn’t *quite* free, but oh, so all but! It has a smattering of
    /// reference counting. No branches, though, so it’s as fast as is computationally possible.
    #[inline]
    #[stable]
    pub fn borrow(&self) -> Ref<T> {
        let borrows = self.borrows.get();
        debug_assert!(borrows != MUTATING);
        self.borrows.set(borrows + 1);
        Ref { _parent: self }
    }

    /// Mutate the contained object if possible.
    ///
    /// If any immutable references produced by calling `borrow()` are active,
    /// this will return false, not executing the function given.
    ///
    /// If there are no immutable references active,
    /// this will execute the mutator function and return true.
    ///
    /// **Caution:** you should avoid touching `self` inside the mutator (not that it would really
    /// make much sense to be touching it, anyway); most notably, you MUST NOT call `borrow` on
    /// `self` inside the mutator, which includes things like the `==` implementation which borrow
    /// the value briefly; while calling `try_mutate` inside it will just return false, in debug
    /// builds calling `borrow` will panic and in release builds it will break memory safety as you
    /// will have both a mutable and an immutable reference to the same object at the same time
    /// (yep, it’s not quite preventing aliasing). So don’t do it.
    #[inline]
    #[stable]
    pub fn try_mutate(&self, mutator: |&mut T|) -> bool {
        if self.borrows.get() == 0 {
            self.borrows.set(MUTATING);
            mutator(unsafe { &mut *self.value.get() });
            self.borrows.set(0);
            true
        } else {
            false
        }
    }
}

/// An immutable reference to a `MuCell`. Dereference to get at the object.
#[stable]
pub struct Ref<'a, T: 'a> {
    _parent: &'a MuCell<T>,
}

#[unsafe_destructor]
#[unstable = "trait is not stable"]
impl<'a, T: 'a> Drop for Ref<'a, T> {
    fn drop(&mut self) {
        self._parent.borrows.set(self._parent.borrows.get() - 1);
    }
}

#[unstable = "trait is not stable"]
impl<'a, T: 'a> Deref<T> for Ref<'a, T> {
    fn deref(&self) -> &T {
        unsafe { &*self._parent.value.get() }
    }
}

#[unstable = "trait is not stable"]
impl<T: PartialEq> PartialEq for MuCell<T> {
    fn eq(&self, other: &MuCell<T>) -> bool {
        *self.borrow() == *other.borrow()
    }
}

#[unstable = "trait is not stable"]
impl<T: Eq> Eq for MuCell<T> { }

#[unstable = "trait is not stable"]
impl<T: PartialOrd> PartialOrd for MuCell<T> {
    fn partial_cmp(&self, other: &MuCell<T>) -> Option<Ordering> {
        self.borrow().partial_cmp(&*other.borrow())
    }
}

#[unstable = "trait is not stable"]
impl<T: Ord> Ord for MuCell<T> {
    fn cmp(&self, other: &MuCell<T>) -> Ordering {
        self.borrow().cmp(&*other.borrow())
    }
}

#[unstable = "trait is not stable"]
impl<T: Default> Default for MuCell<T> {
    fn default() -> MuCell<T> {
        MuCell::new(Default::default())
    }
}

#[unstable = "trait is not stable"]
impl<T: Clone> Clone for MuCell<T> {
    fn clone(&self) -> MuCell<T> {
        MuCell::new(self.borrow().clone())
    }
}

macro_rules! impl_fmt {
    ($($trait_name:ident)*) => {$(
        #[unstable = "trait is not stable"]
        impl<T: fmt::$trait_name> fmt::$trait_name for MuCell<T> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                self.borrow().fmt(f)
            }
        }
    )*}
}
impl_fmt!(Show Octal Binary LowerHex UpperHex Pointer LowerExp UpperExp);

#[unstable = "trait is not stable"]
impl<T: Rand> Rand for MuCell<T> {
    fn rand<R: Rng>(rng: &mut R) -> MuCell<T> {
        MuCell::new(Rand::rand(rng))
    }
}

#[unstable = "trait is not stable"]
impl<T: Hash<S>, S = sip::SipState> Hash<S> for MuCell<T> {
    fn hash(&self, state: &mut S) {
        self.borrow().hash(state)
    }
}

/// Create a new reference type to something inside the cell.
///
/// Why is this necesary? Because of the tracking of immutable references (`Ref<'a, T>` rather than
/// `&'a T`), anything from the object owning the original cell wishing to return a reference to
/// something inside the cell must go producing another such reference type like `Ref`, with its
/// own `Deref` implementation and so forth. (This is the cost of efficient memory safety!)
///
/// Here’s an example of usage:
///
/// ```rust
/// #![feature(phase)]
/// #[phase(plugin, link)] extern crate mucell;
/// use mucell::{MuCell, Ref};
///
/// struct Foo {
///     bar: String,
/// }
///
/// mucell_ref_type! {
///     #[doc = "…"]
///     struct BarRef<'a>(Foo)
///     impl Deref<str>
///     data: &'a str = |x| x.bar.as_slice()
/// }
///
/// fn pull_string_out(foo: &MuCell<Foo>) -> BarRef {
///     // Maybe pretend we did something like `try_mutate` here.
///
///     // We would not be able to return foo.borrow().bar.as_slice()
///     // here because the borrow() lifetime would be too short.
///     // So we use our fancy new ref type!
///     BarRef::from(foo)
/// }
///
/// fn say(s: &str) {
///     println!("The string is “{}”", s);
/// }
///
/// fn demo(foo: &MuCell<Foo>) {
///     say(&*pull_string_out(foo));
/// }
///
/// fn main() {
///     demo(&MuCell::new(Foo { bar: "panic".to_string() }));
/// }
/// ```
///
/// The `vector_munger` example demonstrates a more complex use case.
#[macro_export]
#[experimental]
macro_rules! mucell_ref_type {
    (
        $(#[$attr:meta])*  // suggestions: doc, stability markers
        struct $ref_name:ident<'a>($ty:ty)
        impl Deref<$deref:ty>
        data: $data_ty:ty = |$data_ident:ident| $data_expr:expr
    ) => {
        /// An immutable reference to a `MuCell`. Dereference to get at the object.
        $(#[$attr])*
        pub struct $ref_name<'a> {
            _parent: Ref<'a, $ty>,
            _data: $data_ty,
        }

        #[unstable = "still a little experimental, like the whole macro"]
        impl<'a> $ref_name<'a> {
            /// Construct a reference from the cell.
            #[unstable = "still a little experimental, like the whole macro"]
            fn from(cell: &'a MuCell<$ty>) -> $ref_name<'a> {
                let parent = cell.borrow();
                // This transmutation is to fix the lifetime of the reference so it is 'a rather
                // than the block. Because we keep the parent around in the struct, it’ll be OK;
                // even if the parent destructor is run before any data destructor and it does
                // silly things with any references, because we’re not Sync it doesn’t matter if
                // `borrows` is decremented early. We could just use `transmute(&*parent)` here,
                // but for a macro it’s nice to avoid depending on std or core being in a
                // particular place is of value. (Caring about efficiency? Unoptimised, this way is
                // slightly less efficient, optimised both are noops.)
                let $data_ident: &'a $ty = unsafe { &*(&*parent as *const $ty) };
                let data = $data_expr;
                $ref_name {
                    _parent: parent,
                    _data: data,
                }
            }
        }

        #[unstable = "trait is not stable"]
        impl<'a> Deref<$deref> for $ref_name<'a> {
            fn deref<'b>(&'b self) -> &'b $deref {
                &*self._data
            }
        }
    }
}

#[test]
#[should_fail]
fn test_borrow_in_try_mutate() {
    let a = MuCell::new(());
    a.try_mutate(|_| { let _ = a.borrow(); });
}

#[test]
fn test_try_mutate_in_try_mutate() {
    let a = MuCell::new(());
    assert!(a.try_mutate(|_| assert!(!a.try_mutate(|_| unreachable!()))));
}
<|endoftext|>


<commit_before>#![feature(core)]
#![feature(collections)]
#![feature(io)]
#![feature(test)]

//! # Rust-bio, a rusty bioinformatics library.
//!
//! This library provides implementations of many algorithms and data structures
//! that are useful for bioinformatics.
//! All provided implementations are rigorously tested via continuous
//! integration (https://travis-ci.org/johanneskoester/rust-bio).
//!
//! Currently, rust-bio provides
//!
//! * pattern matching,
//! * pairwise alignment,
//! * suffix arrays,
//! * BWT and FM-Index,
//! * rank/select data structures.
//!
//! Find out more at https://github.com/johanneskoester/rust-bio.

extern crate test;
use std::collections::HashMap;

pub mod utils;
pub mod alphabets;
pub mod pattern_matching;
pub mod data_structures;
pub mod alignment;
pub mod bitencoding;
<commit_msg>Cleanup.<commit_after>#![feature(core)]
#![feature(collections)]
#![feature(test)]

//! # Rust-bio, a rusty bioinformatics library.
//!
//! This library provides implementations of many algorithms and data structures
//! that are useful for bioinformatics.
//! All provided implementations are rigorously tested via continuous
//! integration (https://travis-ci.org/johanneskoester/rust-bio).
//!
//! Currently, rust-bio provides
//!
//! * pattern matching,
//! * pairwise alignment,
//! * suffix arrays,
//! * BWT and FM-Index,
//! * rank/select data structures.
//!
//! Find out more at https://github.com/johanneskoester/rust-bio.

extern crate test;

pub mod utils;
pub mod alphabets;
pub mod pattern_matching;
pub mod data_structures;
pub mod alignment;
pub mod bitencoding;
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;
use std::ffi::CStr;
use std::os::raw::c_char;

use nom::{le_u64,le_u32,le_i32};
use nom::IResult;

// These are all integer_t, aka int
#[allow(non_camel_case_types)]
pub type cpu_type_t = i32;
#[allow(non_camel_case_types)]
pub type cpu_subtype_t = u32;
#[allow(non_camel_case_types)]
pub type vm_prot_t = i32;

#[derive(Debug)]
pub struct MachHeader {
    pub header: MachHeader_,
    pub segments: Vec<SegmentCommand>,
}

#[derive(Debug)]
pub struct MachHeader_ {
    pub magic: u32,
    pub cputype: cpu_type_t,
    pub cpusubtype: cpu_subtype_t,
    pub filetype: u32,
    pub ncmds: u32,
    pub sizeofcmds: u32,
    pub flags: u32,
    reserved :u32,
}

impl MachHeader {
    pub fn parse(bytes: &[u8]) -> Option<MachHeader> {
        if let IResult::Done(_rest, header) = mach_header(bytes) {
            let mut rest = _rest;
            let mut segments = vec![];
            for _ in 0.. header.ncmds {
                if let IResult::Done(_rest, cmd) = segment_command(rest) {
                    rest = _rest;
                    segments.push(cmd);
                } else {
                    return None
                }
            }

            Some(MachHeader {
                header: header,
                segments: segments,
            })
        } else {
            return None
        }
    }
}

#[derive(Debug)]
pub struct SegmentCommand {
    pub cmd: u32,
    pub cmdsize: u32,
    pub segname: String,
    pub vmaddr: u32,
    pub vmsize: u32,
    pub fileoff: u32,
    pub filesize: u32,
    pub maxprot: vm_prot_t,
    pub initprot: vm_prot_t,
    pub nsects: u32,
    pub flags: u32,
}

named!(mach_header<&[u8], MachHeader_>,
       chain!(
           magic: le_u32 ~
           cputype: le_i32 ~
           cpusubtype: le_u32 ~
           filetype: le_u32 ~
           ncmds: le_u32 ~
           sizeofcmds: le_u32 ~
           flags: le_u32 ~
           reserved: le_u32,

           || {
               assert_eq!(0xfeedfacf, magic);
               MachHeader_ {
                   magic: magic,
                   cputype: cputype,
                   // This value needs to be masked to match otool -h
                   cpusubtype: cpusubtype,
                   filetype: filetype,
                   ncmds: ncmds,
                   sizeofcmds: sizeofcmds,
                   flags: flags,
                   reserved: reserved,
               }
           }
           )
       );

named!(segment_command<&[u8], SegmentCommand>,
       chain!(
           cmd: le_u32 ~
           cmdsize: le_u32 ~
           segname: take!(16) ~
           vmaddr: le_u32 ~
           vmsize: le_u32 ~
           fileoff: le_u32 ~
           filesize: le_u32 ~
           maxprot: le_i32 ~
           initprot: le_i32 ~
           nsects: le_u32 ~
           flags: le_u32 ,

           || {

               let slice = unsafe { CStr::from_ptr(segname.as_ptr() as *const c_char) };
               let name = std::str::from_utf8(slice.to_bytes()).unwrap().to_string();

               SegmentCommand {
                   cmd: cmd,
                   cmdsize: cmdsize,
                   segname: name,
                   vmaddr: vmaddr,
                   vmsize: vmsize,
                   fileoff: fileoff,
                   filesize: filesize,
                   maxprot: maxprot,
                   initprot: initprot,
                   nsects: nsects,
                   flags: flags,
               }
           }
        )
    );

<commit_msg>use the 64 bit variant<commit_after>#[macro_use]
extern crate nom;
use std::ffi::CStr;
use std::os::raw::c_char;

use nom::{le_u64,le_u32,le_i32};
use nom::IResult;

// These are all integer_t, aka int
#[allow(non_camel_case_types)]
pub type cpu_type_t = i32;
#[allow(non_camel_case_types)]
pub type cpu_subtype_t = u32;
#[allow(non_camel_case_types)]
pub type vm_prot_t = i32;

#[derive(Debug)]
pub struct MachHeader {
    pub header: MachHeader_,
    pub segments: Vec<SegmentCommand>,
}

#[derive(Debug)]
pub struct MachHeader_ {
    pub magic: u32,
    pub cputype: cpu_type_t,
    pub cpusubtype: cpu_subtype_t,
    pub filetype: u32,
    pub ncmds: u32,
    pub sizeofcmds: u32,
    pub flags: u32,
    reserved :u32,
}

impl MachHeader {
    pub fn parse(bytes: &[u8]) -> Option<MachHeader> {
        if let IResult::Done(_rest, header) = mach_header(bytes) {
            let mut rest = _rest;
            let mut segments = vec![];
            for _ in 0.. header.ncmds {
                if let IResult::Done(_rest, cmd) = segment_command(rest) {
                    rest = _rest;
                    segments.push(cmd);
                } else {
                    return None
                }
            }

            Some(MachHeader {
                header: header,
                segments: segments,
            })
        } else {
            return None
        }
    }
}

#[derive(Debug)]
pub struct SegmentCommand {
    pub cmd: u32,
    pub cmdsize: u32,
    pub segname: String,
    pub vmaddr: u64,
    pub vmsize: u64,
    pub fileoff: u64,
    pub filesize: u64,
    pub maxprot: vm_prot_t,
    pub initprot: vm_prot_t,
    pub nsects: u32,
    pub flags: u32,
}

named!(mach_header<&[u8], MachHeader_>,
       chain!(
           magic: le_u32 ~
           cputype: le_i32 ~
           cpusubtype: le_u32 ~
           filetype: le_u32 ~
           ncmds: le_u32 ~
           sizeofcmds: le_u32 ~
           flags: le_u32 ~
           reserved: le_u32,

           || {
               assert_eq!(0xfeedfacf, magic);
               MachHeader_ {
                   magic: magic,
                   cputype: cputype,
                   // This value needs to be masked to match otool -h
                   cpusubtype: cpusubtype,
                   filetype: filetype,
                   ncmds: ncmds,
                   sizeofcmds: sizeofcmds,
                   flags: flags,
                   reserved: reserved,
               }
           }
           )
       );

named!(segment_command<&[u8], SegmentCommand>,
       chain!(
           cmd: le_u32 ~
           cmdsize: le_u32 ~
           segname: take!(16) ~
           vmaddr: le_u32 ~
           vmsize: le_u32 ~
           fileoff: le_u32 ~
           filesize: le_u32 ~
           maxprot: le_i32 ~
           initprot: le_i32 ~
           nsects: le_u32 ~
           flags: le_u32 ,

           || {

               let slice = unsafe { CStr::from_ptr(segname.as_ptr() as *const c_char) };
               let name = std::str::from_utf8(slice.to_bytes()).unwrap().to_string();

               SegmentCommand {
                   cmd: cmd,
                   cmdsize: cmdsize,
                   segname: name,
                   vmaddr: vmaddr,
                   vmsize: vmsize,
                   fileoff: fileoff,
                   filesize: filesize,
                   maxprot: maxprot,
                   initprot: initprot,
                   nsects: nsects,
                   flags: flags,
               }
           }
        )
    );

<|endoftext|>


<commit_before>//! This crate provides (at this time) a single function, `take()`.
//!
//! `take()` allows for taking `T` out of a `&mut T`, doing anything with it including consuming it, and producing another `T` to put back in the `&mut T`.
//!
//! During `take()`, if a panic occurs, the entire process will be exited, as there's no valid `T` to put back into the `&mut T`.
//!
//! Contrast with `std::mem::replace()`, which allows for putting a different `T` into a `&mut T`, but requiring the new `T` to be available before being able to consume the old `T`.

mod exit_on_panic;

use exit_on_panic::exit_on_panic;

/// Allows use of a value pointed to by `&mut T` as though it was owned, as long as a `T` is made available afterwards.
///
/// The closure must return a valid T.
/// # Important
/// Will exit the program (with status code 101) if the closure panics.
///
/// # Example
/// ```
/// struct Foo;
/// let mut foo = Foo;
/// take_mut::take(&mut foo, |foo| {
///     // Can now consume the Foo, and provide a new value later
///     drop(foo);
///     // Do more stuff
///     Foo // Return new Foo from closure, which goes back into the &mut Foo
/// });
/// ```
pub fn take<T, F>(mut_ref: &mut T, closure: F)
  where F: FnOnce(T) -> T {
    use std::ptr;
    exit_on_panic(|| {
        unsafe {
            let old_t = ptr::read(mut_ref);
            let new_t = closure(old_t);
            ptr::write(mut_ref, new_t);
        }
    });
}

use std::cell::Cell;

pub struct Scope {
    active_holes: Cell<usize>
}

impl Scope {
    pub fn scope<F>(f: F)
    where F: FnOnce(&Scope) {
        let aborter = AbortOnSuddenDrop::new();
        let this = Scope { active_holes: Cell::new(0) };
        f(&this);
        if this.active_holes.get() != 0 {
            panic!("There are still unfilled Holes!");
        }
        aborter.done();
    }
    // TODO: NEED TO GUARANTEE THAT MUTABLE OBJECT IN QUESTION IS NOT A SMALLER LIFETIME
    pub fn take<'s, 'm: 's, T: 'm>(&'s self, mut_ref: &'m mut T) -> (T, Hole<'s, 'm, T>) {
        use std::ptr;

        let num_holes = self.active_holes.get();
        if num_holes == std::usize::MAX {
            panic!("Failed to create new Hole, already usize::MAX unfilled holes.");
        }
        self.active_holes.set(num_holes + 1);
        let t: T;
        let hole: Hole<'s, 'm, T>;
        unsafe {
            t = ptr::read(mut_ref);
            hole = Hole { scope: self, hole: mut_ref };
        };
        (t, hole)
    }
}

pub struct Hole<'scope, 'm, T: 'm> {
    scope: &'scope Scope,
    hole: &'m mut T
}

impl<'scope, 'm, T: 'm> Hole<'scope, 'm, T> {
    pub fn fill(self, t: T) {
        use std::ptr;

        unsafe {
            ptr::write(self.hole, t);
        }

        self.scope.active_holes.set(self.scope.active_holes.get() - 1);
    }
}

#[test]
fn it_works() {
    #[derive(PartialEq, Eq, Debug)]
    enum Foo {A, B};
    impl Drop for Foo {
        fn drop(&mut self) {
            match *self {
                Foo::A => println!("Foo::A dropped"),
                Foo::B => println!("Foo::B dropped")
            }
        }
    }
    let mut foo = Foo::A;
    take(&mut foo, |mut f| {
       drop(f);
       Foo::B
    });
    assert_eq!(&foo, &Foo::B);
}

#[test]
fn scope_based_take() {
    #[derive(Debug)]
    struct Foo;

    #[derive(Debug)]
    struct Bar {
        a: Foo,
        b: Foo
    }
    let mut bar = Bar { a: Foo, b: Foo };
    Scope::scope(|scope| {
        let (a, a_hole) = scope.take(&mut bar.a);
        let (b, b_hole) = scope.take(&mut bar.b);
        // Imagine consuming a and b
        a_hole.fill(Foo);
        b_hole.fill(Foo);
    });
    println!("{:?}", &bar);
}<commit_msg>Switch to exit_on_panic<commit_after>//! This crate provides (at this time) a single function, `take()`.
//!
//! `take()` allows for taking `T` out of a `&mut T`, doing anything with it including consuming it, and producing another `T` to put back in the `&mut T`.
//!
//! During `take()`, if a panic occurs, the entire process will be exited, as there's no valid `T` to put back into the `&mut T`.
//!
//! Contrast with `std::mem::replace()`, which allows for putting a different `T` into a `&mut T`, but requiring the new `T` to be available before being able to consume the old `T`.

mod exit_on_panic;

use exit_on_panic::exit_on_panic;

/// Allows use of a value pointed to by `&mut T` as though it was owned, as long as a `T` is made available afterwards.
///
/// The closure must return a valid T.
/// # Important
/// Will exit the program (with status code 101) if the closure panics.
///
/// # Example
/// ```
/// struct Foo;
/// let mut foo = Foo;
/// take_mut::take(&mut foo, |foo| {
///     // Can now consume the Foo, and provide a new value later
///     drop(foo);
///     // Do more stuff
///     Foo // Return new Foo from closure, which goes back into the &mut Foo
/// });
/// ```
pub fn take<T, F>(mut_ref: &mut T, closure: F)
  where F: FnOnce(T) -> T {
    use std::ptr;
    exit_on_panic(|| {
        unsafe {
            let old_t = ptr::read(mut_ref);
            let new_t = closure(old_t);
            ptr::write(mut_ref, new_t);
        }
    });
}

use std::cell::Cell;

pub struct Scope {
    active_holes: Cell<usize>
}

impl Scope {
    pub fn scope<F>(f: F)
    where F: FnOnce(&Scope) {
        exit_on_panic(|| {
            let this = Scope { active_holes: Cell::new(0) };
            f(&this);
            if this.active_holes.get() != 0 {
                panic!("There are still unfilled Holes!");
            }
        });
    }
    // TODO: NEED TO GUARANTEE THAT MUTABLE OBJECT IN QUESTION IS NOT A SMALLER LIFETIME
    pub fn take<'s, 'm: 's, T: 'm>(&'s self, mut_ref: &'m mut T) -> (T, Hole<'s, 'm, T>) {
        use std::ptr;

        let num_holes = self.active_holes.get();
        if num_holes == std::usize::MAX {
            panic!("Failed to create new Hole, already usize::MAX unfilled holes.");
        }
        self.active_holes.set(num_holes + 1);
        let t: T;
        let hole: Hole<'s, 'm, T>;
        unsafe {
            t = ptr::read(mut_ref);
            hole = Hole { scope: self, hole: mut_ref };
        };
        (t, hole)
    }
}

pub struct Hole<'scope, 'm, T: 'm> {
    scope: &'scope Scope,
    hole: &'m mut T
}

impl<'scope, 'm, T: 'm> Hole<'scope, 'm, T> {
    pub fn fill(self, t: T) {
        use std::ptr;

        unsafe {
            ptr::write(self.hole, t);
        }

        self.scope.active_holes.set(self.scope.active_holes.get() - 1);
    }
}

#[test]
fn it_works() {
    #[derive(PartialEq, Eq, Debug)]
    enum Foo {A, B};
    impl Drop for Foo {
        fn drop(&mut self) {
            match *self {
                Foo::A => println!("Foo::A dropped"),
                Foo::B => println!("Foo::B dropped")
            }
        }
    }
    let mut foo = Foo::A;
    take(&mut foo, |mut f| {
       drop(f);
       Foo::B
    });
    assert_eq!(&foo, &Foo::B);
}

#[test]
fn scope_based_take() {
    #[derive(Debug)]
    struct Foo;

    #[derive(Debug)]
    struct Bar {
        a: Foo,
        b: Foo
    }
    let mut bar = Bar { a: Foo, b: Foo };
    Scope::scope(|scope| {
        let (a, a_hole) = scope.take(&mut bar.a);
        let (b, b_hole) = scope.take(&mut bar.b);
        // Imagine consuming a and b
        a_hole.fill(Foo);
        b_hole.fill(Foo);
    });
    println!("{:?}", &bar);
}<|endoftext|>


<commit_before>use rustc_serialize::{Encodable, Decodable};
use super::master::{self, Master};
use super::slave::Slave;
use super::error::{ErrorKind, Result};
use super::error::master::Result as MasterResult;
use super::value::Topic;
use super::naming::{self, Resolver};
use super::resolve;
use tcpros::{Client, Message, PublisherStream, ServicePair, ServiceResult};
use rosxmlrpc::serde::XmlRpcValue;
use std::time::Duration;

pub struct Ros {
    master: Master,
    slave: Slave,
    hostname: String,
    resolver: Resolver,
    name: String,
}

impl Ros {
    pub fn new(name: &str) -> Result<Ros> {
        let namespace = resolve::namespace();
        let master_uri = resolve::master();
        let hostname = resolve::hostname();
        let name = resolve::name(name);
        let mut ros = Ros::new_raw(&master_uri, &hostname, &namespace, &name)?;
        for (src, dest) in resolve::mappings() {
            ros.map(&src, &dest)?;
        }
        Ok(ros)
    }

    fn new_raw(master_uri: &str, hostname: &str, namespace: &str, name: &str) -> Result<Ros> {
        let namespace = namespace.trim_right_matches("/");

        if name.contains("/") {
            bail!(ErrorKind::Naming(naming::error::ErrorKind::IllegalCharacter(name.into())));
        }

        let name = format!("{}/{}", namespace, name);
        let resolver = Resolver::new(&name)?;

        let slave = Slave::new(&master_uri, &hostname, 0, &name)?;
        let master = Master::new(&master_uri, &name, &slave.uri());
        Ok(Ros {
               master: master,
               slave: slave,
               hostname: String::from(hostname),
               resolver: resolver,
               name: name,
           })
    }

    fn map(&mut self, source: &str, destination: &str) -> Result<()> {
        self.resolver.map(source, destination).map_err(|v| v.into())
    }

    pub fn uri(&self) -> &str {
        return self.slave.uri();
    }

    pub fn param<'a, 'b>(&'a self, name: &'b str) -> Option<Parameter<'a>> {
        self.resolver
            .translate(name)
            .ok()
            .map(|v| {
                     Parameter {
                         master: &self.master,
                         name: v,
                     }
                 })
    }

    pub fn parameters(&self) -> MasterResult<Vec<String>> {
        self.master.get_param_names()
    }

    pub fn state(&self) -> MasterResult<master::SystemState> {
        self.master.get_system_state()
    }

    pub fn topics(&self) -> MasterResult<Vec<Topic>> {
        self.master.get_topic_types()
    }

    pub fn client<T: ServicePair>(&self, service: &str) -> Result<Client<T>> {
        let name = self.resolver.translate(service)?;
        let uri = self.master.lookup_service(&name)?;
        Ok(Client::new(&self.name, &uri, &name))
    }

    pub fn wait_for_service(&self, service: &str, timeout: Option<Duration>) -> Result<()> {
        use super::error::master::ErrorKind::Api;
        use super::error::api::ErrorKind::BadData;
        use std::thread::sleep;

        let name = self.resolver.translate(service)?;
        let now = ::std::time::Instant::now();
        loop {
            let e = match self.master.lookup_service(&name) {
                Ok(_) => return Ok(()),
                Err(e) => e,
            };
            match e.kind() {
                &Api(BadData(ref m)) if m == "no provider" => {
                    if let Some(ref timeout) = timeout {
                        if &now.elapsed() > timeout {
                            return Err(ErrorKind::TimeoutError.into());
                        }
                    }
                    sleep(Duration::from_millis(100));
                    continue;
                }
                _ => {}
            }
            return Err(e.into());
        }
        unreachable!();
    }

    pub fn service<T, F>(&mut self, service: &str, handler: F) -> Result<()>
        where T: ServicePair,
              F: Fn(T::Request) -> ServiceResult<T::Response> + Send + Sync + 'static
    {
        let name = self.resolver.translate(service)?;
        let api = self.slave
            .add_service::<T, F>(&self.hostname, &name, handler)?;

        if let Err(err) = self.master.register_service(&name, &api) {
            self.slave.remove_service(&name);
            self.master.unregister_service(&name, &api)?;
            Err(err.into())
        } else {
            Ok(())
        }

    }

    pub fn subscribe<T, F>(&mut self, topic: &str, callback: F) -> Result<()>
        where T: Message,
              F: Fn(T) -> () + Send + 'static
    {
        let name = self.resolver.translate(topic)?;
        self.slave.add_subscription::<T, F>(&name, callback)?;

        match self.master.register_subscriber(&name, &T::msg_type()) {
            Ok(publishers) => {
                if let Err(err) =
                    self.slave
                        .add_publishers_to_subscription(&name, publishers.into_iter()) {
                    error!("Failed to subscribe to all publishers of topic '{}': {}",
                           name,
                           err);
                }
                Ok(())
            }
            Err(err) => {
                self.slave.remove_subscription(&name);
                self.master.unregister_subscriber(&name)?;
                Err(err.into())
            }
        }
    }

    pub fn publish<T>(&mut self, topic: &str) -> Result<PublisherStream<T>>
        where T: Message
    {
        let name = self.resolver.translate(topic)?;
        let stream = self.slave.add_publication::<T>(&self.hostname, &name)?;
        match self.master.register_publisher(&name, &T::msg_type()) {
            Ok(_) => Ok(stream),
            Err(error) => {
                error!("Failed to register publisher for topic '{}': {}",
                       name,
                       error);
                self.slave.remove_publication(&name);
                self.master.unregister_publisher(&name)?;
                Err(error.into())
            }
        }
    }
}

pub struct Parameter<'a> {
    master: &'a Master,
    name: String,
}

impl<'a> Parameter<'a> {
    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn get<T: Decodable>(&self) -> MasterResult<T> {
        self.master.get_param::<T>(&self.name)
    }

    pub fn get_raw(&self) -> MasterResult<XmlRpcValue> {
        self.master.get_param_any(&self.name)
    }

    pub fn set<T: Encodable>(&self, value: &T) -> MasterResult<()> {
        self.master.set_param::<T>(&self.name, value).and(Ok(()))
    }

    pub fn delete(&self) -> MasterResult<()> {
        self.master.delete_param(&self.name).and(Ok(()))
    }

    pub fn exists(&self) -> MasterResult<bool> {
        self.master.has_param(&self.name)
    }

    pub fn search(&self) -> MasterResult<String> {
        self.master.search_param(&self.name)
    }
}
<commit_msg>expose name and hostname for Ros struct<commit_after>use rustc_serialize::{Encodable, Decodable};
use super::master::{self, Master};
use super::slave::Slave;
use super::error::{ErrorKind, Result};
use super::error::master::Result as MasterResult;
use super::value::Topic;
use super::naming::{self, Resolver};
use super::resolve;
use tcpros::{Client, Message, PublisherStream, ServicePair, ServiceResult};
use rosxmlrpc::serde::XmlRpcValue;
use std::time::Duration;

pub struct Ros {
    master: Master,
    slave: Slave,
    hostname: String,
    resolver: Resolver,
    name: String,
}

impl Ros {
    pub fn new(name: &str) -> Result<Ros> {
        let namespace = resolve::namespace();
        let master_uri = resolve::master();
        let hostname = resolve::hostname();
        let name = resolve::name(name);
        let mut ros = Ros::new_raw(&master_uri, &hostname, &namespace, &name)?;
        for (src, dest) in resolve::mappings() {
            ros.map(&src, &dest)?;
        }
        Ok(ros)
    }

    fn new_raw(master_uri: &str, hostname: &str, namespace: &str, name: &str) -> Result<Ros> {
        let namespace = namespace.trim_right_matches("/");

        if name.contains("/") {
            bail!(ErrorKind::Naming(naming::error::ErrorKind::IllegalCharacter(name.into())));
        }

        let name = format!("{}/{}", namespace, name);
        let resolver = Resolver::new(&name)?;

        let slave = Slave::new(&master_uri, &hostname, 0, &name)?;
        let master = Master::new(&master_uri, &name, &slave.uri());
        Ok(Ros {
               master: master,
               slave: slave,
               hostname: String::from(hostname),
               resolver: resolver,
               name: name,
           })
    }

    fn map(&mut self, source: &str, destination: &str) -> Result<()> {
        self.resolver.map(source, destination).map_err(|v| v.into())
    }

    pub fn uri(&self) -> &str {
        return self.slave.uri();
    }

    pub fn name(&self) -> &str {
        return &self.name;
    }

    pub fn hostname(&self) -> &str {
        return &self.hostname;
    }

    pub fn param<'a, 'b>(&'a self, name: &'b str) -> Option<Parameter<'a>> {
        self.resolver
            .translate(name)
            .ok()
            .map(|v| {
                     Parameter {
                         master: &self.master,
                         name: v,
                     }
                 })
    }

    pub fn parameters(&self) -> MasterResult<Vec<String>> {
        self.master.get_param_names()
    }

    pub fn state(&self) -> MasterResult<master::SystemState> {
        self.master.get_system_state()
    }

    pub fn topics(&self) -> MasterResult<Vec<Topic>> {
        self.master.get_topic_types()
    }

    pub fn client<T: ServicePair>(&self, service: &str) -> Result<Client<T>> {
        let name = self.resolver.translate(service)?;
        let uri = self.master.lookup_service(&name)?;
        Ok(Client::new(&self.name, &uri, &name))
    }

    pub fn wait_for_service(&self, service: &str, timeout: Option<Duration>) -> Result<()> {
        use super::error::master::ErrorKind::Api;
        use super::error::api::ErrorKind::BadData;
        use std::thread::sleep;

        let name = self.resolver.translate(service)?;
        let now = ::std::time::Instant::now();
        loop {
            let e = match self.master.lookup_service(&name) {
                Ok(_) => return Ok(()),
                Err(e) => e,
            };
            match e.kind() {
                &Api(BadData(ref m)) if m == "no provider" => {
                    if let Some(ref timeout) = timeout {
                        if &now.elapsed() > timeout {
                            return Err(ErrorKind::TimeoutError.into());
                        }
                    }
                    sleep(Duration::from_millis(100));
                    continue;
                }
                _ => {}
            }
            return Err(e.into());
        }
        unreachable!();
    }

    pub fn service<T, F>(&mut self, service: &str, handler: F) -> Result<()>
        where T: ServicePair,
              F: Fn(T::Request) -> ServiceResult<T::Response> + Send + Sync + 'static
    {
        let name = self.resolver.translate(service)?;
        let api = self.slave
            .add_service::<T, F>(&self.hostname, &name, handler)?;

        if let Err(err) = self.master.register_service(&name, &api) {
            self.slave.remove_service(&name);
            self.master.unregister_service(&name, &api)?;
            Err(err.into())
        } else {
            Ok(())
        }

    }

    pub fn subscribe<T, F>(&mut self, topic: &str, callback: F) -> Result<()>
        where T: Message,
              F: Fn(T) -> () + Send + 'static
    {
        let name = self.resolver.translate(topic)?;
        self.slave.add_subscription::<T, F>(&name, callback)?;

        match self.master.register_subscriber(&name, &T::msg_type()) {
            Ok(publishers) => {
                if let Err(err) =
                    self.slave
                        .add_publishers_to_subscription(&name, publishers.into_iter()) {
                    error!("Failed to subscribe to all publishers of topic '{}': {}",
                           name,
                           err);
                }
                Ok(())
            }
            Err(err) => {
                self.slave.remove_subscription(&name);
                self.master.unregister_subscriber(&name)?;
                Err(err.into())
            }
        }
    }

    pub fn publish<T>(&mut self, topic: &str) -> Result<PublisherStream<T>>
        where T: Message
    {
        let name = self.resolver.translate(topic)?;
        let stream = self.slave.add_publication::<T>(&self.hostname, &name)?;
        match self.master.register_publisher(&name, &T::msg_type()) {
            Ok(_) => Ok(stream),
            Err(error) => {
                error!("Failed to register publisher for topic '{}': {}",
                       name,
                       error);
                self.slave.remove_publication(&name);
                self.master.unregister_publisher(&name)?;
                Err(error.into())
            }
        }
    }
}

pub struct Parameter<'a> {
    master: &'a Master,
    name: String,
}

impl<'a> Parameter<'a> {
    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn get<T: Decodable>(&self) -> MasterResult<T> {
        self.master.get_param::<T>(&self.name)
    }

    pub fn get_raw(&self) -> MasterResult<XmlRpcValue> {
        self.master.get_param_any(&self.name)
    }

    pub fn set<T: Encodable>(&self, value: &T) -> MasterResult<()> {
        self.master.set_param::<T>(&self.name, value).and(Ok(()))
    }

    pub fn delete(&self) -> MasterResult<()> {
        self.master.delete_param(&self.name).and(Ok(()))
    }

    pub fn exists(&self) -> MasterResult<bool> {
        self.master.has_param(&self.name)
    }

    pub fn search(&self) -> MasterResult<String> {
        self.master.search_param(&self.name)
    }
}
<|endoftext|>


<commit_before>use std::io::{Cursor, Result, SeekFrom, Seek, Error, ErrorKind};
use std::fs::{File};
use std::path::Path;
use byteorder::{LittleEndian, ReadBytesExt};
use mul_reader::MulReader;
use color::Color16;

pub const BLOCK_SIZE: usize = 196;
pub const OFFSET: u32 = 4;
pub const MAP0_SIZE: u32 = 393216;

#[derive(Clone, Copy)]
pub struct Cell {
    pub graphic: u16,
    pub altitude: i8,
}

#[derive(Copy)]
pub struct Block {
    pub header: u32,
    pub cells: [Cell; 64]
}

impl Clone for Block {
    fn clone(&self) -> Self {
        let mut cells = [Cell {graphic: 0, altitude: 0}; 64];
        for i in 0..64 {
            cells[i] = self.cells[i].clone();
        }
        Block {
            header: self.header,
            cells: cells
        }
    }
}

pub struct StaticLocation {
    pub object_id: u16,
    pub x: u8,
    pub y: u8,
    pub altitude: i8,
    pub unknown: u16
}

impl StaticLocation {
    pub fn color_idx(&self) -> u16 {
        self.object_id + 16384
    }
}

pub struct MapReader {
    data_reader: File,
    width: u32,
    height: u32
}

impl MapReader {

    pub fn new(map_path: &Path, width: u32, height: u32) -> Result<MapReader> {
        let data_reader = try!(File::open(map_path));

        Ok(MapReader {
            data_reader: data_reader,
            width: width,
            height: height
        })
    }

    /**
     * Read a specific block from a map
     */
    pub fn read_block(&mut self, id: u32) -> Result<Block> {
        //Cycle to id * 192
        try!(self.data_reader.seek(SeekFrom::Start((id * BLOCK_SIZE as u32) as u64)));
        //Read the header
        let mut block = Block {
            header: try!(self.data_reader.read_u32::<LittleEndian>()),
            cells: [Cell {graphic: 0, altitude: 0}; 64]
        };
        //Read 64 cells
        for i in 0..64 {
            block.cells[i] = Cell{
                graphic: try!(self.data_reader.read_u16::<LittleEndian>()),
                altitude: try!(self.data_reader.read_i8())
            };
        }
        Ok(block)
    }

    pub fn read_block_from_coordinates(&mut self, x: u32, y: u32) -> Result<Block> {
        let width = self.width;
        let height = self.height;
        if x < width && y < height {
            self.read_block(y + (x * height))
        } else {
            Err(Error::new(
                ErrorKind::Other,
                format!("{} {} is outside of valid map coordinates", x, y)
            ))
        }
    }
}

pub struct StaticReader {
    mul_reader: MulReader,
    width: u32,
    height: u32
}

impl StaticReader {

    pub fn new(index_path: &Path, mul_path: &Path, width: u32, height: u32) -> Result<StaticReader> {
        let mul_reader = try!(MulReader::new(index_path, mul_path));

        Ok(StaticReader {
            mul_reader: mul_reader,
            width: width,
            height: height
        })
    }

    pub fn read_block(&mut self, id: u32) -> Result<Vec<StaticLocation>> {
        let raw = try!(self.mul_reader.read(id));
        let len = raw.data.len();
        assert!(len % 7 == 0);
        let mut reader = Cursor::new(raw.data);
        let mut statics = vec![];
        for _i in 0..(len / 7) {
            let object_id = try!(reader.read_u16::<LittleEndian>());
            let x = try!(reader.read_u8());
            let y = try!(reader.read_u8());
            let altitude = try!(reader.read_i8());
            let unknown = try!(reader.read_u16::<LittleEndian>());
            statics.push(StaticLocation{
                object_id: object_id,
                x: x,
                y: y,
                altitude: altitude,
                unknown: unknown
            });
        };
        Ok(statics)
    }

    pub fn read_block_from_coordinates(&mut self, x: u32, y: u32) -> Result<Vec<StaticLocation>> {
        let width = self.width;
        let height = self.height;
        if x < width && y < height {
            self.read_block(y + (x * height))
        } else {
            Err(Error::new(
                ErrorKind::Other,
                format!("{} {} is outside of valid map coordinates", x, y)
            ))
        }
    }
}

pub struct RadarColReader {
    data_reader: File
}

impl RadarColReader {
    pub fn new(radar_col_path: &Path) -> Result<RadarColReader> {
        let data_reader = try!(File::open(radar_col_path));

        Ok(RadarColReader {
            data_reader: data_reader,
        })
    }

    pub fn read_color(&mut self, id: u32) -> Result<Color16> {
        try!(self.data_reader.seek(SeekFrom::Start((id * 2) as u64)));
        let data = try!(self.data_reader.read_u16::<LittleEndian>());
        Ok(data)
    }

    pub fn read_colors(&mut self) -> Result<Vec<Color16>> {
        try!(self.data_reader.seek(SeekFrom::Start(0)));
        let meta = try!(self.data_reader.metadata());
        let mut output = vec![];
        for _i in 0..(meta.len() / 2) {
            output.push(try!(self.data_reader.read_u16::<LittleEndian>()));
        }
        Ok(output)
    }
}
<commit_msg>Embed information about map sizes<commit_after>use std::io::{Cursor, Result, SeekFrom, Seek, Error, ErrorKind};
use std::fs::{File};
use std::path::Path;
use byteorder::{LittleEndian, ReadBytesExt};
use mul_reader::MulReader;
use color::Color16;

pub const BLOCK_SIZE: usize = 196;
pub const OFFSET: u32 = 4;
pub const MAP0_SIZE: u32 = 393216;

pub mod map_size {
    pub const FELUCCA: (u32, u32) = (7168, 4096);
    pub const TRAMMEL: (u32, u32) = (7168, 4096);
    pub const ILSHENAR: (u32, u32) = (2304, 1600);
    pub const MALAS: (u32, u32) = (2560, 2048);
    pub const TOKUNO: (u32, u32) = (1448, 1448);
    pub const TER_MUR: (u32, u32) = (1280, 4096);
}

#[derive(Clone, Copy)]
pub struct Cell {
    pub graphic: u16,
    pub altitude: i8,
}

#[derive(Copy)]
pub struct Block {
    pub checksum: u32,  //Not actually used
    pub cells: [Cell; 64]
}

impl Clone for Block {
    fn clone(&self) -> Self {
        let mut cells = [Cell {graphic: 0, altitude: 0}; 64];
        for i in 0..64 {
            cells[i] = self.cells[i].clone();
        }
        Block {
            checksum: self.checksum,
            cells: cells
        }
    }
}

#[derive(Clone, Copy)]
pub struct StaticLocation {
    pub object_id: u16,
    pub x: u8,
    pub y: u8,
    pub altitude: i8,
    pub checksum: u16  //Not actually used
}

impl StaticLocation {
    pub fn color_idx(&self) -> u16 {
        self.object_id + 16384
    }
}

pub struct MapReader {
    data_reader: File,
    width: u32,
    height: u32
}

impl MapReader {

    pub fn new(map_path: &Path, width: u32, height: u32) -> Result<MapReader> {
        let data_reader = try!(File::open(map_path));

        Ok(MapReader {
            data_reader: data_reader,
            width: width,
            height: height
        })
    }

    /**
     * Read a specific block from a map
     */
    pub fn read_block(&mut self, id: u32) -> Result<Block> {
        //Cycle to id * 192
        try!(self.data_reader.seek(SeekFrom::Start((id * BLOCK_SIZE as u32) as u64)));
        //Read the header
        let mut block = Block {
            checksum: try!(self.data_reader.read_u32::<LittleEndian>()),
            cells: [Cell {graphic: 0, altitude: 0}; 64]
        };
        //Read 64 cells
        for i in 0..64 {
            block.cells[i] = Cell{
                graphic: try!(self.data_reader.read_u16::<LittleEndian>()),
                altitude: try!(self.data_reader.read_i8())
            };
        }
        Ok(block)
    }

    pub fn read_block_from_coordinates(&mut self, x: u32, y: u32) -> Result<Block> {
        let width = self.width;
        let height = self.height;
        if x < width && y < height {
            self.read_block(y + (x * height))
        } else {
            Err(Error::new(
                ErrorKind::Other,
                format!("{} {} is outside of valid map coordinates", x, y)
            ))
        }
    }
}

pub struct StaticReader {
    mul_reader: MulReader,
    width: u32,
    height: u32
}

impl StaticReader {

    pub fn new(index_path: &Path, mul_path: &Path, width: u32, height: u32) -> Result<StaticReader> {
        let mul_reader = try!(MulReader::new(index_path, mul_path));

        Ok(StaticReader {
            mul_reader: mul_reader,
            width: width,
            height: height
        })
    }

    pub fn read_block(&mut self, id: u32) -> Result<Vec<StaticLocation>> {
        let raw = try!(self.mul_reader.read(id));
        let len = raw.data.len();
        assert!(len % 7 == 0);
        let mut reader = Cursor::new(raw.data);
        let mut statics = vec![];
        for _i in 0..(len / 7) {
            let object_id = try!(reader.read_u16::<LittleEndian>());
            let x = try!(reader.read_u8());
            let y = try!(reader.read_u8());
            let altitude = try!(reader.read_i8());
            let checksum = try!(reader.read_u16::<LittleEndian>());
            statics.push(StaticLocation{
                object_id: object_id,
                x: x,
                y: y,
                altitude: altitude,
                checksum: checksum
            });
        };
        Ok(statics)
    }

    pub fn read_block_from_coordinates(&mut self, x: u32, y: u32) -> Result<Vec<StaticLocation>> {
        let width = self.width;
        let height = self.height;
        if x < width && y < height {
            self.read_block(y + (x * height))
        } else {
            Err(Error::new(
                ErrorKind::Other,
                format!("{} {} is outside of valid map coordinates", x, y)
            ))
        }
    }
}

pub struct RadarColReader {
    data_reader: File
}

impl RadarColReader {
    pub fn new(radar_col_path: &Path) -> Result<RadarColReader> {
        let data_reader = try!(File::open(radar_col_path));

        Ok(RadarColReader {
            data_reader: data_reader,
        })
    }

    pub fn read_color(&mut self, id: u32) -> Result<Color16> {
        try!(self.data_reader.seek(SeekFrom::Start((id * 2) as u64)));
        let data = try!(self.data_reader.read_u16::<LittleEndian>());
        Ok(data)
    }

    pub fn read_colors(&mut self) -> Result<Vec<Color16>> {
        try!(self.data_reader.seek(SeekFrom::Start(0)));
        let meta = try!(self.data_reader.metadata());
        let mut output = vec![];
        for _i in 0..(meta.len() / 2) {
            output.push(try!(self.data_reader.read_u16::<LittleEndian>()));
        }
        Ok(output)
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeSet;
use cgmath::InnerSpace;
use event::{SiteEvent, CircleEvent};
use beach_line::{BeachLine, Arc};
use generator::Generator;
use ::Position;

#[derive(Default)]
struct Builder<G: Generator> {
    site_index: usize,
    site_events: Vec<SiteEvent>,
    circle_events: BTreeSet<CircleEvent>,
    beach: BeachLine,
    generator: G,
}

impl<G: Generator> Builder<G> {
    fn build<I: IntoIterator<Item = Position>>(mut self, positions: I) -> G::Result {
        self.site_events.extend(positions.into_iter().map(SiteEvent::from));
        self.site_events.sort();
        loop {
            match (self.site_index == self.site_events.len(), self.circle_events.is_empty()) {
                (true, true) => break,
                (true, false) => self.circle_event(),
                (false, true) => self.site_event(),
                (false, false) => {
                    if self.site_events[self.site_index].theta.value <
                       self.circle_events.iter().next().unwrap().theta {
                        self.site_event()
                    } else {
                        self.circle_event()
                    }
                }
            }
        }
        self.generator.result()
    }

    fn site_event(&mut self) {
        let cell = self.generator.cell();
        let theta = self.site_events[self.site_index].theta.value;
        self.site_index += 1;
        let arc = self.beach.insert(cell, &self.site_events);
        let (prev, next) = self.beach.neighbors(arc);
        self.generator.temporary(self.beach.index(arc), self.beach.index(prev));
        if prev != next {
            self.detach_circle(prev);
            self.detach_circle(next);
            self.attach_circle(prev, theta);
            self.attach_circle(next, theta);
        }
    }

    fn circle_event(&mut self) {
        let circle = *self.circle_events.iter().next().unwrap();
        self.circle_events.remove(&circle);
        let arc = circle.arc;
        let theta = self.beach.circle_theta(arc);
        if theta >= 0.0 {
            let (prev, next) = self.beach.neighbors(arc);
            self.beach.detach_circle(arc);
            self.detach_circle(prev);
            self.detach_circle(next);
            let vertex = self.generator.vertex(self.beach.circle_center(arc),
                                               self.beach.cell(prev),
                                               self.beach.cell(arc),
                                               self.beach.cell(next));
            self.generator.edge(self.beach.index(prev), vertex);
            self.generator.edge(self.beach.index(arc), vertex);
            self.beach.remove(arc);
            if self.beach.prev(prev) == next {
                self.generator.edge(self.beach.index(next), vertex);
                self.beach.remove(prev);
                self.beach.remove(next);
            } else {
                if self.attach_circle(prev, theta) {
                    self.generator.start(self.beach.index(prev), vertex);
                }
                self.attach_circle(next, theta);
            }
        }
    }

    fn attach_circle(&mut self, arc: Arc, min: f64) -> bool {
        let (prev, next) = self.beach.neighbors(arc);
        let position = self.arc_position(arc);
        let from_prev = self.arc_position(prev) - position;
        let from_next = self.arc_position(next) - position;
        let center = from_prev.cross(from_next).normalize();
        let theta = center.z.acos() + center.dot(position).acos();
        if theta >= min {
            self.beach.attach_circle(arc, theta, center);
            self.circle_events.insert(CircleEvent {
                theta: theta,
                arc: arc,
            });
            true
        } else {
            false
        }
    }

    fn detach_circle(&mut self, arc: Arc) {
        let theta = self.beach.circle_theta(arc);
        if theta >= 0.0 {
            self.circle_events.remove(&CircleEvent {
                arc: arc,
                theta: theta,
            });
            self.beach.detach_circle(arc);
        }
    }

    fn arc_position(&self, arc: Arc) -> Position {
        self.site_events[self.beach.cell(arc).index()].position
    }
}

pub fn build<G: Generator, I: IntoIterator<Item = Position>>(positions: I) -> G::Result {
    Builder::<G>::default().build(positions)
}
<commit_msg>Rewrite main loop<commit_after>use std::collections::BTreeSet;
use cgmath::InnerSpace;
use event::{SiteEvent, CircleEvent};
use beach_line::{BeachLine, Arc};
use generator::Generator;
use ::Position;

#[derive(Default)]
struct Builder<G: Generator> {
    site_index: usize,
    site_events: Vec<SiteEvent>,
    circle_events: BTreeSet<CircleEvent>,
    beach: BeachLine,
    generator: G,
}

impl<G: Generator> Builder<G> {
    fn build<I: IntoIterator<Item = Position>>(mut self, positions: I) -> G::Result {
        self.site_events.extend(positions.into_iter().map(SiteEvent::from));
        self.site_events.sort();
        loop {
            let has_sites = self.site_index < self.site_events.len();
            if let Some(circle) = self.circle_events.iter().next().cloned() {
                if has_sites && self.site_events[self.site_index].theta.value < circle.theta {
                    self.site_event();
                } else {
                    self.circle_event(&circle);
                }
            } else if has_sites {
                self.site_event()
            } else {
                break;
            }
        }
        self.generator.result()
    }

    fn site_event(&mut self) {
        let cell = self.generator.cell();
        let theta = self.site_events[self.site_index].theta.value;
        self.site_index += 1;
        let arc = self.beach.insert(cell, &self.site_events);
        let (prev, next) = self.beach.neighbors(arc);
        self.generator.temporary(self.beach.index(arc), self.beach.index(prev));
        if prev != next {
            self.detach_circle(prev);
            self.detach_circle(next);
            self.attach_circle(prev, theta);
            self.attach_circle(next, theta);
        }
    }

    fn circle_event(&mut self, circle: &CircleEvent) {
        self.circle_events.remove(circle);
        let arc = circle.arc;
        let theta = self.beach.circle_theta(arc);
        if theta >= 0.0 {
            let (prev, next) = self.beach.neighbors(arc);
            self.beach.detach_circle(arc);
            self.detach_circle(prev);
            self.detach_circle(next);
            let vertex = self.generator.vertex(self.beach.circle_center(arc),
                                               self.beach.cell(prev),
                                               self.beach.cell(arc),
                                               self.beach.cell(next));
            self.generator.edge(self.beach.index(prev), vertex);
            self.generator.edge(self.beach.index(arc), vertex);
            self.beach.remove(arc);
            if self.beach.prev(prev) == next {
                self.generator.edge(self.beach.index(next), vertex);
                self.beach.remove(prev);
                self.beach.remove(next);
            } else {
                if self.attach_circle(prev, theta) {
                    self.generator.start(self.beach.index(prev), vertex);
                }
                self.attach_circle(next, theta);
            }
        }
    }

    fn attach_circle(&mut self, arc: Arc, min: f64) -> bool {
        let (prev, next) = self.beach.neighbors(arc);
        let position = self.arc_position(arc);
        let from_prev = self.arc_position(prev) - position;
        let from_next = self.arc_position(next) - position;
        let center = from_prev.cross(from_next).normalize();
        let theta = center.z.acos() + center.dot(position).acos();
        if theta >= min {
            self.beach.attach_circle(arc, theta, center);
            self.circle_events.insert(CircleEvent {
                theta: theta,
                arc: arc,
            });
            true
        } else {
            false
        }
    }

    fn detach_circle(&mut self, arc: Arc) {
        let theta = self.beach.circle_theta(arc);
        if theta >= 0.0 {
            self.circle_events.remove(&CircleEvent {
                arc: arc,
                theta: theta,
            });
            self.beach.detach_circle(arc);
        }
    }

    fn arc_position(&self, arc: Arc) -> Position {
        self.site_events[self.beach.cell(arc).index()].position
    }
}

pub fn build<G: Generator, I: IntoIterator<Item = Position>>(positions: I) -> G::Result {
    Builder::<G>::default().build(positions)
}
<|endoftext|>


<commit_before>use low_level as ll;
use error::Error;
use event::{Event, EventStatus, EventLike};

use std::sync::Arc;
use std::cell::RefCell;

struct MemEvents {
    last_write: RefCell<Option<Event>>,
    last_read: RefCell<Vec<Event>>,
}

pub struct Mem {
    pub id: ll::Mem,
    events: Arc<MemEvents>,
}

impl Mem {
    pub fn new(id: ll::Mem) -> Mem {
        let events = MemEvents{
            last_write: RefCell::new(None),
            last_read: RefCell::new(Vec::new()),
        };
        Mem{
            id: id,
            events: Arc::new(events),
        }
    }

    pub fn write_events(self: &Self) -> Vec<ll::Event> {
        let mut tr: Vec<ll::Event> = Vec::with_capacity(2);
        if let Some(ref evt) = *self.events.last_write.borrow() {
            tr.push(evt.id);
        }
        tr.extend(self.events.last_read.borrow().iter().map(|e| e.id));
        tr
    }

    pub fn read_events(self: &Self) -> Vec<ll::Event> {
        if let Some(ref evt) = *self.events.last_write.borrow() {
            vec!(evt.id)
        } else {
            vec!()
        }
    }

    pub fn register_write(self: &mut Self, evt: Event) -> () {
        *self.events.last_write.borrow_mut() = Some(evt);
    }

    pub fn register_read(self: &Self, evt: Event) -> () {
        let mut r = self.events.last_read.borrow_mut();
        r.retain(|e|
                 match e.status().ok().expect("error getting event status") {
                     EventStatus::Complete => false,
                     _ => true,
        });
        r.push(evt);
    }
}

impl Drop for Mem {
    fn drop(self: &mut Self) -> () {
        unsafe {
            Error::check(ll::clReleaseMemObject(self.id))
                .ok().expect("error releasing mem object");
        }
    }
}

impl Clone for Mem {
    fn clone(self: &Self) -> Self {
        unsafe {
            Error::check(ll::clRetainMemObject(self.id))
                .ok().expect("error retaining mem object");
        }
        Mem{ id: self.id, events: self.events.clone() }
    }
}

<commit_msg>adds some debugging code<commit_after>use low_level as ll;
use error::Error;
use event::{Event, EventStatus, EventLike};

use std::sync::Arc;
use std::cell::RefCell;

struct MemEvents {
    last_write: RefCell<Option<Event>>,
    last_read: RefCell<Vec<Event>>,
}

pub struct Mem {
    pub id: ll::Mem,
    events: Arc<MemEvents>,
}

impl Mem {
    pub fn new(id: ll::Mem) -> Mem {
        let events = MemEvents{
            last_write: RefCell::new(None),
            last_read: RefCell::new(Vec::new()),
        };
        Mem{
            id: id,
            events: Arc::new(events),
        }
    }

    pub fn write_events(self: &Self) -> Vec<ll::Event> {
        let mut tr: Vec<ll::Event> = Vec::with_capacity(2);
        if let Some(ref evt) = *self.events.last_write.borrow() {
            tr.push(evt.id);
        }
        tr.extend(self.events.last_read.borrow().iter().map(|e| e.id));
        tr
    }

    pub fn read_events(self: &Self) -> Vec<ll::Event> {
        if let Some(ref evt) = *self.events.last_write.borrow() {
            vec!(evt.id)
        } else {
            vec!()
        }
    }

    pub fn register_write(self: &mut Self, evt: Event) -> () {
        *self.events.last_write.borrow_mut() = Some(evt);
    }

    pub fn register_read(self: &Self, evt: Event) -> () {
        let mut r = self.events.last_read.borrow_mut();
        r.retain(|e|
                 match e.status().ok().expect("error getting event status") {
                     EventStatus::Complete => false,
                     _ => true,
        });
        println!("buffer {:?} has {} events in its read list", self.id, r.len());
        r.push(evt);
    }
}

impl Drop for Mem {
    fn drop(self: &mut Self) -> () {
        unsafe {
            Error::check(ll::clReleaseMemObject(self.id))
                .ok().expect("error releasing mem object");
        }
    }
}

impl Clone for Mem {
    fn clone(self: &Self) -> Self {
        unsafe {
            Error::check(ll::clRetainMemObject(self.id))
                .ok().expect("error retaining mem object");
        }
        Mem{ id: self.id, events: self.events.clone() }
    }
}

<|endoftext|>