<commit_before>//! Provides a Vec-like container for large sizes that is split to blocks.

use std::fmt;
use std::ops;
use std::ops::{Range, RangeFrom, RangeTo, RangeFull};

use itertools;
use odds::vec::VecExt;

/// A generic trait over Rust's built types.
pub trait FromRange {
    #[inline(always)]
    #[doc(hidden)]
    fn from_range(&self, seg: &SplitVec) -> (usize, usize);
}

impl FromRange for RangeFull {
    #[inline(always)]
    fn from_range(&self, seg: &SplitVec) -> (usize, usize) {
        return (0, seg.len());
    }
}

impl FromRange for Range<usize> {
    #[inline(always)]
    fn from_range(&self, _: &SplitVec) -> (usize, usize) {
        return (self.start, self.end);
    }
}

impl FromRange for RangeFrom<usize> {
    #[inline(always)]
    fn from_range(&self, seg: &SplitVec) -> (usize, usize) {
        return (self.start, seg.len());
    }
}

impl FromRange for RangeTo<usize> {
    #[inline(always)]
    fn from_range(&self, _: &SplitVec) -> (usize, usize) {
        return (0, self.end);
    }
}

/// A Vec for large sizes split into smaller blocks.
///
/// Splits a large continuos memory into block sizes to allow insertion/deletion to have an
/// upper bound, based on the block size. It is implemented as a Vec of Vec's, where each Vec
/// has a m inimum and maximum block size. As data is inserted and deleted, from any location,
/// SplitVec will split up and merge the blocks to try and stay between those minimum and maximum
/// block sizes.
pub struct SplitVec {
    vecs: Vec<Vec<u8>>,
    length: usize,
}

#[derive(Copy, Clone)]
struct Index {
    outer: usize,
    inner: usize,
}

/// An iterator over SplitVec contents.
pub struct Items<'a> {
    seg: &'a SplitVec,
    index: Index,
    num_elem: Option<usize>,
}

/// A mutable iterator over SplitVec contents.
pub struct MutItems<'a> {
    seg: &'a mut SplitVec,
    index: Index,
    num_elem: Option<usize>,
}

/// An iterator over the blocks in SplitVec.
pub struct Slices<'a> {
    seg: &'a SplitVec,
    outer: usize,
}

static MIN_BLOCK_SIZE: usize = 1024 * 1024;
static MAX_BLOCK_SIZE: usize = 4 * 1024 * 1024;

impl SplitVec {
    /// Create a new, empty SplitVec
    pub fn new() -> SplitVec {
        SplitVec {
            vecs: Vec::new(),
            length: 0,
        }
    }

    /// Create a SplitVec by consuming a vec as the initial data vector
    pub fn from_vec(values: Vec<u8>) -> SplitVec {
        let len = values.len();
        SplitVec {
            vecs: vec![values],
            length: len,
        }
    }

    /// Create a SplitVec by copying in values from a slice
    pub fn from_slice(values: &[u8]) -> SplitVec {
        SplitVec {
            vecs: vec![values.into()],
            length: values.len(),
        }
    }

    /// Return the length.
    pub fn len(&self) -> usize {
        self.length
    }

    /// Update the saved length value so that the len func will be -O(1)
    fn calc_len(&mut self) {
        self.length = 0;
        for len in self.vecs.iter().map(|v| v.len()) {
            self.length += len
        }
    }

    /// Convert a global pos to a locall index
    fn pos_to_index(&self, pos: usize, for_insert: bool) -> Index {
        if pos == 0 {
            return Index { outer: 0, inner: 0 };
        }

        let mut cur_pos = pos;
        for (i, vec) in self.vecs.iter().enumerate() {
            if cur_pos < vec.len() || (for_insert && cur_pos == vec.len()) {
                return Index {
                    outer: i,
                    inner: cur_pos,
                }
            }
            cur_pos -= vec.len();
        }

        panic!("Position {} is out of bounds", pos);
    }

    /// Give an iterator over a given range
    pub fn iter_range<'a, R: FromRange>(&'a self, range: R) -> Items<'a> {
        let (from, to) = range.from_range(self);
        if to < from {
            panic!("to ({}) is smaller than from ({})!", to, from);
        }

        let idx = self.pos_to_index(from, false);
        Items {
            seg: self,
            index: idx,
            num_elem: Some(to - from),
        }
    }

    /// Give a mutable iterator over a given range
    pub fn mut_iter_range<'a, R: FromRange>(&'a mut self, range: R) -> MutItems<'a> {
        let (from, to) = range.from_range(self);
        if to < from {
            panic!("to ({}) is smaller than from ({})!", to, from);
        }

        let idx = self.pos_to_index(from, false);
        MutItems {
            seg: self,
            index: idx,
            num_elem: Some(to - from),
        }
    }

    /// Provide an iterator over continuous memory slices
    ///
    /// This is useful for doing an efficient save to disk
    pub fn iter_slices<'a>(&'a self) -> Slices<'a> {
        Slices {
            seg: self,
            outer: 0,
        }
    }

    /// Prepare an index for future text insertion, splitting/merging big/small sections respectively
    fn prepare_insert(&mut self, index: Index) -> Index {
        if index.outer >= self.vecs.len() {
            self.vecs.push(Vec::new());
        }

        if self.vecs[index.outer].len() < MAX_BLOCK_SIZE {
            return index;
        }

        let page_start_idx = (index.inner / MIN_BLOCK_SIZE) * MIN_BLOCK_SIZE;
        if page_start_idx == 0 {
            if self.vecs[index.outer].len() > MAX_BLOCK_SIZE {
                let insert_vec: Vec < _ >= self.vecs[index.outer][MIN_BLOCK_SIZE..].into();
                self.vecs.insert(index.outer + 1, insert_vec);
                self.vecs[index.outer].truncate(MIN_BLOCK_SIZE);
            }

            return index;
        } else {
            let insert_vec: Vec<_> = self.vecs[index.outer][page_start_idx..].into();
            self.vecs.insert(index.outer + 1, insert_vec);
            self.vecs[index.outer].truncate(page_start_idx);
            return self.prepare_insert(Index {
                outer: index.outer + 1,
                inner: index.inner - page_start_idx
            })
        }
    }

    /// insert all values from a slice at an offset.
    pub fn insert(&mut self, offset: usize, values: &[u8]) {
        let mut index = self.pos_to_index(offset, true);
        index = self.prepare_insert(index);

        // This is needed for the mut borrow vec
        {
            self.vecs[index.outer].splice(index.inner..index.inner, values.into_iter().cloned());
        }

        self.calc_len();
    }

    /// Moves data out from the supplied range.
    pub fn move_out<R: FromRange>(&mut self, range: R) -> Vec<u8> {
        let (from, to) = range.from_range(self);
        // TODO: Convert to drain when that settles
        assert!(from <= to);
        let mut res = Vec::new();
        let mut index = self.pos_to_index(from, false);
        let num_elem = to - from;

        for _ in 0..num_elem {
            let c = self.vecs[index.outer].remove(index.inner);
            res.push(c);

            if index.inner >= self.vecs[index.outer].len() {
                if self.vecs[index.outer].len() == 0 {
                    self.vecs.remove(index.outer);
                } else {
                    index.inner = 0;
                    index.outer += 1;
                }
            }
        }

        self.calc_len();

        res
    }

    /// Produce of copy of the supplied range
    pub fn copy_out<R: FromRange>(&mut self, range: R) -> Vec<u8> {
        let (from, to) = range.from_range(self);

        // TODO: Make this use direct cocpy rather than iterators
        self.iter_range(from..to).map(|x| *x).collect::<Vec<u8>>()
    }

    /// Copy data from a slice in.
    pub fn copy_in(&mut self, offset: usize, val: &[u8]) {
        for (s, d) in val.iter().zip(self.mut_iter_range(offset..(offset + val.len()))) {
            *d = s.clone();
        }
    }

    /// Replace values in range with the supplied values
    pub fn splice<R: FromRange>(&mut self, range: R, values: &[u8]) -> Vec<u8> {
        // TODO: This is terribly inefficient, will need a reimplementation
        let (from, to) = range.from_range(self);

        let res = self.move_out(from..to);
        self.insert(from, values);

        res
    }

    /// Find a slice.
    pub fn find_slice(&self, needle: &[u8]) -> Option<usize> {
        self.find_slice_from(0, needle)
    }

    /// Find a slice from a certain index and onward
    pub fn find_slice_from(&self, from: usize, needle: &[u8]) -> Option<usize> {
        for i in from..self.len() {
            if itertools::equal(self.iter_range(i..i+needle.len()), needle.iter()) {
                return Some(i);
            }
        }
        None
    }

    #[cfg(test)]
    fn get_lengths(&self) -> Vec<usize> {
        self.vecs.iter().map(|v| v.len()).collect::<Vec<usize>>()
    }
}

impl ops::Index<usize> for SplitVec {
    type Output = u8;
    fn index<'a>(&'a self, _index: usize) -> &'a u8 {
        let idx = self.pos_to_index(_index, false);
        &self.vecs[idx.outer][idx.inner]
    }
}

impl ops::IndexMut<usize> for SplitVec {
    fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut u8 {
        let idx = self.pos_to_index(_index, false);
        &mut self.vecs[idx.outer][idx.inner]
    }
}

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

impl<'a> Iterator for Items<'a> {
    type Item = &'a u8;
    fn next(&mut self) -> Option<&'a u8> {
        if self.index.outer >= self.seg.vecs.len() {
            return None;
        }
        if let Some(ref mut num_elem) = self.num_elem {
            if *num_elem <= 0 {
                return None;
            }
            *num_elem -= 1;
        }

        let elem = {
            let vv = &self.seg.vecs[self.index.outer];
            &vv[self.index.inner]
        };

        self.index.inner += 1;
        if self.index.inner >= self.seg.vecs[self.index.outer].len() {
            self.index.inner = 0;
            self.index.outer += 1;
        }

        Some(elem)
    }
}

impl<'a> Iterator for MutItems<'a> {
    type Item = &'a mut u8;
    fn next(&mut self) -> Option<&'a mut u8> {
        if self.index.outer >= self.seg.vecs.len() {
            return None;
        }
        if let Some(ref mut num_elem) = self.num_elem {
            if *num_elem <= 0 {
                return None;
            }
            *num_elem -= 1;
        }

        let elem_raw: *mut u8 = {
            let vv = &mut self.seg.vecs[self.index.outer];
            &mut vv[self.index.inner]
        };

        self.index.inner += 1;
        if self.index.inner >= self.seg.vecs[self.index.outer].len() {
            self.index.inner = 0;
            self.index.outer += 1;
        }

        Some(unsafe { &mut *elem_raw })
    }
}

impl<'a> Iterator for Slices<'a> {
    type Item = &'a [u8];
    fn next(&mut self) -> Option<&'a [u8]> {
        if self.outer >= self.seg.vecs.len() {
            None
        } else {
            let i = self.outer;
            self.outer += 1;
            Some(&self.seg.vecs[i])
        }
    }
}

#[test]
fn test_small_splitvec() {
    let size = 1024;
    let mut seg = SplitVec::from_vec(vec![1, 2, 3, 4, 5]);
    assert_eq!(Some(4), seg.find_slice(&[5]));

    let seg_len = seg.len();
    seg.insert(seg_len/2, &vec![1 as u8; size]);

    assert_eq!(Some(size + 4), seg.find_slice(&[5]));
}

