<commit_before>use byteorder::{self, ByteOrder, NativeEndian, ReadBytesExt, WriteBytesExt};
use std::collections::{BTreeMap, HashMap};
use std::collections::Bound::{Included, Excluded};
use std::mem;
use std::ptr;

use error::{EvalError, EvalResult};
use primval::PrimVal;

pub struct Memory {
    alloc_map: HashMap<u64, Allocation>,
    next_id: u64,
    pub pointer_size: usize,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct AllocId(u64);

#[derive(Debug)]
pub struct Allocation {
    pub bytes: Vec<u8>,
    pub relocations: BTreeMap<usize, AllocId>,
    // TODO(tsion): undef mask
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Pointer {
    pub alloc_id: AllocId,
    pub offset: usize,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FieldRepr {
    pub offset: usize,
    pub size: usize,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Repr {
    /// Representation for a non-aggregate type such as a boolean, integer, character or pointer.
    Primitive {
        size: usize
    },

    /// The representation for aggregate types including structs, enums, and tuples.
    Aggregate {
        /// The size of the discriminant (an integer). Should be between 0 and 8. Always 0 for
        /// structs and tuples.
        discr_size: usize,

        /// The size of the entire aggregate, including the discriminant.
        size: usize,

        /// The representations of the contents of each variant.
        variants: Vec<Vec<FieldRepr>>,
    },

    Array {
        elem_size: usize,

        /// Number of elements.
        length: usize,
    },
}

impl Memory {
    pub fn new() -> Self {
        Memory {
            alloc_map: HashMap::new(),
            next_id: 0,

            // TODO(tsion): Should this be host's or target's usize?
            pointer_size: mem::size_of::<usize>(),
        }
    }

    pub fn allocate(&mut self, size: usize) -> Pointer {
        let id = AllocId(self.next_id);
        let alloc = Allocation { bytes: vec![0; size], relocations: BTreeMap::new() };
        self.alloc_map.insert(self.next_id, alloc);
        self.next_id += 1;
        Pointer {
            alloc_id: id,
            offset: 0,
        }
    }

    pub fn get(&self, id: AllocId) -> EvalResult<&Allocation> {
        self.alloc_map.get(&id.0).ok_or(EvalError::DanglingPointerDeref)
    }

    pub fn get_mut(&mut self, id: AllocId) -> EvalResult<&mut Allocation> {
        self.alloc_map.get_mut(&id.0).ok_or(EvalError::DanglingPointerDeref)
    }

    fn get_bytes(&self, ptr: Pointer, size: usize) -> EvalResult<&[u8]> {
        let alloc = try!(self.get(ptr.alloc_id));
        try!(alloc.check_no_relocations(ptr.offset, ptr.offset + size));
        Ok(&alloc.bytes[ptr.offset..ptr.offset + size])
    }

    fn get_bytes_mut(&mut self, ptr: Pointer, size: usize) -> EvalResult<&mut [u8]> {
        let alloc = try!(self.get_mut(ptr.alloc_id));
        try!(alloc.check_no_relocations(ptr.offset, ptr.offset + size));
        Ok(&mut alloc.bytes[ptr.offset..ptr.offset + size])
    }

    pub fn copy(&mut self, src: Pointer, dest: Pointer, size: usize) -> EvalResult<()> {
        let (src_bytes, relocations) = {
            let alloc = try!(self.get_mut(src.alloc_id));
            try!(alloc.check_relocation_edges(src.offset, src.offset + size));
            let bytes = alloc.bytes[src.offset..src.offset + size].as_mut_ptr();

            let mut relocations: Vec<(usize, AllocId)> = alloc.relocations
                .range(Included(&src.offset), Excluded(&(src.offset + size)))
                .map(|(&k, &v)| (k, v))
                .collect();

            for &mut (ref mut offset, _) in &mut relocations {
                alloc.relocations.remove(offset);
                *offset += dest.offset;
                *offset -= src.offset;
            }

            (bytes, relocations)
        };

        let dest_bytes = try!(self.get_bytes_mut(dest, size)).as_mut_ptr();

        // TODO(tsion): Clear the destination range's existing relocations.
        try!(self.get_mut(dest.alloc_id)).relocations.extend(relocations);

        // SAFE: The above indexing would have panicked if there weren't at least `size` bytes
        // behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and
        // `dest` could possibly overlap.
        unsafe {
            if src.alloc_id == dest.alloc_id {
                ptr::copy(src_bytes, dest_bytes, size);
            } else {
                ptr::copy_nonoverlapping(src_bytes, dest_bytes, size);
            }
        }

        Ok(())
    }

    pub fn write_bytes(&mut self, ptr: Pointer, src: &[u8]) -> EvalResult<()> {
        self.get_bytes_mut(ptr, src.len()).map(|dest| dest.clone_from_slice(src))
    }

    pub fn read_ptr(&self, ptr: Pointer) -> EvalResult<Pointer> {
        let alloc = try!(self.get(ptr.alloc_id));
        try!(alloc.check_relocation_edges(ptr.offset, ptr.offset + self.pointer_size));
        let bytes = &alloc.bytes[ptr.offset..ptr.offset + self.pointer_size];
        let offset = byteorder::NativeEndian::read_u64(bytes) as usize;

        match alloc.relocations.get(&ptr.offset) {
            Some(&alloc_id) => Ok(Pointer { alloc_id: alloc_id, offset: offset }),
            None => Err(EvalError::ReadBytesAsPointer),
        }
    }

    // TODO(tsion): Detect invalid writes here and elsewhere.
    pub fn write_ptr(&mut self, dest: Pointer, ptr_val: Pointer) -> EvalResult<()> {
        {
            let size = self.pointer_size;
            let bytes = try!(self.get_bytes_mut(dest, size));
            byteorder::NativeEndian::write_u64(bytes, ptr_val.offset as u64);
        }
        let alloc = try!(self.get_mut(dest.alloc_id));
        alloc.relocations.insert(dest.offset, ptr_val.alloc_id);
        Ok(())
    }

    pub fn write_primval(&mut self, ptr: Pointer, val: PrimVal) -> EvalResult<()> {
        match val {
            PrimVal::Bool(b) => self.write_bool(ptr, b),
            PrimVal::I8(n)   => self.write_int(ptr, n as i64, 1),
            PrimVal::I16(n)  => self.write_int(ptr, n as i64, 2),
            PrimVal::I32(n)  => self.write_int(ptr, n as i64, 4),
            PrimVal::I64(n)  => self.write_int(ptr, n as i64, 8),
            PrimVal::U8(n)   => self.write_uint(ptr, n as u64, 1),
            PrimVal::U16(n)  => self.write_uint(ptr, n as u64, 2),
            PrimVal::U32(n)  => self.write_uint(ptr, n as u64, 4),
            PrimVal::U64(n) | PrimVal::IntegerPtr(n) => self.write_uint(ptr, n as u64, 8),
            PrimVal::AbstractPtr(_p) => unimplemented!(),
        }
    }

    pub fn read_bool(&self, ptr: Pointer) -> EvalResult<bool> {
        let bytes = try!(self.get_bytes(ptr, 1));
        match bytes[0] {
            0 => Ok(false),
            1 => Ok(true),
            _ => Err(EvalError::InvalidBool),
        }
    }

    pub fn write_bool(&mut self, ptr: Pointer, b: bool) -> EvalResult<()> {
        self.get_bytes_mut(ptr, 1).map(|bytes| bytes[0] = b as u8)
    }

    pub fn read_int(&self, ptr: Pointer, size: usize) -> EvalResult<i64> {
        self.get_bytes(ptr, size).map(|mut b| b.read_int::<NativeEndian>(size).unwrap())
    }

    pub fn write_int(&mut self, ptr: Pointer, n: i64, size: usize) -> EvalResult<()> {
        self.get_bytes_mut(ptr, size).map(|mut b| b.write_int::<NativeEndian>(n, size).unwrap())
    }

    pub fn read_uint(&self, ptr: Pointer, size: usize) -> EvalResult<u64> {
        self.get_bytes(ptr, size).map(|mut b| b.read_uint::<NativeEndian>(size).unwrap())
    }

    pub fn write_uint(&mut self, ptr: Pointer, n: u64, size: usize) -> EvalResult<()> {
        self.get_bytes_mut(ptr, size).map(|mut b| b.write_uint::<NativeEndian>(n, size).unwrap())
    }
}

impl Allocation {
    fn check_bounds(&self, start: usize, end: usize) -> EvalResult<()> {
        if start <= self.bytes.len() && end <= self.bytes.len() {
            Ok(())
        } else {
            Err(EvalError::PointerOutOfBounds)
        }
    }

    fn count_overlapping_relocations(&self, start: usize, end: usize) -> usize {
        self.relocations.range(
            // FIXME(tsion): Assuming pointer size is 8. Move this method to Memory.
            Included(&start.saturating_sub(8 - 1)),
            Excluded(&end)
        ).count()
    }

    fn check_relocation_edges(&self, start: usize, end: usize) -> EvalResult<()> {
        try!(self.check_bounds(start, end));
        let n =
            self.count_overlapping_relocations(start, start) +
            self.count_overlapping_relocations(end, end);
        if n == 0 {
            Ok(())
        } else {
            Err(EvalError::ReadPointerAsBytes)
        }
    }

    fn check_no_relocations(&self, start: usize, end: usize) -> EvalResult<()> {
        try!(self.check_bounds(start, end));
        if self.count_overlapping_relocations(start, end) == 0 {
            Ok(())
        } else {
            Err(EvalError::ReadPointerAsBytes)
        }
    }
}

impl Pointer {
    pub fn offset(self, i: isize) -> Self {
        Pointer { offset: (self.offset as isize + i) as usize, ..self }
    }
}

impl Repr {
    pub fn size(&self) -> usize {
        match *self {
            Repr::Primitive { size } => size,
            Repr::Aggregate { size, .. } => size,
            Repr::Array { elem_size, length } => elem_size * length,
        }
    }
}
<commit_msg>Stop unintentionally clearing source relocations when copying.<commit_after>use byteorder::{self, ByteOrder, NativeEndian, ReadBytesExt, WriteBytesExt};
use std::collections::{BTreeMap, HashMap};
use std::collections::Bound::{Included, Excluded};
use std::mem;
use std::ptr;

use error::{EvalError, EvalResult};
use primval::PrimVal;

pub struct Memory {
    alloc_map: HashMap<u64, Allocation>,
    next_id: u64,
    pub pointer_size: usize,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct AllocId(u64);

#[derive(Debug)]
pub struct Allocation {
    pub bytes: Vec<u8>,
    pub relocations: BTreeMap<usize, AllocId>,
    // TODO(tsion): undef mask
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Pointer {
    pub alloc_id: AllocId,
    pub offset: usize,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FieldRepr {
    pub offset: usize,
    pub size: usize,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Repr {
    /// Representation for a non-aggregate type such as a boolean, integer, character or pointer.
    Primitive {
        size: usize
    },

    /// The representation for aggregate types including structs, enums, and tuples.
    Aggregate {
        /// The size of the discriminant (an integer). Should be between 0 and 8. Always 0 for
        /// structs and tuples.
        discr_size: usize,

        /// The size of the entire aggregate, including the discriminant.
        size: usize,

        /// The representations of the contents of each variant.
        variants: Vec<Vec<FieldRepr>>,
    },

    Array {
        elem_size: usize,

        /// Number of elements.
        length: usize,
    },
}

impl Memory {
    pub fn new() -> Self {
        Memory {
            alloc_map: HashMap::new(),
            next_id: 0,

            // TODO(tsion): Should this be host's or target's usize?
            pointer_size: mem::size_of::<usize>(),
        }
    }

    pub fn allocate(&mut self, size: usize) -> Pointer {
        let id = AllocId(self.next_id);
        let alloc = Allocation { bytes: vec![0; size], relocations: BTreeMap::new() };
        self.alloc_map.insert(self.next_id, alloc);
        self.next_id += 1;
        Pointer {
            alloc_id: id,
            offset: 0,
        }
    }

    pub fn get(&self, id: AllocId) -> EvalResult<&Allocation> {
        self.alloc_map.get(&id.0).ok_or(EvalError::DanglingPointerDeref)
    }

    pub fn get_mut(&mut self, id: AllocId) -> EvalResult<&mut Allocation> {
        self.alloc_map.get_mut(&id.0).ok_or(EvalError::DanglingPointerDeref)
    }

    fn get_bytes(&self, ptr: Pointer, size: usize) -> EvalResult<&[u8]> {
        let alloc = try!(self.get(ptr.alloc_id));
        try!(alloc.check_no_relocations(ptr.offset, ptr.offset + size));
        Ok(&alloc.bytes[ptr.offset..ptr.offset + size])
    }

    fn get_bytes_mut(&mut self, ptr: Pointer, size: usize) -> EvalResult<&mut [u8]> {
        let alloc = try!(self.get_mut(ptr.alloc_id));
        try!(alloc.check_no_relocations(ptr.offset, ptr.offset + size));
        Ok(&mut alloc.bytes[ptr.offset..ptr.offset + size])
    }

    pub fn copy(&mut self, src: Pointer, dest: Pointer, size: usize) -> EvalResult<()> {
        let (src_bytes, mut relocations) = {
            let alloc = try!(self.get_mut(src.alloc_id));
            try!(alloc.check_relocation_edges(src.offset, src.offset + size));
            let bytes = alloc.bytes[src.offset..src.offset + size].as_mut_ptr();

            let relocations: Vec<(usize, AllocId)> = alloc.relocations
                .range(Included(&src.offset), Excluded(&(src.offset + size)))
                .map(|(&k, &v)| (k, v))
                .collect();

            (bytes, relocations)
        };

        // Update relocation offsets for the new positions in the destination allocation.
        for &mut (ref mut offset, _) in &mut relocations {
            *offset += dest.offset;
            *offset -= src.offset;
        }

        let dest_bytes = try!(self.get_bytes_mut(dest, size)).as_mut_ptr();

        // TODO(tsion): Clear the destination range's existing relocations.
        try!(self.get_mut(dest.alloc_id)).relocations.extend(relocations);

        // SAFE: The above indexing would have panicked if there weren't at least `size` bytes
        // behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and
        // `dest` could possibly overlap.
        unsafe {
            if src.alloc_id == dest.alloc_id {
                ptr::copy(src_bytes, dest_bytes, size);
            } else {
                ptr::copy_nonoverlapping(src_bytes, dest_bytes, size);
            }
        }

        Ok(())
    }

    pub fn write_bytes(&mut self, ptr: Pointer, src: &[u8]) -> EvalResult<()> {
        self.get_bytes_mut(ptr, src.len()).map(|dest| dest.clone_from_slice(src))
    }

    pub fn read_ptr(&self, ptr: Pointer) -> EvalResult<Pointer> {
        let alloc = try!(self.get(ptr.alloc_id));
        try!(alloc.check_relocation_edges(ptr.offset, ptr.offset + self.pointer_size));
        let bytes = &alloc.bytes[ptr.offset..ptr.offset + self.pointer_size];
        let offset = byteorder::NativeEndian::read_u64(bytes) as usize;

        match alloc.relocations.get(&ptr.offset) {
            Some(&alloc_id) => Ok(Pointer { alloc_id: alloc_id, offset: offset }),
            None => Err(EvalError::ReadBytesAsPointer),
        }
    }

    // TODO(tsion): Detect invalid writes here and elsewhere.
    pub fn write_ptr(&mut self, dest: Pointer, ptr_val: Pointer) -> EvalResult<()> {
        {
            let size = self.pointer_size;
            let bytes = try!(self.get_bytes_mut(dest, size));
            byteorder::NativeEndian::write_u64(bytes, ptr_val.offset as u64);
        }
        let alloc = try!(self.get_mut(dest.alloc_id));
        alloc.relocations.insert(dest.offset, ptr_val.alloc_id);
        Ok(())
    }

    pub fn write_primval(&mut self, ptr: Pointer, val: PrimVal) -> EvalResult<()> {
        match val {
            PrimVal::Bool(b) => self.write_bool(ptr, b),
            PrimVal::I8(n)   => self.write_int(ptr, n as i64, 1),
            PrimVal::I16(n)  => self.write_int(ptr, n as i64, 2),
            PrimVal::I32(n)  => self.write_int(ptr, n as i64, 4),
            PrimVal::I64(n)  => self.write_int(ptr, n as i64, 8),
            PrimVal::U8(n)   => self.write_uint(ptr, n as u64, 1),
            PrimVal::U16(n)  => self.write_uint(ptr, n as u64, 2),
            PrimVal::U32(n)  => self.write_uint(ptr, n as u64, 4),
            PrimVal::U64(n) | PrimVal::IntegerPtr(n) => self.write_uint(ptr, n as u64, 8),
            PrimVal::AbstractPtr(_p) => unimplemented!(),
        }
    }

    pub fn read_bool(&self, ptr: Pointer) -> EvalResult<bool> {
        let bytes = try!(self.get_bytes(ptr, 1));
        match bytes[0] {
            0 => Ok(false),
            1 => Ok(true),
            _ => Err(EvalError::InvalidBool),
        }
    }

    pub fn write_bool(&mut self, ptr: Pointer, b: bool) -> EvalResult<()> {
        self.get_bytes_mut(ptr, 1).map(|bytes| bytes[0] = b as u8)
    }

    pub fn read_int(&self, ptr: Pointer, size: usize) -> EvalResult<i64> {
        self.get_bytes(ptr, size).map(|mut b| b.read_int::<NativeEndian>(size).unwrap())
    }

    pub fn write_int(&mut self, ptr: Pointer, n: i64, size: usize) -> EvalResult<()> {
        self.get_bytes_mut(ptr, size).map(|mut b| b.write_int::<NativeEndian>(n, size).unwrap())
    }

    pub fn read_uint(&self, ptr: Pointer, size: usize) -> EvalResult<u64> {
        self.get_bytes(ptr, size).map(|mut b| b.read_uint::<NativeEndian>(size).unwrap())
    }

    pub fn write_uint(&mut self, ptr: Pointer, n: u64, size: usize) -> EvalResult<()> {
        self.get_bytes_mut(ptr, size).map(|mut b| b.write_uint::<NativeEndian>(n, size).unwrap())
    }
}

impl Allocation {
    fn check_bounds(&self, start: usize, end: usize) -> EvalResult<()> {
        if start <= self.bytes.len() && end <= self.bytes.len() {
            Ok(())
        } else {
            Err(EvalError::PointerOutOfBounds)
        }
    }

    fn count_overlapping_relocations(&self, start: usize, end: usize) -> usize {
        self.relocations.range(
            // FIXME(tsion): Assuming pointer size is 8. Move this method to Memory.
            Included(&start.saturating_sub(8 - 1)),
            Excluded(&end)
        ).count()
    }

    fn check_relocation_edges(&self, start: usize, end: usize) -> EvalResult<()> {
        try!(self.check_bounds(start, end));
        let n =
            self.count_overlapping_relocations(start, start) +
            self.count_overlapping_relocations(end, end);
        if n == 0 {
            Ok(())
        } else {
            Err(EvalError::ReadPointerAsBytes)
        }
    }

    fn check_no_relocations(&self, start: usize, end: usize) -> EvalResult<()> {
        try!(self.check_bounds(start, end));
        if self.count_overlapping_relocations(start, end) == 0 {
            Ok(())
        } else {
            Err(EvalError::ReadPointerAsBytes)
        }
    }
}

impl Pointer {
    pub fn offset(self, i: isize) -> Self {
        Pointer { offset: (self.offset as isize + i) as usize, ..self }
    }
}

impl Repr {
    pub fn size(&self) -> usize {
        match *self {
            Repr::Primitive { size } => size,
            Repr::Aggregate { size, .. } => size,
            Repr::Array { elem_size, length } => elem_size * length,
        }
    }
}
<|endoftext|>


<commit_before>//! Metrics for indexing `Rope`s.
//!
//! A [`Metric`] represents a measurement with which indices into a [`Rope`]
//! may be calculated.
//!
//! All [`Rope`] methods are optionally parameterised with [`Metric`]s. This
//! means that you can [`split`], [`insert`], or [`delete`] Ropes on character,
//! line, or grapheme indices, without necessitating the addition of a whole
//! bunch of new, wordy method names like `split_on_grapheme_index` and so on.
//!
//! # Examples
//!
//! If I wanted to delete characters 10 to 15 from rope _r_, I could say:
//!
//! ```
//! # use an_rope::Rope;
//! let mut r = Rope::from("this is a long rope");
//! r.delete(10..15);
//! assert_eq!(&r, "this is a rope");
//! ```
//!
//! Suppose my `Rope` contained some strange Unicode characters, and I realised
//! that I actually wanted to delete _graphemes_ 10 to 13. In that case, I
//! could say:
//!
//! ```
//! # use an_rope::Rope;
//! use an_rope::metric::Grapheme;
//! let mut r = Rope::from("this is a 🆒🆕 rope, 🆗!");
//! r.delete(Grapheme(10)..Grapheme(13));
//! assert_eq!(&r, "this is a rope, 🆗!");
//! ```
//!
//! Or, suppose my `Rope` spanned multiple lines:
//!
//! ```
//! # use an_rope::Rope;
//! use an_rope::metric::Line;
//! let mut r = Rope::from("this is\n\
//!                         a\n\
//!                         multi\n\
//!                         line\n\
//!                         rope");
//! r.delete(Line(2)..Line(3));
//! assert_eq!(&r, "this is\na\nrope");
//! ```
//!
//! [`Metric`]: trait.Metric.html
//! [`Rope`]: ../struct.Rope.html
//! [`split`]: ../struct.Rope.html#method.split
//! [`insert`]: ../struct.Rope.html#method.insert
//! [`delete`]: ../struct.Rope.html#method.delete

use std::convert;
use std::ops::{Add, Sub};
use std::default::Default;
use std::fmt;

/// The class of monoids
///
/// [Monoid]s are types with an accumulative binary operation that has
/// an identity.
///
/// Technically, `Add<Self, Output=Self>` is standing in for "semigroup" here,
/// while [`Default`] is standing in for "identity"[^id].
///
/// An instance _M_ should satisfy the following laws:
///
///  + _x_`.add(`_M_`::default())` = _x_
///  + _M_`::default().add(`_x_`)` = _x_
///  + _x_`.add(`_y_`.add(`_z_`))` = _z_`.add(`_x_`.add(`_y_`))`
///  + _M_`::accumulate(`_a_`)` = _a_`.fold(`_M_`::default,`_M_`::sum)`
///
/// [^id]: A mathematician might point out that it might be more correct to
///        represent the "identity" operation using the [`Zero`] trait rather
///        than [`Default`], as the documentation for `Zero` notes that "[t]his
///        trait is intended for use in conjunction with `Add`, as an identity".
///        However, the `Zero` trait is marked as unstable, so it would only be
///        useable on nightly Rust, and its use is deprecated. Thus, `Default`.
/// [`Default`]: https://doc.rust-lang.org/std/default/trait.Default.html)
/// [`Zero`]: https://doc.rust-lang.org/std/num/trait.Zero.html
/// [Monoid]: http://mathworld.wolfram.com/Monoid.html
pub trait Monoid: Add<Self, Output=Self> + Default + Sized {
    #[inline]
    fn accumulate<F>(xs: F) -> Self
    where F: Iterator<Item=Self>
        , Self: Sized {
        xs.fold(Self::default(), Self::add)
    }
}

/// Trait indicating that a type may be measured with [`Metric`] _M_.
///
/// [`Metric`]: trait.Metric.html
pub trait Measured<M: Metric> {
    /// Apply `Metric` to `Self`
    ///
    /// Although we aren't currently enforcing this, `measure`ing a `Node` with
    /// two children should produce the same result as `measure`ing both
    /// children and `Monoid::sum`ming the result. That is to say, `measure`
    /// should be a [_monoid homomorphism_].
    ///
    /// [_monoid homomorphism_]:
    /// https://en.wikipedia.org/wiki/Monoid#Monoid_homomorphisms
    fn measure(&self) -> M;

    /// Measure the `weight` of `Node` by this `metric`.
    fn measure_weight(&self) -> M;

    /// Convert the `Metric` into a byte index into the given `Node`
    ///
    /// # Returns
    /// - `Some` with the byte index of the beginning of the `n`th  element
    ///    in `node` measured by this `Metric`, if there is an `n`th element
    /// - `None` if there is no `n`th element in `node`
    fn to_byte_index(&self, index: M) -> Option<usize>;
}

/// A [monoid] that can be applied to a type as a measurement.
///
/// [monoid]: trait.Monoid.html
pub trait Metric: Monoid + Eq + Add<usize, Output=Self>
                         + Sub<usize, Output=Self>
                         + Sub<Self, Output=Self>
                         + Eq + Ord
                         + Sized
                         + convert::Into<usize>
                         + Copy
                         + fmt::Debug {

    /// Returns whether text may be split into new leaf nodes using this metric.
    fn is_splittable() -> bool;

    /// Returns the byte index of the next element of this metric in `Node`
    #[inline]
    fn next<M: Measured<Self> >(self, node: &M)-> Option<usize> {
        node.to_byte_index(self + 1)
    }

    /// Returns the byte index of the previous element of this metric in `Node`
    #[inline]
    fn back<M: Measured<Self>>(self, node: &M) -> Option<usize> {
        node.to_byte_index(self - 1)
    }

    /// Returns true if index `i` in `node` is a boundary along this `Metric`
    fn is_boundary<M: Measured<Self>>(node: &M, i: usize) -> bool;
}

macro_attr! {
    /// A metric for calculating indices in `Rope`s based on Unicode graphemes.
    #[derive( Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq
            , NewtypeFrom!
            , NewtypeAdd!(*), NewtypeAdd!(&self, usize), NewtypeAdd!(usize)
            , NewtypeSub!(*), NewtypeSub!(&self, usize), NewtypeSub!(usize)
            , NewtypeMul!(*), NewtypeMul!(&self, usize), NewtypeMul!(usize) )]
    pub struct Grapheme(pub usize);

}
impl Default for Grapheme {
    #[inline] fn default() -> Self { Grapheme(0) }
}
impl Monoid for Grapheme { }

macro_attr! {
    /// A metric for calculating indices in `Rope`s based on line numbering.
    #[derive( Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq
            , NewtypeFrom!
            , NewtypeAdd!(*), NewtypeAdd!(&self, usize), NewtypeAdd!(usize)
            , NewtypeSub!(*), NewtypeSub!(&self, usize), NewtypeSub!(usize)
            , NewtypeMul!(*), NewtypeMul!(&self, usize), NewtypeMul!(usize) )]
    pub struct Line(pub usize);
}
impl Default for Line {
    #[inline] fn default() -> Self { Line(0) }
}

impl Monoid for Line { }

impl Monoid for usize { }
<commit_msg>feat(rope metrics): nicer fmt::Debug implementations for Metrics<commit_after>//! Metrics for indexing `Rope`s.
//!
//! A [`Metric`] represents a measurement with which indices into a [`Rope`]
//! may be calculated.
//!
//! All [`Rope`] methods are optionally parameterised with [`Metric`]s. This
//! means that you can [`split`], [`insert`], or [`delete`] Ropes on character,
//! line, or grapheme indices, without necessitating the addition of a whole
//! bunch of new, wordy method names like `split_on_grapheme_index` and so on.
//!
//! # Examples
//!
//! If I wanted to delete characters 10 to 15 from rope _r_, I could say:
//!
//! ```
//! # use an_rope::Rope;
//! let mut r = Rope::from("this is a long rope");
//! r.delete(10..15);
//! assert_eq!(&r, "this is a rope");
//! ```
//!
//! Suppose my `Rope` contained some strange Unicode characters, and I realised
//! that I actually wanted to delete _graphemes_ 10 to 13. In that case, I
//! could say:
//!
//! ```
//! # use an_rope::Rope;
//! use an_rope::metric::Grapheme;
//! let mut r = Rope::from("this is a 🆒🆕 rope, 🆗!");
//! r.delete(Grapheme(10)..Grapheme(13));
//! assert_eq!(&r, "this is a rope, 🆗!");
//! ```
//!
//! Or, suppose my `Rope` spanned multiple lines:
//!
//! ```
//! # use an_rope::Rope;
//! use an_rope::metric::Line;
//! let mut r = Rope::from("this is\n\
//!                         a\n\
//!                         multi\n\
//!                         line\n\
//!                         rope");
//! r.delete(Line(2)..Line(3));
//! assert_eq!(&r, "this is\na\nrope");
//! ```
//!
//! [`Metric`]: trait.Metric.html
//! [`Rope`]: ../struct.Rope.html
//! [`split`]: ../struct.Rope.html#method.split
//! [`insert`]: ../struct.Rope.html#method.insert
//! [`delete`]: ../struct.Rope.html#method.delete

use std::convert;
use std::ops::{Add, Sub};
use std::default::Default;
use std::fmt;

/// The class of monoids
///
/// [Monoid]s are types with an accumulative binary operation that has
/// an identity.
///
/// Technically, `Add<Self, Output=Self>` is standing in for "semigroup" here,
/// while [`Default`] is standing in for "identity"[^id].
///
/// An instance _M_ should satisfy the following laws:
///
///  + _x_`.add(`_M_`::default())` = _x_
///  + _M_`::default().add(`_x_`)` = _x_
///  + _x_`.add(`_y_`.add(`_z_`))` = _z_`.add(`_x_`.add(`_y_`))`
///  + _M_`::accumulate(`_a_`)` = _a_`.fold(`_M_`::default,`_M_`::sum)`
///
/// [^id]: A mathematician might point out that it might be more correct to
///        represent the "identity" operation using the [`Zero`] trait rather
///        than [`Default`], as the documentation for `Zero` notes that "[t]his
///        trait is intended for use in conjunction with `Add`, as an identity".
///        However, the `Zero` trait is marked as unstable, so it would only be
///        useable on nightly Rust, and its use is deprecated. Thus, `Default`.
/// [`Default`]: https://doc.rust-lang.org/std/default/trait.Default.html)
/// [`Zero`]: https://doc.rust-lang.org/std/num/trait.Zero.html
/// [Monoid]: http://mathworld.wolfram.com/Monoid.html
pub trait Monoid: Add<Self, Output=Self> + Default + Sized {
    #[inline]
    fn accumulate<F>(xs: F) -> Self
    where F: Iterator<Item=Self>
        , Self: Sized {
        xs.fold(Self::default(), Self::add)
    }
}

/// Trait indicating that a type may be measured with [`Metric`] _M_.
///
/// [`Metric`]: trait.Metric.html
pub trait Measured<M: Metric> {
    /// Apply `Metric` to `Self`
    ///
    /// Although we aren't currently enforcing this, `measure`ing a `Node` with
    /// two children should produce the same result as `measure`ing both
    /// children and `Monoid::sum`ming the result. That is to say, `measure`
    /// should be a [_monoid homomorphism_].
    ///
    /// [_monoid homomorphism_]:
    /// https://en.wikipedia.org/wiki/Monoid#Monoid_homomorphisms
    fn measure(&self) -> M;

    /// Measure the `weight` of `Node` by this `metric`.
    fn measure_weight(&self) -> M;

    /// Convert the `Metric` into a byte index into the given `Node`
    ///
    /// # Returns
    /// - `Some` with the byte index of the beginning of the `n`th  element
    ///    in `node` measured by this `Metric`, if there is an `n`th element
    /// - `None` if there is no `n`th element in `node`
    fn to_byte_index(&self, index: M) -> Option<usize>;
}

/// A [monoid] that can be applied to a type as a measurement.
///
/// [monoid]: trait.Monoid.html
pub trait Metric: Monoid + Eq + Add<usize, Output=Self>
                         + Sub<usize, Output=Self>
                         + Sub<Self, Output=Self>
                         + Eq + Ord
                         + Sized
                         + convert::Into<usize>
                         + Copy
                         + fmt::Debug {

    /// Returns whether text may be split into new leaf nodes using this metric.
    fn is_splittable() -> bool;

    /// Returns the byte index of the next element of this metric in `Node`
    #[inline]
    fn next<M: Measured<Self> >(self, node: &M)-> Option<usize> {
        node.to_byte_index(self + 1)
    }

    /// Returns the byte index of the previous element of this metric in `Node`
    #[inline]
    fn back<M: Measured<Self>>(self, node: &M) -> Option<usize> {
        node.to_byte_index(self - 1)
    }

    /// Returns true if index `i` in `node` is a boundary along this `Metric`
    fn is_boundary<M: Measured<Self>>(node: &M, i: usize) -> bool;
}

macro_attr! {
    /// A metric for calculating indices in `Rope`s based on Unicode graphemes.
    #[derive( Clone, Copy, PartialOrd, Ord, PartialEq, Eq
            , NewtypeFrom!
            , NewtypeAdd!(*), NewtypeAdd!(&self, usize), NewtypeAdd!(usize)
            , NewtypeSub!(*), NewtypeSub!(&self, usize), NewtypeSub!(usize)
            , NewtypeMul!(*), NewtypeMul!(&self, usize), NewtypeMul!(usize) )]
    pub struct Grapheme(pub usize);
}

impl Default for Grapheme {
    #[inline] fn default() -> Self { Grapheme(0) }
}

impl Monoid for Grapheme { }

impl fmt::Debug for Grapheme {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
       write!(f, "grapheme {}", self.0)
   }
}

macro_attr! {
    /// A metric for calculating indices in `Rope`s based on line numbering.
    #[derive( Clone, Copy, PartialOrd, Ord, PartialEq, Eq
            , NewtypeFrom!
            , NewtypeAdd!(*), NewtypeAdd!(&self, usize), NewtypeAdd!(usize)
            , NewtypeSub!(*), NewtypeSub!(&self, usize), NewtypeSub!(usize)
            , NewtypeMul!(*), NewtypeMul!(&self, usize), NewtypeMul!(usize) )]
    pub struct Line(pub usize);
}
impl Default for Line {
    #[inline] fn default() -> Self { Line(0) }
}

