<commit_before>//! A thread-safe reference-counted slice type.

use core::prelude::*;

use core::{cmp, fmt, mem, ops};
use core::hash::{Hash, Hasher};

use alloc::arc::{self, Arc, Weak};
use alloc::boxed::Box;

/// A reference-counted slice type.
///
/// This is exactly like `&[T]` except without lifetimes, so the
/// allocation only disappears once all `ArcSlice`s have disappeared.
///
/// NB. this can lead to applications effectively leaking memory if a
/// short subslice of a long `ArcSlice` is held.
///
/// # Examples
///
/// ```rust
/// use shared_slice::arc::ArcSlice;
///
/// let x = ArcSlice::new(Box::new(["foo", "bar", "baz"]));
/// println!("{:?}", x); // ["foo", "bar", "baz"]
/// println!("{:?}", x.slice(1, 3)); // ["bar", "baz"]
/// ```
///
/// Constructing with a dynamic number of elements:
///
/// ```rust
/// # #![allow(unstable)]
/// use shared_slice::arc::ArcSlice;
///
/// let n = 5;
///
/// let v: Vec<u8> = (0u8..n).collect(); // 0, ..., 4
///
/// let x = ArcSlice::new(v.into_boxed_slice());
/// assert_eq!(&*x, [0, 1, 2, 3, 4]);
/// ```
pub struct ArcSlice<T> {
    data: *const [T],
    counts: Arc<()>,
}

unsafe impl<T: Send + Sync> Send for ArcSlice<T> {}
unsafe impl<T: Send + Sync> Sync for ArcSlice<T> {}

/// A non-owning reference-counted slice type.
///
/// This is to `ArcSlice` as `std::sync::Weak` is to `std::sync::Arc`, and
/// allows one to have cyclic references without stopping memory from
/// being deallocated.
pub struct WeakSlice<T> {
    data: *const [T],
    counts: Weak<()>,
}
unsafe impl<T: Send + Sync> Send for WeakSlice<T> {}
unsafe impl<T: Send + Sync> Sync for WeakSlice<T> {}

impl<T> ArcSlice<T> {
    /// Construct a new `ArcSlice` containing the elements of `slice`.
    ///
    /// This reuses the allocation of `slice`.
    pub fn new(slice: Box<[T]>) -> ArcSlice<T> {
        ArcSlice {
            data: unsafe {mem::transmute(slice)},
            counts: Arc::new(())
        }
    }

    /// Downgrade self into a weak slice.
    pub fn downgrade(&self) -> WeakSlice<T> {
        WeakSlice {
            data: self.data,
            counts: self.counts.downgrade()
        }
    }

    /// Construct a new `ArcSlice` that only points to elements at
    /// indices `lo` (inclusive) through `hi` (exclusive).
    ///
    /// This consumes `self` to avoid unnecessary reference-count
    /// modifications. Use `.clone()` if it is necessary to refer to
    /// `self` after calling this.
    ///
    /// # Panics
    ///
    /// Panics if `lo > hi` or if either are strictly greater than
    /// `self.len()`.
    pub fn slice(mut self, lo: usize, hi: usize) -> ArcSlice<T> {
        self.data = unsafe {&(&*self.data)[lo..hi]};
        self
    }
    /// Construct a new `ArcSlice` that only points to elements at
    /// indices up to `hi` (exclusive).
    ///
    /// This consumes `self` to avoid unnecessary reference-count
    /// modifications. Use `.clone()` if it is necessary to refer to
    /// `self` after calling this.
    ///
    /// # Panics
    ///
    /// Panics if `hi > self.len()`.
    pub fn slice_to(self, hi: usize) -> ArcSlice<T> {
        self.slice(0, hi)
    }
    /// Construct a new `ArcSlice` that only points to elements at
    /// indices starting at  `lo` (inclusive).
    ///
    /// This consumes `self` to avoid unnecessary reference-count
    /// modifications. Use `.clone()` if it is necessary to refer to
    /// `self` after calling this.
    ///
    /// # Panics
    ///
    /// Panics if `lo > self.len()`.
    pub fn slice_from(self, lo: usize) -> ArcSlice<T> {
        let hi = self.len();
        self.slice(lo, hi)
    }
}

impl<T> Clone for ArcSlice<T> {
    fn clone(&self) -> ArcSlice<T> {
        ArcSlice {
            data: self.data,
            counts: self.counts.clone()
        }
    }
}

impl<T> ops::Deref for ArcSlice<T> {
    type Target = [T];
    fn deref<'a>(&'a self) -> &'a [T] {
        unsafe {&*self.data}
    }
}

impl<T> AsRef<[T]> for ArcSlice<T> {
    fn as_ref(&self) -> &[T] { &**self }
}

impl<T: PartialEq> PartialEq for ArcSlice<T> {
    fn eq(&self, other: &ArcSlice<T>) -> bool { **self == **other }
    fn ne(&self, other: &ArcSlice<T>) -> bool { **self != **other }
}
impl<T: Eq> Eq for ArcSlice<T> {}

impl<T: PartialOrd> PartialOrd for ArcSlice<T> {
    fn partial_cmp(&self, other: &ArcSlice<T>) -> Option<cmp::Ordering> {
        (**self).partial_cmp(&**other)
    }
    fn lt(&self, other: &ArcSlice<T>) -> bool { **self < **other }
    fn le(&self, other: &ArcSlice<T>) -> bool { **self <= **other }
    fn gt(&self, other: &ArcSlice<T>) -> bool { **self > **other }
    fn ge(&self, other: &ArcSlice<T>) -> bool { **self >= **other }
}
impl<T: Ord> Ord for ArcSlice<T> {
    fn cmp(&self, other: &ArcSlice<T>) -> cmp::Ordering { (**self).cmp(&**other) }
}

impl<T: Hash> Hash for ArcSlice<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

impl<T: fmt::Debug> fmt::Debug for ArcSlice<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

impl<T> WeakSlice<T> {
    /// Attempt to upgrade `self` to a strongly-counted `ArcSlice`.
    ///
    /// Returns `None` if this is not possible (the data has already
    /// been freed).
    pub fn upgrade(&self) -> Option<ArcSlice<T>> {
        self.counts.upgrade().map(|counts| {
            ArcSlice {
                data: self.data,
                counts: counts
            }
        })
    }
}