#[test]
fn test_large_splitvec() {
    let big_size = 4*1024*1024;
    let small_size = 1024;
    let mut seg = SplitVec::from_vec(vec![0; big_size]);

    seg.insert(big_size/2, &vec![1 as u8; small_size]);

    assert_eq!(Some(big_size/2 -1), seg.find_slice(&[0, 1]));

    // Make sure we actually tested a "split" version
    let seg_lengths = seg.get_lengths();
    assert_eq!(2, seg_lengths.len());
    let index = seg_lengths[0];
    let sentinal = 100;
    seg[index] = sentinal;
    seg[index+1] = sentinal +1;
    assert_eq!(Some(index), seg.find_slice(&[sentinal, sentinal+1]));
}
<commit_msg>Bugfix to splice operation in case of splice going over the end<commit_after>//! Provides a Vec-like container for large sizes that is split to blocks.

use std::fmt;
use std::ops;
use std::ops::{Range, RangeFrom, RangeTo, RangeFull};
use std::cmp;

use itertools;
use odds::vec::VecExt;

/// A generic trait over Rust's built types.
pub trait FromRange {
    #[inline(always)]
    #[doc(hidden)]
    fn from_range(&self, seg: &SplitVec) -> (usize, usize);
}

impl FromRange for RangeFull {
    #[inline(always)]
    fn from_range(&self, seg: &SplitVec) -> (usize, usize) {
        return (0, seg.len());
    }
}

impl FromRange for Range<usize> {
    #[inline(always)]
    fn from_range(&self, _: &SplitVec) -> (usize, usize) {
        return (self.start, self.end);
    }
}

impl FromRange for RangeFrom<usize> {
    #[inline(always)]
    fn from_range(&self, seg: &SplitVec) -> (usize, usize) {
        return (self.start, seg.len());
    }
}

impl FromRange for RangeTo<usize> {
    #[inline(always)]
    fn from_range(&self, _: &SplitVec) -> (usize, usize) {
        return (0, self.end);
    }
}

/// A Vec for large sizes split into smaller blocks.
///
/// Splits a large continuos memory into block sizes to allow insertion/deletion to have an
/// upper bound, based on the block size. It is implemented as a Vec of Vec's, where each Vec
/// has a m inimum and maximum block size. As data is inserted and deleted, from any location,
/// SplitVec will split up and merge the blocks to try and stay between those minimum and maximum
/// block sizes.
pub struct SplitVec {
    vecs: Vec<Vec<u8>>,
    length: usize,
}

#[derive(Copy, Clone)]
struct Index {
    outer: usize,
    inner: usize,
}

/// An iterator over SplitVec contents.
pub struct Items<'a> {
    seg: &'a SplitVec,
    index: Index,
    num_elem: Option<usize>,
}

/// A mutable iterator over SplitVec contents.
pub struct MutItems<'a> {
    seg: &'a mut SplitVec,
    index: Index,
    num_elem: Option<usize>,
}

/// An iterator over the blocks in SplitVec.
pub struct Slices<'a> {
    seg: &'a SplitVec,
    outer: usize,
}

static MIN_BLOCK_SIZE: usize = 1024 * 1024;
static MAX_BLOCK_SIZE: usize = 4 * 1024 * 1024;

impl SplitVec {
    /// Create a new, empty SplitVec
    pub fn new() -> SplitVec {
        SplitVec {
            vecs: Vec::new(),
            length: 0,
        }
    }

    /// Create a SplitVec by consuming a vec as the initial data vector
    pub fn from_vec(values: Vec<u8>) -> SplitVec {
        let len = values.len();
        SplitVec {
            vecs: vec![values],
            length: len,
        }
    }

    /// Create a SplitVec by copying in values from a slice
    pub fn from_slice(values: &[u8]) -> SplitVec {
        SplitVec {
            vecs: vec![values.into()],
            length: values.len(),
        }
    }

    /// Return the length.
    pub fn len(&self) -> usize {
        self.length
    }

    /// Update the saved length value so that the len func will be -O(1)
    fn calc_len(&mut self) {
        self.length = 0;
        for len in self.vecs.iter().map(|v| v.len()) {
            self.length += len
        }
    }

    /// Convert a global pos to a locall index
    fn pos_to_index(&self, pos: usize, for_insert: bool) -> Index {
        if pos == 0 {
            return Index { outer: 0, inner: 0 };
        }

        let mut cur_pos = pos;
        for (i, vec) in self.vecs.iter().enumerate() {
            if cur_pos < vec.len() || (for_insert && cur_pos == vec.len()) {
                return Index {
                    outer: i,
                    inner: cur_pos,
                }
            }
            cur_pos -= vec.len();
        }

        panic!("Position {} is out of bounds", pos);
    }

    /// Give an iterator over a given range
    pub fn iter_range<'a, R: FromRange>(&'a self, range: R) -> Items<'a> {
        let (from, to) = range.from_range(self);
        if to < from {
            panic!("to ({}) is smaller than from ({})!", to, from);
        }

        let idx = self.pos_to_index(from, false);
        Items {
            seg: self,
            index: idx,
            num_elem: Some(to - from),
        }
    }

    /// Give a mutable iterator over a given range
    pub fn mut_iter_range<'a, R: FromRange>(&'a mut self, range: R) -> MutItems<'a> {
        let (from, to) = range.from_range(self);
        if to < from {
            panic!("to ({}) is smaller than from ({})!", to, from);
        }

        let idx = self.pos_to_index(from, false);
        MutItems {
            seg: self,
            index: idx,
            num_elem: Some(to - from),
        }
    }

    /// Provide an iterator over continuous memory slices
    ///
    /// This is useful for doing an efficient save to disk
    pub fn iter_slices<'a>(&'a self) -> Slices<'a> {
        Slices {
            seg: self,
            outer: 0,
        }
    }

    /// Prepare an index for future text insertion, splitting/merging big/small sections respectively
    fn prepare_insert(&mut self, index: Index) -> Index {
        if index.outer >= self.vecs.len() {
            self.vecs.push(Vec::new());
        }

        if self.vecs[index.outer].len() < MAX_BLOCK_SIZE {
            return index;
        }

        let page_start_idx = (index.inner / MIN_BLOCK_SIZE) * MIN_BLOCK_SIZE;
        if page_start_idx == 0 {
            if self.vecs[index.outer].len() > MAX_BLOCK_SIZE {
                let insert_vec: Vec < _ >= self.vecs[index.outer][MIN_BLOCK_SIZE..].into();
                self.vecs.insert(index.outer + 1, insert_vec);
                self.vecs[index.outer].truncate(MIN_BLOCK_SIZE);
            }

            return index;
        } else {
            let insert_vec: Vec<_> = self.vecs[index.outer][page_start_idx..].into();
            self.vecs.insert(index.outer + 1, insert_vec);
            self.vecs[index.outer].truncate(page_start_idx);
            return self.prepare_insert(Index {
                outer: index.outer + 1,
                inner: index.inner - page_start_idx
            })
        }
    }

    /// insert all values from a slice at an offset.
    pub fn insert(&mut self, offset: usize, values: &[u8]) {
        let mut index = self.pos_to_index(offset, true);
        index = self.prepare_insert(index);

        // This is needed for the mut borrow vec
        {
            self.vecs[index.outer].splice(index.inner..index.inner, values.into_iter().cloned());
        }

        self.calc_len();
    }

    /// Moves data out from the supplied range.
    pub fn move_out<R: FromRange>(&mut self, range: R) -> Vec<u8> {
        let (from, to) = range.from_range(self);
        // TODO: Convert to drain when that settles
        assert!(from <= to);
        let mut res = Vec::new();
        let mut index = self.pos_to_index(from, false);
        let num_elem = to - from;

        for _ in 0..num_elem {
            let c = self.vecs[index.outer].remove(index.inner);
            res.push(c);

            if index.inner >= self.vecs[index.outer].len() {
                if self.vecs[index.outer].len() == 0 {
                    self.vecs.remove(index.outer);
                } else {
                    index.inner = 0;
                    index.outer += 1;
                }
            }
        }

        self.calc_len();

        res
    }

    /// Produce of copy of the supplied range
    pub fn copy_out<R: FromRange>(&mut self, range: R) -> Vec<u8> {
        let (from, to) = range.from_range(self);

        // TODO: Make this use direct cocpy rather than iterators
        self.iter_range(from..to).map(|x| *x).collect::<Vec<u8>>()
    }

    /// Copy data from a slice in.
    pub fn copy_in(&mut self, offset: usize, val: &[u8]) {
        for (s, d) in val.iter().zip(self.mut_iter_range(offset..(offset + val.len()))) {
            *d = s.clone();
        }
    }

    /// Replace values in range with the supplied values
    pub fn splice<R: FromRange>(&mut self, range: R, values: &[u8]) -> Vec<u8> {
        // TODO: This is terribly inefficient, will need a reimplementation
        let (from, to) = range.from_range(self);
        let res;

        // Make sure that when we pull data out for the splice, we don't go over the end
        if from < self.len() {
            let move_end = cmp::min(self.len(), to);
            res = self.move_out(from..move_end);
        } else {
            res = vec![];
        }

        self.insert(from, values);

        res
    }

    /// Find a slice.
    pub fn find_slice(&self, needle: &[u8]) -> Option<usize> {
        self.find_slice_from(0, needle)
    }

    /// Find a slice from a certain index and onward
    pub fn find_slice_from(&self, from: usize, needle: &[u8]) -> Option<usize> {
        for i in from..self.len() {
            if itertools::equal(self.iter_range(i..i+needle.len()), needle.iter()) {
                return Some(i);
            }
        }
        None
    }

    #[cfg(test)]
    fn get_lengths(&self) -> Vec<usize> {
        self.vecs.iter().map(|v| v.len()).collect::<Vec<usize>>()
    }
}

impl ops::Index<usize> for SplitVec {
    type Output = u8;
    fn index<'a>(&'a self, _index: usize) -> &'a u8 {
        let idx = self.pos_to_index(_index, false);
        &self.vecs[idx.outer][idx.inner]
    }
}

impl ops::IndexMut<usize> for SplitVec {
    fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut u8 {
        let idx = self.pos_to_index(_index, false);
        &mut self.vecs[idx.outer][idx.inner]
    }
}

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

impl<'a> Iterator for Items<'a> {
    type Item = &'a u8;
    fn next(&mut self) -> Option<&'a u8> {
        if self.index.outer >= self.seg.vecs.len() {
            return None;
        }
        if let Some(ref mut num_elem) = self.num_elem {
            if *num_elem <= 0 {
                return None;
            }
            *num_elem -= 1;
        }

        let elem = {
            let vv = &self.seg.vecs[self.index.outer];
            &vv[self.index.inner]
        };

        self.index.inner += 1;
        if self.index.inner >= self.seg.vecs[self.index.outer].len() {
            self.index.inner = 0;
            self.index.outer += 1;
        }

        Some(elem)
    }
}

impl<'a> Iterator for MutItems<'a> {
    type Item = &'a mut u8;
    fn next(&mut self) -> Option<&'a mut u8> {
        if self.index.outer >= self.seg.vecs.len() {
            return None;
        }
        if let Some(ref mut num_elem) = self.num_elem {
            if *num_elem <= 0 {
                return None;
            }
            *num_elem -= 1;
        }