impl Monoid for Line { }

impl Monoid for usize { }

impl fmt::Debug for Line {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
       write!(f, "line {}", self.0)
   }
}
<|endoftext|>


<commit_before>// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
//
// Example 1-10: Motion 101 Acceleration
extern crate nannou;

use nannou::prelude::*;

fn main() {
    nannou::app(model, event, view).run();
}

struct Model {
    mover: Mover,
}

struct Mover {
    position: Point2<f32>,
    velocity: Vector2<f32>,
    acceleration: Vector2<f32>,
    top_speed: f32,
}

impl Mover {
    fn new(rect: Rect<f32>) -> Self {
        let position = pt2(rect.x(), rect.y());
        let velocity = vec2(0.0, 0.0);
        let acceleration = vec2(0.0, 0.0);
        let top_speed = 5.0;
        Mover {
            position,
            velocity,
            acceleration,
            top_speed,
        }
    }

    fn update(&mut self, mouse: Point2<f32>) {
        // Computer a vector that points from position to mouse
        self.acceleration = mouse - self.position;
        // Set magnitude of acceleration
        self.acceleration = self.acceleration.normalize() * 0.2;
        // Velocity chages according to acceleration
        self.velocity += self.acceleration;
        // Limit the velocity by top_speed
        self.velocity - limit_magnitude(self.velocity, self.top_speed);
        // Position changes velocity
        self.position += self.velocity;
    }