// only ArcSlice needs a destructor, since it entirely controls the
// actual allocated data; the deallocation of the counts (which is the
// only thing a WeakSlice needs to do if it is the very last pointer)
// is already handled by Arc<()>/Weak<()>.
impl<T> Drop for ArcSlice<T> {
    fn drop(&mut self) {
        let strong = arc::strong_count(&self.counts);
        if strong == 1 {
            // last one, so let's clean up the stored data
            unsafe {
                let _: Box<[T]> = mem::transmute(self.data);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{ArcSlice, WeakSlice};
    use std::cell::Cell;
    use std::cmp::Ordering;
    #[test]
    fn clone() {
        let x = ArcSlice::new(Box::new([Cell::new(false)]));
        let y = x.clone();

        assert_eq!(x[0].get(), false);
        assert_eq!(y[0].get(), false);

        x[0].set(true);
        assert_eq!(x[0].get(), true);
        assert_eq!(y[0].get(), true);
    }

    #[test]
    fn test_upgrade_downgrade() {
        let x = ArcSlice::new(Box::new([1]));
        let y: WeakSlice<_> = x.downgrade();

        assert_eq!(y.upgrade(), Some(x.clone()));

        drop(x);

        assert!(y.upgrade().is_none())
    }

    #[test]
    fn test_total_cmp() {
        let x = ArcSlice::new(Box::new([1, 2, 3]));
        let y = ArcSlice::new(Box::new([1, 2, 3]));
        let z = ArcSlice::new(Box::new([1, 2, 4]));

        assert_eq!(x, x);
        assert_eq!(x, y);
        assert!(x != z);
        assert!(y != z);

        assert!(x < z);
        assert!(x <= z);
        assert!(!(x > z));
        assert!(!(x >= z));

        assert!(!(z < x));
        assert!(!(z <= x));
        assert!(z > x);
        assert!(z >= x);

        assert_eq!(x.partial_cmp(&x), Some(Ordering::Equal));
        assert_eq!(x.partial_cmp(&y), Some(Ordering::Equal));
        assert_eq!(x.partial_cmp(&z), Some(Ordering::Less));
        assert_eq!(z.partial_cmp(&y), Some(Ordering::Greater));

        assert_eq!(x.cmp(&x), Ordering::Equal);
        assert_eq!(x.cmp(&y), Ordering::Equal);
        assert_eq!(x.cmp(&z), Ordering::Less);
        assert_eq!(z.cmp(&y), Ordering::Greater);
    }

    #[test]
    fn test_partial_cmp() {
        use std::f64;
        let x = ArcSlice::new(Box::new([1.0, f64::NAN]));
        let y = ArcSlice::new(Box::new([1.0, f64::NAN]));
        let z = ArcSlice::new(Box::new([2.0, f64::NAN]));
        let w = ArcSlice::new(Box::new([f64::NAN, 1.0]));
        assert!(!(x == y));
        assert!(x != y);

        assert!(!(x < y));
        assert!(!(x <= y));
        assert!(!(x > y));
        assert!(!(x >= y));

        assert!(x < z);
        assert!(x <= z);
        assert!(!(x > z));
        assert!(!(x >= z));

        assert!(!(z < w));
        assert!(!(z <= w));
        assert!(!(z > w));
        assert!(!(z >= w));

        assert_eq!(x.partial_cmp(&x), None);
        assert_eq!(x.partial_cmp(&y), None);
        assert_eq!(x.partial_cmp(&z), Some(Ordering::Less));
        assert_eq!(z.partial_cmp(&x), Some(Ordering::Greater));

        assert_eq!(x.partial_cmp(&w), None);
        assert_eq!(y.partial_cmp(&w), None);
        assert_eq!(z.partial_cmp(&w), None);
        assert_eq!(w.partial_cmp(&w), None);
    }

    #[test]
    fn test_show() {
        let x = ArcSlice::new(Box::new([1, 2]));
        assert_eq!(format!("{:?}", x), "[1, 2]");

        let y: ArcSlice<i32> = ArcSlice::new(Box::new([]));
        assert_eq!(format!("{:?}", y), "[]");
    }

    #[test]
    fn test_slice() {
        let x = ArcSlice::new(Box::new([1, 2, 3]));
        let real = [1, 2, 3];
        for i in (0..3 + 1) {
            for j in (i..3 + 1) {
                let slice: ArcSlice<_> = x.clone().slice(i, j);
                assert_eq!(&*slice, &real[i..j]);
            }
            assert_eq!(&*x.clone().slice_to(i), &real[..i]);
            assert_eq!(&*x.clone().slice_from(i), &real[i..]);
        }
    }

    #[test]
    fn test_send_sync() {
        fn assert_send<T: Send>() {}
        fn assert_sync<T: Send>() {}

        assert_send::<ArcSlice<u8>>();
        assert_sync::<ArcSlice<u8>>();
        assert_send::<WeakSlice<u8>>();
        assert_sync::<WeakSlice<u8>>();
    }
}
<commit_msg>Fix soundness with Drop in ArcSlice by using Arc<Box<[T]>><commit_after>//! A thread-safe reference-counted slice type.

use core::prelude::*;

use core::{cmp, fmt, ops};
use core::hash::{Hash, Hasher};

use alloc::arc::{Arc, Weak};
use alloc::boxed::Box;

/// A reference-counted slice type.
///
/// This is exactly like `&[T]` except without lifetimes, so the
/// allocation only disappears once all `ArcSlice`s have disappeared.
///
/// NB. this can lead to applications effectively leaking memory if a
/// short subslice of a long `ArcSlice` is held.
///
/// # Examples
///
/// ```rust
/// use shared_slice::arc::ArcSlice;
///
/// let x = ArcSlice::new(Box::new(["foo", "bar", "baz"]));
/// println!("{:?}", x); // ["foo", "bar", "baz"]
/// println!("{:?}", x.slice(1, 3)); // ["bar", "baz"]
/// ```
///
/// Constructing with a dynamic number of elements:
///
/// ```rust
/// # #![allow(unstable)]
/// use shared_slice::arc::ArcSlice;
///
/// let n = 5;
///
/// let v: Vec<u8> = (0u8..n).collect(); // 0, ..., 4
///
/// let x = ArcSlice::new(v.into_boxed_slice());
/// assert_eq!(&*x, [0, 1, 2, 3, 4]);
/// ```
pub struct ArcSlice<T> {
    data: *const [T],
    counts: Arc<Box<[T]>>,
}

unsafe impl<T: Send + Sync> Send for ArcSlice<T> {}
unsafe impl<T: Send + Sync> Sync for ArcSlice<T> {}

/// A non-owning reference-counted slice type.
///
/// This is to `ArcSlice` as `std::sync::Weak` is to `std::sync::Arc`, and
/// allows one to have cyclic references without stopping memory from
/// being deallocated.
pub struct WeakSlice<T> {
    data: *const [T],
    counts: Weak<Box<[T]>>,
}
unsafe impl<T: Send + Sync> Send for WeakSlice<T> {}
unsafe impl<T: Send + Sync> Sync for WeakSlice<T> {}

impl<T> ArcSlice<T> {
    /// Construct a new `ArcSlice` containing the elements of `slice`.
    ///
    /// This reuses the allocation of `slice`.
    pub fn new(slice: Box<[T]>) -> ArcSlice<T> {
        ArcSlice {
            data: &*slice,
            counts: Arc::new(slice),
        }
    }

    /// Downgrade self into a weak slice.
    pub fn downgrade(&self) -> WeakSlice<T> {
        WeakSlice {
            data: self.data,
            counts: self.counts.downgrade()
        }
    }

    /// Construct a new `ArcSlice` that only points to elements at
    /// indices `lo` (inclusive) through `hi` (exclusive).
    ///
    /// This consumes `self` to avoid unnecessary reference-count
    /// modifications. Use `.clone()` if it is necessary to refer to
    /// `self` after calling this.
    ///
    /// # Panics
    ///
    /// Panics if `lo > hi` or if either are strictly greater than
    /// `self.len()`.
    pub fn slice(mut self, lo: usize, hi: usize) -> ArcSlice<T> {
        self.data = unsafe {&(&*self.data)[lo..hi]};
        self
    }
    /// Construct a new `ArcSlice` that only points to elements at
    /// indices up to `hi` (exclusive).
    ///
    /// This consumes `self` to avoid unnecessary reference-count
    /// modifications. Use `.clone()` if it is necessary to refer to
    /// `self` after calling this.
    ///
    /// # Panics
    ///
    /// Panics if `hi > self.len()`.
    pub fn slice_to(self, hi: usize) -> ArcSlice<T> {
        self.slice(0, hi)
    }
    /// Construct a new `ArcSlice` that only points to elements at
    /// indices starting at  `lo` (inclusive).
    ///
    /// This consumes `self` to avoid unnecessary reference-count
    /// modifications. Use `.clone()` if it is necessary to refer to
    /// `self` after calling this.
    ///
    /// # Panics
    ///
    /// Panics if `lo > self.len()`.
    pub fn slice_from(self, lo: usize) -> ArcSlice<T> {
        let hi = self.len();
        self.slice(lo, hi)
    }
}

impl<T> Clone for ArcSlice<T> {
    fn clone(&self) -> ArcSlice<T> {
        ArcSlice {
            data: self.data,
            counts: self.counts.clone()
        }
    }
}

impl<T> ops::Deref for ArcSlice<T> {
    type Target = [T];
    fn deref<'a>(&'a self) -> &'a [T] {
        unsafe {&*self.data}
    }
}

impl<T> AsRef<[T]> for ArcSlice<T> {
    fn as_ref(&self) -> &[T] { &**self }
}

impl<T: PartialEq> PartialEq for ArcSlice<T> {
    fn eq(&self, other: &ArcSlice<T>) -> bool { **self == **other }
    fn ne(&self, other: &ArcSlice<T>) -> bool { **self != **other }
}
impl<T: Eq> Eq for ArcSlice<T> {}

impl<T: PartialOrd> PartialOrd for ArcSlice<T> {
    fn partial_cmp(&self, other: &ArcSlice<T>) -> Option<cmp::Ordering> {
        (**self).partial_cmp(&**other)
    }
    fn lt(&self, other: &ArcSlice<T>) -> bool { **self < **other }
    fn le(&self, other: &ArcSlice<T>) -> bool { **self <= **other }
    fn gt(&self, other: &ArcSlice<T>) -> bool { **self > **other }
    fn ge(&self, other: &ArcSlice<T>) -> bool { **self >= **other }
}
impl<T: Ord> Ord for ArcSlice<T> {
    fn cmp(&self, other: &ArcSlice<T>) -> cmp::Ordering { (**self).cmp(&**other) }
}

impl<T: Hash> Hash for ArcSlice<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

impl<T: fmt::Debug> fmt::Debug for ArcSlice<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

impl<T> WeakSlice<T> {
    /// Attempt to upgrade `self` to a strongly-counted `ArcSlice`.
    ///
    /// Returns `None` if this is not possible (the data has already
    /// been freed).
    pub fn upgrade(&self) -> Option<ArcSlice<T>> {
        self.counts.upgrade().map(|counts| {
            ArcSlice {
                data: self.data,
                counts: counts
            }
        })
    }
}

#[cfg(test)]
mod tests {
    use super::{ArcSlice, WeakSlice};
    use std::sync::{Arc, Mutex};
    use std::cell::Cell;
    use std::cmp::Ordering;
    #[test]
    fn clone() {
        let x = ArcSlice::new(Box::new([Cell::new(false)]));
        let y = x.clone();

        assert_eq!(x[0].get(), false);
        assert_eq!(y[0].get(), false);

        x[0].set(true);
        assert_eq!(x[0].get(), true);
        assert_eq!(y[0].get(), true);
    }

    #[test]
    fn test_upgrade_downgrade() {
        let x = ArcSlice::new(Box::new([1]));
        let y: WeakSlice<_> = x.downgrade();

        assert_eq!(y.upgrade(), Some(x.clone()));

        drop(x);

        assert!(y.upgrade().is_none())
    }

    #[test]
    fn test_total_cmp() {
        let x = ArcSlice::new(Box::new([1, 2, 3]));
        let y = ArcSlice::new(Box::new([1, 2, 3]));
        let z = ArcSlice::new(Box::new([1, 2, 4]));

        assert_eq!(x, x);
        assert_eq!(x, y);
        assert!(x != z);
        assert!(y != z);

        assert!(x < z);
        assert!(x <= z);
        assert!(!(x > z));
        assert!(!(x >= z));

        assert!(!(z < x));
        assert!(!(z <= x));
        assert!(z > x);
        assert!(z >= x);

        assert_eq!(x.partial_cmp(&x), Some(Ordering::Equal));
        assert_eq!(x.partial_cmp(&y), Some(Ordering::Equal));
        assert_eq!(x.partial_cmp(&z), Some(Ordering::Less));
        assert_eq!(z.partial_cmp(&y), Some(Ordering::Greater));

        assert_eq!(x.cmp(&x), Ordering::Equal);
        assert_eq!(x.cmp(&y), Ordering::Equal);
        assert_eq!(x.cmp(&z), Ordering::Less);
        assert_eq!(z.cmp(&y), Ordering::Greater);
    }

    #[test]
    fn test_partial_cmp() {
        use std::f64;
        let x = ArcSlice::new(Box::new([1.0, f64::NAN]));
        let y = ArcSlice::new(Box::new([1.0, f64::NAN]));
        let z = ArcSlice::new(Box::new([2.0, f64::NAN]));
        let w = ArcSlice::new(Box::new([f64::NAN, 1.0]));
        assert!(!(x == y));
        assert!(x != y);

        assert!(!(x < y));
        assert!(!(x <= y));
        assert!(!(x > y));
        assert!(!(x >= y));

        assert!(x < z);
        assert!(x <= z);
        assert!(!(x > z));
        assert!(!(x >= z));

        assert!(!(z < w));
        assert!(!(z <= w));
        assert!(!(z > w));
        assert!(!(z >= w));

        assert_eq!(x.partial_cmp(&x), None);
        assert_eq!(x.partial_cmp(&y), None);
        assert_eq!(x.partial_cmp(&z), Some(Ordering::Less));
        assert_eq!(z.partial_cmp(&x), Some(Ordering::Greater));

        assert_eq!(x.partial_cmp(&w), None);
        assert_eq!(y.partial_cmp(&w), None);
        assert_eq!(z.partial_cmp(&w), None);
        assert_eq!(w.partial_cmp(&w), None);
    }

    #[test]
    fn test_show() {
        let x = ArcSlice::new(Box::new([1, 2]));
        assert_eq!(format!("{:?}", x), "[1, 2]");

        let y: ArcSlice<i32> = ArcSlice::new(Box::new([]));
        assert_eq!(format!("{:?}", y), "[]");
    }

    #[test]
    fn test_slice() {
        let x = ArcSlice::new(Box::new([1, 2, 3]));
        let real = [1, 2, 3];
        for i in (0..3 + 1) {
            for j in (i..3 + 1) {
                let slice: ArcSlice<_> = x.clone().slice(i, j);
                assert_eq!(&*slice, &real[i..j]);
            }
            assert_eq!(&*x.clone().slice_to(i), &real[..i]);
            assert_eq!(&*x.clone().slice_from(i), &real[i..]);
        }
    }

    #[test]
    fn test_send_sync() {
        fn assert_send<T: Send>() {}
        fn assert_sync<T: Send>() {}

        assert_send::<ArcSlice<u8>>();
        assert_sync::<ArcSlice<u8>>();
        assert_send::<WeakSlice<u8>>();
        assert_sync::<WeakSlice<u8>>();
    }

