<commit_before>use std::cmp::Ordering;
use std::collections::{BinaryHeap, HashMap};
use std::hash::{Hasher, BuildHasherDefault};
use std::usize;

use murmurhash3::murmurhash3_x64_128;

// The individual items to store in the BinaryHeap
pub type ItemHash = usize;

#[inline]
pub fn hash_f(item: &[u8], seed: u64) -> ItemHash {
    murmurhash3_x64_128(item, seed).0 as ItemHash
}

#[derive(Debug)]
struct HashedItem<T> {
    hash: ItemHash,
    item: T,
}

impl<T> PartialEq for HashedItem<T> {
    fn eq(&self, other: &HashedItem<T>) -> bool {
        other.hash.eq(&self.hash)
    }
}

impl<T> Eq for HashedItem<T> {}

impl<T> Ord for HashedItem<T> {
    fn cmp(&self, other: &HashedItem<T>) -> Ordering {
        self.hash.cmp(&other.hash)
    }
}

impl<T> PartialOrd for HashedItem<T> {
    fn partial_cmp(&self, other: &HashedItem<T>) -> Option<Ordering> {
        Some(self.hash.cmp(&other.hash))
    }
}

/// If we're using a `HashMap` where the keys themselves are hashes, it's
/// a little silly to re-hash them. That's where the `NoHashHasher` comes in.
pub struct NoHashHasher(u64);

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

impl Hasher for NoHashHasher {
    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        *self = NoHashHasher(
            ((bytes[0] as u64) << 24) +
            ((bytes[1] as u64) << 16) +
            ((bytes[2] as u64) << 8) +
            (bytes[3] as u64)
        );
    }
    fn finish(&self) -> u64 { self.0 }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct KmerCount {
    pub hash: ItemHash,
    pub kmer: Vec<u8>,
    pub count: u16,
    pub extra_count: u16,
}

pub struct MinHashKmers {
    hashes: BinaryHeap<HashedItem<Vec<u8>>>,
    counts: HashMap<ItemHash, (u16, u16), BuildHasherDefault<NoHashHasher>>,
    total_count: u64,
    size: usize,
    seed: u64,
    // heap_lock: Mutex<()>,
    // instead of map_lock, look into using https://docs.rs/chashmap/0.1.2/chashmap/
    // map_lock: Mutex<()>,
}

impl MinHashKmers {
    pub fn new(size: usize, seed: u64) -> Self {
        MinHashKmers {
            hashes: BinaryHeap::with_capacity(size + 1),
            counts: HashMap::with_capacity_and_hasher(size, BuildHasherDefault::default()),
            total_count: 0,
            size: size,
            seed: seed,
            // heap_lock: Mutex::new(()),
            // map_lock: Mutex::new(()),
        }
    }

    pub fn push(&mut self, kmer: &[u8], extra_count: u8) {
        let new_hash = hash_f(kmer, self.seed);
        let add_hash = match self.hashes.peek() {
            None => true,
            Some(old_max_hash) => (new_hash <= (*old_max_hash).hash) || (self.hashes.len() < self.size),
        };

        if add_hash {
            self.total_count += 1;
            if self.counts.contains_key(&new_hash) {
                // let _lock = self.map_lock.lock().unwrap();
                let count = self.counts.entry(new_hash).or_insert((0u16, 0u16));
                (*count).0 += 1;
                (*count).1 += extra_count as u16;
                // drop(_lock);
            } else {
                // let _ = self.heap_lock.lock().unwrap();
                self.hashes.push(HashedItem {
                    hash: new_hash,
                    item: kmer.to_owned(),
                });
                // let _map_lock = self.map_lock.lock().unwrap();
                self.counts.insert(new_hash, (1u16, extra_count as u16));
                if self.hashes.len() > self.size {
                    let hash = self.hashes.pop().unwrap();
                    let old_count = self.counts.remove(&hash.hash).unwrap().0;
                    // TODO: check if old_count / total_count > ...?
                    self.total_count -= old_count as u64;
                }
                // drop(_lock);
                // drop(_map_lock);
            }
        }
    }

    pub fn into_vec(self) -> Vec<KmerCount> {
        let mut vec = self.hashes.into_sorted_vec();

        let mut results = Vec::with_capacity(vec.len());
        for item in vec.drain(..) {
            let counts = *self.counts.get(&item.hash).unwrap();
            let new_item = KmerCount {
                hash: item.hash,
                kmer: item.item,
                count: counts.0,
                extra_count: counts.1,
            };
            results.push(new_item);
        }
        results
    }
}

#[test]
fn test_minhashkmers() {
    let mut queue = MinHashKmers::new(3, 42);
    queue.push(b"ca", 0);
    queue.push(b"cc", 1);
    queue.push(b"ac", 0);
    queue.push(b"ac", 1);
    let array = queue.into_vec();
    assert_eq!(array[0].kmer, vec![b'c', b'c']);
    assert_eq!(array[0].count, 1u16);
    assert_eq!(array[0].extra_count, 1u16);
    assert!(array[0].hash < array[1].hash);
    assert_eq!(array[1].kmer, vec![b'c', b'a']);
    assert_eq!(array[1].count, 1u16);
    assert_eq!(array[1].extra_count, 0u16);
    assert!(array[1].hash < array[2].hash);
    assert_eq!(array[2].kmer, vec![b'a', b'c']);
    assert_eq!(array[2].count, 2u16);
    assert_eq!(array[2].extra_count, 1u16);
}

#[test]
fn test_longer_sequence() {
    let mut queue = MinHashKmers::new(100, 42);

    // for "ACACGGAAATCCTCACGTCGCGGCGCCGGGC"

    // hashes should be:
    //     (3186265289206375993,
    //      3197567229193635484,
    //      5157287830980272133,
    //      7515070071080094037,
    //      9123665698461883699,
    //      9650810550987401968,
    //      10462414310441547028,
    //      12872951831549606632,
    //      13584836512372089324,
    //      14093285637546356047,
    //      16069721578136260683)

}
<commit_msg>Add more traits to KmerCount<commit_after>use std::cmp::Ordering;
use std::collections::{BinaryHeap, HashMap};
use std::hash::{Hasher, BuildHasherDefault};
use std::usize;

use murmurhash3::murmurhash3_x64_128;

// The individual items to store in the BinaryHeap
pub type ItemHash = usize;

#[inline]
pub fn hash_f(item: &[u8], seed: u64) -> ItemHash {
    murmurhash3_x64_128(item, seed).0 as ItemHash
}

#[derive(Debug)]
struct HashedItem<T> {
    hash: ItemHash,
    item: T,
}

impl<T> PartialEq for HashedItem<T> {
    fn eq(&self, other: &HashedItem<T>) -> bool {
        other.hash.eq(&self.hash)
    }
}

impl<T> Eq for HashedItem<T> {}

impl<T> Ord for HashedItem<T> {
    fn cmp(&self, other: &HashedItem<T>) -> Ordering {
        self.hash.cmp(&other.hash)
    }
}

impl<T> PartialOrd for HashedItem<T> {
    fn partial_cmp(&self, other: &HashedItem<T>) -> Option<Ordering> {
        Some(self.hash.cmp(&other.hash))
    }
}

/// If we're using a `HashMap` where the keys themselves are hashes, it's
/// a little silly to re-hash them. That's where the `NoHashHasher` comes in.
pub struct NoHashHasher(u64);

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

impl Hasher for NoHashHasher {
    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        *self = NoHashHasher(
            ((bytes[0] as u64) << 24) +
            ((bytes[1] as u64) << 16) +
            ((bytes[2] as u64) << 8) +
            (bytes[3] as u64)
        );
    }
    fn finish(&self) -> u64 { self.0 }
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Hash, Serialize)]
pub struct KmerCount {
    pub hash: ItemHash,
    pub kmer: Vec<u8>,
    pub count: u16,
    pub extra_count: u16,
}

pub struct MinHashKmers {
    hashes: BinaryHeap<HashedItem<Vec<u8>>>,
    counts: HashMap<ItemHash, (u16, u16), BuildHasherDefault<NoHashHasher>>,
    total_count: u64,
    size: usize,
    seed: u64,
    // heap_lock: Mutex<()>,
    // instead of map_lock, look into using https://docs.rs/chashmap/0.1.2/chashmap/
    // map_lock: Mutex<()>,
}

impl MinHashKmers {
    pub fn new(size: usize, seed: u64) -> Self {
        MinHashKmers {
            hashes: BinaryHeap::with_capacity(size + 1),
            counts: HashMap::with_capacity_and_hasher(size, BuildHasherDefault::default()),
            total_count: 0,
            size: size,
            seed: seed,
            // heap_lock: Mutex::new(()),
            // map_lock: Mutex::new(()),
        }
    }

    pub fn push(&mut self, kmer: &[u8], extra_count: u8) {
        let new_hash = hash_f(kmer, self.seed);
        let add_hash = match self.hashes.peek() {
            None => true,
            Some(old_max_hash) => (new_hash <= (*old_max_hash).hash) || (self.hashes.len() < self.size),
        };

        if add_hash {
            self.total_count += 1;
            if self.counts.contains_key(&new_hash) {
                // let _lock = self.map_lock.lock().unwrap();
                let count = self.counts.entry(new_hash).or_insert((0u16, 0u16));
                (*count).0 += 1;
                (*count).1 += extra_count as u16;
                // drop(_lock);
            } else {
                // let _ = self.heap_lock.lock().unwrap();
                self.hashes.push(HashedItem {
                    hash: new_hash,
                    item: kmer.to_owned(),
                });
                // let _map_lock = self.map_lock.lock().unwrap();
                self.counts.insert(new_hash, (1u16, extra_count as u16));
                if self.hashes.len() > self.size {
                    let hash = self.hashes.pop().unwrap();
                    let old_count = self.counts.remove(&hash.hash).unwrap().0;
                    // TODO: check if old_count / total_count > ...?
                    self.total_count -= old_count as u64;
                }
                // drop(_lock);
                // drop(_map_lock);
            }
        }
    }