    fn display(&self, draw: &app::Draw) {
        // Display circle at x position
        draw.ellipse()
            .xy(self.position)
            .w_h(48.0, 48.0)
            .rgb(0.5, 0.5, 0.5);
    }
}

fn model(app: &App) -> Model {
    let _window = app.new_window().with_dimensions(640, 360).build().unwrap();
    let mover = Mover::new(app.window_rect());
    Model { mover }
}

fn event(app: &App, mut m: Model, event: Event) -> Model {
    // update gets called just before view every frame
    if let Event::Update(_update) = event {
        m.mover.update(pt2(app.mouse.x, app.mouse.y));
    }
    m
}

fn view(app: &App, m: &Model, frame: Frame) -> Frame {
    // Begin drawing
    let draw = app.draw();
    draw.background().color(WHITE);

    m.mover.display(&draw);

    // Write the result of our drawing to the window's OpenGL frame.
    draw.to_frame(app, &frame).unwrap();

    // Return the drawn frame.
    frame
}

// This will be a removed in favour of limir_magnitude method of vector
fn limit_magnitude(v: Vector2<f32>, limit: f32) -> Vector2<f32> {
    if v.magnitude() > limit {
        v.normalize() * limit
    } else {
        v
    }
}
<commit_msg>Fix assignment of limited magnitude in nature of code ch1 n10 example<commit_after>// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
//
// Example 1-10: Motion 101 Acceleration
extern crate nannou;