        let elem_raw: *mut u8 = {
            let vv = &mut self.seg.vecs[self.index.outer];
            &mut vv[self.index.inner]
        };

        self.index.inner += 1;
        if self.index.inner >= self.seg.vecs[self.index.outer].len() {
            self.index.inner = 0;
            self.index.outer += 1;
        }

        Some(unsafe { &mut *elem_raw })
    }
}

impl<'a> Iterator for Slices<'a> {
    type Item = &'a [u8];
    fn next(&mut self) -> Option<&'a [u8]> {
        if self.outer >= self.seg.vecs.len() {
            None
        } else {
            let i = self.outer;
            self.outer += 1;
            Some(&self.seg.vecs[i])
        }
    }
}

#[test]
fn test_small_splitvec() {
    let size = 1024;
    let mut seg = SplitVec::from_vec(vec![1, 2, 3, 4, 5]);
    assert_eq!(Some(4), seg.find_slice(&[5]));

    let seg_len = seg.len();
    seg.insert(seg_len/2, &vec![1 as u8; size]);

    assert_eq!(Some(size + 4), seg.find_slice(&[5]));
}

#[test]
fn test_large_splitvec() {
    let big_size = 4*1024*1024;
    let small_size = 1024;
    let mut seg = SplitVec::from_vec(vec![0; big_size]);

    seg.insert(big_size/2, &vec![1 as u8; small_size]);

    assert_eq!(Some(big_size/2 -1), seg.find_slice(&[0, 1]));

    // Make sure we actually tested a "split" version
    let seg_lengths = seg.get_lengths();
    assert_eq!(2, seg_lengths.len());
    let index = seg_lengths[0];
    let sentinal = 100;
    seg[index] = sentinal;
    seg[index+1] = sentinal +1;
    assert_eq!(Some(index), seg.find_slice(&[sentinal, sentinal+1]));
}
<|endoftext|>


<commit_before>use std::sync::atomic::{Ordering, AtomicU32};
use std::f32;

use failure::Error;
use parking_lot::Mutex;

use {clamp, Point2f, Point2i, Vector2f};
use bounds::{Bounds2f, Bounds2i};
use filter::Filter;
use imageio;
use paramset::ParamSet;
use spectrum::Spectrum;

const FILTER_SIZE: usize = 16;
const FILTER_TABLE_SIZE: usize = FILTER_SIZE * FILTER_SIZE;

stat_memory_counter!("Memory/Film pixels", film_pixel_memory);
pub fn init_stats() {
    film_pixel_memory::init();
}

#[derive(Default)]
struct AtomicFloat {
    bits: AtomicU32,
}

impl AtomicFloat {
    pub fn as_float(&self) -> f32 {
        f32::from_bits(self.bits.load(Ordering::Relaxed))
    }
}

#[derive(Default)]
struct Pixel {
    xyz: [f32; 3],
    filter_weight_sum: f32,
    splat_xyz: [AtomicFloat; 3],
    _pad: f32,
}

pub struct Film {
    pub full_resolution: Point2i,
    pub _diagonal: f32,
    pub filename: String,
    pub cropped_pixel_bounds: Bounds2i,
    pixels: Mutex<Vec<Pixel>>,
    filter_table: [f32; FILTER_TABLE_SIZE],
    filter_radius: Vector2f,
    scale: f32,
}

impl Film {
    pub fn new(resolution: Point2i,
               cropwindow: Bounds2f,
               filter: Box<Filter>,
               diagonal: f32,
               filename: &str,
               scale: f32)
               -> Film {
        let cropped_pixel_bounds =
            Bounds2i::from_points(&Point2i::new((resolution.x as f32 * cropwindow.p_min.x).ceil() as
                                                i32,
                                                (resolution.y as f32 * cropwindow.p_min.y).ceil() as
                                                i32),
                                  &Point2i::new((resolution.x as f32 * cropwindow.p_max.x).ceil() as
                                                i32,
                                                (resolution.y as f32 * cropwindow.p_max.y).ceil() as
                                                i32));

        info!("Created film with full resolution {}. Crop window of {} -> cropped_pixel_bounds {}",
              resolution,
              cropwindow,
              cropped_pixel_bounds);
        let mut pixels = Vec::with_capacity(cropped_pixel_bounds.area() as usize);
        pixels.resize_default(cropped_pixel_bounds.area() as usize);
        film_pixel_memory::add(cropped_pixel_bounds.area() as u64 *
                               ::std::mem::size_of::<Pixel>() as u64);
        let mut filter_table = [0f32; FILTER_TABLE_SIZE];

        let (xwidth, ywidth) = filter.width();
        // Fill in filter table
        for y in 0..FILTER_SIZE {
            let fy = (y as f32 + 0.5) * (ywidth / FILTER_SIZE as f32);
            for x in 0..FILTER_SIZE {
                let fx = (x as f32 + 0.5) * (xwidth / FILTER_SIZE as f32);
                filter_table[y * FILTER_SIZE + x] = filter.evaluate(fx, fy);
            }
        }

        Film {
            full_resolution: resolution,
            pixels: Mutex::new(pixels),
            filter_table: filter_table,
            filter_radius: Vector2f::new(xwidth, ywidth),
            cropped_pixel_bounds: cropped_pixel_bounds,
            scale: scale,
            _diagonal: diagonal * 0.001,
            filename: filename.to_owned(),
        }
    }

    pub fn create(ps: &mut ParamSet, filter: Box<Filter>) -> Box<Film> {
        let mut filename = ps.find_one_string("filename", "".into());
        if filename == "" {
            filename = "image.png".into();
        } else {
            filename = String::from("rt-") + &filename;
        }
        let xres = ps.find_one_int("xresolution", 1280);
        let yres = ps.find_one_int("yresolution", 720);
        let mut crop = Bounds2f::from_points(&Point2f::new(0.0, 0.0), &Point2f::new(1.0, 1.0));
        if let Some(cr) = ps.find_float("cropwindow") {
            if cr.len() == 4 {
                crop.p_min.x = clamp(f32::min(cr[0], cr[1]), 0.0, 1.0);
                crop.p_max.x = clamp(f32::max(cr[0], cr[1]), 0.0, 1.0);
                crop.p_min.y = clamp(f32::min(cr[2], cr[3]), 0.0, 1.0);
                crop.p_max.y = clamp(f32::max(cr[2], cr[3]), 0.0, 1.0);
            } else {
                warn!("\"cropwindow\" expected 4 values");
            }
        }
        let scale = ps.find_one_float("scale", 1.0);
        let diagonal = ps.find_one_float("diagonal", 35.0);
        // TODO max_sample_luminance
        Box::new(Film::new(Point2i::new(xres, yres),
                           crop,
                           filter,
                           diagonal,
                           &filename,
                           scale))
    }

    pub fn get_film_tile(&self, sample_bounds: &Bounds2i) -> FilmTile {
        let half_pixel = Vector2f::new(0.5, 0.5);
        let float_bounds: Bounds2f = (*sample_bounds).into();
        let float_cropped_pixel_bounds: Bounds2f = self.cropped_pixel_bounds.into();

        // This is a bit clunky but we need to do all the computations as floats as the numbers can
        // temporarily be negative which would cause u32 to wrap around.
        let p0 = ceil(float_bounds.p_min - half_pixel - self.filter_radius);
        let p1 = floor(float_bounds.p_max - half_pixel + self.filter_radius +
                       Vector2f::new(1.0, 1.0));
        let sample_extent_bounds = Bounds2f::from_points(&p0, &p1);

        let tile_pixel_bounds: Bounds2i =
            Bounds2i::from(Bounds2f::intersect(&sample_extent_bounds, &float_cropped_pixel_bounds));

        FilmTile::new(&tile_pixel_bounds, &self.filter_radius, &self.filter_table)
    }

    pub fn merge_film_tile(&self, tile: FilmTile) {
        let mut pixels = self.pixels.lock();
        for pixel in &tile.get_pixel_bounds() {
            let tile_pixel = tile.get_pixel(&pixel);
            let pidx = {
                let width = self.cropped_pixel_bounds.p_max.x - self.cropped_pixel_bounds.p_min.x;
                ((pixel.y - self.cropped_pixel_bounds.p_min.y) * width +
                 (pixel.x - self.cropped_pixel_bounds.p_min.x)) as usize
            };
            let xyz = tile_pixel.contrib_sum.to_xyz();
            for i in 0..3 {
                pixels[pidx].xyz[i] += xyz[i];
            }
            pixels[pidx].filter_weight_sum += tile_pixel.filter_weight_sum;
        }
    }

    pub fn write_image(&self) -> Result<(), Error> {
        info!("Converting image to RGB and computing final weighted pixel values");
        let splat_scale = 1.0; // TODO
        let pixels = self.pixels.lock();
        let mut rgb = Vec::with_capacity(3 * self.cropped_pixel_bounds.area() as usize);
        for p in &self.cropped_pixel_bounds {
            // Convert pixel XYZ color to RGB
            let pixel_idx = self.get_pixel_idx(&p);
            let pixel = &pixels[pixel_idx];
            let mut rgb_pixel = Spectrum::from_xyz(&pixel.xyz);

            // Normalize pixel with weight sum
            let filter_weight_sum = pixel.filter_weight_sum;
            if filter_weight_sum != 0.0 {
                let inv_wt = 1.0 / filter_weight_sum;
                rgb_pixel[0] = f32::max(0.0, rgb_pixel[0] * inv_wt);
                rgb_pixel[1] = f32::max(0.0, rgb_pixel[1] * inv_wt);
                rgb_pixel[2] = f32::max(0.0, rgb_pixel[2] * inv_wt);
            }

            let splat_xyz = [pixel.splat_xyz[0].as_float(),
                             pixel.splat_xyz[1].as_float(),
                             pixel.splat_xyz[2].as_float()];
            let mut splat_rgb = Spectrum::from_xyz(&splat_xyz);
            rgb_pixel[0] += splat_scale * splat_rgb[0];
            rgb_pixel[1] += splat_scale * splat_rgb[1];
            rgb_pixel[2] += splat_scale * splat_rgb[2];

            // Scale pixel value by scale
            rgb_pixel[0] *= self.scale;
            rgb_pixel[1] *= self.scale;
            rgb_pixel[2] *= self.scale;

            rgb.push(rgb_pixel[0]);
            rgb.push(rgb_pixel[1]);
            rgb.push(rgb_pixel[2]);
        }

        // Write RGB image
        info!("Writing image {} with bounds {}",
              self.filename,
              self.cropped_pixel_bounds);
        imageio::write_image(&self.filename,
                             &rgb[..],
                             &self.cropped_pixel_bounds,
                             &self.full_resolution)
    }

    pub fn get_sample_bounds(&self) -> Bounds2i {
        let half = Vector2f::new(0.5, 0.5);
        let float_bounds =
            Bounds2f::from_points(&floor(Point2f::from(self.cropped_pixel_bounds.p_min) + half -
                                         self.filter_radius),
                                  &ceil(Point2f::from(self.cropped_pixel_bounds.p_max) - half +
                                        self.filter_radius));

        float_bounds.into()
    }