    pub fn into_vec(self) -> Vec<KmerCount> {
        let mut vec = self.hashes.into_sorted_vec();

        let mut results = Vec::with_capacity(vec.len());
        for item in vec.drain(..) {
            let counts = *self.counts.get(&item.hash).unwrap();
            let new_item = KmerCount {
                hash: item.hash,
                kmer: item.item,
                count: counts.0,
                extra_count: counts.1,
            };
            results.push(new_item);
        }
        results
    }
}

#[test]
fn test_minhashkmers() {
    let mut queue = MinHashKmers::new(3, 42);
    queue.push(b"ca", 0);
    queue.push(b"cc", 1);
    queue.push(b"ac", 0);
    queue.push(b"ac", 1);
    let array = queue.into_vec();
    assert_eq!(array[0].kmer, vec![b'c', b'c']);
    assert_eq!(array[0].count, 1u16);
    assert_eq!(array[0].extra_count, 1u16);
    assert!(array[0].hash < array[1].hash);
    assert_eq!(array[1].kmer, vec![b'c', b'a']);
    assert_eq!(array[1].count, 1u16);
    assert_eq!(array[1].extra_count, 0u16);
    assert!(array[1].hash < array[2].hash);
    assert_eq!(array[2].kmer, vec![b'a', b'c']);
    assert_eq!(array[2].count, 2u16);
    assert_eq!(array[2].extra_count, 1u16);
}

#[test]
fn test_longer_sequence() {
    let mut queue = MinHashKmers::new(100, 42);

    // for "ACACGGAAATCCTCACGTCGCGGCGCCGGGC"

    // hashes should be:
    //     (3186265289206375993,
    //      3197567229193635484,
    //      5157287830980272133,
    //      7515070071080094037,
    //      9123665698461883699,
    //      9650810550987401968,
    //      10462414310441547028,
    //      12872951831549606632,
    //      13584836512372089324,
    //      14093285637546356047,
    //      16069721578136260683)

}
<|endoftext|>


<commit_before>use crate::task::{self, Poll};
use std::fmt;
use std::marker::{PhantomData,Unpin};
use core::mem::PinMut;

use crate::stream::Stream;

/// A custom trait object for polling futures, roughly akin to
/// `Box<dyn Stream<Item = T> + 'a>`.
///
/// This custom trait object was introduced for two reasons:
/// - Currently it is not possible to take `dyn Trait` by value and
///   `Box<dyn Trait>` is not available in no_std contexts.
/// - The `Stream` trait is currently not object safe: The `Stream::poll_next`
///   method makes uses the arbitrary self types feature and traits in which
///   this feature is used are currently not object safe due to current compiler
///   limitations. (See tracking issue for arbitrary self types for more
///   information #44874)
pub struct LocalStreamObj<'a, T> {
    ptr: *mut (),
    poll_next_fn: unsafe fn(*mut (), &mut task::Context) -> Poll<Option<T>>,
    drop_fn: unsafe fn(*mut ()),
    _marker: PhantomData<&'a ()>,
}

impl<'a, T> Unpin for LocalStreamObj<'a, T> {}

impl<'a, T> LocalStreamObj<'a, T> {
    /// Create a `LocalStreamObj` from a custom trait object representation.
    #[inline]
    pub fn new<F: UnsafeStreamObj<'a, T> + 'a>(f: F) -> LocalStreamObj<'a, T> {
        LocalStreamObj {
            ptr: f.into_raw(),
            poll_next_fn: F::poll_next,
            drop_fn: F::drop,
            _marker: PhantomData,
        }
    }

    /// Converts the `LocalStreamObj` into a `StreamObj`
    /// To make this operation safe one has to ensure that the `UnsafeStreamObj`
    /// instance from which this `LocalStreamObj` was created actually
    /// implements `Send`.
    #[inline]
    pub unsafe fn into_stream_obj(self) -> StreamObj<'a, T> {
        StreamObj(self)
    }
}

impl<'a, T> fmt::Debug for LocalStreamObj<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LocalStreamObj")
            .finish()
    }
}

impl<'a, T> From<StreamObj<'a, T>> for LocalStreamObj<'a, T> {
    #[inline]
    fn from(f: StreamObj<'a, T>) -> LocalStreamObj<'a, T> {
        f.0
    }
}

impl<'a, T> Stream for LocalStreamObj<'a, T> {
    type Item = T;

    #[inline]
    fn poll_next(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Option<T>> {
        unsafe {
            (self.poll_next_fn)(self.ptr, cx)
        }
    }
}

impl<'a, T> Drop for LocalStreamObj<'a, T> {
    fn drop(&mut self) {
        unsafe {
            (self.drop_fn)(self.ptr)
        }
    }
}

/// A custom trait object for polling futures, roughly akin to
/// `Box<dyn Stream<Item = T> + Send + 'a>`.
///
/// This custom trait object was introduced for two reasons:
/// - Currently it is not possible to take `dyn Trait` by value and
///   `Box<dyn Trait>` is not available in no_std contexts.
/// - The `Stream` trait is currently not object safe: The `Stream::poll_next`
///   method makes uses the arbitrary self types feature and traits in which
///   this feature is used are currently not object safe due to current compiler
///   limitations. (See tracking issue for arbitray self types for more
///   information #44874)
pub struct StreamObj<'a, T>(LocalStreamObj<'a, T>);

impl<'a, T> Unpin for StreamObj<'a, T> {}
unsafe impl<'a, T> Send for StreamObj<'a, T> {}

impl<'a, T> StreamObj<'a, T> {
    /// Create a `StreamObj` from a custom trait object representation.
    #[inline]
    pub fn new<F: UnsafeStreamObj<'a, T> + Send>(f: F) -> StreamObj<'a, T> {
        StreamObj(LocalStreamObj::new(f))
    }
}

impl<'a, T> fmt::Debug for StreamObj<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("StreamObj")
            .finish()
    }
}

impl<'a, T> Stream for StreamObj<'a, T> {
    type Item = T;

    #[inline]
    fn poll_next(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Option<T>> {
        let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) };
        pinned_field.poll_next(cx)
    }
}

/// A custom implementation of a future trait object for `StreamObj`, providing
/// a hand-rolled vtable.
///
/// This custom representation is typically used only in `no_std` contexts,
/// where the default `Box`-based implementation is not available.
///
/// The implementor must guarantee that it is safe to call `poll` repeatedly (in
/// a non-concurrent fashion) with the result of `into_raw` until `drop` is
/// called.
pub unsafe trait UnsafeStreamObj<'a, T>: 'a {
    /// Convert an owned instance into a (conceptually owned) void pointer.
    fn into_raw(self) -> *mut ();

    /// Poll the future represented by the given void pointer.
    ///
    /// # Safety
    ///
    /// The trait implementor must guarantee that it is safe to repeatedly call
    /// `poll` with the result of `into_raw` until `drop` is called; such calls
    /// are not, however, allowed to race with each other or with calls to
    /// `drop`.
    unsafe fn poll_next(ptr: *mut (), cx: &mut task::Context) -> Poll<Option<T>>;

    /// Drops the future represented by the given void pointer.
    ///
    /// # Safety
    ///
    /// The trait implementor must guarantee that it is safe to call this
    /// function once per `into_raw` invocation; that call cannot race with
    /// other calls to `drop` or `poll`.
    unsafe fn drop(ptr: *mut ());
}

unsafe impl<'a, T, F> UnsafeStreamObj<'a, T> for &'a mut F
    where F: Stream<Item = T> + Unpin + 'a
{
    fn into_raw(self) -> *mut () {
        self as *mut F as *mut ()
    }

    unsafe fn poll_next(ptr: *mut (), cx: &mut task::Context) -> Poll<Option<T>> {
        PinMut::new_unchecked(&mut *(ptr as *mut F)).poll_next(cx)
    }

    unsafe fn drop(_ptr: *mut ()) {}
}

unsafe impl<'a, T, F> UnsafeStreamObj<'a, T> for PinMut<'a, F>
    where F: Stream<Item = T> + 'a
{
    fn into_raw(self) -> *mut () {
        unsafe { PinMut::get_mut_unchecked(self) as *mut F as *mut () }
    }

    unsafe fn poll_next(ptr: *mut (), cx: &mut task::Context) -> Poll<Option<T>> {
        PinMut::new_unchecked(&mut *(ptr as *mut F)).poll_next(cx)
    }

    unsafe fn drop(_ptr: *mut ()) {}
}<commit_msg>src/liballoc/boxed.rs gets copied over too<commit_after>use crate::task::{self, Poll};
use std::fmt;
use std::marker::{PhantomData,Unpin};
use core::mem::PinMut;

use crate::stream::Stream;

/// A custom trait object for polling futures, roughly akin to
/// `Box<dyn Stream<Item = T> + 'a>`.
///
/// This custom trait object was introduced for two reasons:
/// - Currently it is not possible to take `dyn Trait` by value and
///   `Box<dyn Trait>` is not available in no_std contexts.
/// - The `Stream` trait is currently not object safe: The `Stream::poll_next`
///   method makes uses the arbitrary self types feature and traits in which
///   this feature is used are currently not object safe due to current compiler
///   limitations. (See tracking issue for arbitrary self types for more
///   information #44874)
pub struct LocalStreamObj<'a, T> {
    ptr: *mut (),
    poll_next_fn: unsafe fn(*mut (), &mut task::Context) -> Poll<Option<T>>,
    drop_fn: unsafe fn(*mut ()),
    _marker: PhantomData<&'a ()>,
}

impl<'a, T> Unpin for LocalStreamObj<'a, T> {}