    #[test]
    fn test_drop() {
        let drop_flag = Arc::new(Mutex::new(0));
        struct Foo(Arc<Mutex<i32>>);

        impl Drop for Foo {
            fn drop(&mut self) {
                let mut n = self.0.lock().unwrap();
                *n += 1;
            }
        }

        let whole = ArcSlice::new(Box::new([Foo(drop_flag.clone()), Foo(drop_flag.clone())]));

        drop(whole);
        assert_eq!(*drop_flag.lock().unwrap(), 2);

        *drop_flag.lock().unwrap() = 0;

        let whole = ArcSlice::new(Box::new([Foo(drop_flag.clone()), Foo(drop_flag.clone())]));
        let part = whole.slice(1, 2);
        drop(part);
        assert_eq!(*drop_flag.lock().unwrap(), 2);
    }
}
<|endoftext|>


<commit_before>//! Implementation for `arr!` macro.

use super::ArrayLength;
use core::ops::Add;
use typenum::U1;

/// Helper trait for `arr!` macro
pub trait AddLength<T, N: ArrayLength<T>>: ArrayLength<T> {
    /// Resulting length
    type Output: ArrayLength<T>;
}

impl<T, N1, N2> AddLength<T, N2> for N1
where
    N1: ArrayLength<T> + Add<N2>,
    N2: ArrayLength<T>,
    <N1 as Add<N2>>::Output: ArrayLength<T>,
{
    type Output = <N1 as Add<N2>>::Output;
}

/// Helper type for `arr!` macro
pub type Inc<T, U> = <U as AddLength<T, U1>>::Output;

#[doc(hidden)]
#[macro_export]
macro_rules! arr_impl {
    (@replace_expr $e:expr)=>{
        1
    };
    ($T:ty; $N:ty, [$($x:expr),*], []) => ({
        const __ARR_LENGTH:usize=0 $(+ $crate::arr_impl!(@replace_expr $x) )*;
        fn __do_transmute<'a, T, N: $crate::ArrayLength<T>>(arr: [T; __ARR_LENGTH]) -> $crate::GenericArray<T, N> {
            unsafe { $crate::transmute(arr) }
        }

        let _:[();<$N as $crate::typenum::Unsigned>::USIZE]=[();__ARR_LENGTH];

        __do_transmute::<$T,$N>([$($x),*])
    });
    ($T:ty; $N:ty, [], [$x1:expr]) => (
        $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [])
    );
    ($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => (
        $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [$($x),+])
    );
    ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => (
        $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [])
    );
    ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => (
        $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [$($x),+])
    );
}

/// Macro allowing for easy generation of Generic Arrays.
/// Example: `let test = arr![u32; 1, 2, 3];`
#[macro_export]
macro_rules! arr {
    ($T:ty; $(,)*) => ({
        unsafe { $crate::transmute::<[$T; 0], $crate::GenericArray<$T, $crate::typenum::U0>>([]) }
    });
    ($T:ty; $($x:expr),* $(,)*) => (
        $crate::arr_impl!($T; $crate::typenum::U0, [], [$($x),*])
    );
    ($($x:expr,)+) => (arr![$($x),+]);
    () => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`")
}

mod doctests_only{
    ///
    /// # With ellision
    ///
    /// Testing that lifetimes aren't transmuted when they're ellided.
    ///
    /// ```compile_fail
    /// #[macro_use] extern crate generic_array;
    /// fn main() {
    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
    ///        arr![&A; a][0]
    ///    }
    /// }
    /// ```
    ///
    /// ```rust
    /// #[macro_use] extern crate generic_array;
    /// fn main() {
    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
    ///        arr![&A; a][0]
    ///    }
    /// }
    /// ```
    ///
    /// # Without ellision
    ///
    /// Testing that lifetimes aren't transmuted when they're specified explicitly.
    ///
    /// ```compile_fail
    /// #[macro_use] extern crate generic_array;
    /// fn main() {
    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
    ///        arr![&'a A; a][0]
    ///    }
    /// }
    /// ```
    ///
    /// ```compile_fail
    /// #[macro_use] extern crate generic_array;
    /// fn main() {
    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
    ///        arr![&'static A; a][0]
    ///    }
    /// }
    /// ```
    ///
    /// ```rust
    /// #[macro_use] extern crate generic_array;
    /// fn main() {
    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
    ///        arr![&'a A; a][0]
    ///    }
    /// }
    /// ```
    #[allow(dead_code)]
    pub enum DocTests{}
}<commit_msg>Formatting<commit_after>//! Implementation for `arr!` macro.

use super::ArrayLength;
use core::ops::Add;
use typenum::U1;

/// Helper trait for `arr!` macro
pub trait AddLength<T, N: ArrayLength<T>>: ArrayLength<T> {
    /// Resulting length
    type Output: ArrayLength<T>;
}

impl<T, N1, N2> AddLength<T, N2> for N1
where
    N1: ArrayLength<T> + Add<N2>,
    N2: ArrayLength<T>,
    <N1 as Add<N2>>::Output: ArrayLength<T>,
{
    type Output = <N1 as Add<N2>>::Output;
}

/// Helper type for `arr!` macro
pub type Inc<T, U> = <U as AddLength<T, U1>>::Output;

#[doc(hidden)]
#[macro_export]
macro_rules! arr_impl {
    (@replace_expr $e:expr) => { 1 };
    ($T:ty; $N:ty, [$($x:expr),*], []) => ({
        const __ARR_LENGTH: usize = 0 $(+ $crate::arr_impl!(@replace_expr $x) )*;

        #[inline(always)]
        fn __do_transmute<T, N: $crate::ArrayLength<T>>(arr: [T; __ARR_LENGTH]) -> $crate::GenericArray<T, N> {
            unsafe { $crate::transmute(arr) }
        }

        let _: [(); <$N as $crate::typenum::Unsigned>::USIZE] = [(); __ARR_LENGTH];

        __do_transmute::<$T, $N>([$($x),*])
    });
    ($T:ty; $N:ty, [], [$x1:expr]) => (
        $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [])
    );
    ($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => (
        $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [$($x),+])
    );
    ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => (
        $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [])
    );
    ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => (
        $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [$($x),+])
    );
}