use nannou::prelude::*;

fn main() {
    nannou::app(model, event, view).run();
}

struct Model {
    mover: Mover,
}

struct Mover {
    position: Point2<f32>,
    velocity: Vector2<f32>,
    acceleration: Vector2<f32>,
    top_speed: f32,
}

impl Mover {
    fn new(rect: Rect<f32>) -> Self {
        let position = pt2(rect.x(), rect.y());
        let velocity = vec2(0.0, 0.0);
        let acceleration = vec2(0.0, 0.0);
        let top_speed = 5.0;
        Mover {
            position,
            velocity,
            acceleration,
            top_speed,
        }
    }

    fn update(&mut self, mouse: Point2<f32>) {
        // Computer a vector that points from position to mouse
        self.acceleration = mouse - self.position;
        // Set magnitude of acceleration
        self.acceleration = self.acceleration.normalize() * 0.2;
        // Velocity chages according to acceleration
        self.velocity += self.acceleration;
        // Limit the velocity by top_speed
        self.velocity = limit_magnitude(self.velocity, self.top_speed);
        // Position changes velocity
        self.position += self.velocity;
    }

    fn display(&self, draw: &app::Draw) {
        // Display circle at x position
        draw.ellipse()
            .xy(self.position)
            .w_h(48.0, 48.0)
            .rgb(0.5, 0.5, 0.5);
    }
}

fn model(app: &App) -> Model {
    let _window = app.new_window().with_dimensions(640, 360).build().unwrap();
    let mover = Mover::new(app.window_rect());
    Model { mover }
}

fn event(app: &App, mut m: Model, event: Event) -> Model {
    // update gets called just before view every frame
    if let Event::Update(_update) = event {
        m.mover.update(pt2(app.mouse.x, app.mouse.y));
    }
    m
}

fn view(app: &App, m: &Model, frame: Frame) -> Frame {
    // Begin drawing
    let draw = app.draw();
    draw.background().color(WHITE);

    m.mover.display(&draw);

    // Write the result of our drawing to the window's OpenGL frame.
    draw.to_frame(app, &frame).unwrap();

    // Return the drawn frame.
    frame
}

// This will be a removed in favour of limir_magnitude method of vector
fn limit_magnitude(v: Vector2<f32>, limit: f32) -> Vector2<f32> {
    if v.magnitude() > limit {
        v.normalize() * limit
    } else {
        v
    }
}
<|endoftext|>


<commit_before>use std::collections::{RingBuf, HashSet};
use std::mem;
use std::ptr;

use block_allocator::BlockAllocator;
use block_info::BlockInfo;
use constants::{BLOCK_SIZE, LINE_SIZE};
use gc_object::GCObject;

pub struct LineAllocator {
    block_allocator: BlockAllocator,
    object_map: HashSet<*mut GCObject>,
    unavailable_blocks: RingBuf<*mut BlockInfo>,
    recyclable_blocks: RingBuf<*mut BlockInfo>,
    current_block: Option<(*mut BlockInfo, u16, u16)>,
}

impl LineAllocator {
    pub fn new(block_allocator: BlockAllocator) -> LineAllocator {
        return LineAllocator {
            block_allocator: block_allocator,
            object_map: HashSet::new(),
            unavailable_blocks: RingBuf::new(),
            recyclable_blocks: RingBuf::new(),
            current_block: None,
        };
    }

    pub fn is_gc_object(&self, object: *mut GCObject) -> bool {
        return self.object_map.contains(&object);
    }

    pub fn allocate(&mut self, size: uint, variables: uint) -> Option<*mut GCObject> {
        debug!("Request to allocate an object of size {}", size);
        let block_tuple = self.current_block
                              .and_then(|tp| self.scan_for_hole(size, tp))
                              .or_else(|| self.scan_recyclables(size))
                              .or_else(|| self.get_new_block());
        return match block_tuple {
            None => None,
            Some((block, low, high)) => {
                self.current_block = Some((block, low + size as u16, high));
                let object = unsafe { (*block).offset(low as uint) };
                self.object_map.insert(object);
                unsafe { ptr::write(object, GCObject::new(size, variables)); }
                debug!("Allocated object {} of size {} in {}", object, size, block);
                Some(object)
            }
        };
    }

    fn scan_for_hole(&mut self, size: uint, tuple: (*mut BlockInfo, u16, u16))
        -> Option<(*mut BlockInfo, u16, u16)> {
            let (block, low, high) = tuple;
            return match (high - low) as uint >= size {
                true => {
                    debug!("Found hole in block {:p}", block);
                    Some(tuple)
                },
                false => match unsafe{ (*block).scan_block(high) } {
                    None => {
                        debug!("Push block {:p} into unavailable_blocks", block);
                        self.unavailable_blocks.push_back(block);
                        None
                    },
                    Some((low, high)) =>
                        self.scan_for_hole(size, (block, low, high)),
                }
            };
        }

    fn scan_recyclables(&mut self, size: uint) -> Option<(*mut BlockInfo, u16, u16)> {
        return match self.recyclable_blocks.pop_front() {
            None => None,
            Some(block) => match unsafe{ (*block).scan_block((LINE_SIZE - 1) as u16) } {
                None => {
                    debug!("Push block {:p} into unavailable_blocks", block);
                    self.unavailable_blocks.push_back(block);
                    self.scan_recyclables(size)
                },
                Some((low, high)) => self.scan_for_hole(size, (block, low, high))
                                         .or_else(|| self.scan_recyclables(size)),
            }
        };
    }

    fn get_new_block(&mut self) -> Option<(*mut BlockInfo, u16, u16)> {
        debug!("Request new block from block_allocator");
        return self.block_allocator.get_block()
                   .map(|block| (block, LINE_SIZE as u16, (BLOCK_SIZE - 1) as u16));
    }

    pub fn return_empty_blocks(&mut self) {
        let mut recyclable_blocks = RingBuf::new();
        for block in self.current_block.take().map(|(b, _, _)| b).into_iter()
                         .chain(self.recyclable_blocks.drain())
                         .chain(self.unavailable_blocks.drain()) {
            if unsafe{ (*block).is_empty() } {
                debug!("Return block {:p} to global block allocator", block);
                self.block_allocator.return_block(block);
            } else {
                debug!("Recycle block {:p}", block);
                recyclable_blocks.push_back(block);
            }
        }
        self.recyclable_blocks.extend(recyclable_blocks.into_iter());
    }

    unsafe fn get_block_ptr(&mut self, object: *mut GCObject) -> *mut BlockInfo {
        let block_offset = object as uint % BLOCK_SIZE;
        return mem::transmute((object as *mut u8).offset(-(block_offset as int)));
    }

    pub fn decrement_lines(&mut self, object: *mut GCObject) {
        unsafe{ (*self.get_block_ptr(object)).decrement_lines(object); }
    }

    pub fn increment_lines(&mut self, object: *mut GCObject) {
        unsafe{ (*self.get_block_ptr(object)).increment_lines(object); }
    }

    pub fn clear_line_counts(&mut self) {
        // This will only be called after the RCCollector did his work and
        // self.return_empty_blocks() was invoked. So every managed block is
        // in self.recyclable_blocks.
        for block in self.recyclable_blocks.iter_mut() {
            unsafe{ (**block).clear_line_counts(); }
        }
    }
}
<commit_msg>Implement operations on LineAllocator.object_map<commit_after>use std::collections::{RingBuf, HashSet};
use std::mem;
use std::ptr;

use block_allocator::BlockAllocator;
use block_info::BlockInfo;
use constants::{BLOCK_SIZE, LINE_SIZE};
use gc_object::GCObject;

pub struct LineAllocator {
    block_allocator: BlockAllocator,
    object_map: HashSet<*mut GCObject>,
    unavailable_blocks: RingBuf<*mut BlockInfo>,
    recyclable_blocks: RingBuf<*mut BlockInfo>,
    current_block: Option<(*mut BlockInfo, u16, u16)>,
}

impl LineAllocator {
    pub fn new(block_allocator: BlockAllocator) -> LineAllocator {
        return LineAllocator {
            block_allocator: block_allocator,
            object_map: HashSet::new(),
            unavailable_blocks: RingBuf::new(),
            recyclable_blocks: RingBuf::new(),
            current_block: None,
        };
    }

    pub fn set_gc_object(&mut self, object: *mut GCObject) {
        self.object_map.insert(object);
    }

    pub fn unset_gc_object(&mut self, object: *mut GCObject) {
        self.object_map.remove(&object);
    }

    pub fn clear_object_map(&mut self) {
        self.object_map.clear();
    }

    pub fn is_gc_object(&self, object: *mut GCObject) -> bool {
        return self.object_map.contains(&object);
    }

    pub fn allocate(&mut self, size: uint, variables: uint) -> Option<*mut GCObject> {
        debug!("Request to allocate an object of size {}", size);
        let block_tuple = self.current_block
                              .and_then(|tp| self.scan_for_hole(size, tp))
                              .or_else(|| self.scan_recyclables(size))
                              .or_else(|| self.get_new_block());
        return match block_tuple {
            None => None,
            Some((block, low, high)) => {
                self.current_block = Some((block, low + size as u16, high));
                let object = unsafe { (*block).offset(low as uint) };
                self.set_gc_object(object);
                unsafe { ptr::write(object, GCObject::new(size, variables)); }
                debug!("Allocated object {} of size {} in {}", object, size, block);
                Some(object)
            }
        };
    }

    fn scan_for_hole(&mut self, size: uint, tuple: (*mut BlockInfo, u16, u16))
        -> Option<(*mut BlockInfo, u16, u16)> {
            let (block, low, high) = tuple;
            return match (high - low) as uint >= size {
                true => {
                    debug!("Found hole in block {:p}", block);
                    Some(tuple)
                },
                false => match unsafe{ (*block).scan_block(high) } {
                    None => {
                        debug!("Push block {:p} into unavailable_blocks", block);
                        self.unavailable_blocks.push_back(block);
                        None
                    },
                    Some((low, high)) =>
                        self.scan_for_hole(size, (block, low, high)),
                }
            };
        }

    fn scan_recyclables(&mut self, size: uint) -> Option<(*mut BlockInfo, u16, u16)> {
        return match self.recyclable_blocks.pop_front() {
            None => None,
            Some(block) => match unsafe{ (*block).scan_block((LINE_SIZE - 1) as u16) } {
                None => {
                    debug!("Push block {:p} into unavailable_blocks", block);
                    self.unavailable_blocks.push_back(block);
                    self.scan_recyclables(size)
                },
                Some((low, high)) => self.scan_for_hole(size, (block, low, high))
                                         .or_else(|| self.scan_recyclables(size)),
            }
        };
    }

    fn get_new_block(&mut self) -> Option<(*mut BlockInfo, u16, u16)> {
        debug!("Request new block from block_allocator");
        return self.block_allocator.get_block()
                   .map(|block| (block, LINE_SIZE as u16, (BLOCK_SIZE - 1) as u16));
    }

    pub fn return_empty_blocks(&mut self) {
        let mut recyclable_blocks = RingBuf::new();
        for block in self.current_block.take().map(|(b, _, _)| b).into_iter()
                         .chain(self.recyclable_blocks.drain())
                         .chain(self.unavailable_blocks.drain()) {
            if unsafe{ (*block).is_empty() } {
                debug!("Return block {:p} to global block allocator", block);
                self.block_allocator.return_block(block);
            } else {
                debug!("Recycle block {:p}", block);
                recyclable_blocks.push_back(block);
            }
        }
        self.recyclable_blocks.extend(recyclable_blocks.into_iter());
    }