impl<'a, T> LocalStreamObj<'a, T> {
    /// Create a `LocalStreamObj` from a custom trait object representation.
    #[inline]
    pub fn new<F: UnsafeStreamObj<'a, T> + 'a>(f: F) -> LocalStreamObj<'a, T> {
        LocalStreamObj {
            ptr: f.into_raw(),
            poll_next_fn: F::poll_next,
            drop_fn: F::drop,
            _marker: PhantomData,
        }
    }

    /// Converts the `LocalStreamObj` into a `StreamObj`
    /// To make this operation safe one has to ensure that the `UnsafeStreamObj`
    /// instance from which this `LocalStreamObj` was created actually
    /// implements `Send`.
    #[inline]
    pub unsafe fn into_stream_obj(self) -> StreamObj<'a, T> {
        StreamObj(self)
    }
}

impl<'a, T> fmt::Debug for LocalStreamObj<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LocalStreamObj")
            .finish()
    }
}

impl<'a, T> From<StreamObj<'a, T>> for LocalStreamObj<'a, T> {
    #[inline]
    fn from(f: StreamObj<'a, T>) -> LocalStreamObj<'a, T> {
        f.0
    }
}

impl<'a, T> Stream for LocalStreamObj<'a, T> {
    type Item = T;

    #[inline]
    fn poll_next(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Option<T>> {
        unsafe {
            (self.poll_next_fn)(self.ptr, cx)
        }
    }
}

impl<'a, T> Drop for LocalStreamObj<'a, T> {
    fn drop(&mut self) {
        unsafe {
            (self.drop_fn)(self.ptr)
        }
    }
}

/// A custom trait object for polling futures, roughly akin to
/// `Box<dyn Stream<Item = T> + Send + 'a>`.
///
/// This custom trait object was introduced for two reasons:
/// - Currently it is not possible to take `dyn Trait` by value and
///   `Box<dyn Trait>` is not available in no_std contexts.
/// - The `Stream` trait is currently not object safe: The `Stream::poll_next`
///   method makes uses the arbitrary self types feature and traits in which
///   this feature is used are currently not object safe due to current compiler
///   limitations. (See tracking issue for arbitray self types for more
///   information #44874)
pub struct StreamObj<'a, T>(LocalStreamObj<'a, T>);

impl<'a, T> Unpin for StreamObj<'a, T> {}
unsafe impl<'a, T> Send for StreamObj<'a, T> {}

impl<'a, T> StreamObj<'a, T> {
    /// Create a `StreamObj` from a custom trait object representation.
    #[inline]
    pub fn new<F: UnsafeStreamObj<'a, T> + Send>(f: F) -> StreamObj<'a, T> {
        StreamObj(LocalStreamObj::new(f))
    }
}

impl<'a, T> fmt::Debug for StreamObj<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("StreamObj")
            .finish()
    }
}

impl<'a, T> Stream for StreamObj<'a, T> {
    type Item = T;

    #[inline]
    fn poll_next(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Option<T>> {
        let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) };
        pinned_field.poll_next(cx)
    }
}

/// A custom implementation of a future trait object for `StreamObj`, providing
/// a hand-rolled vtable.
///
/// This custom representation is typically used only in `no_std` contexts,
/// where the default `Box`-based implementation is not available.
///
/// The implementor must guarantee that it is safe to call `poll` repeatedly (in
/// a non-concurrent fashion) with the result of `into_raw` until `drop` is
/// called.
pub unsafe trait UnsafeStreamObj<'a, T>: 'a {
    /// Convert an owned instance into a (conceptually owned) void pointer.
    fn into_raw(self) -> *mut ();

    /// Poll the future represented by the given void pointer.
    ///
    /// # Safety
    ///
    /// The trait implementor must guarantee that it is safe to repeatedly call
    /// `poll` with the result of `into_raw` until `drop` is called; such calls
    /// are not, however, allowed to race with each other or with calls to
    /// `drop`.
    unsafe fn poll_next(ptr: *mut (), cx: &mut task::Context) -> Poll<Option<T>>;

    /// Drops the future represented by the given void pointer.
    ///
    /// # Safety
    ///
    /// The trait implementor must guarantee that it is safe to call this
    /// function once per `into_raw` invocation; that call cannot race with
    /// other calls to `drop` or `poll`.
    unsafe fn drop(ptr: *mut ());
}

unsafe impl<'a, T, F> UnsafeStreamObj<'a, T> for &'a mut F
    where F: Stream<Item = T> + Unpin + 'a
{
    fn into_raw(self) -> *mut () {
        self as *mut F as *mut ()
    }

    unsafe fn poll_next(ptr: *mut (), cx: &mut task::Context) -> Poll<Option<T>> {
        PinMut::new_unchecked(&mut *(ptr as *mut F)).poll_next(cx)
    }

    unsafe fn drop(_ptr: *mut ()) {}
}

unsafe impl<'a, T, F> UnsafeStreamObj<'a, T> for PinMut<'a, F>
    where F: Stream<Item = T> + 'a
{
    fn into_raw(self) -> *mut () {
        unsafe { PinMut::get_mut_unchecked(self) as *mut F as *mut () }
    }

    unsafe fn poll_next(ptr: *mut (), cx: &mut task::Context) -> Poll<Option<T>> {
        PinMut::new_unchecked(&mut *(ptr as *mut F)).poll_next(cx)
    }

    unsafe fn drop(_ptr: *mut ()) {}
}

if_std! {
    use std::boxed::{Box,PinBox};

    unsafe impl<'a, T, F> UnsafeStreamObj<'a, T> for Box<F>
        where F: Stream<Item = T> + 'a
    {
        fn into_raw(self) -> *mut () {
            Box::into_raw(self) as *mut ()
        }

        unsafe fn poll_next(ptr: *mut (), cx: &mut task::Context) -> Poll<Option<T>> {
            let ptr = ptr as *mut F;
            let pin: PinMut<F> = PinMut::new_unchecked(&mut *ptr);
            pin.poll_next(cx)
        }

        unsafe fn drop(ptr: *mut ()) {
            drop(Box::from_raw(ptr as *mut F))
        }
    }

    unsafe impl<'a, T, F> UnsafeStreamObj<'a, T> for PinBox<F>
        where F: Stream<Item = T> + 'a
    {
        fn into_raw(self) -> *mut () {
            PinBox::into_raw(self) as *mut ()
        }

        unsafe fn poll_next(ptr: *mut (), cx: &mut task::Context) -> Poll<Option<T>> {
            let ptr = ptr as *mut F;
            let pin: PinMut<F> = PinMut::new_unchecked(&mut *ptr);
            pin.poll_next(cx)
        }

        unsafe fn drop(ptr: *mut ()) {
            drop(PinBox::from_raw(ptr as *mut F))
        }
    }

    impl<'a, F: Stream<Item = ()> + Send + 'a> From<PinBox<F>> for StreamObj<'a, ()> {
        fn from(boxed: PinBox<F>) -> Self {
            StreamObj::new(boxed)
        }
    }

    impl<'a, F: Stream<Item = ()> + Send + 'a> From<Box<F>> for StreamObj<'a, ()> {
        fn from(boxed: Box<F>) -> Self {
            StreamObj::new(boxed)
        }
    }

    impl<'a, F: Stream<Item = ()> + 'a> From<PinBox<F>> for LocalStreamObj<'a, ()> {
        fn from(boxed: PinBox<F>) -> Self {
            LocalStreamObj::new(boxed)
        }
    }

    impl<'a, F: Stream<Item = ()> + 'a> From<Box<F>> for LocalStreamObj<'a, ()> {
        fn from(boxed: Box<F>) -> Self {
            LocalStreamObj::new(boxed)
        }
    }
}<|endoftext|>


<commit_before>use bodyparser;

use iron::prelude::*;
use iron::mime::Mime;
use iron::method::Method::*;
use iron::headers::*;
use iron::status;

use router::{Router};

pub fn api(req: &mut Request) -> IronResult<Response> {
    match req.method {
        Get => {
            // Collect object ID (or set it to empty string if not found)
            let obj_id = req.extensions.get::<Router>().unwrap().find("obj_id").unwrap_or("");

            let user_agent = req.headers.get::<UserAgent>().unwrap();
            // TODO Perform some simple vetting of user-agent to discern browser v programmatic/API access
            // let content_type = "text/plain".parse::<Mime>().unwrap();
            let content_type = "text/html".parse::<Mime>().unwrap();

            // let response_body: String = format!("Hello!\n\nObject ID: \'{}\'", obj_id);
            let mut response_body: String = String::new();
            html!(response_body, {
                html {
                    h1 "Welcome!"
                    p { "You have reached API endpoint for object: " $obj_id }
                }
            });
            Ok(Response::with((content_type, status::Ok, response_body)))
        },
        Put => {
            // TODO Not implemented yet
            Ok(Response::with((status::Ok)))
        },
        Post => {
            let json_data = req.get::<bodyparser::Json>();
            match json_data {
                Ok(Some(data)) => {
                    info!("Data received!");
                    // TODO Use/store JSON data
                    // for (key, value) in data.as_object().unwrap().iter() {
                    //     println!("\t- {}: {}", key, value);
                    // }
                },
                Ok(None) => info!("No data received!"),
                Err(e) => {
                    error!("{}", e);
                    return Ok(Response::with((status::BadRequest)))
                }
            }
            Ok(Response::with((status::Ok)))
        },
        Delete => {
            //TODO Not implemented yet
            Ok(Response::with((status::Ok)))
        },
        _ => {
            warn!("Unrecognized request method.");
            Ok(Response::with((status::BadRequest)))
        }
    }
}
<commit_msg>Playing around with maud and requests.<commit_after>use bodyparser;

use iron::prelude::*;
use iron::mime::Mime;
use iron::method::Method::*;
use iron::headers::*;
use iron::status;

use router::{Router};