/// Macro allowing for easy generation of Generic Arrays.
/// Example: `let test = arr![u32; 1, 2, 3];`
#[macro_export]
macro_rules! arr {
    ($T:ty; $(,)*) => ({
        unsafe { $crate::transmute::<[$T; 0], $crate::GenericArray<$T, $crate::typenum::U0>>([]) }
    });
    ($T:ty; $($x:expr),* $(,)*) => (
        $crate::arr_impl!($T; $crate::typenum::U0, [], [$($x),*])
    );
    ($($x:expr,)+) => (arr![$($x),+]);
    () => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`")
}

mod doctests_only {
    ///
    /// # With ellision
    ///
    /// Testing that lifetimes aren't transmuted when they're ellided.
    ///
    /// ```compile_fail
    /// #[macro_use] extern crate generic_array;
    /// fn main() {
    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
    ///        arr![&A; a][0]
    ///    }
    /// }
    /// ```
    ///
    /// ```rust
    /// #[macro_use] extern crate generic_array;
    /// fn main() {
    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
    ///        arr![&A; a][0]
    ///    }
    /// }
    /// ```
    ///
    /// # Without ellision
    ///
    /// Testing that lifetimes aren't transmuted when they're specified explicitly.
    ///
    /// ```compile_fail
    /// #[macro_use] extern crate generic_array;
    /// fn main() {
    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
    ///        arr![&'a A; a][0]
    ///    }
    /// }
    /// ```
    ///
    /// ```compile_fail
    /// #[macro_use] extern crate generic_array;
    /// fn main() {
    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
    ///        arr![&'static A; a][0]
    ///    }
    /// }
    /// ```
    ///
    /// ```rust
    /// #[macro_use] extern crate generic_array;
    /// fn main() {
    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
    ///        arr![&'a A; a][0]
    ///    }
    /// }
    /// ```
    #[allow(dead_code)]
    pub enum DocTests {}
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate dent;
extern crate term;
extern crate term_size;

use clap::{App, Arg};
use dent::plot;
use dent::summary::Summary;
use dent::t_test::{SigLevel, TTest, welch_t_test};

use std::fs::File;
use std::path::Path;
use std::io::{self, BufRead, BufReader};

mod fmt;

fn print_summary(s: &Summary) {
    let width = 10;
    let size_width = 6;

    println!(
        "{n:>nw$}  {min:>w$}  {max:>w$}  {med:>w$}  {mean:>w$}  {sd:>w$}  {se:>w$}",
        w = width,
        nw = size_width,
        n = "N",
        min = "Min",
        max = "Max",
        med = "Median",
        mean = "Mean",
        sd= "StdDev",
        se = "StdErr",
    );
    println!(
        "{n:>nw$}  {min:>w$}  {max:>w$}  {med:>w$}  {mean:>w$}  {sd:>w$}  {se:>w$}",
        w = width,
        nw = size_width,
        n = fmt::f(s.size(), width),
        min = fmt::f(s.min(), width),
        max = fmt::f(s.max(), width),
        med = fmt::f(s.median(), width),
        mean = fmt::f(s.mean(), width),
        sd = fmt::f(s.standard_deviation(), width),
        se = fmt::f(s.standard_error(), width),
    );
}

fn print_t_test(t_test: &TTest) {
    let width = 12;
    let reject = if t_test.reject { "yes" } else { "no" };

    println!("{l:>w$} = {v}", w = width, l = "Reject H₀?", v = reject);
    println!("{l:>w$} = {v}", w = width, l = "α", v = t_test.alpha);
    println!("{l:>w$} = {v}", w = width, l = "t", v = t_test.t);
    println!("{l:>w$} = {v}", w = width, l = "Crit. v", v = t_test.crit);
    println!("{l:>w$} = {v}", w = width, l = "DF", v = t_test.df);
}

fn summarize_file(path: &str, lax_parsing: bool) -> Summary {
    let p = Path::new(path);
    let f = File::open(p).unwrap();
    let reader = BufReader::new(f);

    let data = read_data(reader, lax_parsing);

    Summary::new(&data).unwrap()
}

fn read_data<R>(reader: R, lax_parsing: bool) -> Vec<f64> where R: BufRead {
    let mut data: Vec<f64> = vec![];

    for l in reader.lines() {
        let s = l.unwrap().trim().to_string();

        if s.is_empty() {
            continue;
        }

        match s.parse() {
            Ok(d) => data.push(d),
            err => if !lax_parsing { err.unwrap(); }
        }
    }

    data
}

fn parse_alpha(arg: &str) -> SigLevel {
    match arg {
        ".001" => SigLevel::Alpha001,
        ".005" => SigLevel::Alpha005,
        ".01"  => SigLevel::Alpha010,
        ".025" => SigLevel::Alpha025,
        ".05"  => SigLevel::Alpha050,
        ".1"   => SigLevel::Alpha100,
        _ => panic!(),
    }
}

fn summarize_stdin(lax_parsing: bool) -> Summary {
    let stdin = io::stdin();
    let data = read_data(stdin.lock(), lax_parsing);

    Summary::new(&data).unwrap()
}

fn display_t_test(
    summary1: &Summary,
    summary2: &Summary,
    alpha: SigLevel,
    draw_plot: bool,
    width: usize,
    ascii: bool,
) {
    let t_test = welch_t_test(&summary1, &summary2, alpha);

    if draw_plot {
        let p = plot::comparison_plot(&[&summary1, &summary2], width, ascii, true);
        println!("{}\n", p);
    }

    print_summary(&summary1);
    println!();
    print_summary(&summary2);
    println!();
    print_t_test(&t_test);
}

fn main() {
    let matches = App::new("dent")
        .version("0.3.0")
        .author("Joe Ranweiler <joe@lemma.co>")
        .about("A tiny tool for t-tests &c.")
        .arg(Arg::with_name("stdin")
             .short("s")
             .long("stdin")
             .help("Read and summarize data from stdin"))
        .arg(Arg::with_name("files")
             .multiple(true)
             .value_name("FILES")
             .takes_value(true)
             .required_unless("stdin")
             .help("Path to one or more files of sample data"))
        .arg(Arg::with_name("alpha")
             .short("a")
             .long("alpha")
             .value_name("ALPHA")
             .help("Significance level α")
             .takes_value(true)
             .default_value(".05"))
        .arg(Arg::with_name("lax")
             .long("lax")
             .help("Ignore non-numeric input lines"))
        .arg(Arg::with_name("plot")
             .short("p")
             .long("plot")
             .help("Print standard boxplots"))
        .arg(Arg::with_name("ascii")
             .long("ascii")
             .help("Use only ASCII characters in boxplots"))
        .arg(Arg::with_name("width")
             .short("w")
             .long("width")
             .value_name("WIDTH")
             .takes_value(true)
             .help("Width of boxplot"))
        .get_matches();

    let ascii = matches.is_present("ascii");
    let lax_parsing = matches.is_present("lax");
    let draw_plot = matches.is_present("plot");
    let use_stdin = matches.is_present("stdin");

    let width = matches
        .value_of("width")
        .and_then(|w| w.parse::<usize>().ok())
        .or(term_size::dimensions().map(|(w, _)| w))
        .unwrap_or(80);

    let summaries = if use_stdin {
        vec![summarize_stdin(lax_parsing)]
    } else {
        matches.values_of("files").unwrap()
            .map(|f| summarize_file(f, lax_parsing))
            .collect()
    };

    match summaries.len() {
        0 => unreachable!(),
        2 => {
            let alpha = parse_alpha(matches.value_of("alpha").unwrap());

            display_t_test(
                &summaries[0],
                &summaries[1],
                alpha,
                draw_plot,
                width,
                ascii,
            );
        }
        _ => {
            if draw_plot {
                let summary_refs: Vec<&Summary> = summaries
                    .iter()
                    .collect();

                let plot = plot::comparison_plot(&summary_refs, width, ascii, true);
                println!("{}\n", plot);
            }

            for i in 0..summaries.len() {
                if i > 0 {
                    println!();
                }
                print_summary(&summaries[i]);
            }
        },
    };
}
<commit_msg>Log file open errors<commit_after>extern crate clap;
extern crate dent;
extern crate term;
extern crate term_size;

use clap::{App, Arg};
use dent::plot;
use dent::summary::Summary;
use dent::t_test::{SigLevel, TTest, welch_t_test};

use std::fs::File;
use std::path::Path;
use std::io::{self, BufRead, BufReader};

mod fmt;
mod log;

fn fail<E>(err: E) -> ! where E: std::error::Error {
    log::error(&format!("{}", err));
    std::process::exit(1);
}

fn print_summary(s: &Summary) {
    let width = 10;
    let size_width = 6;

    println!(
        "{n:>nw$}  {min:>w$}  {max:>w$}  {med:>w$}  {mean:>w$}  {sd:>w$}  {se:>w$}",
        w = width,
        nw = size_width,
        n = "N",
        min = "Min",
        max = "Max",
        med = "Median",
        mean = "Mean",
        sd= "StdDev",
        se = "StdErr",
    );
    println!(
        "{n:>nw$}  {min:>w$}  {max:>w$}  {med:>w$}  {mean:>w$}  {sd:>w$}  {se:>w$}",
        w = width,
        nw = size_width,
        n = fmt::f(s.size(), width),
        min = fmt::f(s.min(), width),
        max = fmt::f(s.max(), width),
        med = fmt::f(s.median(), width),
        mean = fmt::f(s.mean(), width),
        sd = fmt::f(s.standard_deviation(), width),
        se = fmt::f(s.standard_error(), width),
    );
}

fn print_t_test(t_test: &TTest) {
    let width = 12;
    let reject = if t_test.reject { "yes" } else { "no" };

    println!("{l:>w$} = {v}", w = width, l = "Reject H₀?", v = reject);
    println!("{l:>w$} = {v}", w = width, l = "α", v = t_test.alpha);
    println!("{l:>w$} = {v}", w = width, l = "t", v = t_test.t);
    println!("{l:>w$} = {v}", w = width, l = "Crit. v", v = t_test.crit);
    println!("{l:>w$} = {v}", w = width, l = "DF", v = t_test.df);
}

fn summarize_file(path: &str, lax_parsing: bool) -> Summary {
    let p = Path::new(path);
    let f = match File::open(p) {
        Ok(f) => f,
        Err(e) => fail(e),
    };
    let reader = BufReader::new(f);

    let data = read_data(reader, lax_parsing);

    Summary::new(&data).unwrap()
}

fn read_data<R>(reader: R, lax_parsing: bool) -> Vec<f64> where R: BufRead {
    let mut data: Vec<f64> = vec![];

    for l in reader.lines() {
        let s = l.unwrap().trim().to_string();

        if s.is_empty() {
            continue;
        }

        match s.parse() {
            Ok(d) => data.push(d),
            err => if !lax_parsing { err.unwrap(); }
        }
    }

    data
}

fn parse_alpha(arg: &str) -> SigLevel {
    match arg {
        ".001" => SigLevel::Alpha001,
        ".005" => SigLevel::Alpha005,
        ".01"  => SigLevel::Alpha010,
        ".025" => SigLevel::Alpha025,
        ".05"  => SigLevel::Alpha050,
        ".1"   => SigLevel::Alpha100,
        _ => panic!(),
    }
}

fn summarize_stdin(lax_parsing: bool) -> Summary {
    let stdin = io::stdin();
    let data = read_data(stdin.lock(), lax_parsing);

    Summary::new(&data).unwrap()
}

fn display_t_test(
    summary1: &Summary,
    summary2: &Summary,
    alpha: SigLevel,
    draw_plot: bool,
    width: usize,
    ascii: bool,
) {
    let t_test = welch_t_test(&summary1, &summary2, alpha);

    if draw_plot {
        let p = plot::comparison_plot(&[&summary1, &summary2], width, ascii, true);
        println!("{}\n", p);
    }

    print_summary(&summary1);
    println!();
    print_summary(&summary2);
    println!();
    print_t_test(&t_test);
}

fn main() {
    let matches = App::new("dent")
        .version("0.3.0")
        .author("Joe Ranweiler <joe@lemma.co>")
        .about("A tiny tool for t-tests &c.")
        .arg(Arg::with_name("stdin")
             .short("s")
             .long("stdin")
             .help("Read and summarize data from stdin"))
        .arg(Arg::with_name("files")
             .multiple(true)
             .value_name("FILES")
             .takes_value(true)
             .required_unless("stdin")
             .help("Path to one or more files of sample data"))
        .arg(Arg::with_name("alpha")
             .short("a")
             .long("alpha")
             .value_name("ALPHA")
             .help("Significance level α")
             .takes_value(true)
             .default_value(".05"))
        .arg(Arg::with_name("lax")
             .long("lax")
             .help("Ignore non-numeric input lines"))
        .arg(Arg::with_name("plot")
             .short("p")
             .long("plot")
             .help("Print standard boxplots"))
        .arg(Arg::with_name("ascii")
             .long("ascii")
             .help("Use only ASCII characters in boxplots"))
        .arg(Arg::with_name("width")
             .short("w")
             .long("width")
             .value_name("WIDTH")
             .takes_value(true)
             .help("Width of boxplot"))
        .get_matches();

    let ascii = matches.is_present("ascii");
    let lax_parsing = matches.is_present("lax");
    let draw_plot = matches.is_present("plot");
    let use_stdin = matches.is_present("stdin");

    let width = matches
        .value_of("width")
        .and_then(|w| w.parse::<usize>().ok())
        .or(term_size::dimensions().map(|(w, _)| w))
        .unwrap_or(80);

    let summaries = if use_stdin {
        vec![summarize_stdin(lax_parsing)]
    } else {
        matches.values_of("files").unwrap()
            .map(|f| summarize_file(f, lax_parsing))
            .collect()
    };

    match summaries.len() {
        0 => unreachable!(),
        2 => {
            let alpha = parse_alpha(matches.value_of("alpha").unwrap());

            display_t_test(
                &summaries[0],
                &summaries[1],
                alpha,
                draw_plot,
                width,
                ascii,
            );
        }
        _ => {
            if draw_plot {
                let summary_refs: Vec<&Summary> = summaries
                    .iter()
                    .collect();

                let plot = plot::comparison_plot(&summary_refs, width, ascii, true);
                println!("{}\n", plot);
            }

            for i in 0..summaries.len() {
                if i > 0 {
                    println!();
                }
                print_summary(&summaries[i]);
            }
        },
    };
}
<|endoftext|>


<commit_before>// Copyright 2016 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use super::*;

use objc::runtime::Class;
use cocoa::foundation::NSUInteger;

#[repr(u64)]
#[allow(non_camel_case_types)]
pub enum MTLLoadAction {
    DontCare = 0,
    Load = 1,
    Clear = 2,
}

#[repr(u64)]
#[allow(non_camel_case_types)]
pub enum MTLStoreAction {
    DontCare = 0,
    Store = 1,
    MultisampleResolve = 2,
}

#[repr(C)]
#[derive(Debug)]
pub struct MTLClearColor {
    red: f64,
    green: f64,
    blue: f64,
    alpha: f64
}

impl MTLClearColor {
    #[inline]
    pub fn new(red: f64, green: f64, blue: f64, alpha: f64) -> Self {
        MTLClearColor {
            red: red,
            green: green,
            blue: blue,
            alpha: alpha
        }
    }
}

pub enum MTLRenderPassAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassAttachmentDescriptor;
    pub struct RenderPassAttachmentDescriptor;
    pub struct RenderPassAttachmentDescriptorRef;
}

impl RenderPassAttachmentDescriptorRef {
    pub fn texture(&self) -> Option<&TextureRef> {
        unsafe {
            msg_send![self, texture]
        }
    }

    pub fn set_texture(&self, texture: Option<&TextureRef>) {
        unsafe {
            msg_send![self, setTexture:texture];
        }
    }

    pub fn level(&self) -> NSUInteger {
        unsafe {
            msg_send![self, level]
        }
    }

    pub fn set_level(&self, level: NSUInteger) {
        unsafe {
            msg_send![self, setLevel:level]
        }
    }

    pub fn slice(&self) -> NSUInteger {
        unsafe {
            msg_send![self, slice]
        }
    }

    pub fn set_slice(&self, slice: NSUInteger) {
        unsafe {
            msg_send![self, setSlice:slice]
        }
    }

    pub fn depth_plane(&self) -> NSUInteger {
        unsafe {
            msg_send![self, depthPlane]
        }
    }