    unsafe fn get_block_ptr(&mut self, object: *mut GCObject) -> *mut BlockInfo {
        let block_offset = object as uint % BLOCK_SIZE;
        return mem::transmute((object as *mut u8).offset(-(block_offset as int)));
    }

    pub fn decrement_lines(&mut self, object: *mut GCObject) {
        unsafe{ (*self.get_block_ptr(object)).decrement_lines(object); }
    }

    pub fn increment_lines(&mut self, object: *mut GCObject) {
        unsafe{ (*self.get_block_ptr(object)).increment_lines(object); }
    }

    pub fn clear_line_counts(&mut self) {
        // This will only be called after the RCCollector did his work and
        // self.return_empty_blocks() was invoked. So every managed block is
        // in self.recyclable_blocks.
        for block in self.recyclable_blocks.iter_mut() {
            unsafe{ (**block).clear_line_counts(); }
        }
    }
}
<|endoftext|>


<commit_before>//! Items in the scene heirarchy.

use std::fmt;
use std::hash::{Hash, Hasher};
use std::sync::mpsc;

use mint;

use audio;
use camera::Camera;
use hub::{Hub, Message, Operation, SubLight, SubNode};
use light;
use mesh::Mesh;
use node::NodePointer;
use scene::SyncGuard;
use skeleton::{Bone, Skeleton};
use sprite::Sprite;
use text::Text;

//Note: no local state should be here, only remote links
/// `Base` represents a concrete entity that can be added to the scene.
///
/// One cannot construct `Base` directly. Wrapper types such as [`Camera`],
/// [`Mesh`], and [`Group`] are provided instead.
///
/// Any type that implements [`Object`] may be converted to its concrete
/// `Base` type with the method [`Object::upcast`]. This is useful for
/// storing generic objects in containers.
///
/// [`Camera`]: ../camera/struct.Camera.html
/// [`Mesh`]: ../mesh/struct.Mesh.html
/// [`Group`]: ../object/struct.Group.html
/// [`Object`]: ../object/trait.Object.html
/// [`Object::upcast`]: ../object/trait.Object.html#method.upcast
#[derive(Clone)]
pub struct Base {
    pub(crate) node: NodePointer,
    pub(crate) tx: mpsc::Sender<Message>,
}

/// Marks data structures that are able to added to the scene graph.
pub trait Object: AsRef<Base> {
    /// The internal data for the object.
    ///
    /// Three-rs objects normally expose a write-only interface, making it possible to change
    /// an object's internal values but not possible to read those values.
    /// [`SyncGuard::resolve_data`] allows for that data to be read in a controlled way, with.
    /// the data for the specific object type determined by the `Data` trait member.
    ///
    /// Each object type has its own internal data, and not all object types can provide access
    /// to meaningful data. Types that cannot provide user-facing data will specify `()`
    /// for `Data`.
    type Data;

    /// Retrieves the internal data for the object.
    ///
    /// Prefer to use [`SyncGuard::resolve_data`] over calling this directly.
    fn resolve_data(&self, sync_guard: &mut SyncGuard) -> Self::Data;

    /// Converts into the base type.
    fn upcast(&self) -> Base {
        self.as_ref().clone()
    }

    /// Invisible objects are not rendered by cameras.
    fn set_visible(
        &self,
        visible: bool,
    ) {
        self.as_ref().send(Operation::SetVisible(visible));
    }

    /// Sets the name of the object.
    fn set_name<S: Into<String>>(
        &self,
        name: S,
    ) {
        self.as_ref().send(Operation::SetName(name.into()));
    }

    /// Set both position, orientation and scale.
    fn set_transform<P, Q>(
        &self,
        pos: P,
        rot: Q,
        scale: f32,
    ) where
        Self: Sized,
        P: Into<mint::Point3<f32>>,
        Q: Into<mint::Quaternion<f32>>,
    {
        self.as_ref().send(Operation::SetTransform(Some(pos.into()), Some(rot.into()), Some(scale)));
    }

    /// Set position.
    fn set_position<P>(
        &self,
        pos: P,
    ) where
        Self: Sized,
        P: Into<mint::Point3<f32>>,
    {
        self.as_ref().send(Operation::SetTransform(Some(pos.into()), None, None));
    }

    /// Set orientation.
    fn set_orientation<Q>(
        &self,
        rot: Q,
    ) where
        Self: Sized,
        Q: Into<mint::Quaternion<f32>>,
    {
        self.as_ref().send(Operation::SetTransform(None, Some(rot.into()), None));
    }

    /// Set scale.
    fn set_scale(
        &self,
        scale: f32,
    ) {
        self.as_ref().send(Operation::SetTransform(None, None, Some(scale)));
    }

    /// Set weights.
    //Note: needed for animations
    fn set_weights(
        &self,
        weights: Vec<f32>,
    ) {
        self.as_ref().send(Operation::SetWeights(weights));
    }

    /// Rotates object in the specific direction of `target`.
    fn look_at<E, T>(
        &self,
        eye: E,
        target: T,
        up: Option<mint::Vector3<f32>>,
    ) where
        Self: Sized,
        E: Into<mint::Point3<f32>>,
        T: Into<mint::Point3<f32>>,
    {
        use cgmath::{InnerSpace, Point3, Quaternion, Rotation, Vector3};
        let p: [mint::Point3<f32>; 2] = [eye.into(), target.into()];
        let dir = (Point3::from(p[0]) - Point3::from(p[1])).normalize();
        let z = Vector3::unit_z();
        let up = match up {
            Some(v) => Vector3::from(v).normalize(),
            None if dir.dot(z).abs() < 0.99 => z,
            None => Vector3::unit_y(),
        };
        let q = Quaternion::look_at(dir, up).invert();
        self.set_transform(p[0], q, 1.0);
    }
}

impl PartialEq for Base {
    fn eq(
        &self,
        other: &Base,
    ) -> bool {
        self.node == other.node
    }
}

impl Eq for Base {}

impl Hash for Base {
    fn hash<H: Hasher>(
        &self,
        state: &mut H,
    ) {
        self.node.hash(state);
    }
}

impl fmt::Debug for Base {
    fn fmt(
        &self,
        f: &mut fmt::Formatter,
    ) -> fmt::Result {
        self.node.fmt(f)
    }
}

impl Base {
    pub(crate) fn send(
        &self,
        operation: Operation,
    ) {
        let _ = self.tx.send((self.node.downgrade(), operation));
    }
}

// Required for `Base` to implement `trait Object`.
impl AsRef<Base> for Base {
    fn as_ref(&self) -> &Base {
        self
    }
}

impl Object for Base {
    type Data = ObjectType;

    fn resolve_data(&self, sync_guard: &mut SyncGuard) -> Self::Data {
        let node = &sync_guard.hub[self];
        match &node.sub_node {
            // TODO: Handle resolving cameras better (`Empty` is only used for cameras).
            SubNode::Camera(..) => ObjectType::Camera(Camera {
                object: self.clone(),
            }),

            SubNode::Group { .. } => ObjectType::Group(Group {
                object: self.clone(),
            }),

            SubNode::Audio(..) => ObjectType::AudioSource(audio::Source {
                object: self.clone(),
            }),

            SubNode::UiText(..) => ObjectType::Text(Text {
                object: self.clone(),
            }),

            // TODO: Differentiate between `Mesh` and `DynamicMesh`.
            SubNode::Visual(..) => ObjectType::Mesh(Mesh {
                object: self.clone(),
            }),

            SubNode::Bone { .. } => ObjectType::Bone(Bone {
                object: self.clone(),
            }),

            SubNode::Skeleton(..) => ObjectType::Skeleton(Skeleton {
                object: self.clone(),
            }),

            SubNode::Light(light) => match light.sub_light {
                SubLight::Ambient => ObjectType::AmbientLight(light::Ambient {
                    object: self.clone(),
                }),

                SubLight::Directional => ObjectType::DirectionalLight(light::Directional {
                    object: self.clone(),
                    shadow: light.shadow.as_ref().map(|&(ref map, _)| map.clone()),
                }),

                SubLight::Point => ObjectType::PointLight(light::Point {
                    object: self.clone(),
                }),

                SubLight::Hemisphere { .. } => ObjectType::HemisphereLight(light::Hemisphere {
                    object: self.clone(),
                }),
            },
        }
    }
}

/// The possible concrete types that a [`Base`] can be resolved to.
///
/// When using [`SyncGuard::resolve_data`] with a [`Base`], it will resolve to the concrete
/// object type that the base represents.
pub enum ObjectType {
    /// An audio source.
    AudioSource(audio::Source),

    /// An ambient light.
    AmbientLight(light::Ambient),

    /// A directional light.
    DirectionalLight(light::Directional),

    /// A hemisphere light.
    HemisphereLight(light::Hemisphere),

    /// A point light.
    PointLight(light::Point),

    /// A mesh.
    Mesh(Mesh),

    /// A group.
    Group(Group),

    /// A skeleton.
    Skeleton(Skeleton),

    /// A bone in a skeleton.
    Bone(Bone),

    /// A 2D sprite.
    Sprite(Sprite),

    /// A UI text object.
    Text(Text),

    /// A camera.
    Camera(Camera),
}

/// Marks an object type that can be downcast from a [`Base`].
pub trait DowncastObject: Sized {
    /// Attempts to extract the concrete type of the object from an [`ObjectType`].
    ///
    /// Prefer to use [`SyncGuard::downcast`] over calling this directly.
    fn downcast(object: ObjectType) -> Option<Self>;
}

/// Groups are used to combine several other objects or groups to work with them
/// as with a single entity.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Group {
    object: Base,
}

impl AsRef<Base> for Group {
    fn as_ref(&self) -> &Base { &self.object }
}

impl Object for Group {
    type Data = Vec<Base>;

    fn resolve_data(&self, sync_guard: &mut SyncGuard) -> Vec<Base> {
        let mut children = Vec::new();
        let node = &sync_guard.hub[self];

        let mut child = match node.sub_node {
            SubNode::Group { ref first_child } => first_child.clone(),
            _ => panic!("`Group` had a bad sub node type: {:?}", node.sub_node),
        };

        while let Some(child_pointer) = child {
            child = sync_guard.hub.nodes[&child_pointer].next_sibling.clone();

            children.push(Base {
                node: child_pointer,
                tx: sync_guard.hub.message_tx.clone(),
            });
        }

        children
    }
}

impl DowncastObject for Group {
    fn downcast(object: ObjectType) -> Option<Self> {
        match object {
            ObjectType::Group(group) => Some(group),
            _ => None,
        }
    }
}

impl Group {
    pub(crate) fn new(hub: &mut Hub) -> Self {
        let sub = SubNode::Group { first_child: None };
        Group {
            object: hub.spawn(sub),
        }
    }

    /// Add new [`Object`](trait.Object.html) to the group.
    pub fn add<T: Object>(
        &self,
        child: &T,
    ) {
        let node = child.as_ref().node.clone();
        self.as_ref().send(Operation::AddChild(node));
    }

    /// Removes a child [`Object`](trait.Object.html) from the group.
    pub fn remove<T: Object>(
        &self,
        child: &T,
    ) {
        let node = child.as_ref().node.clone();
        self.as_ref().send(Operation::RemoveChild(node));
    }
}
<commit_msg>Derive Debug and Clone for ObjectType<commit_after>//! Items in the scene heirarchy.

use std::fmt;
use std::hash::{Hash, Hasher};
use std::sync::mpsc;

use mint;

use audio;
use camera::Camera;
use hub::{Hub, Message, Operation, SubLight, SubNode};
use light;
use mesh::Mesh;
use node::NodePointer;
use scene::SyncGuard;
use skeleton::{Bone, Skeleton};
use sprite::Sprite;
use text::Text;

//Note: no local state should be here, only remote links
/// `Base` represents a concrete entity that can be added to the scene.
///
/// One cannot construct `Base` directly. Wrapper types such as [`Camera`],
/// [`Mesh`], and [`Group`] are provided instead.
///
/// Any type that implements [`Object`] may be converted to its concrete
/// `Base` type with the method [`Object::upcast`]. This is useful for
/// storing generic objects in containers.
///
/// [`Camera`]: ../camera/struct.Camera.html
/// [`Mesh`]: ../mesh/struct.Mesh.html
/// [`Group`]: ../object/struct.Group.html
/// [`Object`]: ../object/trait.Object.html
/// [`Object::upcast`]: ../object/trait.Object.html#method.upcast
#[derive(Clone)]
pub struct Base {
    pub(crate) node: NodePointer,
    pub(crate) tx: mpsc::Sender<Message>,
}