pub fn api(req: &mut Request) -> IronResult<Response> {
    match req.method {
        Get => {
            // Collect object ID (or set it to empty string if not found)
            let obj_id = req.extensions.get::<Router>().unwrap().find("obj_id").unwrap_or("n/a");

            let user_agent = req.headers.get::<UserAgent>().unwrap();
            // TODO Perform some simple vetting of user-agent to discern browser v programmatic/API access
            // let content_type = "text/plain".parse::<Mime>().unwrap();
            let content_type = "text/html".parse::<Mime>().unwrap();

            let remote_addr = req.remote_addr.to_string();
            let user_ip = remote_addr.split(":").nth(0).unwrap();

            // let response_body: String = format!("Hello!\n\nObject ID: \'{}\'", obj_id);
            let mut response_body: String = String::new();
            html!(response_body, {
                html {
                    head {
                        title "API"
                    }
                    body {
                        h1 "Welcome!"
                        p { "You have reached the API endpoint for object: " b { $obj_id } }
                        p { "Your IP address is: " b { $user_ip } }
                    }
                }
            });
            Ok(Response::with((content_type, status::Ok, response_body)))
        },
        Put => {
            // TODO Not implemented yet
            Ok(Response::with((status::Ok)))
        },
        Post => {
            let json_data = req.get::<bodyparser::Json>();
            match json_data {
                Ok(Some(data)) => {
                    info!("Data received!");
                    // TODO Use/store JSON data
                    // for (key, value) in data.as_object().unwrap().iter() {
                    //     println!("\t- {}: {}", key, value);
                    // }
                },
                Ok(None) => info!("No data received!"),
                Err(e) => {
                    error!("{}", e);
                    return Ok(Response::with((status::BadRequest)))
                }
            }
            Ok(Response::with((status::Ok)))
        },
        Delete => {
            //TODO Not implemented yet
            Ok(Response::with((status::Ok)))
        },
        _ => {
            warn!("Unrecognized request method.");
            Ok(Response::with((status::BadRequest)))
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use euclid::{point2, size2, default::Box2D};
use api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use std::cmp;

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct AllocId(u32);

fn pack_alloc_id(region_index: usize, location: TextureLocation) -> AllocId {
    AllocId(
        region_index as u32 & 0xFFFF
        | (location.0 as u32) << 16
        | (location.1 as u32) << 24
    )
}

fn unpack_alloc_id(id: AllocId) -> (usize, TextureLocation) {
    (
        (id.0 & 0xFFFF) as usize,
        TextureLocation(
            ((id.0 >> 16) & 0xFF) as u8,
            ((id.0 >> 24) & 0xFF) as u8,
        ),
    )
}

#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum SlabSizes {
    Default,
    Glyphs,
}

impl SlabSizes {
    fn get(&self, requested_size: DeviceIntSize) -> SlabSize {
        match *self {
            SlabSizes::Default => Self::default_slab_size(requested_size),
            SlabSizes::Glyphs => Self::glyphs_slab_size(requested_size),
        }
    }

    fn default_slab_size(size: DeviceIntSize) -> SlabSize {
        fn quantize_dimension(size: i32) -> i32 {
            match size {
                0 => unreachable!(),
                1..=16 => 16,
                17..=32 => 32,
                33..=64 => 64,
                65..=128 => 128,
                129..=256 => 256,
                257..=512 => 512,
                _ => panic!("Invalid dimensions for cache!"),
            }
        }

        let x_size = quantize_dimension(size.width);
        let y_size = quantize_dimension(size.height);

        let (width, height) = match (x_size, y_size) {
            // Special cased rectangular slab pages.
            (512, 0..=64) => (512, 64),
            (512, 128) => (512, 128),
            (512, 256) => (512, 256),
            (0..=64, 512) => (64, 512),
            (128, 512) => (128, 512),
            (256, 512) => (256, 512),

            // If none of those fit, use a square slab size.
            (x_size, y_size) => {
                let square_size = cmp::max(x_size, y_size);
                (square_size, square_size)
            }
        };

        SlabSize {
            width,
            height,
        }
    }

    fn glyphs_slab_size(size: DeviceIntSize) -> SlabSize {
        fn quantize_dimension(size: i32) -> i32 {
            match size {
                0 => unreachable!(),
                1..=8 => 8,
                9..=16 => 16,
                17..=32 => 32,
                33..=64 => 64,
                65..=128 => 128,
                _ => panic!("Invalid dimensions for cache!"),
            }
        }

        let x_size = quantize_dimension(size.width);
        let y_size = quantize_dimension(size.height);

        let (width, height) = match (x_size, y_size) {
            // Special cased rectangular slab pages.
            (8, 16) => (8, 16),
            (16, 32) => (16, 32),

            // If none of those fit, use a square slab size.
            (x_size, y_size) => {
                let square_size = cmp::max(x_size, y_size);
                (square_size, square_size)
            }
        };

        SlabSize {
            width,
            height,
        }
    }
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Copy, Clone, PartialEq)]
struct SlabSize {
    width: i32,
    height: i32,
}

impl SlabSize {
    fn invalid() -> SlabSize {
        SlabSize {
            width: 0,
            height: 0,
        }
    }
}

// The x/y location within a texture region of an allocation.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct TextureLocation(pub u8, pub u8);

impl TextureLocation {
    fn new(x: i32, y: i32) -> Self {
        debug_assert!(x >= 0 && y >= 0 && x < 0x100 && y < 0x100);
        TextureLocation(x as u8, y as u8)
    }
}

/// A region is a rectangular part of a texture cache texture, split into fixed-size slabs.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct TextureRegion {
    index: usize,
    slab_size: SlabSize,
    offset: DeviceIntPoint,
    free_slots: Vec<TextureLocation>,
    total_slot_count: usize,
}

impl TextureRegion {
    fn new(index: usize, offset: DeviceIntPoint) -> Self {
        TextureRegion {
            index,
            slab_size: SlabSize::invalid(),
            offset,
            free_slots: Vec::new(),
            total_slot_count: 0,
        }
    }

    // Initialize a region to be an allocator for a specific slab size.
    fn init(&mut self, slab_size: SlabSize, region_size: i32, empty_regions: &mut usize) {
        debug_assert!(self.slab_size == SlabSize::invalid());
        debug_assert!(self.free_slots.is_empty());

        self.slab_size = slab_size;
        let slots_per_x_axis = region_size / self.slab_size.width;
        let slots_per_y_axis = region_size / self.slab_size.height;

        // Add each block to a freelist.
        for y in 0 .. slots_per_y_axis {
            for x in 0 .. slots_per_x_axis {
                self.free_slots.push(TextureLocation::new(x, y));
            }
        }

        self.total_slot_count = self.free_slots.len();
        *empty_regions -= 1;
    }

    // Deinit a region, allowing it to become a region with
    // a different allocator size.
    fn deinit(&mut self, empty_regions: &mut usize) {
        self.slab_size = SlabSize::invalid();
        self.free_slots.clear();
        self.total_slot_count = 0;
        *empty_regions += 1;
    }

    fn is_empty(&self) -> bool {
        self.slab_size == SlabSize::invalid()
    }

    // Attempt to allocate a fixed size block from this region.
    fn alloc(&mut self) -> Option<(DeviceIntPoint, TextureLocation)> {
        debug_assert!(self.slab_size != SlabSize::invalid());

        self.free_slots.pop().map(|location| {(
            point2(
                self.offset.x + self.slab_size.width * location.0 as i32,
                self.offset.y + self.slab_size.height * location.1 as i32,
            ),
            location,
        )})
    }

    // Free a block in this region.
    fn free(&mut self, location: TextureLocation, empty_regions: &mut usize) {
        self.free_slots.push(location);

        // If this region is completely unused, deinit it
        // so that it can become a different slab size
        // as required.
        if self.free_slots.len() == self.total_slot_count {
            self.deinit(empty_regions);
        }
    }
}

/// A 2D texture divided into regions.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct SlabAllocator {
    regions: Vec<TextureRegion>,
    size: i32,
    region_size: i32,
    empty_regions: usize,
    slab_sizes: SlabSizes,
}

impl SlabAllocator {
    pub fn new(size: i32, region_size: i32, slab_sizes: SlabSizes) -> Self {
        let regions_per_row = size / region_size;
        let num_regions = (regions_per_row * regions_per_row) as usize;

        let mut regions = Vec::with_capacity(num_regions);

        for index in 0..num_regions {
            let offset = point2(
                (index as i32 % regions_per_row) * region_size,
                (index as i32 / regions_per_row) * region_size,
            );

            regions.push(TextureRegion::new(index, offset));
        }

        SlabAllocator {
            regions,
            region_size,
            size,
            empty_regions: num_regions,
            slab_sizes,
        }
    }

    pub fn is_empty(&self) -> bool {
        self.empty_regions == self.regions.len()
    }

    // Returns the region index and allocated rect.
    pub fn allocate(&mut self, size: DeviceIntSize) -> Option<(AllocId, DeviceIntRect)> {
        let slab_size = self.slab_sizes.get(size);

        // Keep track of the location of an empty region,
        // in case we need to select a new empty region
        // after the loop.
        let mut empty_region_index = None;

        let allocated_size = size2(slab_size.width, slab_size.height);

        // Run through the existing regions of this size, and see if
        // we can find a free block in any of them.
        for (i, region) in self.regions.iter_mut().enumerate() {
            if region.is_empty() {
                empty_region_index = Some(i);
            } else if region.slab_size == slab_size {
                if let Some((origin, location)) = region.alloc() {
                    return Some((
                        pack_alloc_id(region.index, location),
                        DeviceIntRect {
                            origin,
                            size: allocated_size,
                        }
                    ));
                }
            }
        }

        if let Some(empty_region_index) = empty_region_index {
            let region = &mut self.regions[empty_region_index];
            region.init(slab_size, self.region_size, &mut self.empty_regions);
            let (origin, location) = region.alloc().unwrap();

            return Some((
                pack_alloc_id(region.index, location),
                DeviceIntRect {
                    origin,
                    size: allocated_size,
                },
            ))
        }

        None
    }

    pub fn deallocate(&mut self, id: AllocId) -> DeviceIntSize {
        let (region_index, location) = unpack_alloc_id(id);

        let region = &mut self.regions[region_index];
        region.free(location, &mut self.empty_regions);

        size2(region.slab_size.width, region.slab_size.height)
    }