    fn get_pixel_idx(&self, p: &Point2i) -> usize {
        assert!(self.cropped_pixel_bounds.inside_exclusive(p));
        let width = self.cropped_pixel_bounds.p_max.x - self.cropped_pixel_bounds.p_min.x;
        let offset = (p.x - self.cropped_pixel_bounds.p_min.x) +
                     (p.y - self.cropped_pixel_bounds.p_min.y) * width;
        offset as usize
    }
}

pub struct FilmTile {
    pixel_bounds: Bounds2i,
    filter_radius: Vector2f,
    inv_filter_radius: Vector2f,
    filter_table: Box<[f32]>,
    pub pixels: Vec<FilmTilePixel>,
}

impl FilmTile {
    pub fn new(pixel_bounds: &Bounds2i, filter_radius: &Vector2f, filter: &[f32]) -> FilmTile {
        let mut filter_table = Vec::new();
        filter_table.extend_from_slice(filter);
        FilmTile {
            pixel_bounds: *pixel_bounds,
            filter_radius: *filter_radius,
            inv_filter_radius: Vector2f::new(1.0 / filter_radius.x, 1.0 / filter_radius.y),
            // Duplicating the filter table in every table is wasteful, but keeping a reference to
            // the data from Film leads to all kind of lifetime issues...
            filter_table: filter_table.into_boxed_slice(),
            pixels: vec![FilmTilePixel::default(); pixel_bounds.area() as usize],
        }
    }

    pub fn add_sample(&mut self, p_film: &Point2f, colour: Spectrum) {
        if colour.has_nan() {
            warn!("colour has NaNs! Ignoring");
            return;
        }
        let float_pixel_bounds: Bounds2f = self.pixel_bounds.into();
        // Convert to discrete pixel space
        let p_film_discrete = *p_film - Vector2f::new(0.5, 0.5);
        // compute sample raster extent (i.e. how many pixels are affected)
        // (x0, y0) -> (x1, y1) is the zone of the image affected by the sample
        let p0_f = ceil(p_film_discrete - self.filter_radius);

        let p1_f = floor(p_film_discrete + self.filter_radius + Vector2f::new(1.0, 1.0));

        let bounds: Bounds2i = Bounds2i::from(Bounds2f::intersect(&Bounds2f::from_points(&p0_f,
                                                                                &p1_f),
                                                                  &float_pixel_bounds));
        let (p0, p1) = (bounds.p_min, bounds.p_max);

        assert!(p1.x >= p0.x && p1.y >= p0.y,
                format!("p_film={}, p0={}, p1={}, pixel_bounds={:?}",
                        p_film,
                        p0,
                        p1,
                        self.pixel_bounds));

        let filter_table_size = FILTER_SIZE as f32;

        // Precompute x and y filter table offset
        let mut ifx = Vec::with_capacity(p1.x as usize - p0.x as usize);
        for x in p0.x..p1.x {
            let fx = ((x as f32 - p_film_discrete.x) * self.inv_filter_radius.x *
                      filter_table_size)
                    .abs();
            ifx.push(fx.floor().min(filter_table_size - 1.0) as usize);
        }
        let mut ify = Vec::with_capacity(p1.y as usize - p0.y as usize);
        for y in p0.y..p1.y {
            let fy = ((y as f32 - p_film_discrete.y) * self.inv_filter_radius.y *
                      filter_table_size)
                    .abs();
            ify.push(fy.floor().min(filter_table_size - 1.0) as usize);
        }

        // Add this sample's contribution to all the affected pixels
        for y in p0.y..p1.y {
            for x in p0.x..p1.x {
                let offset = ify[(y - p0.y) as usize] * FILTER_SIZE + ifx[(x - p0.x) as usize];
                let filter_weight = &self.filter_table[offset];
                let idx = self.get_pixel_index(&Point2i::new(x, y));
                let pixel = &mut self.pixels[idx];
                pixel.contrib_sum += colour * *filter_weight;
                pixel.filter_weight_sum += *filter_weight;
            }
        }
    }

    pub fn get_pixel<'a>(&'a self, p: &Point2i) -> &'a FilmTilePixel {
        &self.pixels[self.get_pixel_index(p)]
    }

    pub fn get_pixel_bounds(&self) -> Bounds2i {
        self.pixel_bounds
    }

    fn get_pixel_index(&self, p: &Point2i) -> usize {
        let width = self.pixel_bounds.p_max.x - self.pixel_bounds.p_min.x;
        let pidx = (p.y - self.pixel_bounds.p_min.y) * width + (p.x - self.pixel_bounds.p_min.x);
        pidx as usize
    }
}

#[derive(Clone, Default)]
pub struct FilmTilePixel {
    contrib_sum: Spectrum,
    filter_weight_sum: f32,
}

fn ceil(p: Point2f) -> Point2f {
    Point2f::new(p.x.ceil(), p.y.ceil())
}

fn floor(p: Point2f) -> Point2f {
    Point2f::new(p.x.floor(), p.y.floor())
}
<commit_msg>Implement max_sample_luminance<commit_after>use std::sync::atomic::{Ordering, AtomicU32};
use std::f32;

use failure::Error;
use parking_lot::Mutex;

use {clamp, Point2f, Point2i, Vector2f};
use bounds::{Bounds2f, Bounds2i};
use filter::Filter;
use imageio;
use paramset::ParamSet;
use spectrum::Spectrum;

const FILTER_SIZE: usize = 16;
const FILTER_TABLE_SIZE: usize = FILTER_SIZE * FILTER_SIZE;

stat_memory_counter!("Memory/Film pixels", film_pixel_memory);
pub fn init_stats() {
    film_pixel_memory::init();
}

#[derive(Default)]
struct AtomicFloat {
    bits: AtomicU32,
}

impl AtomicFloat {
    pub fn as_float(&self) -> f32 {
        f32::from_bits(self.bits.load(Ordering::Relaxed))
    }
}

#[derive(Default)]
struct Pixel {
    xyz: [f32; 3],
    filter_weight_sum: f32,
    splat_xyz: [AtomicFloat; 3],
    _pad: f32,
}

pub struct Film {
    pub full_resolution: Point2i,
    pub _diagonal: f32,
    pub filename: String,
    pub cropped_pixel_bounds: Bounds2i,
    pixels: Mutex<Vec<Pixel>>,
    filter_table: [f32; FILTER_TABLE_SIZE],
    filter_radius: Vector2f,
    scale: f32,
    max_sample_luminance: f32,
}

impl Film {
    pub fn new(resolution: Point2i,
               cropwindow: Bounds2f,
               filter: Box<Filter>,
               diagonal: f32,
               filename: &str,
               scale: f32,
               max_sample_luminance: f32)
               -> Film {
        let cropped_pixel_bounds =
            Bounds2i::from_points(&Point2i::new((resolution.x as f32 * cropwindow.p_min.x).ceil() as
                                                i32,
                                                (resolution.y as f32 * cropwindow.p_min.y).ceil() as
                                                i32),
                                  &Point2i::new((resolution.x as f32 * cropwindow.p_max.x).ceil() as
                                                i32,
                                                (resolution.y as f32 * cropwindow.p_max.y).ceil() as
                                                i32));

        info!("Created film with full resolution {}. Crop window of {} -> cropped_pixel_bounds {}",
              resolution,
              cropwindow,
              cropped_pixel_bounds);
        let mut pixels = Vec::with_capacity(cropped_pixel_bounds.area() as usize);
        pixels.resize_default(cropped_pixel_bounds.area() as usize);
        film_pixel_memory::add(cropped_pixel_bounds.area() as u64 *
                               ::std::mem::size_of::<Pixel>() as u64);
        let mut filter_table = [0f32; FILTER_TABLE_SIZE];

        let (xwidth, ywidth) = filter.width();
        // Fill in filter table
        for y in 0..FILTER_SIZE {
            let fy = (y as f32 + 0.5) * (ywidth / FILTER_SIZE as f32);
            for x in 0..FILTER_SIZE {
                let fx = (x as f32 + 0.5) * (xwidth / FILTER_SIZE as f32);
                filter_table[y * FILTER_SIZE + x] = filter.evaluate(fx, fy);
            }
        }

        Film {
            full_resolution: resolution,
            pixels: Mutex::new(pixels),
            filter_table,
            filter_radius: Vector2f::new(xwidth, ywidth),
            cropped_pixel_bounds: cropped_pixel_bounds,
            scale,
            _diagonal: diagonal * 0.001,
            filename: filename.to_owned(),
            max_sample_luminance
        }
    }

    pub fn create(ps: &mut ParamSet, filter: Box<Filter>) -> Box<Film> {
        let mut filename = ps.find_one_string("filename", "".into());
        if filename == "" {
            filename = "image.png".into();
        } else {
            filename = String::from("rt-") + &filename;
        }
        let xres = ps.find_one_int("xresolution", 1280);
        let yres = ps.find_one_int("yresolution", 720);
        let mut crop = Bounds2f::from_points(&Point2f::new(0.0, 0.0), &Point2f::new(1.0, 1.0));
        if let Some(cr) = ps.find_float("cropwindow") {
            if cr.len() == 4 {
                crop.p_min.x = clamp(f32::min(cr[0], cr[1]), 0.0, 1.0);
                crop.p_max.x = clamp(f32::max(cr[0], cr[1]), 0.0, 1.0);
                crop.p_min.y = clamp(f32::min(cr[2], cr[3]), 0.0, 1.0);
                crop.p_max.y = clamp(f32::max(cr[2], cr[3]), 0.0, 1.0);
            } else {
                warn!("\"cropwindow\" expected 4 values");
            }
        }
        let scale = ps.find_one_float("scale", 1.0);
        let diagonal = ps.find_one_float("diagonal", 35.0);
        let max_sample_luminance = ps.find_one_float("maxsampleluminance", f32::INFINITY);
        // TODO max_sample_luminance
        Box::new(Film::new(Point2i::new(xres, yres),
                           crop,
                           filter,
                           diagonal,
                           &filename,
                           scale, max_sample_luminance))
    }

    pub fn get_film_tile(&self, sample_bounds: &Bounds2i) -> FilmTile {
        let half_pixel = Vector2f::new(0.5, 0.5);
        let float_bounds: Bounds2f = (*sample_bounds).into();
        let float_cropped_pixel_bounds: Bounds2f = self.cropped_pixel_bounds.into();

        // This is a bit clunky but we need to do all the computations as floats as the numbers can
        // temporarily be negative which would cause u32 to wrap around.
        let p0 = ceil(float_bounds.p_min - half_pixel - self.filter_radius);
        let p1 = floor(float_bounds.p_max - half_pixel + self.filter_radius +
                       Vector2f::new(1.0, 1.0));
        let sample_extent_bounds = Bounds2f::from_points(&p0, &p1);

        let tile_pixel_bounds: Bounds2i =
            Bounds2i::from(Bounds2f::intersect(&sample_extent_bounds, &float_cropped_pixel_bounds));

        FilmTile::new(&tile_pixel_bounds, &self.filter_radius, &self.filter_table, self.max_sample_luminance)
    }