/// Marks data structures that are able to added to the scene graph.
pub trait Object: AsRef<Base> {
    /// The internal data for the object.
    ///
    /// Three-rs objects normally expose a write-only interface, making it possible to change
    /// an object's internal values but not possible to read those values.
    /// [`SyncGuard::resolve_data`] allows for that data to be read in a controlled way, with.
    /// the data for the specific object type determined by the `Data` trait member.
    ///
    /// Each object type has its own internal data, and not all object types can provide access
    /// to meaningful data. Types that cannot provide user-facing data will specify `()`
    /// for `Data`.
    type Data;

    /// Retrieves the internal data for the object.
    ///
    /// Prefer to use [`SyncGuard::resolve_data`] over calling this directly.
    fn resolve_data(&self, sync_guard: &mut SyncGuard) -> Self::Data;

    /// Converts into the base type.
    fn upcast(&self) -> Base {
        self.as_ref().clone()
    }

    /// Invisible objects are not rendered by cameras.
    fn set_visible(
        &self,
        visible: bool,
    ) {
        self.as_ref().send(Operation::SetVisible(visible));
    }

    /// Sets the name of the object.
    fn set_name<S: Into<String>>(
        &self,
        name: S,
    ) {
        self.as_ref().send(Operation::SetName(name.into()));
    }

    /// Set both position, orientation and scale.
    fn set_transform<P, Q>(
        &self,
        pos: P,
        rot: Q,
        scale: f32,
    ) where
        Self: Sized,
        P: Into<mint::Point3<f32>>,
        Q: Into<mint::Quaternion<f32>>,
    {
        self.as_ref().send(Operation::SetTransform(Some(pos.into()), Some(rot.into()), Some(scale)));
    }

    /// Set position.
    fn set_position<P>(
        &self,
        pos: P,
    ) where
        Self: Sized,
        P: Into<mint::Point3<f32>>,
    {
        self.as_ref().send(Operation::SetTransform(Some(pos.into()), None, None));
    }

    /// Set orientation.
    fn set_orientation<Q>(
        &self,
        rot: Q,
    ) where
        Self: Sized,
        Q: Into<mint::Quaternion<f32>>,
    {
        self.as_ref().send(Operation::SetTransform(None, Some(rot.into()), None));
    }

    /// Set scale.
    fn set_scale(
        &self,
        scale: f32,
    ) {
        self.as_ref().send(Operation::SetTransform(None, None, Some(scale)));
    }

    /// Set weights.
    //Note: needed for animations
    fn set_weights(
        &self,
        weights: Vec<f32>,
    ) {
        self.as_ref().send(Operation::SetWeights(weights));
    }

    /// Rotates object in the specific direction of `target`.
    fn look_at<E, T>(
        &self,
        eye: E,
        target: T,
        up: Option<mint::Vector3<f32>>,
    ) where
        Self: Sized,
        E: Into<mint::Point3<f32>>,
        T: Into<mint::Point3<f32>>,
    {
        use cgmath::{InnerSpace, Point3, Quaternion, Rotation, Vector3};
        let p: [mint::Point3<f32>; 2] = [eye.into(), target.into()];
        let dir = (Point3::from(p[0]) - Point3::from(p[1])).normalize();
        let z = Vector3::unit_z();
        let up = match up {
            Some(v) => Vector3::from(v).normalize(),
            None if dir.dot(z).abs() < 0.99 => z,
            None => Vector3::unit_y(),
        };
        let q = Quaternion::look_at(dir, up).invert();
        self.set_transform(p[0], q, 1.0);
    }
}

impl PartialEq for Base {
    fn eq(
        &self,
        other: &Base,
    ) -> bool {
        self.node == other.node
    }
}

impl Eq for Base {}

impl Hash for Base {
    fn hash<H: Hasher>(
        &self,
        state: &mut H,
    ) {
        self.node.hash(state);
    }
}

impl fmt::Debug for Base {
    fn fmt(
        &self,
        f: &mut fmt::Formatter,
    ) -> fmt::Result {
        self.node.fmt(f)
    }
}

impl Base {
    pub(crate) fn send(
        &self,
        operation: Operation,
    ) {
        let _ = self.tx.send((self.node.downgrade(), operation));
    }
}

// Required for `Base` to implement `trait Object`.
impl AsRef<Base> for Base {
    fn as_ref(&self) -> &Base {
        self
    }
}

impl Object for Base {
    type Data = ObjectType;

    fn resolve_data(&self, sync_guard: &mut SyncGuard) -> Self::Data {
        let node = &sync_guard.hub[self];
        match &node.sub_node {
            // TODO: Handle resolving cameras better (`Empty` is only used for cameras).
            SubNode::Camera(..) => ObjectType::Camera(Camera {
                object: self.clone(),
            }),

            SubNode::Group { .. } => ObjectType::Group(Group {
                object: self.clone(),
            }),

            SubNode::Audio(..) => ObjectType::AudioSource(audio::Source {
                object: self.clone(),
            }),

            SubNode::UiText(..) => ObjectType::Text(Text {
                object: self.clone(),
            }),

            // TODO: Differentiate between `Mesh` and `DynamicMesh`.
            SubNode::Visual(..) => ObjectType::Mesh(Mesh {
                object: self.clone(),
            }),

            SubNode::Bone { .. } => ObjectType::Bone(Bone {
                object: self.clone(),
            }),

            SubNode::Skeleton(..) => ObjectType::Skeleton(Skeleton {
                object: self.clone(),
            }),

            SubNode::Light(light) => match light.sub_light {
                SubLight::Ambient => ObjectType::AmbientLight(light::Ambient {
                    object: self.clone(),
                }),

                SubLight::Directional => ObjectType::DirectionalLight(light::Directional {
                    object: self.clone(),
                    shadow: light.shadow.as_ref().map(|&(ref map, _)| map.clone()),
                }),

                SubLight::Point => ObjectType::PointLight(light::Point {
                    object: self.clone(),
                }),

                SubLight::Hemisphere { .. } => ObjectType::HemisphereLight(light::Hemisphere {
                    object: self.clone(),
                }),
            },
        }
    }
}

/// The possible concrete types that a [`Base`] can be resolved to.
///
/// When using [`SyncGuard::resolve_data`] with a [`Base`], it will resolve to the concrete
/// object type that the base represents.
#[derive(Debug, Clone)]
pub enum ObjectType {
    /// An audio source.
    AudioSource(audio::Source),

    /// An ambient light.
    AmbientLight(light::Ambient),

    /// A directional light.
    DirectionalLight(light::Directional),

    /// A hemisphere light.
    HemisphereLight(light::Hemisphere),

    /// A point light.
    PointLight(light::Point),

    /// A mesh.
    Mesh(Mesh),

    /// A group.
    Group(Group),

    /// A skeleton.
    Skeleton(Skeleton),

    /// A bone in a skeleton.
    Bone(Bone),

    /// A 2D sprite.
    Sprite(Sprite),

    /// A UI text object.
    Text(Text),

    /// A camera.
    Camera(Camera),
}

/// Marks an object type that can be downcast from a [`Base`].
pub trait DowncastObject: Sized {
    /// Attempts to extract the concrete type of the object from an [`ObjectType`].
    ///
    /// Prefer to use [`SyncGuard::downcast`] over calling this directly.
    fn downcast(object: ObjectType) -> Option<Self>;
}

/// Groups are used to combine several other objects or groups to work with them
/// as with a single entity.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Group {
    object: Base,
}

impl AsRef<Base> for Group {
    fn as_ref(&self) -> &Base { &self.object }
}

impl Object for Group {
    type Data = Vec<Base>;

    fn resolve_data(&self, sync_guard: &mut SyncGuard) -> Vec<Base> {
        let mut children = Vec::new();
        let node = &sync_guard.hub[self];

        let mut child = match node.sub_node {
            SubNode::Group { ref first_child } => first_child.clone(),
            _ => panic!("`Group` had a bad sub node type: {:?}", node.sub_node),
        };

        while let Some(child_pointer) = child {
            child = sync_guard.hub.nodes[&child_pointer].next_sibling.clone();

            children.push(Base {
                node: child_pointer,
                tx: sync_guard.hub.message_tx.clone(),
            });
        }

        children
    }
}

impl DowncastObject for Group {
    fn downcast(object: ObjectType) -> Option<Self> {
        match object {
            ObjectType::Group(group) => Some(group),
            _ => None,
        }
    }
}

impl Group {
    pub(crate) fn new(hub: &mut Hub) -> Self {
        let sub = SubNode::Group { first_child: None };
        Group {
            object: hub.spawn(sub),
        }
    }

    /// Add new [`Object`](trait.Object.html) to the group.
    pub fn add<T: Object>(
        &self,
        child: &T,
    ) {
        let node = child.as_ref().node.clone();
        self.as_ref().send(Operation::AddChild(node));
    }

    /// Removes a child [`Object`](trait.Object.html) from the group.
    pub fn remove<T: Object>(
        &self,
        child: &T,
    ) {
        let node = child.as_ref().node.clone();
        self.as_ref().send(Operation::RemoveChild(node));
    }
}
<|endoftext|>


<commit_before>extern crate core;

use core::num::FromPrimitive;
use core::fmt;

use std::rand::random;

use Direction::{SpinUp, SpinDown, SpinSuper};
use Plan::{Trivial, OddBall};

#[derive(Copy)]
#[derive(Show)]
enum Direction {
    SpinUp,
    SpinDown,
    SpinSuper,
}

impl fmt::String for Direction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r = match self {
            &SpinUp => "SpinUp",
            &SpinDown => "SpinDown",
            &SpinSuper => "SpinSuper"
        };
        write!(f, "{}", r)
    }
}

struct Pair<T> {
    lhs: T,
    rhs: T
}

struct Particle {
    spin: Direction
}

enum Plan {
    Trivial, // up-up-up -> down-down-down
    OddBall  // up-down-up -> down-up-down
}

enum Detector {
    D12, // 12 o'clock
    D3, // 3 o'clock
    D9, // 9 o' clock
}

impl Particle {
    fn new_pair () -> Pair<Particle> {
        let d1 = SpinSuper;
        let d2 = SpinSuper;
        let p1 = Particle{spin: d1};
        let p2 = Particle{spin: d2};

        return Pair{lhs: p1, rhs: p2};
    }

    pub fn measure (&mut self, theta: int) {
        // TODO theta = 60degrees use 3/4th and 1/4th
        // TODO theta = 0 SpinUp
        // TODO theta = 180 SpinDown
    }

    // NOTE on spooky and premeditated only if measured in the same
    // direction must the spins be opposite

    // measure with with a message
    pub fn spooky (&mut self, friend: &mut Particle) -> Pair<Direction> {

        let spin = match self.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            SpinSuper => SpinUp
        };
        friend.spin = spin;

        let spin = match friend.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            _ => panic!("broke the universe")
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }

    pub fn premeditated (&mut self, friend: &mut Particle, plan: Plan) -> Pair<Direction> {

        let rnd = random::<f32>();

        let direction;

        if rnd < 0.33 {
            direction = Detector::D12;
        } else if rnd >= 0.33 && rnd < 0.66 {
            direction = Detector::D3;
        } else {
            direction = Detector::D9;
        }

        let spin = match plan {
            Trivial => SpinUp,
            OddBall => match direction {
                Detector::D3 => SpinDown,
                _ => SpinUp
            }
        };
        friend.spin = spin;

        let spin = match friend.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            _ => panic!("broke the universe")
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }
}

fn main () {

    let particles = Particle::new_pair();

    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;

    lhs.spooky(&mut rhs);

    println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);

    // premeditated should give +55.6% difference, spooky would give 50%

    let particles = Particle::new_pair();

    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;
    lhs.premeditated(&mut rhs, OddBall);
    println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);

}
<commit_msg>add more detector logic<commit_after>extern crate core;