    pub fn set_depth_plane(&self, depth_plane: NSUInteger) {
        unsafe {
            msg_send![self, setDepthPlane:depth_plane]
        }
    }

    pub fn resolve_texture(&self) -> Option<&TextureRef> {
        unsafe {
            msg_send![self, resolveTexture]
        }
    }

    pub fn set_resolve_texture(&self, resolve_texture: Option<&TextureRef>) {
        unsafe {
            msg_send![self, setResolveTexture:resolve_texture]
        }
    }

    pub fn resolve_level(&self) -> NSUInteger {
        unsafe {
            msg_send![self, resolveLevel]
        }
    }

    pub fn set_resolve_level(&self, resolve_level: NSUInteger) {
        unsafe {
            msg_send![self, setResolveLevel:resolve_level]
        }
    }

    pub fn resolve_slice(&self) -> NSUInteger {
        unsafe {
            msg_send![self, resolveSlice]
        }
    }

    pub fn set_resolve_slice(&self, resolve_slice: NSUInteger) {
        unsafe {
            msg_send![self, setResolveSlice:resolve_slice]
        }
    }

    pub fn resolve_depth_plane(&self) -> NSUInteger {
        unsafe {
            msg_send![self, resolveDepthPlane]
        }
    }

    pub fn set_resolve_depth_plane(&self, resolve_depth_plane: NSUInteger) {
        unsafe {
            msg_send![self, setResolveDepthPlane:resolve_depth_plane]
        }
    }

    pub fn load_action(&self) -> MTLLoadAction {
        unsafe {
            msg_send![self, loadAction]
        }
    }

    pub fn set_load_action(&self, load_action: MTLLoadAction) {
        unsafe {
            msg_send![self, setLoadAction:load_action]
        }
    }

    pub fn store_action(&self) -> MTLStoreAction {
        unsafe {
            msg_send![self, storeAction]
        }
    }

    pub fn set_store_action(&self, store_action: MTLStoreAction) {
        unsafe {
            msg_send![self, setStoreAction:store_action]
        }
    }
}

pub enum MTLRenderPassColorAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassColorAttachmentDescriptor;
    pub struct RenderPassColorAttachmentDescriptor;
    pub struct RenderPassColorAttachmentDescriptorRef;
    type ParentType = RenderPassAttachmentDescriptorRef;
}

impl RenderPassColorAttachmentDescriptor {
    pub fn new() -> Self {
        unsafe {
            let class = Class::get("MTLRenderPassColorAttachmentDescriptor").unwrap();
            msg_send![class, new]
        }
    }
}

impl RenderPassColorAttachmentDescriptorRef {
    pub fn clear_color(&self) -> MTLClearColor {
        unsafe {
            msg_send![self, clearColor]
        }
    }

    pub fn set_clear_color(&self, clear_color: MTLClearColor) {
        unsafe {
            msg_send![self, setClearColor:clear_color]
        }
    }
}

pub enum MTLRenderPassDepthAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassDepthAttachmentDescriptor;
    pub struct RenderPassDepthAttachmentDescriptor;
    pub struct RenderPassDepthAttachmentDescriptorRef;
    type ParentType = RenderPassAttachmentDescriptorRef;
}

impl RenderPassDepthAttachmentDescriptorRef {
    pub fn clear_depth(&self) -> f64 {
        unsafe {
            msg_send![self, clearDepth]
        }
    }

    pub fn set_clear_depth(&self, clear_depth: f64) {
        unsafe {
            msg_send![self, setClearDepth:clear_depth]
        }
    }
}

pub enum MTLRenderPassStencilAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassStencilAttachmentDescriptor;
    pub struct RenderPassStencilAttachmentDescriptor;
    pub struct RenderPassStencilAttachmentDescriptorRef;
    type ParentType = RenderPassAttachmentDescriptorRef;
}

impl RenderPassStencilAttachmentDescriptorRef {
    pub fn clear_stencil(&self) -> u32 {
        unsafe {
            msg_send![self, clearStencil]
        }
    }

    pub fn set_clear_stencil(&self, clear_stencil: u32) {
        unsafe {
            msg_send![self, setClearStencil:clear_stencil]
        }
    }
}

pub enum MTLRenderPassColorAttachmentDescriptorArray {}

foreign_obj_type! {
    type CType = MTLRenderPassColorAttachmentDescriptorArray;
    pub struct RenderPassColorAttachmentDescriptorArray;
    pub struct RenderPassColorAttachmentDescriptorArrayRef;
}

impl RenderPassColorAttachmentDescriptorArrayRef {
    pub fn object_at(&self, index: usize) -> Option<&RenderPassColorAttachmentDescriptorRef> {
        unsafe {
            msg_send![self, objectAtIndexedSubscript:index]
        }
    }

    pub fn set_object_at(&self, index: usize, attachment: Option<&RenderPassColorAttachmentDescriptorRef>) {
        unsafe {
            msg_send![self, setObject:attachment
                     atIndexedSubscript:index]
        }
    }
}

pub enum MTLRenderPassDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassDescriptor;
    pub struct RenderPassDescriptor;
    pub struct RenderPassDescriptorRef;
}

impl RenderPassDescriptor {
    pub fn new<'a>() -> &'a RenderPassDescriptorRef {
        unsafe {
            let class = Class::get("MTLRenderPassDescriptorInternal").unwrap();
            msg_send![class, renderPassDescriptor]
        }
    }
}

impl RenderPassDescriptorRef {
    pub fn color_attachments(&self) -> &RenderPassColorAttachmentDescriptorArrayRef {
        unsafe {
            msg_send![self, colorAttachments]
        }
    }

    pub fn depth_attachment(&self) -> Option<&RenderPassDepthAttachmentDescriptorRef> {
        unsafe {
            msg_send![self, depthAttachment]
        }
    }

    pub fn set_depth_attachment(&self, depth_attachment: Option<&RenderPassDepthAttachmentDescriptorRef>) {
        unsafe {
            msg_send![self, setDepthAttachment:depth_attachment]
        }
    }

    pub fn stencil_attachment(&self) -> Option<&RenderPassStencilAttachmentDescriptorRef> {
        unsafe {
            msg_send![self, stencilAttachment]
        }
    }

    pub fn set_stencil_attachment(&self, stencil_attachment: Option<&RenderPassStencilAttachmentDescriptorRef>) {
        unsafe {
            msg_send![self, setStencilAttachment:stencil_attachment]
        }
    }

    pub fn visibility_result_buffer(&self) -> Option<&BufferRef> {
        unsafe {
            msg_send![self, visibilityResultBuffer]
        }
    }

    pub fn render_target_array_length(&self) -> NSUInteger {
        unsafe {
            msg_send![self, renderTargetArrayLength]
        }
    }

    pub fn set_render_target_array_length(&self, length: NSUInteger) {
        unsafe {
            msg_send![self, setRenderTargetArrayLength:length]
        }
    }
}
<commit_msg>Fix Clone derive on MTLClearColor and others<commit_after>// Copyright 2016 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use super::*;

use objc::runtime::Class;
use cocoa::foundation::NSUInteger;

#[repr(u64)]
#[derive(Clone, Debug)]
pub enum MTLLoadAction {
    DontCare = 0,
    Load = 1,
    Clear = 2,
}

#[repr(u64)]
#[derive(Clone, Debug)]
pub enum MTLStoreAction {
    DontCare = 0,
    Store = 1,
    MultisampleResolve = 2,
}

#[repr(C)]
#[derive(Clone, Debug)]
pub struct MTLClearColor {
    red: f64,
    green: f64,
    blue: f64,
    alpha: f64
}

impl MTLClearColor {
    #[inline]
    pub fn new(red: f64, green: f64, blue: f64, alpha: f64) -> Self {
        MTLClearColor {
            red: red,
            green: green,
            blue: blue,
            alpha: alpha
        }
    }
}

pub enum MTLRenderPassAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassAttachmentDescriptor;
    pub struct RenderPassAttachmentDescriptor;
    pub struct RenderPassAttachmentDescriptorRef;
}

impl RenderPassAttachmentDescriptorRef {
    pub fn texture(&self) -> Option<&TextureRef> {
        unsafe {
            msg_send![self, texture]
        }
    }

    pub fn set_texture(&self, texture: Option<&TextureRef>) {
        unsafe {
            msg_send![self, setTexture:texture];
        }
    }

    pub fn level(&self) -> NSUInteger {
        unsafe {
            msg_send![self, level]
        }
    }

    pub fn set_level(&self, level: NSUInteger) {
        unsafe {
            msg_send![self, setLevel:level]
        }
    }

    pub fn slice(&self) -> NSUInteger {
        unsafe {
            msg_send![self, slice]
        }
    }

    pub fn set_slice(&self, slice: NSUInteger) {
        unsafe {
            msg_send![self, setSlice:slice]
        }
    }

    pub fn depth_plane(&self) -> NSUInteger {
        unsafe {
            msg_send![self, depthPlane]
        }
    }

    pub fn set_depth_plane(&self, depth_plane: NSUInteger) {
        unsafe {
            msg_send![self, setDepthPlane:depth_plane]
        }
    }

    pub fn resolve_texture(&self) -> Option<&TextureRef> {
        unsafe {
            msg_send![self, resolveTexture]
        }
    }

    pub fn set_resolve_texture(&self, resolve_texture: Option<&TextureRef>) {
        unsafe {
            msg_send![self, setResolveTexture:resolve_texture]
        }
    }

    pub fn resolve_level(&self) -> NSUInteger {
        unsafe {
            msg_send![self, resolveLevel]
        }
    }

    pub fn set_resolve_level(&self, resolve_level: NSUInteger) {
        unsafe {
            msg_send![self, setResolveLevel:resolve_level]
        }
    }

    pub fn resolve_slice(&self) -> NSUInteger {
        unsafe {
            msg_send![self, resolveSlice]
        }
    }

    pub fn set_resolve_slice(&self, resolve_slice: NSUInteger) {
        unsafe {
            msg_send![self, setResolveSlice:resolve_slice]
        }
    }

    pub fn resolve_depth_plane(&self) -> NSUInteger {
        unsafe {
            msg_send![self, resolveDepthPlane]
        }
    }

    pub fn set_resolve_depth_plane(&self, resolve_depth_plane: NSUInteger) {
        unsafe {
            msg_send![self, setResolveDepthPlane:resolve_depth_plane]
        }
    }

    pub fn load_action(&self) -> MTLLoadAction {
        unsafe {
            msg_send![self, loadAction]
        }
    }

    pub fn set_load_action(&self, load_action: MTLLoadAction) {
        unsafe {
            msg_send![self, setLoadAction:load_action]
        }
    }

    pub fn store_action(&self) -> MTLStoreAction {
        unsafe {
            msg_send![self, storeAction]
        }
    }

    pub fn set_store_action(&self, store_action: MTLStoreAction) {
        unsafe {
            msg_send![self, setStoreAction:store_action]
        }
    }
}

pub enum MTLRenderPassColorAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassColorAttachmentDescriptor;
    pub struct RenderPassColorAttachmentDescriptor;
    pub struct RenderPassColorAttachmentDescriptorRef;
    type ParentType = RenderPassAttachmentDescriptorRef;
}