    pub fn merge_film_tile(&self, tile: FilmTile) {
        let mut pixels = self.pixels.lock();
        for pixel in &tile.get_pixel_bounds() {
            let tile_pixel = tile.get_pixel(&pixel);
            let pidx = {
                let width = self.cropped_pixel_bounds.p_max.x - self.cropped_pixel_bounds.p_min.x;
                ((pixel.y - self.cropped_pixel_bounds.p_min.y) * width +
                 (pixel.x - self.cropped_pixel_bounds.p_min.x)) as usize
            };
            let xyz = tile_pixel.contrib_sum.to_xyz();
            for i in 0..3 {
                pixels[pidx].xyz[i] += xyz[i];
            }
            pixels[pidx].filter_weight_sum += tile_pixel.filter_weight_sum;
        }
    }

    pub fn write_image(&self) -> Result<(), Error> {
        info!("Converting image to RGB and computing final weighted pixel values");
        let splat_scale = 1.0; // TODO
        let pixels = self.pixels.lock();
        let mut rgb = Vec::with_capacity(3 * self.cropped_pixel_bounds.area() as usize);
        for p in &self.cropped_pixel_bounds {
            // Convert pixel XYZ color to RGB
            let pixel_idx = self.get_pixel_idx(&p);
            let pixel = &pixels[pixel_idx];
            let mut rgb_pixel = Spectrum::from_xyz(&pixel.xyz);

            // Normalize pixel with weight sum
            let filter_weight_sum = pixel.filter_weight_sum;
            if filter_weight_sum != 0.0 {
                let inv_wt = 1.0 / filter_weight_sum;
                rgb_pixel[0] = f32::max(0.0, rgb_pixel[0] * inv_wt);
                rgb_pixel[1] = f32::max(0.0, rgb_pixel[1] * inv_wt);
                rgb_pixel[2] = f32::max(0.0, rgb_pixel[2] * inv_wt);
            }

            let splat_xyz = [pixel.splat_xyz[0].as_float(),
                             pixel.splat_xyz[1].as_float(),
                             pixel.splat_xyz[2].as_float()];
            let mut splat_rgb = Spectrum::from_xyz(&splat_xyz);
            rgb_pixel[0] += splat_scale * splat_rgb[0];
            rgb_pixel[1] += splat_scale * splat_rgb[1];
            rgb_pixel[2] += splat_scale * splat_rgb[2];

            // Scale pixel value by scale
            rgb_pixel[0] *= self.scale;
            rgb_pixel[1] *= self.scale;
            rgb_pixel[2] *= self.scale;

            rgb.push(rgb_pixel[0]);
            rgb.push(rgb_pixel[1]);
            rgb.push(rgb_pixel[2]);
        }

        // Write RGB image
        info!("Writing image {} with bounds {}",
              self.filename,
              self.cropped_pixel_bounds);
        imageio::write_image(&self.filename,
                             &rgb[..],
                             &self.cropped_pixel_bounds,
                             &self.full_resolution)
    }

    pub fn get_sample_bounds(&self) -> Bounds2i {
        let half = Vector2f::new(0.5, 0.5);
        let float_bounds =
            Bounds2f::from_points(&floor(Point2f::from(self.cropped_pixel_bounds.p_min) + half -
                                         self.filter_radius),
                                  &ceil(Point2f::from(self.cropped_pixel_bounds.p_max) - half +
                                        self.filter_radius));

        float_bounds.into()
    }

    fn get_pixel_idx(&self, p: &Point2i) -> usize {
        assert!(self.cropped_pixel_bounds.inside_exclusive(p));
        let width = self.cropped_pixel_bounds.p_max.x - self.cropped_pixel_bounds.p_min.x;
        let offset = (p.x - self.cropped_pixel_bounds.p_min.x) +
                     (p.y - self.cropped_pixel_bounds.p_min.y) * width;
        offset as usize
    }
}

pub struct FilmTile {
    pixel_bounds: Bounds2i,
    filter_radius: Vector2f,
    inv_filter_radius: Vector2f,
    filter_table: Box<[f32]>,
    pub pixels: Vec<FilmTilePixel>,
    max_sample_luminance: f32,
}

impl FilmTile {
    pub fn new(pixel_bounds: &Bounds2i, filter_radius: &Vector2f, filter: &[f32], max_sample_luminance: f32) -> FilmTile {
        let mut filter_table = Vec::new();
        filter_table.extend_from_slice(filter);
        FilmTile {
            pixel_bounds: *pixel_bounds,
            filter_radius: *filter_radius,
            inv_filter_radius: Vector2f::new(1.0 / filter_radius.x, 1.0 / filter_radius.y),
            // Duplicating the filter table in every table is wasteful, but keeping a reference to
            // the data from Film leads to all kind of lifetime issues...
            filter_table: filter_table.into_boxed_slice(),
            pixels: vec![FilmTilePixel::default(); pixel_bounds.area() as usize],
            max_sample_luminance,
        }
    }

    pub fn add_sample(&mut self, p_film: &Point2f, colour: Spectrum) {
        if colour.has_nan() {
            warn!("colour has NaNs! Ignoring");
            return;
        }
        let L = if colour.y() > self.max_sample_luminance {
            colour * self.max_sample_luminance / colour.y()
        } else {
            colour
        };
        let float_pixel_bounds: Bounds2f = self.pixel_bounds.into();
        // Convert to discrete pixel space
        let p_film_discrete = *p_film - Vector2f::new(0.5, 0.5);
        // compute sample raster extent (i.e. how many pixels are affected)
        // (x0, y0) -> (x1, y1) is the zone of the image affected by the sample
        let p0_f = ceil(p_film_discrete - self.filter_radius);

        let p1_f = floor(p_film_discrete + self.filter_radius + Vector2f::new(1.0, 1.0));

        let bounds: Bounds2i = Bounds2i::from(Bounds2f::intersect(&Bounds2f::from_points(&p0_f,
                                                                                &p1_f),
                                                                  &float_pixel_bounds));
        let (p0, p1) = (bounds.p_min, bounds.p_max);

        assert!(p1.x >= p0.x && p1.y >= p0.y,
                format!("p_film={}, p0={}, p1={}, pixel_bounds={:?}",
                        p_film,
                        p0,
                        p1,
                        self.pixel_bounds));

        let filter_table_size = FILTER_SIZE as f32;

        // Precompute x and y filter table offset
        let mut ifx = Vec::with_capacity(p1.x as usize - p0.x as usize);
        for x in p0.x..p1.x {
            let fx = ((x as f32 - p_film_discrete.x) * self.inv_filter_radius.x *
                      filter_table_size)
                    .abs();
            ifx.push(fx.floor().min(filter_table_size - 1.0) as usize);
        }
        let mut ify = Vec::with_capacity(p1.y as usize - p0.y as usize);
        for y in p0.y..p1.y {
            let fy = ((y as f32 - p_film_discrete.y) * self.inv_filter_radius.y *
                      filter_table_size)
                    .abs();
            ify.push(fy.floor().min(filter_table_size - 1.0) as usize);
        }

        // Add this sample's contribution to all the affected pixels
        for y in p0.y..p1.y {
            for x in p0.x..p1.x {
                let offset = ify[(y - p0.y) as usize] * FILTER_SIZE + ifx[(x - p0.x) as usize];
                let filter_weight = &self.filter_table[offset];
                let idx = self.get_pixel_index(&Point2i::new(x, y));
                let pixel = &mut self.pixels[idx];
                pixel.contrib_sum += L * *filter_weight;
                pixel.filter_weight_sum += *filter_weight;
            }
        }
    }

    pub fn get_pixel<'a>(&'a self, p: &Point2i) -> &'a FilmTilePixel {
        &self.pixels[self.get_pixel_index(p)]
    }

    pub fn get_pixel_bounds(&self) -> Bounds2i {
        self.pixel_bounds
    }

    fn get_pixel_index(&self, p: &Point2i) -> usize {
        let width = self.pixel_bounds.p_max.x - self.pixel_bounds.p_min.x;
        let pidx = (p.y - self.pixel_bounds.p_min.y) * width + (p.x - self.pixel_bounds.p_min.x);
        pidx as usize
    }
}

#[derive(Clone, Default)]
pub struct FilmTilePixel {
    contrib_sum: Spectrum,
    filter_weight_sum: f32,
}

fn ceil(p: Point2f) -> Point2f {
    Point2f::new(p.x.ceil(), p.y.ceil())
}

fn floor(p: Point2f) -> Point2f {
    Point2f::new(p.x.floor(), p.y.floor())
}
<|endoftext|>


<commit_before>use std::fmt;
// use std::iter;
use std::slice;
use std::ops;
use std::collections::HashMap;
use error::*;

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Operator {
    Add,
    Sub,
    Mul,
    Div,
}

#[cfg_attr(rustfmt, rustfmt_skip)]
impl fmt::Display for Operator {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Operator::*;
        write!(f, "{}", match *self {
            Add => "+",
            Sub => "-",
            Mul => "*",
            Div => "/",
        })
    }
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Arity {
    Nullary,
    Unary,
    Binary,
    Ternary,
    Multiary,  // 2+ arguments
}

impl fmt::Display for Arity {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Arity::*;
        let text = match *self {
            Nullary => "0",
            Unary   => "1",
            Binary  => "2",
            Ternary => "3",
            Multiary => "at least 2",
        };

        write!(f, "{} args", text)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Atom {
    Op(Operator),
    // Bool(bool),
    Int(i64),
    // Float(f64),
    // Str(String),
}

impl fmt::Display for Atom {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Atom::*;
        match *self {
            Op(ref t) => write!(f, "{}", t),
            // Bool(ref t) => write!(f, "{}", t),
            Int(ref t) => write!(f, "{}", t),
            // Float(ref t) => write!(f, "{}", t),
            // Str(ref t) => write!(f, "{}", t),
        }
    }
}

impl From<Operator> for Atom {
    fn from(x: Operator) -> Self {
        Atom::Op(x)
    }
}

impl From<i64> for Atom {
    fn from(x: i64) -> Self {
        Atom::Int(x)
    }
}

impl ops::Add<Atom> for Atom {
    type Output = Atom;
    fn add(self, rhs: Atom) -> Self::Output {
        use self::Atom::*;
        match (self, rhs) {
            (Int(i), Int(j)) => Int(i + j),
            _ => panic!(),
        }
    }
}

impl ops::Sub<Atom> for Atom {
    type Output = Atom;
    fn sub(self, rhs: Atom) -> Self::Output {
        use self::Atom::*;
        match (self, rhs) {
            (Int(i), Int(j)) => Int(i - j),
            _ => panic!(),
        }
    }
}

impl ops::Mul<Atom> for Atom {
    type Output = Atom;
    fn mul(self, rhs: Atom) -> Self::Output {
        use self::Atom::*;
        match (self, rhs) {
            (Int(i), Int(j)) => Int(i * j),
            _ => panic!(),
        }
    }
}