use core::num::FromPrimitive;
use core::fmt;

use std::rand::random;

use Direction::{SpinUp, SpinDown, SpinSuper};
use Plan::{Trivial, OddBall};

#[derive(Copy)]
#[derive(Show)]
enum Direction {
    SpinUp,
    SpinDown,
    SpinSuper,
}

impl fmt::String for Direction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r = match self {
            &SpinUp => "SpinUp",
            &SpinDown => "SpinDown",
            &SpinSuper => "SpinSuper"
        };
        write!(f, "{}", r)
    }
}

impl fmt::String for Detector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Detector::{D12, D3, D9};
        let r = match self {
            &D12 => "12 oclock",
            &D3 => "3 oclock",
            &D9 => "9 oclock"
        };
        write!(f, "{}", r)
    }
}

struct Pair<T> {
    lhs: T,
    rhs: T
}

struct Particle {
    spin: Direction
}

enum Plan {
    Trivial, // up-up-up -> down-down-down
    OddBall  // up-down-up -> down-up-down
}

#[derive(Show)]
enum Detector {
    D12, // 12 o'clock
    D3, // 3 o'clock
    D9, // 9 o' clock
}

impl Particle {
    fn new_pair () -> Pair<Particle> {
        let d1 = SpinSuper;
        let d2 = SpinSuper;
        let p1 = Particle{spin: d1};
        let p2 = Particle{spin: d2};

        return Pair{lhs: p1, rhs: p2};
    }

    pub fn measure (&mut self, theta: int) {
        // TODO theta = 60degrees use 3/4th and 1/4th
        // TODO theta = 0 SpinUp
        // TODO theta = 180 SpinDown
    }

    // NOTE on spooky and premeditated only if measured in the same
    // direction must the spins be opposite

    // measure with with a message
    pub fn spooky (&mut self, friend: &mut Particle) -> Pair<Direction> {

        let spin = match self.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            SpinSuper => SpinUp
        };
        friend.spin = spin;

        let spin = match friend.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            _ => panic!("broke the universe")
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }

    pub fn premeditated (&mut self, friend: &mut Particle, plan: Plan) -> Pair<Direction> {

        let rnd = random::<f32>();

        let detector;
        if rnd < 0.33 {
            detector = Detector::D12;
        } else if rnd >= 0.33 && rnd < 0.66 {
            detector = Detector::D3;
        } else {
            detector = Detector::D9;
        }

        println!("{}", detector);

        let spin = match plan {
            Trivial => SpinUp,
            OddBall => match detector {
                Detector::D3 => SpinDown,
                _ => SpinUp
            }
        };
        friend.spin = spin;

        let spin = match plan {
            Trivial => SpinDown,
            OddBall => match detector {
                Detector::D3 => SpinUp,
                _ => SpinDown
            }
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }
}

fn main () {

    let particles = Particle::new_pair();

    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;

    lhs.spooky(&mut rhs);

    println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);

    // premeditated should give +55.6% difference, spooky would give 50%

    let particles = Particle::new_pair();

    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;
    lhs.premeditated(&mut rhs, OddBall);
    println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);

}
<|endoftext|>


<commit_before>extern crate gcc;

use std::process::Command;

const AYUMI_PATH: &'static str = "ayumi-lib/ayumi.c";
fn main() {
    // init submodules
    Command::new("git").arg("submodule").arg("update").output().unwrap_or_else(|e| {
        panic!("ayumi-lib build failed: {}", e);
    });
    // compile lib
    gcc::compile_library("libayumi.a", &[AYUMI_PATH]);
}
<commit_msg>Second build file fix<commit_after>extern crate gcc;

use std::env;
use std::process::Command;

const AYUMI_PATH: &'static str = "ayumi-lib/ayumi.c";
fn main() {
    // init submodules
    Command::new("git").args(&["submodule", "update", "--init", "ayumi-lib"])
                       .current_dir(env::var("CARGO_MANIFEST_DIR").unwrap())
                       .output().unwrap();
    // compile lib
    gcc::compile_library("libayumi.a", &[AYUMI_PATH]);
}
<|endoftext|>


<commit_before>extern crate gcc;
#[macro_use] extern crate lazy_static;
extern crate regex;
extern crate semver;

use regex::Regex;
use semver::Version;
use std::env;
use std::ffi::OsStr;
use std::io::{self, ErrorKind};
use std::path::PathBuf;
use std::process::Command;

lazy_static!{
    /// LLVM version used by this version of the crate.
    static ref CRATE_VERSION: Version = {
        let crate_version = Version::parse(env!("CARGO_PKG_VERSION"))
            .expect("Crate version is somehow not valid semver");
        Version {
            major: crate_version.major / 10,
            minor: crate_version.major % 10,
            .. crate_version
        }
    };

    /// Filesystem path to an llvm-config binary for the correct version.
    static ref LLVM_CONFIG_PATH: PathBuf = {
        // Try llvm-config via PATH first.
        if let Some(name) = locate_system_llvm_config() {
            return name.into();
        } else {
            println!("Didn't find usable system-wide LLVM.");
        }

        // Did the user give us a binary path to use? If yes, try
        // to use that and fail if it doesn't work.
        let binary_prefix_var = format!("LLVM_SYS_{}_PREFIX",
                                        env!("CARGO_PKG_VERSION_MAJOR"));
        if let Some(path) = env::var_os(&binary_prefix_var) {
            let mut pb: PathBuf = path.into();
            pb.push("bin");
            pb.push("llvm-config");

            let ver = llvm_version(&pb)
                .expect(&format!("Failed to execute {:?}", &pb));
            if is_compatible_llvm(&ver) {
                return pb;
            } else {
                panic!("LLVM binaries specified by {} are the wrong version.
                        (Found {}, need {}.)", binary_prefix_var, ver, *CRATE_VERSION);
            }
        } else {
            println!("{} not set, not using precompiled binaries", binary_prefix_var);
        }

        // No binaries. Offer to download and compile a blessed version,
        // but only with positive confirmation. It's a fairly large download,
        // takes a while and could get wiped out by a `cargo clean` so it's
        // useful if doing an install but is in general not recommended.
        let autobuild_var = format!("LLVM_SYS_{}_AUTOBUILD",
                                    env!("CARGO_PKG_VERSION_MAJOR"));
        match env::var_os(&autobuild_var) {
            Some(ref x) => {
                if x == "YES" {
                    unimplemented!();
                } else {
                    println!("{} must be exactly \"YES\" to enable autobuild (is {:?})",
                             autobuild_var, x);
                }
            }
            None => {
                println!("{} not set, will not automatically compile LLVM",
                         autobuild_var);
            }
        }

        panic!("Could not find a compatible version of LLVM");
    };
}

/// Try to find a system-wide version of llvm-config that is compatible with
/// this crate.
///
/// Returns None on failure.
fn locate_system_llvm_config() -> Option<&'static str> {
    match llvm_version("llvm-config") {
        Ok(ref version) if is_compatible_llvm(version) => {
            // Compatible version found. Nice.
            return Some("llvm-config");
        },
        Ok(version) => {
            // Version mismatch. Will try further searches, but warn that
            // we're not using the system one.
            println!("Found LLVM version {} on PATH, but need {}.",
                     version, *CRATE_VERSION);
        },
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            // Looks like we failed to execute any llvm-config. Keep
            // searching.
        },
        // Some other error, probably a weird failure. Give up.
        Err(e) => panic!("Failed to search PATH for llvm-config: {}", e),
    }

    None
}

/// Check whether the given version of LLVM is blacklisted,
/// returning `Some(reason)` if it is.
fn is_blacklisted_llvm(llvm_version: &Version) -> Option<&'static str> {
    static BLACKLIST: &'static [(u64, u64, u64, &'static str)] = &[];

    let blacklist_var = format!("LLVM_SYS_{}_IGNORE_BLACKLIST",
                                env!("CARGO_PKG_VERSION_MAJOR"));
    if let Some(x) = env::var_os(&blacklist_var) {
        if &x == "YES" {
            println!("cargo:warning=Ignoring blacklist entry for LLVM {}", llvm_version);
            return None;
        } else {
            println!("cargo:warning={} is set but not exactly \"YES\"; blacklist is still honored.",
                     &blacklist_var);
        }
    }

    for &(major, minor, patch, reason) in BLACKLIST.iter() {
        let bad_version = Version {
            major: major, minor: minor, patch: patch,
            pre: vec![], build: vec![],
        };

        if &bad_version == llvm_version {
            return Some(reason);
        }
    }
    None
}

/// Check whether the given LLVM version is compatible with this version of
/// the crate.
fn is_compatible_llvm(llvm_version: &Version) -> bool {
    if let Some(reason) = is_blacklisted_llvm(llvm_version) {
        println!("Found LLVM {}, which is blacklisted: {}", llvm_version, reason);
        return false;
    }

    let strict = env::var_os(format!("LLVM_SYS_{}_STRICT_VERSIONING",
                                     env!("CARGO_PKG_VERSION_MAJOR"))).is_some()
        || cfg!(feature="strict-versioning");
    if strict {
        llvm_version.major == CRATE_VERSION.major &&
            llvm_version.minor == CRATE_VERSION.minor
    } else {
        llvm_version.major >= CRATE_VERSION.major ||
            (llvm_version.major == CRATE_VERSION.major &&
             llvm_version.minor >= CRATE_VERSION.minor)
    }
}

/// Get the output from running `llvm-config` with the given argument.
///
/// Lazily searches for or compiles LLVM as configured by the environment
/// variables.
fn llvm_config(arg: &str) -> String {
    llvm_config_ex(&*LLVM_CONFIG_PATH, arg)
        .expect("Surprising failure from llvm-config")
}

/// Invoke the specified binary as llvm-config.
///
/// Explicit version of the `llvm_config` function that bubbles errors
/// up.
fn llvm_config_ex<S: AsRef<OsStr>>(binary: S, arg: &str)
        -> io::Result<String> {
    Command::new(binary)
        .arg(arg)
        .arg("--link-static")   // Don't use dylib for >= 3.9
        .output()
        .map(|output| String::from_utf8(output.stdout)
            .expect("Output from llvm-config was not valid UTF-8"))
}

/// Get the LLVM version using llvm-config.
fn llvm_version<S: AsRef<OsStr>>(binary: S) -> io::Result<Version> {
    let version_str = try!(llvm_config_ex(binary.as_ref(), "--version"));

    // LLVM isn't really semver and uses version suffixes to build
    // version strings like '3.8.0svn', so limit what we try to parse
    // to only the numeric bits.
    let re = Regex::new(r"^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)")
        .unwrap();
    let m = re.find(&version_str)
        .expect("Could not determine LLVM version from llvm-config.");

    Ok(Version::parse(&version_str[m.start()..m.end()]).unwrap())
}

/// Get the names of the dylibs required by LLVM, including the C++ standard
/// library.
fn get_system_libraries() -> Vec<String> {
    llvm_config("--system-libs")
        .split(&[' ', '\n'] as &[char])
        .filter(|s| !s.is_empty())
        .map(|flag| {
            if cfg!(target_env = "msvc") {
                // Same as --libnames, foo.lib
                assert!(flag.ends_with(".lib"));
                &flag[..flag.len() - 4]
            } else {
                // Linker flags style, -lfoo
                assert!(flag.starts_with("-l"));
                &flag[2..]
            }
        })
        .chain(get_system_libcpp())
        .map(str::to_owned)
        .collect::<Vec<String>>()
}

/// Get the library that must be linked for C++, if any.
fn get_system_libcpp() -> Option<&'static str> {
    if cfg!(target_env = "msvc") {
        // MSVC doesn't need an explicit one.
        None
    } else if cfg!(target_os = "macos") {
        // On OS X 10.9 and later, LLVM's libc++ is the default. On earlier
        // releases GCC's libstdc++ is default. Unfortunately we can't
        // reasonably detect which one we need (on older ones libc++ is
        // available and can be selected with -stdlib=lib++), so assume the
        // latest, at the cost of breaking the build on older OS releases
        // when LLVM was built against libstdc++.
        Some("c++")
    } else {
        // Otherwise assume GCC's libstdc++.
        // This assumption is probably wrong on some platforms, but would need
        // testing on them.
        Some("stdc++")
    }
}