    pub fn num_regions(&self) -> usize {
        self.regions.len()
    }

    pub fn dump_as_svg(&self, rect: &Box2D<f32>, output: &mut dyn std::io::Write) -> std::io::Result<()> {
        use svg_fmt::*;

        let region_spacing = 5.0;
        let text_spacing = 15.0;
        let regions_per_row = (self.size / self.region_size) as usize;
        let wh = rect.size().width.min(rect.size().height);
        let region_wh = (wh - region_spacing) / regions_per_row as f32 - region_spacing;

        let x0 = rect.min.x;
        let y0 = rect.min.y;

        for (idx, region) in self.regions.iter().enumerate() {
            let slab_size = region.slab_size;
            let x = x0 + (idx % regions_per_row) as f32 * (region_wh + region_spacing);

            let y = y0 + text_spacing + (idx / regions_per_row) as f32 * (region_wh + region_spacing);

            let texture_background = if region.is_empty() { rgb(30, 30, 30) } else { rgb(40, 40, 130) };
            writeln!(output, "    {}", rectangle(x, y, region_wh, region_wh).inflate(1.0, 1.0).fill(rgb(10, 10, 10)))?;
            writeln!(output, "    {}", rectangle(x, y, region_wh, region_wh).fill(texture_background))?;

            let sw = (slab_size.width as f32 / self.region_size as f32) * region_wh;
            let sh = (slab_size.height as f32 / self.region_size as f32) * region_wh;

            for slot in &region.free_slots {
                let sx = x + slot.0 as f32 * sw;
                let sy = y + slot.1 as f32 * sh;

                // Allocation slot.
                writeln!(output, "    {}", rectangle(sx, sy, sw, sh).inflate(-0.5, -0.5).fill(rgb(30, 30, 30)))?;
            }

            if slab_size.width != 0 {
                let region_text = format!("{}x{}", slab_size.width, slab_size.height);
                let tx = x + 1.0;
                let ty = y + region_wh - 1.0;
                writeln!(output, "    {}", text(tx, ty, region_text).color(rgb(230, 230, 230)))?;
            }
        }

        Ok(())
    }
}
<commit_msg>Bug 1680769 - Fix incorrect returned size in some cases. r=jnicol<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use euclid::{point2, size2, default::Box2D};
use api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use std::cmp;

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct AllocId(u32);

fn pack_alloc_id(region_index: usize, location: TextureLocation) -> AllocId {
    AllocId(
        region_index as u32 & 0xFFFF
        | (location.0 as u32) << 16
        | (location.1 as u32) << 24
    )
}

fn unpack_alloc_id(id: AllocId) -> (usize, TextureLocation) {
    (
        (id.0 & 0xFFFF) as usize,
        TextureLocation(
            ((id.0 >> 16) & 0xFF) as u8,
            ((id.0 >> 24) & 0xFF) as u8,
        ),
    )
}

#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum SlabSizes {
    Default,
    Glyphs,
}

impl SlabSizes {
    fn get(&self, requested_size: DeviceIntSize) -> SlabSize {
        match *self {
            SlabSizes::Default => Self::default_slab_size(requested_size),
            SlabSizes::Glyphs => Self::glyphs_slab_size(requested_size),
        }
    }

    fn default_slab_size(size: DeviceIntSize) -> SlabSize {
        fn quantize_dimension(size: i32) -> i32 {
            match size {
                0 => unreachable!(),
                1..=16 => 16,
                17..=32 => 32,
                33..=64 => 64,
                65..=128 => 128,
                129..=256 => 256,
                257..=512 => 512,
                _ => panic!("Invalid dimensions for cache!"),
            }
        }

        let x_size = quantize_dimension(size.width);
        let y_size = quantize_dimension(size.height);

        let (width, height) = match (x_size, y_size) {
            // Special cased rectangular slab pages.
            (512, 0..=64) => (512, 64),
            (512, 128) => (512, 128),
            (512, 256) => (512, 256),
            (0..=64, 512) => (64, 512),
            (128, 512) => (128, 512),
            (256, 512) => (256, 512),

            // If none of those fit, use a square slab size.
            (x_size, y_size) => {
                let square_size = cmp::max(x_size, y_size);
                (square_size, square_size)
            }
        };

        SlabSize {
            width,
            height,
        }
    }

    fn glyphs_slab_size(size: DeviceIntSize) -> SlabSize {
        fn quantize_dimension(size: i32) -> i32 {
            match size {
                0 => unreachable!(),
                1..=8 => 8,
                9..=16 => 16,
                17..=32 => 32,
                33..=64 => 64,
                65..=128 => 128,
                _ => panic!("Invalid dimensions for cache!"),
            }
        }

        let x_size = quantize_dimension(size.width);
        let y_size = quantize_dimension(size.height);

        let (width, height) = match (x_size, y_size) {
            // Special cased rectangular slab pages.
            (8, 16) => (8, 16),
            (16, 32) => (16, 32),

            // If none of those fit, use a square slab size.
            (x_size, y_size) => {
                let square_size = cmp::max(x_size, y_size);
                (square_size, square_size)
            }
        };

        SlabSize {
            width,
            height,
        }
    }
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Copy, Clone, PartialEq)]
struct SlabSize {
    width: i32,
    height: i32,
}

impl SlabSize {
    fn invalid() -> SlabSize {
        SlabSize {
            width: 0,
            height: 0,
        }
    }
}

// The x/y location within a texture region of an allocation.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct TextureLocation(pub u8, pub u8);

impl TextureLocation {
    fn new(x: i32, y: i32) -> Self {
        debug_assert!(x >= 0 && y >= 0 && x < 0x100 && y < 0x100);
        TextureLocation(x as u8, y as u8)
    }
}

/// A region is a rectangular part of a texture cache texture, split into fixed-size slabs.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct TextureRegion {
    index: usize,
    slab_size: SlabSize,
    offset: DeviceIntPoint,
    free_slots: Vec<TextureLocation>,
    total_slot_count: usize,
}

impl TextureRegion {
    fn new(index: usize, offset: DeviceIntPoint) -> Self {
        TextureRegion {
            index,
            slab_size: SlabSize::invalid(),
            offset,
            free_slots: Vec::new(),
            total_slot_count: 0,
        }
    }

    // Initialize a region to be an allocator for a specific slab size.
    fn init(&mut self, slab_size: SlabSize, region_size: i32, empty_regions: &mut usize) {
        debug_assert!(self.slab_size == SlabSize::invalid());
        debug_assert!(self.free_slots.is_empty());

        self.slab_size = slab_size;
        let slots_per_x_axis = region_size / self.slab_size.width;
        let slots_per_y_axis = region_size / self.slab_size.height;

        // Add each block to a freelist.
        for y in 0 .. slots_per_y_axis {
            for x in 0 .. slots_per_x_axis {
                self.free_slots.push(TextureLocation::new(x, y));
            }
        }

        self.total_slot_count = self.free_slots.len();
        *empty_regions -= 1;
    }

    // Deinit a region, allowing it to become a region with
    // a different allocator size.
    fn deinit(&mut self, empty_regions: &mut usize) {
        self.slab_size = SlabSize::invalid();
        self.free_slots.clear();
        self.total_slot_count = 0;
        *empty_regions += 1;
    }

    fn is_empty(&self) -> bool {
        self.slab_size == SlabSize::invalid()
    }

    // Attempt to allocate a fixed size block from this region.
    fn alloc(&mut self) -> Option<(DeviceIntPoint, TextureLocation)> {
        debug_assert!(self.slab_size != SlabSize::invalid());

        self.free_slots.pop().map(|location| {(
            point2(
                self.offset.x + self.slab_size.width * location.0 as i32,
                self.offset.y + self.slab_size.height * location.1 as i32,
            ),
            location,
        )})
    }

    // Free a block in this region.
    fn free(&mut self, location: TextureLocation, empty_regions: &mut usize) {
        self.free_slots.push(location);

        // If this region is completely unused, deinit it
        // so that it can become a different slab size
        // as required.
        if self.free_slots.len() == self.total_slot_count {
            self.deinit(empty_regions);
        }
    }
}

/// A 2D texture divided into regions.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct SlabAllocator {
    regions: Vec<TextureRegion>,
    size: i32,
    region_size: i32,
    empty_regions: usize,
    slab_sizes: SlabSizes,
}

impl SlabAllocator {
    pub fn new(size: i32, region_size: i32, slab_sizes: SlabSizes) -> Self {
        let regions_per_row = size / region_size;
        let num_regions = (regions_per_row * regions_per_row) as usize;

        let mut regions = Vec::with_capacity(num_regions);

        for index in 0..num_regions {
            let offset = point2(
                (index as i32 % regions_per_row) * region_size,
                (index as i32 / regions_per_row) * region_size,
            );

            regions.push(TextureRegion::new(index, offset));
        }

        SlabAllocator {
            regions,
            region_size,
            size,
            empty_regions: num_regions,
            slab_sizes,
        }
    }

    pub fn is_empty(&self) -> bool {
        self.empty_regions == self.regions.len()
    }

    // Returns the region index and allocated rect.
    pub fn allocate(&mut self, size: DeviceIntSize) -> Option<(AllocId, DeviceIntRect)> {
        let slab_size = self.slab_sizes.get(size);

        // Keep track of the location of an empty region,
        // in case we need to select a new empty region
        // after the loop.
        let mut empty_region_index = None;

        let allocated_size = size2(slab_size.width, slab_size.height);

        // Run through the existing regions of this size, and see if
        // we can find a free block in any of them.
        for (i, region) in self.regions.iter_mut().enumerate() {
            if region.is_empty() {
                empty_region_index = Some(i);
            } else if region.slab_size == slab_size {
                if let Some((origin, location)) = region.alloc() {
                    return Some((
                        pack_alloc_id(region.index, location),
                        DeviceIntRect {
                            origin,
                            size: allocated_size,
                        }
                    ));
                }
            }
        }

        if let Some(empty_region_index) = empty_region_index {
            let region = &mut self.regions[empty_region_index];
            region.init(slab_size, self.region_size, &mut self.empty_regions);
            let (origin, location) = region.alloc().unwrap();

            return Some((
                pack_alloc_id(region.index, location),
                DeviceIntRect {
                    origin,
                    size: allocated_size,
                },
            ))
        }

        None
    }