impl RenderPassColorAttachmentDescriptor {
    pub fn new() -> Self {
        unsafe {
            let class = Class::get("MTLRenderPassColorAttachmentDescriptor").unwrap();
            msg_send![class, new]
        }
    }
}

impl RenderPassColorAttachmentDescriptorRef {
    pub fn clear_color(&self) -> MTLClearColor {
        unsafe {
            msg_send![self, clearColor]
        }
    }

    pub fn set_clear_color(&self, clear_color: MTLClearColor) {
        unsafe {
            msg_send![self, setClearColor:clear_color]
        }
    }
}

pub enum MTLRenderPassDepthAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassDepthAttachmentDescriptor;
    pub struct RenderPassDepthAttachmentDescriptor;
    pub struct RenderPassDepthAttachmentDescriptorRef;
    type ParentType = RenderPassAttachmentDescriptorRef;
}

impl RenderPassDepthAttachmentDescriptorRef {
    pub fn clear_depth(&self) -> f64 {
        unsafe {
            msg_send![self, clearDepth]
        }
    }

    pub fn set_clear_depth(&self, clear_depth: f64) {
        unsafe {
            msg_send![self, setClearDepth:clear_depth]
        }
    }
}

pub enum MTLRenderPassStencilAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassStencilAttachmentDescriptor;
    pub struct RenderPassStencilAttachmentDescriptor;
    pub struct RenderPassStencilAttachmentDescriptorRef;
    type ParentType = RenderPassAttachmentDescriptorRef;
}

impl RenderPassStencilAttachmentDescriptorRef {
    pub fn clear_stencil(&self) -> u32 {
        unsafe {
            msg_send![self, clearStencil]
        }
    }

    pub fn set_clear_stencil(&self, clear_stencil: u32) {
        unsafe {
            msg_send![self, setClearStencil:clear_stencil]
        }
    }
}

pub enum MTLRenderPassColorAttachmentDescriptorArray {}

foreign_obj_type! {
    type CType = MTLRenderPassColorAttachmentDescriptorArray;
    pub struct RenderPassColorAttachmentDescriptorArray;
    pub struct RenderPassColorAttachmentDescriptorArrayRef;
}

impl RenderPassColorAttachmentDescriptorArrayRef {
    pub fn object_at(&self, index: usize) -> Option<&RenderPassColorAttachmentDescriptorRef> {
        unsafe {
            msg_send![self, objectAtIndexedSubscript:index]
        }
    }

    pub fn set_object_at(&self, index: usize, attachment: Option<&RenderPassColorAttachmentDescriptorRef>) {
        unsafe {
            msg_send![self, setObject:attachment
                     atIndexedSubscript:index]
        }
    }
}

pub enum MTLRenderPassDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPassDescriptor;
    pub struct RenderPassDescriptor;
    pub struct RenderPassDescriptorRef;
}

impl RenderPassDescriptor {
    pub fn new<'a>() -> &'a RenderPassDescriptorRef {
        unsafe {
            let class = Class::get("MTLRenderPassDescriptorInternal").unwrap();
            msg_send![class, renderPassDescriptor]
        }
    }
}

impl RenderPassDescriptorRef {
    pub fn color_attachments(&self) -> &RenderPassColorAttachmentDescriptorArrayRef {
        unsafe {
            msg_send![self, colorAttachments]
        }
    }

    pub fn depth_attachment(&self) -> Option<&RenderPassDepthAttachmentDescriptorRef> {
        unsafe {
            msg_send![self, depthAttachment]
        }
    }

    pub fn set_depth_attachment(&self, depth_attachment: Option<&RenderPassDepthAttachmentDescriptorRef>) {
        unsafe {
            msg_send![self, setDepthAttachment:depth_attachment]
        }
    }

    pub fn stencil_attachment(&self) -> Option<&RenderPassStencilAttachmentDescriptorRef> {
        unsafe {
            msg_send![self, stencilAttachment]
        }
    }

    pub fn set_stencil_attachment(&self, stencil_attachment: Option<&RenderPassStencilAttachmentDescriptorRef>) {
        unsafe {
            msg_send![self, setStencilAttachment:stencil_attachment]
        }
    }

    pub fn visibility_result_buffer(&self) -> Option<&BufferRef> {
        unsafe {
            msg_send![self, visibilityResultBuffer]
        }
    }

    pub fn render_target_array_length(&self) -> NSUInteger {
        unsafe {
            msg_send![self, renderTargetArrayLength]
        }
    }

    pub fn set_render_target_array_length(&self, length: NSUInteger) {
        unsafe {
            msg_send![self, setRenderTargetArrayLength:length]
        }
    }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Repeat_a_string

#[test]
fn check_repeat() {
    assert!("ha".repeat(5).as_slice() == "hahahahaha");
}<commit_msg>add main to repeat_str<commit_after>// http://rosettacode.org/wiki/Repeat_a_string

#[cfg(not(test))]
fn main() {
    println!("{}", "ha".repeat(5).as_slice());
}

#[test]
fn check_repeat() {
    assert!("ha".repeat(5).as_slice() == "hahahahaha");
}
<|endoftext|>


<commit_before>use crate::aabb::AABB;
use crate::pt_renderer::{Intersect, Ray};
use crate::stats;
use crate::triangle::RTTriangle;

pub struct BVHNode {
    aabb: AABB,
    pub start_i: usize,
    pub end_i: usize,
    left_child_i: Option<usize>,
    right_child_i: Option<usize>,
}

impl BVHNode {
    fn new(triangles: &[RTTriangle], start_i: usize, end_i: usize) -> BVHNode {
        let mut node = BVHNode {
            aabb: AABB::from_triangles(&triangles[start_i..end_i]),
            start_i,
            end_i,
            left_child_i: None,
            right_child_i: None,
        };
        for tri in triangles[(start_i + 1)..end_i].iter() {
            node.aabb.add_aabb(&tri.aabb());
        }
        node
    }

    fn n_tris(&self) -> usize {
        self.end_i - self.start_i
    }

    pub fn is_leaf(&self) -> bool {
        self.left_child_i.is_none()
    }
}

impl Intersect<'_, f32> for BVHNode {
    fn intersect(&self, ray: &Ray) -> Option<f32> {
        self.aabb.intersect(ray)
    }
}

const MAX_LEAF_SIZE: usize = 8;

#[allow(dead_code)]
#[derive(Clone, Copy)]
pub enum SplitMode {
    Object,
    Spatial,
    SAH,
}

pub struct BVH {
    nodes: Vec<BVHNode>,
}

impl BVH {
    pub fn empty() -> BVH {
        BVH { nodes: Vec::new() }
    }

    pub fn build(triangles: &mut Vec<RTTriangle>, split_mode: SplitMode) -> BVH {
        stats::start_bvh();
        let bvh = match split_mode {
            SplitMode::Object => build_object_median(triangles),
            SplitMode::Spatial => build_spatial_median(triangles),
            SplitMode::SAH => build_sah(triangles),
        };
        stats::stop_bvh(&bvh);
        bvh
    }

    pub fn get_children(&self, node: &BVHNode) -> Option<(&BVHNode, &BVHNode)> {
        if let Some(left_i) = node.left_child_i {
            Some((
                &self.nodes[left_i],
                &self.nodes[node.right_child_i.unwrap()],
            ))
        } else {
            None
        }
    }

    pub fn root(&self) -> &BVHNode {
        &self.nodes[0]
    }

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

    pub fn n_tris(&self) -> usize {
        self.root().n_tris()
    }
}

fn build_object_median(triangles: &mut Vec<RTTriangle>) -> BVH {
    let mut nodes = Vec::with_capacity(f32::log2(triangles.len() as f32) as usize);
    nodes.push(BVHNode::new(triangles, 0, triangles.len()));
    let mut split_stack = vec![0usize];

    while let Some(node_i) = split_stack.pop() {
        let start_i = nodes[node_i].start_i;
        let end_i = nodes[node_i].end_i;
        let axis_i = nodes[node_i].aabb.longest_edge_i();
        triangles[start_i..end_i].sort_unstable_by(|tri1, tri2| {
            let c1 = tri1.center()[axis_i];
            let c2 = tri2.center()[axis_i];
            c1.partial_cmp(&c2).unwrap()
        });
        let mid_i = (start_i + end_i) / 2;

        let left_child = BVHNode::new(triangles, start_i, mid_i);
        nodes[node_i].left_child_i = Some(nodes.len());
        if left_child.n_tris() > MAX_LEAF_SIZE {
            split_stack.push(nodes.len());
        }
        nodes.push(left_child);

        let right_child = BVHNode::new(triangles, mid_i, end_i);
        nodes[node_i].right_child_i = Some(nodes.len());
        if right_child.n_tris() > MAX_LEAF_SIZE {
            split_stack.push(nodes.len());
        }
        nodes.push(right_child);
    }
    nodes.shrink_to_fit();
    BVH { nodes }
}

fn build_spatial_median(triangles: &mut Vec<RTTriangle>) -> BVH {
    let mut nodes = Vec::with_capacity(f32::log2(triangles.len() as f32) as usize);
    nodes.push(BVHNode::new(triangles, 0, triangles.len()));
    let mut split_stack = vec![0usize];

    while let Some(node_i) = split_stack.pop() {
        let start_i = nodes[node_i].start_i;
        let end_i = nodes[node_i].end_i;
        let axis_i = nodes[node_i].aabb.longest_edge_i();
        triangles[start_i..end_i].sort_unstable_by(|tri1, tri2| {
            let c1 = tri1.center()[axis_i];
            let c2 = tri2.center()[axis_i];
            c1.partial_cmp(&c2).unwrap()
        });
        let mid_offset = find_spatial_median(&triangles[start_i..end_i], axis_i);
        let mid_i = start_i + mid_offset;

        let left_child = BVHNode::new(triangles, start_i, mid_i);
        nodes[node_i].left_child_i = Some(nodes.len());
        if left_child.n_tris() > MAX_LEAF_SIZE {
            split_stack.push(nodes.len());
        }
        nodes.push(left_child);

        let right_child = BVHNode::new(triangles, mid_i, end_i);
        nodes[node_i].right_child_i = Some(nodes.len());
        if right_child.n_tris() > MAX_LEAF_SIZE {
            split_stack.push(nodes.len());
        }
        nodes.push(right_child);
    }
    nodes.shrink_to_fit();
    BVH { nodes }
}

fn build_sah(triangles: &mut Vec<RTTriangle>) -> BVH {
    let mut nodes = Vec::with_capacity(f32::log2(triangles.len() as f32) as usize);
    nodes.push(BVHNode::new(triangles, 0, triangles.len()));
    let mut split_stack = vec![0usize];

    while let Some(node_i) = split_stack.pop() {
        let start_i = nodes[node_i].start_i;
        let end_i = nodes[node_i].end_i;
        let mid_i = if let Some(offset) = find_sah_split(&mut triangles[start_i..end_i]) {
            start_i + offset
        } else {
            continue;
        };

        let left_child = BVHNode::new(triangles, start_i, mid_i);
        nodes[node_i].left_child_i = Some(nodes.len());
        if left_child.n_tris() > MAX_LEAF_SIZE {
            split_stack.push(nodes.len());
        }
        nodes.push(left_child);

        let right_child = BVHNode::new(triangles, mid_i, end_i);
        nodes[node_i].right_child_i = Some(nodes.len());
        if right_child.n_tris() > MAX_LEAF_SIZE {
            split_stack.push(nodes.len());
        }
        nodes.push(right_child);
    }
    nodes.shrink_to_fit();
    BVH { nodes }
}