/// Get the names of libraries to link against.
fn get_link_libraries() -> Vec<String> {
    // Using --libnames in conjunction with --libdir is particularly important
    // for MSVC when LLVM is in a path with spaces, but it is generally less of
    // a hack than parsing linker flags output from --libs and --ldflags.
    llvm_config("--libnames")
        .split(&[' ', '\n'] as &[char])
        .filter(|s| !s.is_empty())
        .map(|name| {
            // --libnames gives library filenames. Extract only the name that
            // we need to pass to the linker.
            if cfg!(target_env = "msvc") {
                // LLVMfoo.lib
                assert!(name.ends_with(".lib"));
                &name[..name.len() - 4]
            } else {
                // libLLVMfoo.a
                assert!(name.starts_with("lib") && name.ends_with(".a"));
                &name[3..name.len() - 2]
            }
        })
        .map(str::to_owned)
        .collect::<Vec<String>>()
}

fn main() {
    let libdir = llvm_config("--libdir");

    // Export information to other crates
    println!("cargo:config_path={}", LLVM_CONFIG_PATH.display()); // will be DEP_LLVM_CONFIG_PATH
    println!("cargo:libdir={}", libdir); // DEP_LLVM_LIBDIR

    // Link LLVM libraries
    println!("cargo:rustc-link-search=native={}", libdir);
    for name in get_link_libraries() {
        println!("cargo:rustc-link-lib=static={}", name);
    }

    // Link system libraries
    for name in get_system_libraries() {
        println!("cargo:rustc-link-lib=dylib={}", name);
    }

    // Build the extra wrapper functions.
    std::env::set_var("CFLAGS", llvm_config("--cflags").trim());
    gcc::compile_library("libtargetwrappers.a", &["wrappers/target.c"]);
}
<commit_msg>Add build-time libffi linking workaround for #12.<commit_after>extern crate gcc;
#[macro_use] extern crate lazy_static;
extern crate regex;
extern crate semver;

use regex::Regex;
use semver::Version;
use std::env;
use std::ffi::OsStr;
use std::io::{self, ErrorKind};
use std::path::PathBuf;
use std::process::Command;

lazy_static!{
    /// LLVM version used by this version of the crate.
    static ref CRATE_VERSION: Version = {
        let crate_version = Version::parse(env!("CARGO_PKG_VERSION"))
            .expect("Crate version is somehow not valid semver");
        Version {
            major: crate_version.major / 10,
            minor: crate_version.major % 10,
            .. crate_version
        }
    };

    /// Filesystem path to an llvm-config binary for the correct version.
    static ref LLVM_CONFIG_PATH: PathBuf = {
        // Try llvm-config via PATH first.
        if let Some(name) = locate_system_llvm_config() {
            return name.into();
        } else {
            println!("Didn't find usable system-wide LLVM.");
        }

        // Did the user give us a binary path to use? If yes, try
        // to use that and fail if it doesn't work.
        let binary_prefix_var = format!("LLVM_SYS_{}_PREFIX",
                                        env!("CARGO_PKG_VERSION_MAJOR"));
        if let Some(path) = env::var_os(&binary_prefix_var) {
            let mut pb: PathBuf = path.into();
            pb.push("bin");
            pb.push("llvm-config");

            let ver = llvm_version(&pb)
                .expect(&format!("Failed to execute {:?}", &pb));
            if is_compatible_llvm(&ver) {
                return pb;
            } else {
                panic!("LLVM binaries specified by {} are the wrong version.
                        (Found {}, need {}.)", binary_prefix_var, ver, *CRATE_VERSION);
            }
        } else {
            println!("{} not set, not using precompiled binaries", binary_prefix_var);
        }

        // No binaries. Offer to download and compile a blessed version,
        // but only with positive confirmation. It's a fairly large download,
        // takes a while and could get wiped out by a `cargo clean` so it's
        // useful if doing an install but is in general not recommended.
        let autobuild_var = format!("LLVM_SYS_{}_AUTOBUILD",
                                    env!("CARGO_PKG_VERSION_MAJOR"));
        match env::var_os(&autobuild_var) {
            Some(ref x) => {
                if x == "YES" {
                    unimplemented!();
                } else {
                    println!("{} must be exactly \"YES\" to enable autobuild (is {:?})",
                             autobuild_var, x);
                }
            }
            None => {
                println!("{} not set, will not automatically compile LLVM",
                         autobuild_var);
            }
        }

        panic!("Could not find a compatible version of LLVM");
    };
}

/// Try to find a system-wide version of llvm-config that is compatible with
/// this crate.
///
/// Returns None on failure.
fn locate_system_llvm_config() -> Option<&'static str> {
    match llvm_version("llvm-config") {
        Ok(ref version) if is_compatible_llvm(version) => {
            // Compatible version found. Nice.
            return Some("llvm-config");
        },
        Ok(version) => {
            // Version mismatch. Will try further searches, but warn that
            // we're not using the system one.
            println!("Found LLVM version {} on PATH, but need {}.",
                     version, *CRATE_VERSION);
        },
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            // Looks like we failed to execute any llvm-config. Keep
            // searching.
        },
        // Some other error, probably a weird failure. Give up.
        Err(e) => panic!("Failed to search PATH for llvm-config: {}", e),
    }

    None
}

/// Check whether the given version of LLVM is blacklisted,
/// returning `Some(reason)` if it is.
fn is_blacklisted_llvm(llvm_version: &Version) -> Option<&'static str> {
    static BLACKLIST: &'static [(u64, u64, u64, &'static str)] = &[];

    let blacklist_var = format!("LLVM_SYS_{}_IGNORE_BLACKLIST",
                                env!("CARGO_PKG_VERSION_MAJOR"));
    if let Some(x) = env::var_os(&blacklist_var) {
        if &x == "YES" {
            println!("cargo:warning=Ignoring blacklist entry for LLVM {}", llvm_version);
            return None;
        } else {
            println!("cargo:warning={} is set but not exactly \"YES\"; blacklist is still honored.",
                     &blacklist_var);
        }
    }

    for &(major, minor, patch, reason) in BLACKLIST.iter() {
        let bad_version = Version {
            major: major, minor: minor, patch: patch,
            pre: vec![], build: vec![],
        };

        if &bad_version == llvm_version {
            return Some(reason);
        }
    }
    None
}

/// Check whether the given LLVM version is compatible with this version of
/// the crate.
fn is_compatible_llvm(llvm_version: &Version) -> bool {
    if let Some(reason) = is_blacklisted_llvm(llvm_version) {
        println!("Found LLVM {}, which is blacklisted: {}", llvm_version, reason);
        return false;
    }

    let strict = env::var_os(format!("LLVM_SYS_{}_STRICT_VERSIONING",
                                     env!("CARGO_PKG_VERSION_MAJOR"))).is_some()
        || cfg!(feature="strict-versioning");
    if strict {
        llvm_version.major == CRATE_VERSION.major &&
            llvm_version.minor == CRATE_VERSION.minor
    } else {
        llvm_version.major >= CRATE_VERSION.major ||
            (llvm_version.major == CRATE_VERSION.major &&
             llvm_version.minor >= CRATE_VERSION.minor)
    }
}

/// Get the output from running `llvm-config` with the given argument.
///
/// Lazily searches for or compiles LLVM as configured by the environment
/// variables.
fn llvm_config(arg: &str) -> String {
    llvm_config_ex(&*LLVM_CONFIG_PATH, arg)
        .expect("Surprising failure from llvm-config")
}

/// Invoke the specified binary as llvm-config.
///
/// Explicit version of the `llvm_config` function that bubbles errors
/// up.
fn llvm_config_ex<S: AsRef<OsStr>>(binary: S, arg: &str)
        -> io::Result<String> {
    Command::new(binary)
        .arg(arg)
        .arg("--link-static")   // Don't use dylib for >= 3.9
        .output()
        .map(|output| String::from_utf8(output.stdout)
            .expect("Output from llvm-config was not valid UTF-8"))
}

/// Get the LLVM version using llvm-config.
fn llvm_version<S: AsRef<OsStr>>(binary: S) -> io::Result<Version> {
    let version_str = try!(llvm_config_ex(binary.as_ref(), "--version"));

    // LLVM isn't really semver and uses version suffixes to build
    // version strings like '3.8.0svn', so limit what we try to parse
    // to only the numeric bits.
    let re = Regex::new(r"^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)")
        .unwrap();
    let m = re.find(&version_str)
        .expect("Could not determine LLVM version from llvm-config.");

    Ok(Version::parse(&version_str[m.start()..m.end()]).unwrap())
}

/// Get the names of the dylibs required by LLVM, including the C++ standard
/// library.
fn get_system_libraries() -> Vec<String> {
    llvm_config("--system-libs")
        .split(&[' ', '\n'] as &[char])
        .filter(|s| !s.is_empty())
        .map(|flag| {
            if cfg!(target_env = "msvc") {
                // Same as --libnames, foo.lib
                assert!(flag.ends_with(".lib"));
                &flag[..flag.len() - 4]
            } else {
                // Linker flags style, -lfoo
                assert!(flag.starts_with("-l"));
                &flag[2..]
            }
        })
        .chain(get_system_libcpp())
        .map(str::to_owned)
        .collect::<Vec<String>>()
}

/// Get the library that must be linked for C++, if any.
fn get_system_libcpp() -> Option<&'static str> {
    if cfg!(target_env = "msvc") {
        // MSVC doesn't need an explicit one.
        None
    } else if cfg!(target_os = "macos") {
        // On OS X 10.9 and later, LLVM's libc++ is the default. On earlier
        // releases GCC's libstdc++ is default. Unfortunately we can't
        // reasonably detect which one we need (on older ones libc++ is
        // available and can be selected with -stdlib=lib++), so assume the
        // latest, at the cost of breaking the build on older OS releases
        // when LLVM was built against libstdc++.
        Some("c++")
    } else {
        // Otherwise assume GCC's libstdc++.
        // This assumption is probably wrong on some platforms, but would need
        // testing on them.
        Some("stdc++")
    }
}

/// Get the names of libraries to link against.
fn get_link_libraries() -> Vec<String> {
    // Using --libnames in conjunction with --libdir is particularly important
    // for MSVC when LLVM is in a path with spaces, but it is generally less of
    // a hack than parsing linker flags output from --libs and --ldflags.
    llvm_config("--libnames")
        .split(&[' ', '\n'] as &[char])
        .filter(|s| !s.is_empty())
        .map(|name| {
            // --libnames gives library filenames. Extract only the name that
            // we need to pass to the linker.
            if cfg!(target_env = "msvc") {
                // LLVMfoo.lib
                assert!(name.ends_with(".lib"));
                &name[..name.len() - 4]
            } else {
                // libLLVMfoo.a
                assert!(name.starts_with("lib") && name.ends_with(".a"));
                &name[3..name.len() - 2]
            }
        })
        .map(str::to_owned)
        .collect::<Vec<String>>()
}

fn main() {
    let libdir = llvm_config("--libdir");

    // Export information to other crates
    println!("cargo:config_path={}", LLVM_CONFIG_PATH.display()); // will be DEP_LLVM_CONFIG_PATH
    println!("cargo:libdir={}", libdir); // DEP_LLVM_LIBDIR

    // Link LLVM libraries
    println!("cargo:rustc-link-search=native={}", libdir);
    for name in get_link_libraries() {
        println!("cargo:rustc-link-lib=static={}", name);
    }

    // Link system libraries
    for name in get_system_libraries() {
        println!("cargo:rustc-link-lib=dylib={}", name);
    }

    // Link libffi if the user requested this workaround.
    // See https://bitbucket.org/tari/llvm-sys.rs/issues/12/
    let force_ffi = env::var_os(format!("LLVM_SYS_{}_FFI_WORKAROUND",
                                        env!("CARGO_PKG_VERSION_MAJOR")))
        .is_some();
    if force_ffi {
        println!("cargo:rustc-link-lib=dylib={}", "ffi");
    }

    // Build the extra wrapper functions.
    std::env::set_var("CFLAGS", llvm_config("--cflags").trim());
    gcc::compile_library("libtargetwrappers.a", &["wrappers/target.c"]);
}
<|endoftext|>