    pub fn deallocate(&mut self, id: AllocId) -> DeviceIntSize {
        let (region_index, location) = unpack_alloc_id(id);

        let region = &mut self.regions[region_index];
        let size = size2(region.slab_size.width, region.slab_size.height);

        region.free(location, &mut self.empty_regions);

        size
    }

    pub fn num_regions(&self) -> usize {
        self.regions.len()
    }

    pub fn dump_as_svg(&self, rect: &Box2D<f32>, output: &mut dyn std::io::Write) -> std::io::Result<()> {
        use svg_fmt::*;

        let region_spacing = 5.0;
        let text_spacing = 15.0;
        let regions_per_row = (self.size / self.region_size) as usize;
        let wh = rect.size().width.min(rect.size().height);
        let region_wh = (wh - region_spacing) / regions_per_row as f32 - region_spacing;

        let x0 = rect.min.x;
        let y0 = rect.min.y;

        for (idx, region) in self.regions.iter().enumerate() {
            let slab_size = region.slab_size;
            let x = x0 + (idx % regions_per_row) as f32 * (region_wh + region_spacing);

            let y = y0 + text_spacing + (idx / regions_per_row) as f32 * (region_wh + region_spacing);

            let texture_background = if region.is_empty() { rgb(30, 30, 30) } else { rgb(40, 40, 130) };
            writeln!(output, "    {}", rectangle(x, y, region_wh, region_wh).inflate(1.0, 1.0).fill(rgb(10, 10, 10)))?;
            writeln!(output, "    {}", rectangle(x, y, region_wh, region_wh).fill(texture_background))?;

            let sw = (slab_size.width as f32 / self.region_size as f32) * region_wh;
            let sh = (slab_size.height as f32 / self.region_size as f32) * region_wh;

            for slot in &region.free_slots {
                let sx = x + slot.0 as f32 * sw;
                let sy = y + slot.1 as f32 * sh;

                // Allocation slot.
                writeln!(output, "    {}", rectangle(sx, sy, sw, sh).inflate(-0.5, -0.5).fill(rgb(30, 30, 30)))?;
            }

            if slab_size.width != 0 {
                let region_text = format!("{}x{}", slab_size.width, slab_size.height);
                let tx = x + 1.0;
                let ty = y + region_wh - 1.0;
                writeln!(output, "    {}", text(tx, ty, region_text).color(rgb(230, 230, 230)))?;
            }
        }

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


<commit_before>use auxv;
use utils::*;

use std::slice;

const AUX_CNT:usize = 38;

pub struct KernelBlock<'a>{
    pub argc: isize,
    pub argv: &'a[*const u8],
    pub envc: isize,
    pub env: &'a[*const u8],
    pub auxv: *const auxv::Elf64_auxv_t,
}

impl<'b> KernelBlock<'b> {
    pub fn getauxval(&self, t:u64) -> Result<u64, ()> {
        unsafe {
            let ptr = self.auxv.clone();
            let mut i = 1;
            let mut v = &*ptr;
            //            while v.a_type != auxv::AT::NULL {
            while v.a_type != 0 {
                if v.a_type == t {
                    return Ok (v.a_val);
                }
                v = &*ptr.offset(i);
                i += 1;
            }
        }
        Err(())
    }

    // TODO: add auxc and make auxv a slice of auxv_t
    pub fn new<'a> (args: *const u64) -> KernelBlock<'a> {
        unsafe {
            let argc = (*args) as isize;
            let argv = args.offset(1) as *const *const u8;
            let envp = argv.offset(argc + 1);

            let mut p = envp;
            let mut envc = 1;
            // two null pointers mark end of envp
            // and beginning of the auxillary vectors
            while !(*p).is_null() {
                p = p.offset(1);
                envc += 1;
            }
            p = p.offset(1);
            let auxv = p as *const auxv::Elf64_auxv_t;
            KernelBlock {
                argc: argc,
                argv: slice::from_raw_parts(argv, argc as usize),
                envc: envc,
                env: slice::from_raw_parts(envp, envc as usize),
                auxv: auxv,
            }
        }
    }

    // consider using inout stack-allocated &[u64] slice?
    pub fn get_aux (&self) -> Vec<u64> {
        let mut aux:Vec<u64> = vec![0; AUX_CNT];
        let mut i:isize = 0;
        unsafe {
            while (&*self.auxv.offset(i)).a_val != auxv::AT_NULL {
                let auxv_t = &*self.auxv.offset(i);
                // musl wants the aux a_val array to be indexed by AT_<TYPE>
                aux[auxv_t.a_type as usize] = auxv_t.a_val;
                i += 1;
            }
        }
        aux
    }

    pub unsafe fn unsafe_print (&self) -> () {
        write(&"argc: ");
        write_u64(self.argc as u64, false);
        write(&"\n");
        write(&"argv[0]: ");
        write_chars_at(self.argv[0]);
        write(&"\n");
        write(&"envc: ");
        write_u64(self.envc as u64, false);
        write(&"\n");
    }
}
<commit_msg>added const check in KernelBlock instead of hardcoded 0;<commit_after>use auxv;
use utils::*;

use std::slice;

const AUX_CNT:usize = 38;

pub struct KernelBlock<'a>{
    pub argc: isize,
    pub argv: &'a[*const u8],
    pub envc: isize,
    pub env: &'a[*const u8],
    pub auxv: *const auxv::Elf64_auxv_t,
}

impl<'b> KernelBlock<'b> {
    pub fn getauxval(&self, t:u64) -> Result<u64, ()> {
        unsafe {
            let ptr = self.auxv.clone();
            let mut i = 1;
            let mut v = &*ptr;
            while v.a_type != auxv::AT_NULL {
                if v.a_type == t {
                    return Ok (v.a_val);
                }
                v = &*ptr.offset(i);
                i += 1;
            }
        }
        Err(())
    }

    // TODO: add auxc and make auxv a slice of auxv_t
    pub fn new<'a> (args: *const u64) -> KernelBlock<'a> {
        unsafe {
            let argc = (*args) as isize;
            let argv = args.offset(1) as *const *const u8;
            let envp = argv.offset(argc + 1);

            let mut p = envp;
            let mut envc = 1;
            // two null pointers mark end of envp
            // and beginning of the auxillary vectors
            while !(*p).is_null() {
                p = p.offset(1);
                envc += 1;
            }
            p = p.offset(1);
            let auxv = p as *const auxv::Elf64_auxv_t;
            KernelBlock {
                argc: argc,
                argv: slice::from_raw_parts(argv, argc as usize),
                envc: envc,
                env: slice::from_raw_parts(envp, envc as usize),
                auxv: auxv,
            }
        }
    }

    // consider using inout stack-allocated &[u64] slice?
    pub fn get_aux (&self) -> Vec<u64> {
        let mut aux:Vec<u64> = vec![0; AUX_CNT];
        let mut i:isize = 0;
        unsafe {
            while (&*self.auxv.offset(i)).a_val != auxv::AT_NULL {
                let auxv_t = &*self.auxv.offset(i);
                // musl wants the aux a_val array to be indexed by AT_<TYPE>
                aux[auxv_t.a_type as usize] = auxv_t.a_val;
                i += 1;
            }
        }
        aux
    }

    pub unsafe fn unsafe_print (&self) -> () {
        write(&"argc: ");
        write_u64(self.argc as u64, false);
        write(&"\n");
        write(&"argv[0]: ");
        write_chars_at(self.argv[0]);
        write(&"\n");
        write(&"envc: ");
        write_u64(self.envc as u64, false);
        write(&"\n");
    }
}
<|endoftext|>


<commit_before>use std::libc::*;
use std::cast::transmute;
use std::str::raw;

use ffi;
use types::LuaType;
use status::LuaStatus;
use lua::Lua;

/**
 *  Proxy to Lua state FFI.
 *
 *  The goal is to provide some functions which don't need to be called in unsafe block everytime we want to call them.
 */
pub struct State<'self>
{
    priv L: *ffi::lua_State,
    priv managed: bool,
}

impl<'self> State<'self>
{
    /**
     *  Create a new Lua state, which is managed by this struct.
     *
     *  When this struct is dropped, the state is closed, and is not usable anymore.
     */
    #[fixed_stack_segment]
    pub fn new() -> State
    {
        State {
            L: unsafe {
                ffi::luaL_newstate()
            },
            managed: true,
        }
    }

    /**
     *  Create a new state from an existing Lua state.
     *
     *  Marked as unsafe as we know nothing about this Lua state lifetime.
     */
    pub unsafe fn from_ffi(L: *ffi::lua_State) -> State
    {
        State {
            L: L,
            managed: false,
        }
    }

    /**
     *  Close the Lua state.
     *
     *  Marked as unsafe as the pointer is not usable anymore after this function call.
     */
    #[fixed_stack_segment]
    pub unsafe fn close(&mut self)
    {
        ffi::lua_close(self.L);
    }

    /// Load lua standard libraries.
    #[fixed_stack_segment]
    pub fn load_stdlibs(&self)
    {
        unsafe
        {
            ffi::luaL_openlibs(self.L);
        }
    }

    /// Get type of a stack element at specified index.
    #[fixed_stack_segment]
    pub fn get_type(&self, idx: int) -> LuaType
    {
        let ty = unsafe {
            ffi::lua_type(self.L, idx as c_int)
        };
        LuaType::from_lua(ty)
    }

    /// Create a new Lua thread.
    #[fixed_stack_segment]
    pub fn new_thread(&self) -> State
    {
        unsafe
        {
            State::from_ffi(ffi::lua_newthread(self.L))
        }
    }