fn find_spatial_median(triangles: &[RTTriangle], axis_i: usize) -> usize {
    let min_val = triangles.first().unwrap().center()[axis_i];
    let max_val = triangles.last().unwrap().center()[axis_i];
    let mid_val = (max_val + min_val) / 2.0;
    let i = triangles
        .iter()
        .position(|ref tri| tri.center()[axis_i] > mid_val)
        .unwrap_or(0);
    // Use object median if all centers are on one side of the median
    if i == 0 {
        triangles.len() / 2
    } else {
        i
    }
}

fn find_sah_split(triangles: &mut [RTTriangle]) -> Option<usize> {
    let mut min_score = std::f32::MAX;
    let mut min_axis = 0;
    let mut min_i = 0;
    for axis in 0..3 {
        triangles.sort_unstable_by(|tri1, tri2| {
            let c1 = tri1.center()[axis];
            let c2 = tri2.center()[axis];
            c1.partial_cmp(&c2).unwrap()
        });
        let mut right_bbs = Vec::with_capacity(triangles.len());
        right_bbs.push(triangles.last().unwrap().aabb());
        for i in 1..triangles.len() {
            let mut new_bb = right_bbs[i - 1].clone();
            new_bb.add_aabb(&triangles[triangles.len() - 1 - i].aabb());
            right_bbs.push(new_bb);
        }
        let mut left_bb = AABB::empty();
        for i in 0..triangles.len() {
            left_bb.add_aabb(&triangles[i].aabb());
            let right_bb = &right_bbs[right_bbs.len() - 1 - i];
            let score = i as f32 * left_bb.area() + (triangles.len() - i) as f32 * right_bb.area();
            if score < min_score {
                min_score = score;
                min_axis = axis;
                min_i = i;
            }
        }
    }
    if min_i == 0 {
        None
    } else {
        if min_axis != 2 {
            triangles.sort_unstable_by(|tri1, tri2| {
                let c1 = tri1.center()[min_axis];
                let c2 = tri2.center()[min_axis];
                c1.partial_cmp(&c2).unwrap()
            });
        }
        Some(min_i)
    }
}
<commit_msg>Combine BVH builders<commit_after>use crate::aabb::AABB;
use crate::pt_renderer::{Intersect, Ray};
use crate::stats;
use crate::triangle::RTTriangle;

pub struct BVHNode {
    aabb: AABB,
    pub start_i: usize,
    pub end_i: usize,
    left_child_i: Option<usize>,
    right_child_i: Option<usize>,
}

impl BVHNode {
    fn new(triangles: &[RTTriangle], start_i: usize, end_i: usize) -> BVHNode {
        let mut node = BVHNode {
            aabb: AABB::from_triangles(&triangles[start_i..end_i]),
            start_i,
            end_i,
            left_child_i: None,
            right_child_i: None,
        };
        for tri in triangles[(start_i + 1)..end_i].iter() {
            node.aabb.add_aabb(&tri.aabb());
        }
        node
    }

    fn n_tris(&self) -> usize {
        self.end_i - self.start_i
    }

    pub fn is_leaf(&self) -> bool {
        self.left_child_i.is_none()
    }
}

impl Intersect<'_, f32> for BVHNode {
    fn intersect(&self, ray: &Ray) -> Option<f32> {
        self.aabb.intersect(ray)
    }
}

const MAX_LEAF_SIZE: usize = 8;

#[allow(dead_code)]
#[derive(Clone, Copy)]
pub enum SplitMode {
    Object,
    Spatial,
    SAH,
}

pub struct BVH {
    nodes: Vec<BVHNode>,
}

impl BVH {
    pub fn empty() -> BVH {
        BVH { nodes: Vec::new() }
    }

    pub fn build(triangles: &mut Vec<RTTriangle>, split_mode: SplitMode) -> BVH {
        stats::start_bvh();
        let mut nodes = Vec::with_capacity(f32::log2(triangles.len() as f32) as usize);
        nodes.push(BVHNode::new(triangles, 0, triangles.len()));
        let mut split_stack = vec![0usize];

        while let Some(node_i) = split_stack.pop() {
            let start_i = nodes[node_i].start_i;
            let end_i = nodes[node_i].end_i;
            let mid_offset = match split_mode {
                SplitMode::Object => {
                    let axis_i = nodes[node_i].aabb.longest_edge_i();
                    triangles[start_i..end_i].sort_unstable_by(|tri1, tri2| {
                        let c1 = tri1.center()[axis_i];
                        let c2 = tri2.center()[axis_i];
                        c1.partial_cmp(&c2).unwrap()
                    });
                    object_split(&triangles[start_i..end_i])
                }
                SplitMode::Spatial => {
                    let axis_i = nodes[node_i].aabb.longest_edge_i();
                    triangles[start_i..end_i].sort_unstable_by(|tri1, tri2| {
                        let c1 = tri1.center()[axis_i];
                        let c2 = tri2.center()[axis_i];
                        c1.partial_cmp(&c2).unwrap()
                    });
                    spatial_split(&triangles[start_i..end_i], axis_i)
                }
                SplitMode::SAH => {
                    sah_split(&mut triangles[start_i..end_i])
                }
            };
            let mid_i = if let Some(offset) = mid_offset {
                start_i + offset
            } else {
                continue;
            };

            let left_child = BVHNode::new(triangles, start_i, mid_i);
            nodes[node_i].left_child_i = Some(nodes.len());
            if left_child.n_tris() > MAX_LEAF_SIZE {
                split_stack.push(nodes.len());
            }
            nodes.push(left_child);

            let right_child = BVHNode::new(triangles, mid_i, end_i);
            nodes[node_i].right_child_i = Some(nodes.len());
            if right_child.n_tris() > MAX_LEAF_SIZE {
                split_stack.push(nodes.len());
            }
            nodes.push(right_child);
        }
        nodes.shrink_to_fit();
        let bvh = BVH { nodes };
        stats::stop_bvh(&bvh);
        bvh
    }

    pub fn get_children(&self, node: &BVHNode) -> Option<(&BVHNode, &BVHNode)> {
        if let Some(left_i) = node.left_child_i {
            Some((
                &self.nodes[left_i],
                &self.nodes[node.right_child_i.unwrap()],
            ))
        } else {
            None
        }
    }

    pub fn root(&self) -> &BVHNode {
        &self.nodes[0]
    }

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

    pub fn n_tris(&self) -> usize {
        self.root().n_tris()
    }
}

fn object_split(triangles: &[RTTriangle]) -> Option<usize> {
    Some(triangles.len() / 2)
}

fn spatial_split(triangles: &[RTTriangle], axis_i: usize) -> Option<usize> {
    let min_val = triangles.first().unwrap().center()[axis_i];
    let max_val = triangles.last().unwrap().center()[axis_i];
    let mid_val = (max_val + min_val) / 2.0;
    // TODO: this could use binary search
    let i = triangles
        .iter()
        .position(|ref tri| tri.center()[axis_i] > mid_val)
        .unwrap_or(0);
    // Use object median if all centers are on one side of the median
    if i == 0 {
        object_split(triangles)
    } else {
        Some(i)
    }
}

fn sah_split(triangles: &mut [RTTriangle]) -> Option<usize> {
    let mut min_score = std::f32::MAX;
    let mut min_axis = 0;
    let mut min_i = 0;
    for axis in 0..3 {
        triangles.sort_unstable_by(|tri1, tri2| {
            let c1 = tri1.center()[axis];
            let c2 = tri2.center()[axis];
            c1.partial_cmp(&c2).unwrap()
        });
        let mut right_bbs = Vec::with_capacity(triangles.len());
        right_bbs.push(triangles.last().unwrap().aabb());
        for i in 1..triangles.len() {
            let mut new_bb = right_bbs[i - 1].clone();
            new_bb.add_aabb(&triangles[triangles.len() - 1 - i].aabb());
            right_bbs.push(new_bb);
        }
        let mut left_bb = AABB::empty();
        for i in 0..triangles.len() {
            left_bb.add_aabb(&triangles[i].aabb());
            let right_bb = &right_bbs[right_bbs.len() - 1 - i];
            let score = i as f32 * left_bb.area() + (triangles.len() - i) as f32 * right_bb.area();
            if score < min_score {
                min_score = score;
                min_axis = axis;
                min_i = i;
            }
        }
    }
    if min_i == 0 {
        None
    } else {
        if min_axis != 2 {
            triangles.sort_unstable_by(|tri1, tri2| {
                let c1 = tri1.center()[min_axis];
                let c2 = tri2.center()[min_axis];
                c1.partial_cmp(&c2).unwrap()
            });
        }
        Some(min_i)
    }
}
<|endoftext|>


<commit_before>use std::collections::{BTreeSet, BTreeMap};
use std::fmt;

type Terminal = char;
type TerminalSet = BTreeSet<Terminal>;
type NonTerminal = char;
type NonTerminalSet = BTreeSet<NonTerminal>;

#[derive(Clone, Debug)]
enum TNT {
    T(Terminal),
    NT(NonTerminal),
    Lambda,
}

type Derivation = Vec<TNT>;
type DerivationVec = Vec<Derivation>;

type Productions<T> = Vec<(NonTerminal, T)>;
type ProductionsMap = BTreeMap<NonTerminal, DerivationVec>;

#[derive(Clone, Debug)]
struct CFG {
    vn: NonTerminalSet,
    vt: TerminalSet,
    p: ProductionsMap,
    s: NonTerminal,
}

impl CFG {
    pub fn new<T: Into<String>>(vn: NonTerminalSet, vt: TerminalSet, p: Productions<T>, s: NonTerminal) -> CFG {
        let mut p_map: ProductionsMap = BTreeMap::new();

        // TODO: this assumes terminals and non terminals can never have the same
        // letter, but doesnot check it
        // TODO: check if vn and vt are effectively disjoint
        for (nt, der_str) in p {
            let mut dervec: DerivationVec = {
                if let Some(dervec) = p_map.get(&nt) {
                    dervec.clone()
                } else {
                    vec!()
                }
            };

            let mut der: Derivation = vec!();

            let der_string = der_str.into();

            if der_string.len() == 0 {
                der.push(TNT::Lambda);
            }

            for c in der_string.chars() {
                println!("c {:?}", c);
                if vn.contains(&c) {
                    println!("vn {:?}", c);
                    der.push( TNT::NT(c.clone()) );
                    continue
                }

                if vt.contains(&c) {
                    der.push( TNT::T(c.clone()) );
                    continue
                }

                panic!("Char in derivation does not belong to VN or VT {:?}", c);
            }

            dervec.push(der);
            p_map.insert(nt.clone(), dervec);
        }

        CFG {
            vn: vn,
            vt: vt,
            p: p_map,
            s: s,
        }
    }
}