impl ops::Div<Atom> for Atom {
    type Output = Atom;
    fn div(self, rhs: Atom) -> Self::Output {
        use self::Atom::*;
        match (self, rhs) {
            (Int(i), Int(j)) => Int(i / j),
            _ => panic!(),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    Atom(Atom),
    List(List),
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Value::*;
        match *self {
            Atom(ref t) => write!(f, "{}", t),
            List(ref t) => write!(f, "{}", t),
        }
    }
}

impl<T> From<T> for Value where T: Into<Atom> {
    fn from(v: T) -> Self {
        Value::Atom(v.into())
    }
}

impl ops::Add<Value> for Value {
    type Output = Value;
    fn add(self, rhs: Value) -> Self::Output {
        use self::Value::*;
        match (self, rhs) {
            (Atom(i), Atom(j)) => Atom(i + j),
            _ => panic!(),
        }
    }
}

impl ops::Sub<Value> for Value {
    type Output = Value;
    fn sub(self, rhs: Value) -> Self::Output {
        use self::Value::*;
        match (self, rhs) {
            (Atom(i), Atom(j)) => Atom(i - j),
            _ => panic!(),
        }
    }
}

impl ops::Mul<Value> for Value {
    type Output = Value;
    fn mul(self, rhs: Value) -> Self::Output {
        use self::Value::*;
        match (self, rhs) {
            (Atom(i), Atom(j)) => Atom(i * j),
            _ => panic!(),
        }
    }
}

impl ops::Div<Value> for Value {
    type Output = Value;
    fn div(self, rhs: Value) -> Self::Output {
        use self::Value::*;
        match (self, rhs) {
            (Atom(i), Atom(j)) => Atom(i / j),
            _ => panic!(),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Node {
    Atom (Atom),
    List (List),
    Expr (Expr),
}

impl Node {
    fn eval(&self) -> Result<Value> {
        use self::Node::*;
        match *self {
            Atom(a) => Ok(Value::Atom(a)),
            List(ref l) => Ok(Value::List(l.clone())),
            Expr(ref e) => e.eval(),
        }
    }
}

impl<T> From<T> for Node where T: Into<Atom> {
    fn from(v: T) -> Self {
        Node::Atom(v.into())
    }
}

// impl<T> From<T> for Node where T: Into<List> {
//     fn from(l: T) -> Self {
//         Node::List(l.into())
//     }
// }
//
// impl<T> From<T> for Node where T: Into<Expr> {
//     fn from(e: T) -> Self {
//         Node::Expr(e.into())
//     }
// }

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Node::*;
        match *self {
            Atom(ref a) => write!(f, "{}", a),
            List(ref l) => write!(f, "{}", l),
            Expr(ref e) => write!(f, "{}", e),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct List {
    inner: Vec<Node>
}

impl List {
    pub fn new() -> Self {
        List { inner: Vec::new() }
    }
}

impl From<Vec<Node>> for List {
    fn from(v: Vec<Node>) -> Self {
        List { inner: v }
    }
}

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let elements = self.inner.iter()
            .map(ToString::to_string)
            .collect::<Vec<_>>()
            .join(" ");
        write!(f, "( {} )", elements)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct Expr {
    op: Operator,
    args: Vec<Node>
}

impl Expr {
    pub fn new(op: Operator, args: Vec<Node>) -> Self {
        Expr { op: op, args: args }
    }

    pub fn op(&self) -> Operator {
        self.op
    }

    pub fn args(&self) -> slice::Iter<Node> {
        self.args.iter()
    }

    pub fn num_args(&self) -> usize {
        self.args.len()
    }

    pub fn expect_arity(&self, arity: Arity) -> bool {
        use self::Arity::*;
        let num_args = self.num_args();
        match arity {
            Nullary  => num_args == 0,
            Unary    => num_args == 1,
            Binary   => num_args == 2,
            Ternary  => num_args == 3,
            Multiary => num_args >= 2,
        }
    }

    pub fn eval(&self) -> Result<Value> {
        // use self::Node::*;
        // use self::Atom::*;
        use self::Operator::*;
        use self::Arity::*;

        // Arity = number of arguments accepted
        let mut arity = HashMap::new();

        arity.insert(Add, Multiary);
        arity.insert(Sub, Binary);
        arity.insert(Mul, Multiary);
        arity.insert(Div, Binary);

        let op = self.op();

        // Evaluate all arguments
        println!("{:#?}", self.args());
        let mut args: Vec<_> = self.args().map(|x| x.eval()).collect();

        // Check if operator is found
        if let Some(expected_arity) = arity.get(&op) {
            // Return the first expr that cannot eval correctly
            if let &Some(ref err) = args.iter().find(|&x| x.is_err()) {
                (*err).clone()
            }
            // Check if number of arguments match expected number
            else if !self.expect_arity(*expected_arity) {
                Err(format!(
                    "{} operator expected {} arguments, but received {}",
                    op, expected_arity, self.num_args()
                ).into())
            }
            // Perform actual operation
            else {
                let mut eval_args = args.into_iter().map(Result::unwrap);
                match op {
                    Add => Ok(eval_args.fold(0.into(), |acc, x| acc + x)),
                    Sub => {
                        let a = eval_args.next().unwrap();
                        let b = eval_args.next().unwrap();
                        Ok(a - b)
                    },
                    Mul => Ok(eval_args.fold(1.into(), |acc, x| acc * x)),
                    Div => {
                        let a = eval_args.next().unwrap();
                        let b = eval_args.next().unwrap();
                        Ok(a / b)
                    }
                }
            }
        }
        else {
            Err(format!("operator {} not found", op).into())
        }
    }
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let elements = self.args.iter()
            .map(ToString::to_string)
            .collect::<Vec<_>>()
            .join(" ");
        write!(f, "( {} {} )", self.op, elements)
    }
}
<commit_msg>Fix borrowck errors (does not eval correctly)<commit_after>use std::fmt;
// use std::iter;
use std::slice;
use std::ops;
use std::collections::HashMap;
use error::*;

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Operator {
    Add,
    Sub,
    Mul,
    Div,
}

#[cfg_attr(rustfmt, rustfmt_skip)]
impl fmt::Display for Operator {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Operator::*;
        write!(f, "{}", match *self {
            Add => "+",
            Sub => "-",
            Mul => "*",
            Div => "/",
        })
    }
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Arity {
    Nullary,
    Unary,
    Binary,
    Ternary,
    Multiary,  // 2+ arguments
}

impl fmt::Display for Arity {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Arity::*;
        let text = match *self {
            Nullary => "0",
            Unary   => "1",
            Binary  => "2",
            Ternary => "3",
            Multiary => "at least 2",
        };

        write!(f, "{} args", text)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Atom {
    Op(Operator),
    // Bool(bool),
    Int(i64),
    // Float(f64),
    // Str(String),
}

impl fmt::Display for Atom {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Atom::*;
        match *self {
            Op(ref t) => write!(f, "{}", t),
            // Bool(ref t) => write!(f, "{}", t),
            Int(ref t) => write!(f, "{}", t),
            // Float(ref t) => write!(f, "{}", t),
            // Str(ref t) => write!(f, "{}", t),
        }
    }
}

impl From<Operator> for Atom {
    fn from(x: Operator) -> Self {
        Atom::Op(x)
    }
}

impl From<i64> for Atom {
    fn from(x: i64) -> Self {
        Atom::Int(x)
    }
}

impl ops::Add<Atom> for Atom {
    type Output = Atom;
    fn add(self, rhs: Atom) -> Self::Output {
        use self::Atom::*;
        match (self, rhs) {
            (Int(i), Int(j)) => Int(i + j),
            _ => panic!(),
        }
    }
}

impl ops::Sub<Atom> for Atom {
    type Output = Atom;
    fn sub(self, rhs: Atom) -> Self::Output {
        use self::Atom::*;
        match (self, rhs) {
            (Int(i), Int(j)) => Int(i - j),
            _ => panic!(),
        }
    }
}

impl ops::Mul<Atom> for Atom {
    type Output = Atom;
    fn mul(self, rhs: Atom) -> Self::Output {
        use self::Atom::*;
        match (self, rhs) {
            (Int(i), Int(j)) => Int(i * j),
            _ => panic!(),
        }
    }
}

impl ops::Div<Atom> for Atom {
    type Output = Atom;
    fn div(self, rhs: Atom) -> Self::Output {
        use self::Atom::*;
        match (self, rhs) {
            (Int(i), Int(j)) => Int(i / j),
            _ => panic!(),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    Atom(Atom),
    List(List),
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Value::*;
        match *self {
            Atom(ref t) => write!(f, "{}", t),
            List(ref t) => write!(f, "{}", t),
        }
    }
}

impl<T> From<T> for Value where T: Into<Atom> {
    fn from(v: T) -> Self {
        Value::Atom(v.into())
    }
}

impl ops::Add<Value> for Value {
    type Output = Value;
    fn add(self, rhs: Value) -> Self::Output {
        use self::Value::*;
        match (self, rhs) {
            (Atom(i), Atom(j)) => Atom(i + j),
            _ => panic!(),
        }
    }
}

impl ops::Sub<Value> for Value {
    type Output = Value;
    fn sub(self, rhs: Value) -> Self::Output {
        use self::Value::*;
        match (self, rhs) {
            (Atom(i), Atom(j)) => Atom(i - j),
            _ => panic!(),
        }
    }
}

impl ops::Mul<Value> for Value {
    type Output = Value;
    fn mul(self, rhs: Value) -> Self::Output {
        use self::Value::*;
        match (self, rhs) {
            (Atom(i), Atom(j)) => Atom(i * j),
            _ => panic!(),
        }
    }
}

impl ops::Div<Value> for Value {
    type Output = Value;
    fn div(self, rhs: Value) -> Self::Output {
        use self::Value::*;
        match (self, rhs) {
            (Atom(i), Atom(j)) => Atom(i / j),
            _ => panic!(),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Node {
    Atom (Atom),
    List (List),
    Expr (Expr),
}

impl Node {
    fn eval(&self) -> Result<Value> {
        use self::Node::*;
        match *self {
            Atom(a) => Ok(Value::Atom(a)),
            List(ref l) => Ok(Value::List(l.clone())),
            Expr(ref e) => e.eval(),
        }
    }
}

impl<T> From<T> for Node where T: Into<Atom> {
    fn from(v: T) -> Self {
        Node::Atom(v.into())
    }
}

// impl<T> From<T> for Node where T: Into<List> {
//     fn from(l: T) -> Self {
//         Node::List(l.into())
//     }
// }
//
// impl<T> From<T> for Node where T: Into<Expr> {
//     fn from(e: T) -> Self {
//         Node::Expr(e.into())
//     }
// }

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Node::*;
        match *self {
            Atom(ref a) => write!(f, "{}", a),
            List(ref l) => write!(f, "{}", l),
            Expr(ref e) => write!(f, "{}", e),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct List {
    inner: Vec<Node>
}

impl List {
    pub fn new() -> Self {
        List { inner: Vec::new() }
    }
}

impl From<Vec<Node>> for List {
    fn from(v: Vec<Node>) -> Self {
        List { inner: v }
    }
}

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let elements = self.inner.iter()
            .map(ToString::to_string)
            .collect::<Vec<_>>()
            .join(" ");
        write!(f, "( {} )", elements)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct Expr {
    op: Operator,
    args: Vec<Node>
}

impl Expr {
    pub fn new(op: Operator, args: Vec<Node>) -> Self {
        Expr { op: op, args: args }
    }

    pub fn op(&self) -> Operator {
        self.op
    }

    pub fn args(&self) -> slice::Iter<Node> {
        self.args.iter()
    }

    pub fn num_args(&self) -> usize {
        self.args.len()
    }

    pub fn expect_arity(&self, arity: Arity) -> bool {
        use self::Arity::*;
        let num_args = self.num_args();
        match arity {
            Nullary  => num_args == 0,
            Unary    => num_args == 1,
            Binary   => num_args == 2,
            Ternary  => num_args == 3,
            Multiary => num_args >= 2,
        }
    }

    pub fn eval(&self) -> Result<Value> {
        // use self::Node::*;
        // use self::Atom::*;
        use self::Operator::*;
        use self::Arity::*;

        // Arity = number of arguments accepted
        let mut arity = HashMap::new();

        arity.insert(Add, Multiary);
        arity.insert(Sub, Binary);
        arity.insert(Mul, Multiary);
        arity.insert(Div, Binary);

        let op = self.op();

        let expected_arity = match arity.get(&op) {
            Some(e) => e,
            None => return Err(format!("operator {} not found", op).into())
        };

        // Check if number of arguments match expected number
        if !self.expect_arity(*expected_arity) {
            return Err(format!(
                "{} operator expected {} arguments, but received {}",
                op, expected_arity, self.num_args()
            ).into())
        }

        let mut args = self.args().map(Node::eval);

        // Return the first expr that cannot eval correctly
        if let Some(err) = args.find(|x| x.is_err()) {
            err
        } else {
            let mut eval_args = args.map(Result::unwrap);
            match op {
                Add => Ok(eval_args.fold(0.into(), |acc, x| acc + x)),
                Sub => {
                    let a = eval_args.next().unwrap();
                    let b = eval_args.next().unwrap();
                    Ok(a - b)
                },
                Mul => Ok(eval_args.fold(1.into(), |acc, x| acc * x)),
                Div => {
                    let a = eval_args.next().unwrap();
                    let b = eval_args.next().unwrap();
                    Ok(a / b)
                }
            }
        }
    }
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let elements = self.args.iter()
            .map(ToString::to_string)
            .collect::<Vec<_>>()
            .join(" ");
        write!(f, "( {} {} )", self.op, elements)
    }
}
<|endoftext|>


<commit_before>// C API for mp4parse module.
// Parses ISO Base Media Format aka video/mp4 streams.

// 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 https://mozilla.org/MPL/2.0/.

use std;
use std::io::Cursor;
use byteorder;

// Symbols we need from our rust api.
use MediaContext;
use read_box;

/// Allocate an opaque rust-side parser context.
#[no_mangle]
pub unsafe extern "C" fn mp4parse_new() -> *mut MediaContext {
    std::mem::transmute(Box::new(MediaContext::new()))
}

/// Free a rust-side parser context.
#[no_mangle]
pub extern "C" fn mp4parse_free(context: *mut MediaContext) {
    unsafe {
        assert!(!context.is_null());
        let _: Box<MediaContext> = std::mem::transmute(context);
    }
}

/// Feed a buffer through read_box(), returning the number of detected tracks.
#[no_mangle]
pub extern "C" fn mp4parse_read(context: *mut MediaContext, buffer: *const u8, size: usize) -> i32 {
    // Validate arguments from C.
    if context.is_null() {
        return -1;
    }
    if buffer.is_null() || size < 8 {
        return -1;
    }

    let mut context: &mut MediaContext = unsafe { &mut *context };

    // Wrap the buffer we've been give in a slice.
    let b = unsafe { std::slice::from_raw_parts(buffer, size) };
    let mut c = Cursor::new(b);

    // Parse in a subthread to catch any panics.
    let task = std::thread::spawn(move || {
        loop {
            match read_box(&mut c, &mut context) {
                Ok(_) => {},
                Err(byteorder::Error::UnexpectedEOF) => { break },
                Err(e) => { panic!(e); },
            }
        }
        // Make sure the track count fits in an i32 so we can use
        // negative values for failure.
        assert!(context.tracks.len() < std::i32::MAX as usize);
        context.tracks.len() as i32
    });
    task.join().unwrap_or(-1)
}

#[test]
fn new_context() {
    let context = unsafe {
        let context = mp4parse_new();
        assert!(!context.is_null());
        context
    };
    mp4parse_free(context);
}

#[test]
#[should_panic(expected = "assertion failed")]
fn free_null_context() {
    mp4parse_free(std::ptr::null_mut());
}

#[test]
fn arg_validation() {
    let null_buffer = std::ptr::null();
    let null_context = std::ptr::null_mut();
    assert_eq!(-1, mp4parse_read(null_context, null_buffer, 0));

    let context = unsafe { mp4parse_new() };
    assert!(!context.is_null());

    assert_eq!(-1, mp4parse_read(context, null_buffer, 0));

    let buffer = vec![0u8; 8];
    for size in (0..buffer.len()) {
        println!("testing buffer length {}", size);
        assert_eq!(-1, mp4parse_read(context, buffer.as_ptr(), size));
    }

    mp4parse_free(context);
}
<commit_msg>Remove unsafe from mp4parse_new declaration.<commit_after>// C API for mp4parse module.
// Parses ISO Base Media Format aka video/mp4 streams.

// 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 https://mozilla.org/MPL/2.0/.

use std;
use std::io::Cursor;
use byteorder;

// Symbols we need from our rust api.
use MediaContext;
use read_box;

/// Allocate an opaque rust-side parser context.
#[no_mangle]
pub extern "C" fn mp4parse_new() -> *mut MediaContext {
    unsafe {
        std::mem::transmute(Box::new(MediaContext::new()))
    }
}

/// Free a rust-side parser context.
#[no_mangle]
pub extern "C" fn mp4parse_free(context: *mut MediaContext) {
    unsafe {
        assert!(!context.is_null());
        let _: Box<MediaContext> = std::mem::transmute(context);
    }
}

/// Feed a buffer through read_box(), returning the number of detected tracks.
#[no_mangle]
pub extern "C" fn mp4parse_read(context: *mut MediaContext, buffer: *const u8, size: usize) -> i32 {
    // Validate arguments from C.
    if context.is_null() {
        return -1;
    }
    if buffer.is_null() || size < 8 {
        return -1;
    }

    let mut context: &mut MediaContext = unsafe { &mut *context };

    // Wrap the buffer we've been give in a slice.
    let b = unsafe { std::slice::from_raw_parts(buffer, size) };
    let mut c = Cursor::new(b);

    // Parse in a subthread to catch any panics.
    let task = std::thread::spawn(move || {
        loop {
            match read_box(&mut c, &mut context) {
                Ok(_) => {},
                Err(byteorder::Error::UnexpectedEOF) => { break },
                Err(e) => { panic!(e); },
            }
        }
        // Make sure the track count fits in an i32 so we can use
        // negative values for failure.
        assert!(context.tracks.len() < std::i32::MAX as usize);
        context.tracks.len() as i32
    });
    task.join().unwrap_or(-1)
}

#[test]
fn new_context() {
    let context = mp4parse_new();
    assert!(!context.is_null());
    mp4parse_free(context);
}

#[test]
#[should_panic(expected = "assertion failed")]
fn free_null_context() {
    mp4parse_free(std::ptr::null_mut());
}

#[test]
fn arg_validation() {
    let null_buffer = std::ptr::null();
    let null_context = std::ptr::null_mut();
    assert_eq!(-1, mp4parse_read(null_context, null_buffer, 0));

    let context = mp4parse_new();
    assert!(!context.is_null());

    assert_eq!(-1, mp4parse_read(context, null_buffer, 0));

    let buffer = vec![0u8; 8];
    for size in (0..buffer.len()) {
        println!("testing buffer length {}", size);
        assert_eq!(-1, mp4parse_read(context, buffer.as_ptr(), size));
    }

    mp4parse_free(context);
}
<|endoftext|>


<commit_before>use std::net::{TcpStream};

use std::io::prelude::*;
use std::io::BufReader;

extern crate byteorder;

use self::byteorder::{BigEndian,ByteOrder};
use std::string::FromUtf8Error;

pub const MAX_TEXT_LEN: usize = 2048;

pub fn read_text (mut s: &mut TcpStream,) -> Option<String> {
    let mut size = [0;2];

    if let Ok(_) = s.read_exact(&mut size) {
        let size = BigEndian::read_u16(&size);
        let mut v = vec![0;size as usize];

        if let Ok(_) = s.read_exact(&mut v) {
            if let Ok(text) = String::from_utf8(v) {
                return Some(text)
            }
        }
    }

    return None
}

pub fn write_text (mut s: &mut TcpStream, text: &str) {
    let mut bytes = &text.as_bytes();

    let len;
    if bytes.len() > MAX_TEXT_LEN { len = MAX_TEXT_LEN; }
    else { len = bytes.len(); }

    let mut size = [0;2];
    BigEndian::write_u16(&mut size, len as u16);

    s.write_all(&[2]);
    s.write_all(&size);
    s.write_all(&bytes[0..len]);
}

// NOTE: may be better to return a tuple with the bytes slice separate from vec
pub fn text_as_bytes (text: &str) -> Vec<u8> {
    let mut bytes = &text.as_bytes();

    let len;
    if bytes.len() > MAX_TEXT_LEN { len = MAX_TEXT_LEN; }
    else { len = bytes.len(); }

    let mut size = [0;2];
    BigEndian::write_u16(&mut size, len as u16);

    let mut v = vec!(2, size[0],size[1]);
    v.extend_from_slice(&bytes[0..len]);

    v
}
<commit_msg>add max chat recv<commit_after>use std::net::{TcpStream};

use std::io::prelude::*;
use std::io::BufReader;

extern crate byteorder;

use self::byteorder::{BigEndian,ByteOrder};
use std::string::FromUtf8Error;

pub const MAX_TEXT_LEN: usize = 2048;

pub fn read_text (mut s: &mut TcpStream,) -> Option<String> {
    let mut size = [0;2];

    if let Ok(_) = s.read_exact(&mut size) {
        let size = BigEndian::read_u16(&size);

        if size > MAX_TEXT_LEN as u16 { panic!("unbounded chat size reached") }

        let mut v = vec![0;size as usize];

        if let Ok(_) = s.read_exact(&mut v) {
            if let Ok(text) = String::from_utf8(v) {
                return Some(text)
            }
        }
    }

    return None
}

pub fn write_text (mut s: &mut TcpStream, text: &str) {
    let mut bytes = &text.as_bytes();

    let len;
    if bytes.len() > MAX_TEXT_LEN { len = MAX_TEXT_LEN; }
    else { len = bytes.len(); }

    let mut size = [0;2];
    BigEndian::write_u16(&mut size, len as u16);

    s.write_all(&[2]);
    s.write_all(&size);
    s.write_all(&bytes[0..len]);
}

// NOTE: may be better to return a tuple with the bytes slice separate from vec
pub fn text_as_bytes (text: &str) -> Vec<u8> {
    let mut bytes = &text.as_bytes();

    let len;
    if bytes.len() > MAX_TEXT_LEN { len = MAX_TEXT_LEN; }
    else { len = bytes.len(); }

    let mut size = [0;2];
    BigEndian::write_u16(&mut size, len as u16);

    let mut v = vec!(2, size[0],size[1]);
    v.extend_from_slice(&bytes[0..len]);

    v
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;

fn main() {
    let mut dst = VecDeque::new();
    dst.push_front(Box::new(1));
    dst.push_front(Box::new(2));
    dst.pop_back();

    let mut src = VecDeque::new();
    src.push_front(Box::new(2));
    dst.append(&mut src);
    for a in dst.iter() {
      assert_eq!(**a, 2);
    }

    // Regression test for Debug and Diaplay impl's
    println!("{:?} {:?}", dst, dst.iter());
    println!("{:?}", VecDeque::<u32>::new().iter());

    for a in dst {
      assert_eq!(*a, 2);
    }
}
<commit_msg>test VecDeque::iter_mut aliasing<commit_after>use std::collections::VecDeque;

fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>) {
    // Gather all those references.
    let mut refs: Vec<&mut T> = iter.collect();
    // Use them all. Twice, to be sure we got all interleavings.
    for r in refs.iter_mut() {
        std::mem::swap(dummy, r);
    }
    for r in refs {
        std::mem::swap(dummy, r);
    }
}

fn main() {
    let mut dst = VecDeque::new();
    dst.push_front(Box::new(1));
    dst.push_front(Box::new(2));
    dst.pop_back();

    let mut src = VecDeque::new();
    src.push_front(Box::new(2));
    dst.append(&mut src);
    for a in dst.iter() {
      assert_eq!(**a, 2);
    }

    // Regression test for Debug and Diaplay impl's
    println!("{:?} {:?}", dst, dst.iter());
    println!("{:?}", VecDeque::<u32>::new().iter());

    for a in dst {
        assert_eq!(*a, 2);
    }

    // # Aliasing tests.
    let mut v = std::collections::VecDeque::new();
    v.push_back(1);
    v.push_back(2);

    // Test `fold` bad aliasing.
    let mut it = v.iter_mut();
    let ref0 = it.next().unwrap();
    let sum = it.fold(0, |x, y| x + *y);
    assert_eq!(*ref0 + sum, 3);

    // Test general iterator aliasing.
    v.push_front(0);
    test_all_refs(&mut 0, v.iter_mut());
}
<|endoftext|>


<commit_before>// Core types.
// Copyright (c) 2015 by Shipeng Feng.
// Licensed under the BSD License, see LICENSE for more details.

use std::os;
use std::path::Path;
use std::slice::SliceConcatExt;

use getopts;

use types::{Params, CommandCallback};
use types::{Options, Argument};
use formatting::HelpFormatter;

/// The command is the basic type of command line applications in cli.  This
/// handles command line parsing.
pub struct Command {
    name: String,  // The name of the command to use
    callback: CommandCallback,  // The callback to execute
    options: Vec<Options>,  // The options to register with this command
    arguments: Vec<Argument>,  // The arguments to register with this command
    help: String,  // The help message to use for this command
    epilog: String,  // Printed at the end of the help page
    short_help: String,  // The short help to use for this command, this is shown on the command listing of the parent command
    add_help_option: bool,  // Whether this command registers "--help", default to be true
}

impl Command {
    pub fn new(name: &str, callback: CommandCallback) -> Command {
        Command {
            name: name.to_string(),
            callback: callback,
            options: Vec::new(),
            arguments: Vec::new(),
            help: String::new(),
            epilog: String::new(),
            short_help: String::new(),
            add_help_option: true,
        }
    }

    /// Attaches an option to the command.
    pub fn option(&mut self, short_name: &'static str, long_name: &'static str, help: &'static str,
                  is_flag: bool, is_bool_flag: bool, multiple: bool,
                  required: bool, default: Option<&'static str>) {
        let option = Options::new(short_name, long_name, help, is_flag,
                                  is_bool_flag, multiple, required, default);
        self.options.push(option);
    }

    /// Attaches an argument to the command.
    pub fn argument(&mut self, name: &'static str, required: bool, default: Option<&'static str>) {
        let argument = Argument::new(name, required, default);
        self.arguments.push(argument);
    }

    fn make_formatter(&self) -> HelpFormatter {
        HelpFormatter::new(80, 2)
    }

    fn format_usage(&self, formatter: &mut HelpFormatter) {
        let mut pieces: Vec<String> = Vec::new();
        pieces.push("[OPTIONS]".to_string());
        for argument in self.arguments.iter() {
            pieces.push(argument.get_usage_piece());
        }
        formatter.write_usage(self.name.as_slice(), pieces.concat(), "Usage: ")
    }

    pub fn get_usage(&self) -> String {
        let mut formatter = self.make_formatter();
        self.format_usage(&mut formatter);
        formatter.getvalue()
    }

    fn format_help_text(&self, formatter: &mut HelpFormatter) {
        if !self.help.is_empty() {
            formatter.write_paragraph();
            formatter.indent();
            formatter.write_text(self.help.clone());
            formatter.dedent();
        }
    }

    fn format_options(&self, formatter: &mut HelpFormatter) {
        ()
    }

    fn format_epilog(&self, formatter: &mut HelpFormatter) {
    }

    fn format_help(&self, formatter: &mut HelpFormatter) {
        self.format_usage(formatter);
        self.format_help_text(formatter);
        self.format_options(formatter);
        self.format_epilog(formatter);
    }

    pub fn get_help(&self) -> String {
        let mut formatter = self.make_formatter();
        self.format_help(&mut formatter);
        formatter.getvalue()
    }

    /// Returns the help option.
    fn get_help_option(&self) -> Options {
        let help_option_names = vec!["h", "help"];
        let show_help = |params: Params| {
            print!("{}", self.get_help());
        };
        return Options::new(help_option_names[0], help_option_names[1],
                            "Show this message and exit.", true, true, false, false, None);
    }

    /// This invokes the command with given arguments.
    pub fn invoke(&self, pragram_name: String, args: Vec<String>) {
        let args = self.parse_args(args);
        let callback = self.callback;
        callback(args);
    }

    /// Get all options plus help option.
    fn get_options(&self) -> Vec<Options> {
        let mut options: Vec<Options> = Vec::new();
        for option in self.options.iter() {
            options.push(option.clone());
        }
        let help_option = self.get_help_option();
        options.push(help_option);
        return options;
    }

    /// Creates the underlying option parser for this command.
    fn make_parser(&self) -> getopts::Options {
        let mut parser = getopts::Options::new();
        for option in self.get_options().iter() {
            option.add_to_parser(&mut parser);
        }
        return parser;
    }

    /// Create the parser and parses the arguments.
    fn parse_args(&self, args: Vec<String>) -> Vec<String> {
        args
    }

    /// This is the way to run one command application.
    pub fn run(&self) {
        let mut args = os::args();
        let program = args.remove(0);
        let program_path = Path::new(program.as_slice());
        let program_name = program_path.file_name().unwrap().to_str().unwrap();
        self.invoke(program_name.to_string(), args);
    }
}
<commit_msg>Prepare for bashcomplete<commit_after>// Core types.
// Copyright (c) 2015 by Shipeng Feng.
// Licensed under the BSD License, see LICENSE for more details.

use std::os;
use std::path::Path;
use std::slice::SliceConcatExt;

use getopts;

use types::{Params, CommandCallback};
use types::{Options, Argument};
use formatting::HelpFormatter;

/// The command is the basic type of command line applications in cli.  This
/// handles command line parsing.
pub struct Command {
    name: String,  // The name of the command to use
    callback: CommandCallback,  // The callback to execute
    options: Vec<Options>,  // The options to register with this command
    arguments: Vec<Argument>,  // The arguments to register with this command
    help: String,  // The help message to use for this command
    epilog: String,  // Printed at the end of the help page
    short_help: String,  // The short help to use for this command, this is shown on the command listing of the parent command
    add_help_option: bool,  // Whether this command registers "--help", default to be true
}

impl Command {
    pub fn new(name: &str, callback: CommandCallback) -> Command {
        Command {
            name: name.to_string(),
            callback: callback,
            options: Vec::new(),
            arguments: Vec::new(),
            help: String::new(),
            epilog: String::new(),
            short_help: String::new(),
            add_help_option: true,
        }
    }

    /// Attaches an option to the command.
    pub fn option(&mut self, short_name: &'static str, long_name: &'static str, help: &'static str,
                  is_flag: bool, is_bool_flag: bool, multiple: bool,
                  required: bool, default: Option<&'static str>) {
        let option = Options::new(short_name, long_name, help, is_flag,
                                  is_bool_flag, multiple, required, default);
        self.options.push(option);
    }

    /// Attaches an argument to the command.
    pub fn argument(&mut self, name: &'static str, required: bool, default: Option<&'static str>) {
        let argument = Argument::new(name, required, default);
        self.arguments.push(argument);
    }

    fn make_formatter(&self) -> HelpFormatter {
        HelpFormatter::new(80, 2)
    }

    fn format_usage(&self, formatter: &mut HelpFormatter) {
        let mut pieces: Vec<String> = Vec::new();
        pieces.push("[OPTIONS]".to_string());
        for argument in self.arguments.iter() {
            pieces.push(argument.get_usage_piece());
        }
        formatter.write_usage(self.name.as_slice(), pieces.concat(), "Usage: ")
    }

    pub fn get_usage(&self) -> String {
        let mut formatter = self.make_formatter();
        self.format_usage(&mut formatter);
        formatter.getvalue()
    }

    fn format_help_text(&self, formatter: &mut HelpFormatter) {
        if !self.help.is_empty() {
            formatter.write_paragraph();
            formatter.indent();
            formatter.write_text(self.help.clone());
            formatter.dedent();
        }
    }

    fn format_options(&self, formatter: &mut HelpFormatter) {
        ()
    }

    fn format_epilog(&self, formatter: &mut HelpFormatter) {
    }

    fn format_help(&self, formatter: &mut HelpFormatter) {
        self.format_usage(formatter);
        self.format_help_text(formatter);
        self.format_options(formatter);
        self.format_epilog(formatter);
    }

    pub fn get_help(&self) -> String {
        let mut formatter = self.make_formatter();
        self.format_help(&mut formatter);
        formatter.getvalue()
    }

    /// Returns the help option.
    fn get_help_option(&self) -> Options {
        let help_option_names = vec!["h", "help"];
        let show_help = |params: Params| {
            print!("{}", self.get_help());
        };
        return Options::new(help_option_names[0], help_option_names[1],
                            "Show this message and exit.", true, true, false, false, None);
    }

    /// This invokes the command with given arguments.
    pub fn invoke(&self, pragram_name: String, args: Vec<String>) {
        let args = self.parse_args(args);
        let callback = self.callback;
        callback(args);
    }

    /// Get all options plus help option.
    fn get_options(&self) -> Vec<Options> {
        let mut options: Vec<Options> = Vec::new();
        for option in self.options.iter() {
            options.push(option.clone());
        }
        let help_option = self.get_help_option();
        options.push(help_option);
        return options;
    }

    /// Creates the underlying option parser for this command.
    fn make_parser(&self) -> getopts::Options {
        let mut parser = getopts::Options::new();
        for option in self.get_options().iter() {
            option.add_to_parser(&mut parser);
        }
        return parser;
    }

    /// Create the parser and parses the arguments.
    fn parse_args(&self, args: Vec<String>) -> Vec<String> {
        args
    }

    /// This is the way to run one command application.
    pub fn run(&self) {
        let mut args = os::args();
        let program = args.remove(0);
        let program_path = Path::new(program.as_slice());
        let program_name = program_path.file_name().unwrap().to_str().unwrap();
        // Hook for the Bash completion.
        // bashcomplete(self, program_name);
        self.invoke(program_name.to_string(), args);
    }
}
<|endoftext|>