    /// Get Lua version.
    #[fixed_stack_segment]
    pub fn version(&self) -> int
    {
        unsafe
        {
            ffi::lua_version(self.L) as int
        }
    }

    /// Pop a stack element specified by his index.
    #[fixed_stack_segment]
    pub fn pop(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_pop(self.L, idx as c_int);
        }
    }

    /// Get global value. Push to the stack.
    #[fixed_stack_segment]
    pub fn get_global(&self, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_getglobal(self.L, c_name);
            free(transmute(c_name));
        }
    }

    /// Set global value. Pop from the stack.
    #[fixed_stack_segment]
    pub fn set_global(&self, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_setglobal(self.L, c_name);
            free(transmute(c_name));
        }
    }

    /// Get field value. Push to the stack.
    #[fixed_stack_segment]
    pub fn get_field(&self, idx: int, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_getfield(self.L, idx as c_int, c_name);
            free(transmute(c_name));
        }
    }

    /// Set field value. Pop from the stack.
    #[fixed_stack_segment]
    pub fn set_field(&self, idx: int, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_setfield(self.L, idx as c_int, c_name);
            free(transmute(c_name));
        }
    }

    #[fixed_stack_segment]
    pub fn load_file(&self, filename: &str) -> LuaStatus
    {
        let status = unsafe {
            let filename = filename.to_c_str().unwrap();
            let status = ffi::luaL_loadfile(self.L, filename);
            free(transmute(filename));

            status
        };

        LuaStatus::from_lua(status)
    }

    #[fixed_stack_segment]
    pub fn pcall(&self, nargs: int, nresults: int, errfunc: int) -> LuaStatus
    {
        let status = unsafe {
            ffi::lua_pcall(self.L, nargs as c_int, nresults as c_int, errfunc as c_int)
        };

        LuaStatus::from_lua(status)
    }

    pub fn exec(&self) -> LuaStatus
    {
        self.pcall(0, ffi::LUA_MULTRET as int, 0)
    }

    // Stack functions
    #[fixed_stack_segment]
    pub fn upvalue_index(i: int) -> int
    {
        unsafe
        {
            ffi::lua_upvalueindex(i as c_int) as int
        }
    }

    /// Get index of the stack's top.
    #[fixed_stack_segment]
    pub fn get_top(&self) -> int
    {
        unsafe
        {
            ffi::lua_gettop(self.L) as int
        }
    }

    /// Set index of the stack's top.
    #[fixed_stack_segment]
    pub fn set_top(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_settop(self.L, idx as c_int);
        }
    }

    /// Removes the element at the given valid index.
    #[fixed_stack_segment]
    pub fn remove(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_remove(self.L, idx as c_int);
        }
    }

    // Table functions
    #[fixed_stack_segment]
    pub fn new_table(&self, )
    {
        unsafe
        {
            ffi::lua_newtable(self.L);
        }
    }

    #[fixed_stack_segment]
    pub fn create_table(&self, narr: int, nrec: int)
    {
        unsafe
        {
            ffi::lua_createtable(self.L, narr as c_int, nrec as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn set_table(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_settable(self.L, idx as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn raw_set(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_rawset(self.L, idx as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn raw_set_index(&self, idx: int, i: int)
    {
        unsafe
        {
            ffi::lua_rawseti(self.L, idx as c_int, i as c_int);
        }
    }

    // Push functions

    #[fixed_stack_segment]
    pub fn push_nil(&self)
    {
        unsafe
        {
            ffi::lua_pushnil(self.L);
        }
    }

    #[fixed_stack_segment]
    pub fn push_float(&self, n: f64)
    {
        unsafe
        {
            ffi::lua_pushnumber(self.L, n as ffi::lua_Number);
        }
    }

    #[fixed_stack_segment]
    pub fn push_int(&self, n: int)
    {
        unsafe
        {
            ffi::lua_pushinteger(self.L, n as ffi::lua_Integer);
        }
    }

    #[fixed_stack_segment]
    pub fn push_uint(&self, n: uint)
    {
        unsafe
        {
            ffi::lua_pushunsigned(self.L, n as ffi::lua_Unsigned);
        }
    }

    #[fixed_stack_segment]
    pub fn push_str(&self, s: &str)
    {
        unsafe
        {
            let c_str = s.to_c_str().unwrap();
            ffi::lua_pushstring(self.L, c_str);
            free(transmute(c_str));
        }
    }

    #[fixed_stack_segment]
    pub fn push_bool(&self, b: bool)
    {
        unsafe
        {
            let n = if b { 1 } else { 0 };
            ffi::lua_pushboolean(self.L, n);
        }
    }

    #[fixed_stack_segment]
    pub fn push_userdata<T>(&self, p: *T)
    {
        unsafe
        {
            ffi::lua_pushlightuserdata(self.L, transmute(p));
        }
    }

    #[fixed_stack_segment]
    pub fn push_cclosure(&self, f: ffi::lua_CFunction, n: int)
    {
        unsafe
        {
            ffi::lua_pushcclosure(self.L, f, n as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn push_cfunction(&self, f: ffi::lua_CFunction)
    {
        unsafe
        {
            ffi::lua_pushcfunction(self.L, f);
        }
    }

    pub fn push_function(&self, f: fn(l: &'self Lua) -> int)
    {
        self.push_userdata(f as *());
        self.push_cclosure(_lua_state_closure, 1);
    }

    // Get functions

    #[fixed_stack_segment]
    pub fn get_float(&self, idx: int) -> f64
    {
        unsafe
        {
            ffi::lua_tonumber(self.L, idx as c_int) as f64
        }
    }

    #[fixed_stack_segment]
    pub fn get_int(&self, idx: int) -> int
    {
        unsafe
        {
            ffi::lua_tointeger(self.L, idx as c_int) as int
        }
    }

    #[fixed_stack_segment]
    pub fn get_uint(&self, idx: int) -> uint
    {
        unsafe
        {
            ffi::lua_tounsigned(self.L, idx as c_int) as uint
        }
    }

    #[fixed_stack_segment]
    pub fn get_str(&self, idx: int) -> ~str
    {
        unsafe
        {
            let c_str = ffi::lua_tostring(self.L, idx as c_int);
            raw::from_c_str(c_str)
        }
    }

    #[fixed_stack_segment]
    pub fn get_bool(&self, idx: int) -> bool
    {
        unsafe
        {
            ffi::lua_toboolean(self.L, idx as c_int) != 0
        }
    }

    #[fixed_stack_segment]
    pub fn get_userdata<T>(&self, idx: int) -> *T
    {
        unsafe
        {
            transmute(ffi::lua_touserdata(self.L, idx as c_int))
        }
    }

    #[fixed_stack_segment]
    pub fn get_cfunction(&self, idx: int) -> ffi::lua_CFunction
    {
        unsafe
        {
            ffi::lua_tocfunction(self.L, idx as c_int)
        }
    }

    // Function related functions
    #[fixed_stack_segment]
    pub fn register(&self, name: &str, f: ffi::lua_CFunction)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_register(self.L, c_name, f);
            free(transmute(c_name));
        }
    }

    // Misc functions
    #[fixed_stack_segment]
    pub fn error(&self) -> int
    {
        unsafe
        {
            ffi::lua_error(self.L) as int
        }
    }
}

extern "C" fn _lua_state_closure(L: *ffi::lua_State) -> c_int
{
    let lua = Lua {
        state: unsafe {
            State::from_ffi(L)
        },
    };
    let f: fn(l: &Lua) -> int = match lua.get_arg(0) {
        Some(p) => p,
        None => fail!("I'm sorry Dave I'm afraid I can't do that."),
    };

    f(&lua) as c_int
}

impl<'self> Drop for State<'self>
{
    fn drop(&mut self)
    {
        if self.managed
        {
            unsafe
            {
                self.close();
            }
        }
    }
}
<commit_msg>Add lua::state::State::load_str method.<commit_after>use std::libc::*;
use std::cast::transmute;
use std::str::raw;

use ffi;
use types::LuaType;
use status::LuaStatus;
use lua::Lua;

/**
 *  Proxy to Lua state FFI.
 *
 *  The goal is to provide some functions which don't need to be called in unsafe block everytime we want to call them.
 */
pub struct State<'self>
{
    priv L: *ffi::lua_State,
    priv managed: bool,
}

impl<'self> State<'self>
{
    /**
     *  Create a new Lua state, which is managed by this struct.
     *
     *  When this struct is dropped, the state is closed, and is not usable anymore.
     */
    #[fixed_stack_segment]
    pub fn new() -> State
    {
        State {
            L: unsafe {
                ffi::luaL_newstate()
            },
            managed: true,
        }
    }

    /**
     *  Create a new state from an existing Lua state.
     *
     *  Marked as unsafe as we know nothing about this Lua state lifetime.
     */
    pub unsafe fn from_ffi(L: *ffi::lua_State) -> State
    {
        State {
            L: L,
            managed: false,
        }
    }

    /**
     *  Close the Lua state.
     *
     *  Marked as unsafe as the pointer is not usable anymore after this function call.
     */
    #[fixed_stack_segment]
    pub unsafe fn close(&mut self)
    {
        ffi::lua_close(self.L);
    }

    /// Load lua standard libraries.
    #[fixed_stack_segment]
    pub fn load_stdlibs(&self)
    {
        unsafe
        {
            ffi::luaL_openlibs(self.L);
        }
    }

    /// Get type of a stack element at specified index.
    #[fixed_stack_segment]
    pub fn get_type(&self, idx: int) -> LuaType
    {
        let ty = unsafe {
            ffi::lua_type(self.L, idx as c_int)
        };
        LuaType::from_lua(ty)
    }

    /// Create a new Lua thread.
    #[fixed_stack_segment]
    pub fn new_thread(&self) -> State
    {
        unsafe
        {
            State::from_ffi(ffi::lua_newthread(self.L))
        }
    }

    /// Get Lua version.
    #[fixed_stack_segment]
    pub fn version(&self) -> int
    {
        unsafe
        {
            ffi::lua_version(self.L) as int
        }
    }

    /// Pop a stack element specified by his index.
    #[fixed_stack_segment]
    pub fn pop(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_pop(self.L, idx as c_int);
        }
    }

    /// Get global value. Push to the stack.
    #[fixed_stack_segment]
    pub fn get_global(&self, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_getglobal(self.L, c_name);
            free(transmute(c_name));
        }
    }

    /// Set global value. Pop from the stack.
    #[fixed_stack_segment]
    pub fn set_global(&self, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_setglobal(self.L, c_name);
            free(transmute(c_name));
        }
    }

    /// Get field value. Push to the stack.
    #[fixed_stack_segment]
    pub fn get_field(&self, idx: int, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_getfield(self.L, idx as c_int, c_name);
            free(transmute(c_name));
        }
    }

    /// Set field value. Pop from the stack.
    #[fixed_stack_segment]
    pub fn set_field(&self, idx: int, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_setfield(self.L, idx as c_int, c_name);
            free(transmute(c_name));
        }
    }

    #[fixed_stack_segment]
    pub fn load_file(&self, filename: &str) -> LuaStatus
    {
        let status = unsafe {
            let filename = filename.to_c_str().unwrap();
            let status = ffi::luaL_loadfile(self.L, filename);
            free(transmute(filename));

            status
        };

        LuaStatus::from_lua(status)
    }

    #[fixed_stack_segment]
    pub fn load_str(&self, source: &str) -> LuaStatus
    {
        let status = unsafe {
            let source = source.to_c_str().unwrap();
            let status = ffi::luaL_loadstring(self.L, source);
            free(transmute(source));

            status
        };

        LuaStatus::from_lua(status)
    }

    #[fixed_stack_segment]
    pub fn pcall(&self, nargs: int, nresults: int, errfunc: int) -> LuaStatus
    {
        let status = unsafe {
            ffi::lua_pcall(self.L, nargs as c_int, nresults as c_int, errfunc as c_int)
        };

        LuaStatus::from_lua(status)
    }

    pub fn exec(&self) -> LuaStatus
    {
        self.pcall(0, ffi::LUA_MULTRET as int, 0)
    }

    // Stack functions
    #[fixed_stack_segment]
    pub fn upvalue_index(i: int) -> int
    {
        unsafe
        {
            ffi::lua_upvalueindex(i as c_int) as int
        }
    }

    /// Get index of the stack's top.
    #[fixed_stack_segment]
    pub fn get_top(&self) -> int
    {
        unsafe
        {
            ffi::lua_gettop(self.L) as int
        }
    }

    /// Set index of the stack's top.
    #[fixed_stack_segment]
    pub fn set_top(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_settop(self.L, idx as c_int);
        }
    }

    /// Removes the element at the given valid index.
    #[fixed_stack_segment]
    pub fn remove(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_remove(self.L, idx as c_int);
        }
    }

    // Table functions
    #[fixed_stack_segment]
    pub fn new_table(&self, )
    {
        unsafe
        {
            ffi::lua_newtable(self.L);
        }
    }

    #[fixed_stack_segment]
    pub fn create_table(&self, narr: int, nrec: int)
    {
        unsafe
        {
            ffi::lua_createtable(self.L, narr as c_int, nrec as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn set_table(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_settable(self.L, idx as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn raw_set(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_rawset(self.L, idx as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn raw_set_index(&self, idx: int, i: int)
    {
        unsafe
        {
            ffi::lua_rawseti(self.L, idx as c_int, i as c_int);
        }
    }

    // Push functions

    #[fixed_stack_segment]
    pub fn push_nil(&self)
    {
        unsafe
        {
            ffi::lua_pushnil(self.L);
        }
    }

    #[fixed_stack_segment]
    pub fn push_float(&self, n: f64)
    {
        unsafe
        {
            ffi::lua_pushnumber(self.L, n as ffi::lua_Number);
        }
    }

    #[fixed_stack_segment]
    pub fn push_int(&self, n: int)
    {
        unsafe
        {
            ffi::lua_pushinteger(self.L, n as ffi::lua_Integer);
        }
    }

    #[fixed_stack_segment]
    pub fn push_uint(&self, n: uint)
    {
        unsafe
        {
            ffi::lua_pushunsigned(self.L, n as ffi::lua_Unsigned);
        }
    }

    #[fixed_stack_segment]
    pub fn push_str(&self, s: &str)
    {
        unsafe
        {
            let c_str = s.to_c_str().unwrap();
            ffi::lua_pushstring(self.L, c_str);
            free(transmute(c_str));
        }
    }

    #[fixed_stack_segment]
    pub fn push_bool(&self, b: bool)
    {
        unsafe
        {
            let n = if b { 1 } else { 0 };
            ffi::lua_pushboolean(self.L, n);
        }
    }

    #[fixed_stack_segment]
    pub fn push_userdata<T>(&self, p: *T)
    {
        unsafe
        {
            ffi::lua_pushlightuserdata(self.L, transmute(p));
        }
    }

    #[fixed_stack_segment]
    pub fn push_cclosure(&self, f: ffi::lua_CFunction, n: int)
    {
        unsafe
        {
            ffi::lua_pushcclosure(self.L, f, n as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn push_cfunction(&self, f: ffi::lua_CFunction)
    {
        unsafe
        {
            ffi::lua_pushcfunction(self.L, f);
        }
    }

    pub fn push_function(&self, f: fn(l: &'self Lua) -> int)
    {
        self.push_userdata(f as *());
        self.push_cclosure(_lua_state_closure, 1);
    }

    // Get functions

    #[fixed_stack_segment]
    pub fn get_float(&self, idx: int) -> f64
    {
        unsafe
        {
            ffi::lua_tonumber(self.L, idx as c_int) as f64
        }
    }

    #[fixed_stack_segment]
    pub fn get_int(&self, idx: int) -> int
    {
        unsafe
        {
            ffi::lua_tointeger(self.L, idx as c_int) as int
        }
    }

    #[fixed_stack_segment]
    pub fn get_uint(&self, idx: int) -> uint
    {
        unsafe
        {
            ffi::lua_tounsigned(self.L, idx as c_int) as uint
        }
    }

    #[fixed_stack_segment]
    pub fn get_str(&self, idx: int) -> ~str
    {
        unsafe
        {
            let c_str = ffi::lua_tostring(self.L, idx as c_int);
            raw::from_c_str(c_str)
        }
    }

    #[fixed_stack_segment]
    pub fn get_bool(&self, idx: int) -> bool
    {
        unsafe
        {
            ffi::lua_toboolean(self.L, idx as c_int) != 0
        }
    }

    #[fixed_stack_segment]
    pub fn get_userdata<T>(&self, idx: int) -> *T
    {
        unsafe
        {
            transmute(ffi::lua_touserdata(self.L, idx as c_int))
        }
    }

    #[fixed_stack_segment]
    pub fn get_cfunction(&self, idx: int) -> ffi::lua_CFunction
    {
        unsafe
        {
            ffi::lua_tocfunction(self.L, idx as c_int)
        }
    }

    // Function related functions
    #[fixed_stack_segment]
    pub fn register(&self, name: &str, f: ffi::lua_CFunction)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_register(self.L, c_name, f);
            free(transmute(c_name));
        }
    }

    // Misc functions
    #[fixed_stack_segment]
    pub fn error(&self) -> int
    {
        unsafe
        {
            ffi::lua_error(self.L) as int
        }
    }
}

extern "C" fn _lua_state_closure(L: *ffi::lua_State) -> c_int
{
    let lua = Lua {
        state: unsafe {
            State::from_ffi(L)
        },
    };
    let f: fn(l: &Lua) -> int = match lua.get_arg(0) {
        Some(p) => p,
        None => fail!("I'm sorry Dave I'm afraid I can't do that."),
    };

    f(&lua) as c_int
}

impl<'self> Drop for State<'self>
{
    fn drop(&mut self)
    {
        if self.managed
        {
            unsafe
            {
                self.close();
            }
        }
    }
}
<|endoftext|>


<commit_before>
use {Field, Value, Borrowed, Matrix2d, Line};
use {Transform2d};
use vecmath::{translate, rotate_radians, scale, shear, multiply, identity};
use {View};

/// A line context.
pub struct LineContext<'a> {
    /// Base/original transform.
    pub base: Field<'a, Matrix2d>,
    /// Current transform.
    pub transform: Field<'a, Matrix2d>,
    /// Current line.
    pub line: Field<'a, Line>,
}

impl<'a> Transform2d<'a> for LineContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(self.transform.get(), &trans))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(self.transform.get(), &rot))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(self.transform.get(), &scale))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(alwyas)]
    fn shear(&'a self, sx: f64, sy: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(alwyas)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(self.transform.get(), &shear))
            },
            line: Borrowed(self.line.get()),
        }
    }
}

impl<'a> View<'a> for LineContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            line: Borrowed(self.line.get()),
        }
    }
}

<commit_msg>Sorted use alphabetically<commit_after>
use {
    Field,
    Borrowed,
    Line,
    Matrix2d,
    Transform2d,
    Value,
    View,
};
use vecmath::{
    identity,
    multiply,
    rotate_radians,
    scale,
    shear,
    translate,
};

/// A line context.
pub struct LineContext<'a> {
    /// Base/original transform.
    pub base: Field<'a, Matrix2d>,
    /// Current transform.
    pub transform: Field<'a, Matrix2d>,
    /// Current line.
    pub line: Field<'a, Line>,
}

impl<'a> Transform2d<'a> for LineContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(self.transform.get(), &trans))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(self.transform.get(), &rot))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(self.transform.get(), &scale))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(alwyas)]
    fn shear(&'a self, sx: f64, sy: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(alwyas)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(self.transform.get(), &shear))
            },
            line: Borrowed(self.line.get()),
        }
    }
}

impl<'a> View<'a> for LineContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            line: Borrowed(self.line.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> LineContext<'a> {
        LineContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            line: Borrowed(self.line.get()),
        }
    }
}

<|endoftext|>