impl fmt::Display for CFG {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "\n\n").unwrap();
        write!(f, "Context Free Grammar \n").unwrap();
        write!(f, "==================== \n").unwrap();
        write!(f, "VN: {:?} \n", self.vn).unwrap();
        write!(f, "VT: {:?} \n", self.vt).unwrap();
        write!(f, "S: {:?} \n", self.s).unwrap();
        write!(f, "Productions: \n").unwrap();
        for (nt, dervec) in &self.p {
            for der in dervec {
                let mut der_string = String::new();
                for e in der {
                    match *e {
                        TNT::T(t) => der_string.push(t),
                        TNT::NT(nt) => der_string.push(nt),
                        _ => {},
                    }
                }
                write!(f, "{:?} -> {:?} \n", nt, der_string).unwrap();
            }
        }

        write!(f, "\n")
    }
}

// TODO work on the tree impl
//
//struct Tree {
    //root: NonTerminal,
    //children: Vec<Terminal U NonTerminal U Lambda U Tree?>
//}

// 2nd iteration of tree
//struct Node {
    //val: NonTerminal or Terminal or Lambda,
    //children: Option<Node>
//}

//fn tree(cfg: CFG, nt: NonTerminal) -> Tree {
    //TODO
    //Creates a single level derivation tree for the given nonterminal
    //in the given cfg
//}

#[cfg(test)]
mod tests {
    #[test]
    fn cfg_new_test() {

        use super::{CFG, NonTerminalSet, TerminalSet, NonTerminal, Productions};

        let vn: NonTerminalSet = charset!('S');
        let vt: TerminalSet = charset!('a', '(', ')');
        let s: NonTerminal = 'S';
        let p: Productions<&'static str> = vec!(
            ('S', "(S)" ),
            ('S', "a" )
        );

        let g = CFG::new(vt, vn, p, s);
        println!("Resulted grammar {}", g);
    }
}
<commit_msg>cfg: 2nd iteration<commit_after>use std::collections::{BTreeSet, BTreeMap};
use std::fmt;

type Terminal = char;
type TerminalSet = BTreeSet<Terminal>;
type NonTerminal = char;
type NonTerminalSet = BTreeSet<NonTerminal>;

#[derive(Clone, Debug)]
enum TNT {
    T(Terminal),
    NT(NonTerminal),
    Lambda,
}

type Derivation = Vec<TNT>;
type DerivationVec = Vec<Derivation>;

type Productions<T> = Vec<(NonTerminal, T)>;
type ProductionsMap = BTreeMap<NonTerminal, DerivationVec>;

#[derive(Clone, Debug)]
struct CFG {
    vn: NonTerminalSet,
    vt: TerminalSet,
    p: ProductionsMap,
    s: NonTerminal,
}

// TODO:
// - handy function to print trees!
// - handy function to go from TNT -> Char
// - handy function to go from Derivation -> String

impl CFG {
    pub fn new<T: Into<String> + fmt::Debug>(vn: NonTerminalSet, vt: TerminalSet, p: Productions<T>, s: NonTerminal) -> CFG {
        let mut p_map: ProductionsMap = BTreeMap::new();

        if !vn.is_disjoint(&vt) {
            panic!("VN and VT must be disjoint.\nVN: {:?} \nVT: {:?}", vn, vt);
        }

        for (nt, der_str) in p {
            if !vn.contains(&nt) {
                panic!("NonTerminal in production rule does not belong to VN {:?} -> {:?} \n {:?}", nt, der_str, vn);
            }

            let dervec = p_map.entry(nt).or_insert(vec!());

            let mut der: Derivation = vec!();

            let der_string = der_str.into();

            if der_string.len() == 0 {
                der.push(TNT::Lambda);
            }

            for c in der_string.chars() {
                if vn.contains(&c) {
                    der.push( TNT::NT(c.clone()) );
                    continue
                }

                if vt.contains(&c) {
                    der.push( TNT::T(c.clone()) );
                    continue
                }

                panic!("Char in derivation {:?} -> {:?} does not belong to VN or VT {:?}", nt, der_string, c);
            }

            dervec.push(der);
        }

        CFG {
            vn: vn,
            vt: vt,
            p: p_map,
            s: s,
        }
    }

    pub fn get_nt_derivations(&self, nt: &NonTerminal) -> DerivationVec {
        //TODO: optimize the case where the nt is not found
        self.p.get(nt).unwrap().clone()
    }
}

impl fmt::Display for CFG {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "\n\n").unwrap();
        write!(f, "Context Free Grammar \n").unwrap();
        write!(f, "==================== \n").unwrap();
        write!(f, "VN: {:?} \n", self.vn).unwrap();
        write!(f, "VT: {:?} \n", self.vt).unwrap();
        write!(f, "S: {:?} \n", self.s).unwrap();
        write!(f, "Productions: \n").unwrap();
        for (nt, dervec) in &self.p {
            for der in dervec {
                let mut der_string = String::new();
                for e in der {
                    match *e {
                        TNT::T(t) => der_string.push(t),
                        TNT::NT(nt) => der_string.push(nt),
                        _ => {},
                    }
                }
                write!(f, "{:?} -> {:?} \n", nt, der_string).unwrap();
            }
        }

        write!(f, "\n")
    }
}

#[derive(Debug, Clone)]
struct TNode {
    val: TNT,
    children: Vec<TNode>
}

impl TNode {
    pub fn new(val: TNT, children: Vec<TNode>) -> TNode {
        TNode {
            val: val,
            children: children,
        }
    }

}

impl fmt::Display for TNode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

// Need to create a single derivation tree for... a single production rule like this
// A -> (A)
//TODO
//Creates a single level derivation tree for the given nonterminal
//in the given cfg
fn tree(nt: &NonTerminal, der: &Derivation) -> TNode {
    let mut children: Vec<TNode> = vec!();
    for e in der {
        let node = TNode::new(e.clone(), vec!());
        children.push(node);
    }
    // TODO: check if the nt is effectively a nonterminal or not
    let root = TNode::new(TNT::NT(nt.clone()), children);
    root
}

#[cfg(test)]
mod tests {
    #[test]
    fn cfg_new_test() {
        use super::{CFG, NonTerminalSet, TerminalSet, NonTerminal, Productions};

        let vn: NonTerminalSet = charset!('S');
        let vt: TerminalSet = charset!('a', '(', ')');
        let s: NonTerminal = 'S';
        let p: Productions<&'static str> = vec!(
            ('S', "(S)" ),
            ('S', "a" )
        );

        let g = CFG::new(vn, vt, p, s);
        println!("Resulted grammar {}", g);
    }

    #[test]
    fn tree_test() {
        use super::{TNT, tree};

        let der = vec!( TNT::T('('), TNT::NT('S'), TNT::T(')') );
        let t = tree(&'S', &der);
        println!("Resulted tree {}", t);
    }
}
<|endoftext|>


<commit_before>use getopts;

const USAGE: &'static str = "Usage: corectl [OPTIONS] COMMAND [COMMAND OPTIONS]

Commands:
    deploy      Deploy fleet units
    help        Output this help message
    version     Output corectl's version number";

pub fn run(args: Vec<String>) -> Result<String, String> {
    let mut options = getopts::Options::new();
    options.optflag("h", "help", "Output this help message");
    options.optflag("v", "version", "Output corectl's version number");
    let matches = match options.parse(args.iter().skip(1)) {
        Ok(matches) => matches,
        Err(fail) => return Err(fail.to_err_msg())
    };
    let usage = Ok(options.usage(USAGE));

    if matches.opt_present("v") {
        return version();
    } else if matches.opt_present("h") {
        return usage;
    }

    if matches.free.len() == 0 {
        return usage;
    }

    let command = matches.free[0].as_slice();

    match command {
        "version" => version(),
        "deploy" => deploy(matches.free.clone()),
        "help" => usage,
        unknown => { Err(format!("Unknown command: {}. Run `corectl` for help.", unknown)) }
    }
}

fn deploy(args: Vec<String>) -> Result<String, String> {
    Ok("Deployed stuff.".to_string())
}

fn version() -> Result<String, String> {
    Ok(env!("CARGO_PKG_VERSION").to_string())
}

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

    #[test]
    fn it_prints_help_with_no_args() {
        let output = run(vec!["corectl".to_string()]);

        assert!(output.unwrap().starts_with("Usage: corectl [OPTIONS] COMMAND [COMMAND OPTIONS]\n\nOptions:"));
    }
}
<commit_msg>Add tests for help/version command variants.<commit_after>use getopts;

pub const USAGE: &'static str = "Usage: corectl [OPTIONS] COMMAND [COMMAND OPTIONS]

Commands:
    deploy      Deploy fleet units
    help        Output this help message
    version     Output corectl's version number";

pub fn run(args: Vec<String>) -> Result<String, String> {
    let mut options = getopts::Options::new();
    options.optflag("h", "help", "Output this help message");
    options.optflag("v", "version", "Output corectl's version number");
    let matches = match options.parse(args.iter().skip(1)) {
        Ok(matches) => matches,
        Err(fail) => return Err(fail.to_err_msg())
    };
    let usage = Ok(options.usage(USAGE));

    if matches.opt_present("v") {
        return version();
    } else if matches.opt_present("h") {
        return usage;
    }

    if matches.free.len() == 0 {
        return usage;
    }

    let command = matches.free[0].as_slice();

    match command {
        "version" => version(),
        "deploy" => deploy(matches.free.clone()),
        "help" => usage,
        unknown => { Err(format!("Unknown command: {}. Run `corectl` for help.", unknown)) }
    }
}

fn deploy(args: Vec<String>) -> Result<String, String> {
    Ok("Deployed stuff.".to_string())
}

fn version() -> Result<String, String> {
    Ok(env!("CARGO_PKG_VERSION").to_string())
}

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

    #[test]
    fn it_prints_help_with_no_args() {
        let output = run(vec!["corectl".to_string()]);

        assert!(output.unwrap().starts_with(USAGE));
    }

    #[test]
    fn it_prints_help_with_help_command() {
        let output = run(vec!["corectl".to_string(), "help".to_string()]);

        assert!(output.unwrap().starts_with(USAGE));
    }

    #[test]
    fn it_prints_help_with_help_flag() {
        let output = run(vec!["corectl".to_string(), "--help".to_string()]);

        assert!(output.unwrap().starts_with(USAGE));
    }

    #[test]
    fn it_prints_help_with_h_flag() {
        let output = run(vec!["corectl".to_string(), "-h".to_string()]);

        assert!(output.unwrap().starts_with(USAGE));
    }

    #[test]
    fn it_prints_version_with_version_command() {
        let output = run(vec!["corectl".to_string(), "version".to_string()]);

        assert_eq!(output.unwrap(), env!("CARGO_PKG_VERSION"));
    }

    #[test]
    fn it_prints_version_with_version_flag() {
        let output = run(vec!["corectl".to_string(), "--version".to_string()]);

        assert_eq!(output.unwrap(), env!("CARGO_PKG_VERSION"));
    }

    #[test]
    fn it_prints_version_with_v_flag() {
        let output = run(vec!["corectl".to_string(), "-v".to_string()]);

        assert_eq!(output.unwrap(), env!("CARGO_PKG_VERSION"));
    }
}
<|endoftext|>