<commit_before>extern crate time;

use std::iter::Iterator;

use time::{now_utc, Tm, Duration};

pub struct ProgressRecord {

    /// How many elements before this
    num: usize,

    /// How long since we started iterating.
    iterating_for: Duration,

    size_hint: (usize, Option<usize>),

    recent_rate: f32,

    /// The timestamp of when the previous record was created. Will be None if this is first.
    previous_record_tm: Option<Tm>,

    /// When the iteration started
    started_iterating: Tm,

}

impl ProgressRecord {
    /// Returns a basic log message of where we are now. You can construct this yourself, but this
    /// is a helpful convience method.
    pub fn message(&self) -> String {
        format!("{} - Seen {} Rate {}/sec", self.duration_since_start().num_seconds(), self.num_done(), self.recent_rate())
    }

    /// Duration since iteration started
    pub fn duration_since_start(&self) -> Duration {
        self.iterating_for
    }

    /// Number of items we've generated so far
    pub fn num_done(&self) -> usize {
        self.num
    }

    /// Tm for when the previous record was generated. None if there was no previous record.
    pub fn previous_record_tm(&self) -> Option<Tm> {
        self.previous_record_tm
    }

    /// When the iteration started
    pub fn started_iterating(&self) -> Tm {
        self.started_iterating
    }

    /// Prints a basic message
    pub fn print_message(&self) {
        println!("{}", self.message());
    }

    /// Number of items per second
    pub fn rate(&self) -> f32 {
        // number of items per second
        (self.num_done() as f32) / (self.duration_since_start().num_seconds() as f32)
    }

    /// None if we don't know how much we've done (as a fraction), otherwise a value form 0 to 1
    /// for what fraction along we are.
    pub fn fraction(&self) -> Option<f32> {
        if self.is_size_known() {
            let remaining = self.size_hint.0;
            let done = self.num_done();
            Some(( done as f32 ) / ( (remaining+done) as f32 ))
        } else {
            None
        }
    }

    /// None if we don't know how much we've done, otherwise value for 0 to 100 representing how
    /// far along as a percentage we are.
    pub fn percent(&self) -> Option<f32> {
        match self.fraction() {
            None => { None }
            Some(f) => { Some(f * 100.0) }
        }
    }

    /// Print out `msg`, but only if there has been `n` items.
    /// Often you want to print out a debug message every 1,000 items or so. This function does
    /// that.
    pub fn print_every_sec<T: std::fmt::Display>(&self, n: f32, msg: T) {
        if self.should_print_every_sec(n) {
            print!("{}", msg);
        }
    }

    /// Do thing but only if there has been `n` items.
    /// Often you want to print out a debug message every 1,000 items or so. This function does
    /// that.
    pub fn do_every_sec<F: Fn(&Self)>(&self, n: f32, f: F) {
        if self.should_print_every_sec(n) {
            f(self);
        }
    }

    /// If we want to print every `n` sec, should we print now?
    pub fn should_print_every_sec(&self, n: f32) -> bool {
        // get the secs since start as a f32. We only work in millisecond percision
        let secs_since_start: f32 = (self.duration_since_start().num_milliseconds() as f32) / 1_000.;

        let now = now_utc();

        match self.previous_record_tm() {
            None => {
                // This iteration is the first time, so we should print if more than `n` seconds
                // have gone past
                secs_since_start > n
            },
            Some(last_time) => {
                let last_time_offset = ( last_time - self.started_iterating() );
                let last_time_offset: f32 = (last_time_offset.num_milliseconds() as f32) / 1_000.;

                let current_step = (secs_since_start / n);
                let last_step = (last_time_offset / n);

                current_step.trunc() > last_step.trunc()
            },
        }
    }

    /// If we want to print every `n` items, should we print now?
    pub fn should_print_every_items(&self, n: usize) -> bool {
        (self.num_done() - 1) % n == 0
    }

    /// Print out `msg`, but only if there has been `n` items.
    /// Often you want to print out a debug message every 1,000 items or so. This function does
    /// that.
    pub fn print_every<T: std::fmt::Display>(&self, n: usize, msg: T) {
        if self.should_print_every_items(n) {
            print!("{}", msg);
        }
    }

    /// Does the size_hint tell us exactly how many items are left? False iff there is some
    /// ambiguity/unknown
    fn is_size_known(&self) -> bool {
        match self.size_hint.1 {
            None => { false },
            Some(x) => { self.size_hint.0 == x },
        }
    }

    /// The rate of the last few items.
    pub fn recent_rate(&self) -> f32 {
        self.recent_rate
    }

}

/// Wraps an iterator and keeps track of state used for `ProgressRecord`'s
pub struct ProgressRecorderIter<I> {

    /// The iterator that we are iteating on
    iter: I,

    /// How many items have been seen
    count: usize,

    /// When did we start iterating
    started_iterating: Tm,

    /// Keeps track of recent times
    recent_times: Vec<Tm>
}

impl<I: Iterator> ProgressRecorderIter<I> {
    /// Create a new `ProgressRecorderIter` from another iterator.
    pub fn new(iter: I) -> ProgressRecorderIter<I> {
        ProgressRecorderIter{ iter: iter, count: 0, started_iterating: now_utc(), recent_times: Vec::with_capacity(5) }
    }

    /// Calculate the current `ProgressRecord` for where we are now.
    fn generate_record(&mut self) -> ProgressRecord {
        // recent_times is a vec of times, with newer times at the end. However it'll always be <
        // 100 elements long.
        let now = now_utc();
        self.recent_times.push(now);
        while self.recent_times.len() > 100 {
            self.recent_times.remove(0);
        }

        //println!("\nStart of generate_record");
        //println!("Recents {:?} now {}", self.recent_times.iter().map(|d| { format!("{}", d.rfc3339()) }).collect::<Vec<_>>(), now.rfc3339());
        let recent_rate = match self.recent_times.get(0) { None => { ::std::f32::INFINITY }, Some(&first) => {
            //println!("{} {}", self.recent_times.len() as f32, (now - first).num_seconds() as f32);
            (self.recent_times.len() as f32 ) / ((now - first).num_seconds() as f32)
        }, };

        // last element of recent_times will be the current time, for this record. so second last
        // will be the previous time. In python we'd do [-1] for the last, and [-2] for second
        // last.
        let previous_record_tm = match self.recent_times.len() {
            0 | 1 => { None },
            _ => {
                self.recent_times.get(self.recent_times.len()-2).map(|t| { t.clone() })
            }
        };
        //if let Some(t) = previous_record_tm {
        //    println!("Previous record {}", t.rfc3339());
        //}

        self.count += 1;
        ProgressRecord{ num: self.count, iterating_for: now - self.started_iterating, size_hint: self.iter.size_hint(), recent_rate: recent_rate, previous_record_tm: previous_record_tm, started_iterating: self.started_iterating }
    }

}

/// An iterator that records it's progress as it goes along
pub trait ProgressableIter<I> {
    fn progress(self) -> ProgressRecorderIter<I>;
}

impl<I> ProgressableIter<I> for I where I: Iterator {
    /// Convert an iterator into a `ProgressRecorderIter`.
    fn progress(self) -> ProgressRecorderIter<I> {
        ProgressRecorderIter::new(self)
    }
}

impl<I> Iterator for ProgressRecorderIter<I> where I: Iterator {
    type Item = (ProgressRecord, <I as Iterator>::Item);

    #[inline]
    fn next(&mut self) -> Option<(ProgressRecord, <I as Iterator>::Item)> {
        self.iter.next().map(|a| {
            (self.generate_record(), a)
        })
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }

    #[inline]
    fn count(self) -> usize {
        self.iter.count()
    }
}

mod test {
    #[test]
    fn test_simple() {
        use super::ProgressableIter;
        use std::thread::sleep_ms;
        use time::{now_utc, Duration};

        let vec: Vec<u8> = vec![0, 1, 2, 3, 4];
        let mut progressor = vec.iter().progress();

        sleep_ms(500);
        let (state, _) = progressor.next().unwrap();
        assert_eq!(state.message(), "0 - Seen 1 Rate inf/sec");
        // It'll always print on the first one
        assert_eq!(state.should_print_every_items(2), true);
        assert_eq!(state.should_print_every_items(3), true);
        assert_eq!(state.should_print_every_items(5), true);
        assert_eq!(state.rate(), ::std::f32::INFINITY);
        assert_eq!(state.recent_rate(), ::std::f32::INFINITY);
        // First run, so there should be nothing here
        assert!(state.previous_record_tm().is_none());

        assert_eq!(state.should_print_every_sec(1.), false);
        assert_eq!(state.should_print_every_sec(2.), false);
        assert_eq!(state.should_print_every_sec(0.3), true);

        sleep_ms(500);

        let (state, _) = progressor.next().unwrap();
        assert_eq!(state.message(), "1 - Seen 2 Rate inf/sec");
        assert_eq!(state.should_print_every_items(2), false);
        assert_eq!(state.should_print_every_items(3), false);
        assert_eq!(state.should_print_every_items(5), false);
        assert_eq!(state.rate(), 2.);
        //assert_eq!(state.recent_rate(), 2.);
        // This'll be the time for the first one
        assert!(state.previous_record_tm().is_some());
        let last_time = state.previous_record_tm().unwrap();
        assert_eq!((now_utc() - last_time).num_milliseconds(), 500);
        assert!((now_utc() - last_time).num_milliseconds() < 550);
        assert!((now_utc() - last_time).num_milliseconds() >= 500);
        assert_eq!(state.should_print_every_sec(1.), true);
        assert_eq!(state.should_print_every_sec(2.), false);
        assert_eq!(state.should_print_every_sec(0.8), true);

        sleep_ms(500);
        let (state, _) = progressor.next().unwrap();
        assert_eq!(state.message(), "1 - Seen 3 Rate 3/sec");
        assert_eq!(state.should_print_every_items(2), true);
        assert_eq!(state.should_print_every_items(3), false);
        assert_eq!(state.should_print_every_items(5), false);
        assert_eq!(state.rate(), 3.);
        assert_eq!(state.recent_rate(), 3.);
        assert_eq!(state.should_print_every_sec(1.), false);
        assert_eq!(state.should_print_every_sec(2.), false);
        assert_eq!(state.should_print_every_sec(0.8), false);
        assert_eq!(state.should_print_every_sec(1.5), true);

        sleep_ms(500);
        let (state, _) = progressor.next().unwrap();
        assert_eq!(state.message(), "2 - Seen 4 Rate 4/sec");
        assert_eq!(state.should_print_every_items(2), false);
        assert_eq!(state.should_print_every_items(3), true);
        assert_eq!(state.should_print_every_items(5), false);
        assert_eq!(state.rate(), 2.);
        assert_eq!(state.recent_rate(), 4.);
    }

    #[test]
    fn test_size_hint() {
        use super::ProgressableIter;
        use time::Duration;

        let vec: Vec<u8> = vec![0, 1, 2, 3, 4];
        let mut progressor = vec.iter().progress();

        let (state, _) = progressor.next().unwrap();
        assert_eq!(state.fraction(), Some(0.2));
        assert_eq!(state.percent(), Some(20.));

        let (state, _) = progressor.next().unwrap();
        assert_eq!(state.fraction(), Some(0.4));
        assert_eq!(state.percent(), Some(40.));

        let mut progressor = (0..).progress();

        let (state, val) = progressor.next().unwrap();
        assert_eq!(val, 0);
        assert_eq!(state.fraction(), None);
        let (state, val) = progressor.next().unwrap();
        assert_eq!(val, 1);
        assert_eq!(state.fraction(), None);

    }
}

<commit_msg>refactor: Rename methods to be consistent<commit_after>extern crate time;

use std::iter::Iterator;

use time::{now_utc, Tm, Duration};

pub struct ProgressRecord {

    /// How many elements before this
    num: usize,

    /// How long since we started iterating.
    iterating_for: Duration,

    size_hint: (usize, Option<usize>),

    recent_rate: f32,

    /// The timestamp of when the previous record was created. Will be None if this is first.
    previous_record_tm: Option<Tm>,

    /// When the iteration started
    started_iterating: Tm,

}

impl ProgressRecord {
    /// Returns a basic log message of where we are now. You can construct this yourself, but this
    /// is a helpful convience method.
    pub fn message(&self) -> String {
        format!("{} - Seen {} Rate {}/sec", self.duration_since_start().num_seconds(), self.num_done(), self.recent_rate())
    }

    /// Duration since iteration started
    pub fn duration_since_start(&self) -> Duration {
        self.iterating_for
    }

    /// Number of items we've generated so far
    pub fn num_done(&self) -> usize {
        self.num
    }

    /// Tm for when the previous record was generated. None if there was no previous record.
    pub fn previous_record_tm(&self) -> Option<Tm> {
        self.previous_record_tm
    }

    /// When the iteration started
    pub fn started_iterating(&self) -> Tm {
        self.started_iterating
    }

    /// Prints a basic message
    pub fn print_message(&self) {
        println!("{}", self.message());
    }

    /// Number of items per second
    pub fn rate(&self) -> f32 {
        // number of items per second
        (self.num_done() as f32) / (self.duration_since_start().num_seconds() as f32)
    }

    /// None if we don't know how much we've done (as a fraction), otherwise a value form 0 to 1
    /// for what fraction along we are.
    pub fn fraction(&self) -> Option<f32> {
        if self.is_size_known() {
            let remaining = self.size_hint.0;
            let done = self.num_done();
            Some(( done as f32 ) / ( (remaining+done) as f32 ))
        } else {
            None
        }
    }

    /// None if we don't know how much we've done, otherwise value for 0 to 100 representing how
    /// far along as a percentage we are.
    pub fn percent(&self) -> Option<f32> {
        match self.fraction() {
            None => { None }
            Some(f) => { Some(f * 100.0) }
        }
    }

    /// Print out `msg`, but only if there has been `n` seconds since last printout
    pub fn print_every_n_sec<T: std::fmt::Display>(&self, n: f32, msg: T) {
        if self.should_do_every_n_sec(n) {
            print!("{}", msg);
        }
    }

    /// Do thing but only every n sec (as far as possible).
    /// Could be a print statement.
    pub fn do_every_n_sec<F: Fn(&Self)>(&self, n: f32, f: F) {
        if self.should_do_every_n_sec(n) {
            f(self);
        }
    }

    /// If we want to print every `n` sec, should we print now?
    pub fn should_do_every_n_sec(&self, n: f32) -> bool {
        // get the secs since start as a f32. We only work in millisecond percision
        let secs_since_start: f32 = (self.duration_since_start().num_milliseconds() as f32) / 1_000.;

        let now = now_utc();

        match self.previous_record_tm() {
            None => {
                // This iteration is the first time, so we should print if more than `n` seconds
                // have gone past
                secs_since_start > n
            },
            Some(last_time) => {
                let last_time_offset = ( last_time - self.started_iterating() );
                let last_time_offset: f32 = (last_time_offset.num_milliseconds() as f32) / 1_000.;

                let current_step = (secs_since_start / n);
                let last_step = (last_time_offset / n);

                current_step.trunc() > last_step.trunc()
            },
        }
    }

    /// If we want to print every `n` items, should we print now?
    pub fn should_do_every_n_items(&self, n: usize) -> bool {
        (self.num_done() - 1) % n == 0
    }

    /// Print out `msg`, but only if there has been `n` items.
    /// Often you want to print out a debug message every 1,000 items or so. This function does
    /// that.
    pub fn print_every_n_items<T: std::fmt::Display>(&self, n: usize, msg: T) {
        if self.should_do_every_n_items(n) {
            print!("{}", msg);
        }
    }

    /// Do thing but only every n items.
    /// Could be a print statement.
    pub fn do_every_n_items<F: Fn(&Self)>(&self, n: usize, f: F) {
        if self.should_do_every_n_items(n) {
            f(self);
        }
    }

    /// Does the size_hint tell us exactly how many items are left? False iff there is some
    /// ambiguity/unknown
    fn is_size_known(&self) -> bool {
        match self.size_hint.1 {
            None => { false },
            Some(x) => { self.size_hint.0 == x },
        }
    }

    /// The rate of the last few items.
    pub fn recent_rate(&self) -> f32 {
        self.recent_rate
    }

}

/// Wraps an iterator and keeps track of state used for `ProgressRecord`'s
pub struct ProgressRecorderIter<I> {

    /// The iterator that we are iteating on
    iter: I,

    /// How many items have been seen
    count: usize,

    /// When did we start iterating
    started_iterating: Tm,

    /// Keeps track of recent times
    recent_times: Vec<Tm>
}

impl<I: Iterator> ProgressRecorderIter<I> {
    /// Create a new `ProgressRecorderIter` from another iterator.
    pub fn new(iter: I) -> ProgressRecorderIter<I> {
        ProgressRecorderIter{ iter: iter, count: 0, started_iterating: now_utc(), recent_times: Vec::with_capacity(5) }
    }

    /// Calculate the current `ProgressRecord` for where we are now.
    fn generate_record(&mut self) -> ProgressRecord {
        // recent_times is a vec of times, with newer times at the end. However it'll always be <
        // 100 elements long.
        let now = now_utc();
        self.recent_times.push(now);
        while self.recent_times.len() > 100 {
            self.recent_times.remove(0);
        }

        //println!("\nStart of generate_record");
        //println!("Recents {:?} now {}", self.recent_times.iter().map(|d| { format!("{}", d.rfc3339()) }).collect::<Vec<_>>(), now.rfc3339());
        let recent_rate = match self.recent_times.get(0) { None => { ::std::f32::INFINITY }, Some(&first) => {
            //println!("{} {}", self.recent_times.len() as f32, (now - first).num_seconds() as f32);
            (self.recent_times.len() as f32 ) / ((now - first).num_seconds() as f32)
        }, };

        // last element of recent_times will be the current time, for this record. so second last
        // will be the previous time. In python we'd do [-1] for the last, and [-2] for second
        // last.
        let previous_record_tm = match self.recent_times.len() {
            0 | 1 => { None },
            _ => {
                self.recent_times.get(self.recent_times.len()-2).map(|t| { t.clone() })
            }
        };
        //if let Some(t) = previous_record_tm {
        //    println!("Previous record {}", t.rfc3339());
        //}

        self.count += 1;
        ProgressRecord{ num: self.count, iterating_for: now - self.started_iterating, size_hint: self.iter.size_hint(), recent_rate: recent_rate, previous_record_tm: previous_record_tm, started_iterating: self.started_iterating }
    }

}

/// An iterator that records it's progress as it goes along
pub trait ProgressableIter<I> {
    fn progress(self) -> ProgressRecorderIter<I>;
}

impl<I> ProgressableIter<I> for I where I: Iterator {
    /// Convert an iterator into a `ProgressRecorderIter`.
    fn progress(self) -> ProgressRecorderIter<I> {
        ProgressRecorderIter::new(self)
    }
}

impl<I> Iterator for ProgressRecorderIter<I> where I: Iterator {
    type Item = (ProgressRecord, <I as Iterator>::Item);

    #[inline]
    fn next(&mut self) -> Option<(ProgressRecord, <I as Iterator>::Item)> {
        self.iter.next().map(|a| {
            (self.generate_record(), a)
        })
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }

    #[inline]
    fn count(self) -> usize {
        self.iter.count()
    }
}

mod test {
    #[test]
    fn test_simple() {
        use super::ProgressableIter;
        use std::thread::sleep_ms;
        use time::{now_utc, Duration};

        let vec: Vec<u8> = vec![0, 1, 2, 3, 4];
        let mut progressor = vec.iter().progress();

        sleep_ms(500);
        let (state, _) = progressor.next().unwrap();
        assert_eq!(state.message(), "0 - Seen 1 Rate inf/sec");
        // It'll always print on the first one
        assert_eq!(state.should_do_every_n_items(2), true);
        assert_eq!(state.should_do_every_n_items(3), true);
        assert_eq!(state.should_do_every_n_items(5), true);
        assert_eq!(state.rate(), ::std::f32::INFINITY);
        assert_eq!(state.recent_rate(), ::std::f32::INFINITY);
        // First run, so there should be nothing here
        assert!(state.previous_record_tm().is_none());

        assert_eq!(state.should_do_every_n_sec(1.), false);
        assert_eq!(state.should_do_every_n_sec(2.), false);
        assert_eq!(state.should_do_every_n_sec(0.3), true);

        sleep_ms(500);

        let (state, _) = progressor.next().unwrap();
        assert_eq!(state.message(), "1 - Seen 2 Rate inf/sec");
        assert_eq!(state.should_do_every_n_items(2), false);
        assert_eq!(state.should_do_every_n_items(3), false);
        assert_eq!(state.should_do_every_n_items(5), false);
        assert_eq!(state.rate(), 2.);
        //assert_eq!(state.recent_rate(), 2.);
        // This'll be the time for the first one
        assert!(state.previous_record_tm().is_some());
        let last_time = state.previous_record_tm().unwrap();
        assert_eq!((now_utc() - last_time).num_milliseconds(), 500);
        assert!((now_utc() - last_time).num_milliseconds() < 550);
        assert!((now_utc() - last_time).num_milliseconds() >= 500);
        assert_eq!(state.should_do_every_n_sec(1.), true);
        assert_eq!(state.should_do_every_n_sec(2.), false);
        assert_eq!(state.should_do_every_n_sec(0.8), true);

        sleep_ms(500);
        let (state, _) = progressor.next().unwrap();
        assert_eq!(state.message(), "1 - Seen 3 Rate 3/sec");
        assert_eq!(state.should_do_every_n_items(2), true);
        assert_eq!(state.should_do_every_n_items(3), false);
        assert_eq!(state.should_do_every_n_items(5), false);
        assert_eq!(state.rate(), 3.);
        assert_eq!(state.recent_rate(), 3.);
        assert_eq!(state.should_do_every_n_sec(1.), false);
        assert_eq!(state.should_do_every_n_sec(2.), false);
        assert_eq!(state.should_do_every_n_sec(0.8), false);
        assert_eq!(state.should_do_every_n_sec(1.5), true);

        sleep_ms(500);
        let (state, _) = progressor.next().unwrap();
        assert_eq!(state.message(), "2 - Seen 4 Rate 4/sec");
        assert_eq!(state.should_do_every_n_items(2), false);
        assert_eq!(state.should_do_every_n_items(3), true);
        assert_eq!(state.should_do_every_n_items(5), false);
        assert_eq!(state.rate(), 2.);
        assert_eq!(state.recent_rate(), 4.);
    }

    #[test]
    fn test_size_hint() {
        use super::ProgressableIter;
        use time::Duration;

        let vec: Vec<u8> = vec![0, 1, 2, 3, 4];
        let mut progressor = vec.iter().progress();

        let (state, _) = progressor.next().unwrap();
        assert_eq!(state.fraction(), Some(0.2));
        assert_eq!(state.percent(), Some(20.));

        let (state, _) = progressor.next().unwrap();
        assert_eq!(state.fraction(), Some(0.4));
        assert_eq!(state.percent(), Some(40.));

        let mut progressor = (0..).progress();

        let (state, val) = progressor.next().unwrap();
        assert_eq!(val, 0);
        assert_eq!(state.fraction(), None);
        let (state, val) = progressor.next().unwrap();
        assert_eq!(val, 1);
        assert_eq!(state.fraction(), None);

    }
}

<|endoftext|>


<commit_before>#![allow(dead_code)]
#![feature(plugin, custom_derive)]
#![plugin(serde_macros)]

#[macro_use]
extern crate nom;
extern crate serde;

#[cfg(test)] extern crate serde_json;

pub use self::models::*;
pub use self::parsing::*;
mod models;
mod parsing;

<commit_msg>Don't allow dead code annotation<commit_after>#![feature(plugin, custom_derive)]
#![plugin(serde_macros)]

#[macro_use]
extern crate nom;
extern crate serde;

#[cfg(test)] extern crate serde_json;

pub use self::models::*;
pub use self::parsing::*;
mod models;
mod parsing;

<|endoftext|>


<commit_before>#![cfg_attr(feature = "unstable", feature(plugin))]
#![cfg_attr(feature = "unstable", plugin(clippy))]

//! An implementation of the [Shoemake Arcball Camera](http://dl.acm.org/citation.cfm?id=155312)
//! using [cgmath](https://crates.io/crates/cgmath). See the
//! [cube example](https://github.com/Twinklebear/arcball/blob/master/examples/cube.rs) for an example
//! of use with [glium](https://crates.io/crates/glium).
extern crate cgmath;

use cgmath::prelude::*;
use cgmath::{Matrix4, Quaternion, Vector2, Vector3};

/// The Shoemake Arcball camera.
pub struct ArcballCamera {
    look_at: Matrix4<f32>,
    translation: Matrix4<f32>,
    rotation: Quaternion<f32>,
    camera: Matrix4<f32>,
    inv_camera: Matrix4<f32>,
    motion_speed: f32,
    zoom_speed: f32,
    inv_screen: [f32; 2],
}

impl ArcballCamera {
    /// Create a new Arcball camera starting from the look at matrix `look_at`. The `motion_speed`
    /// sets the speed for panning and `zoom_speed` the speed for zooming the camera. `screen` should be
    /// `[screen_width, screen_height]`
    pub fn new(look_at: &Matrix4<f32>, motion_speed: f32, zoom_speed: f32, screen: [f32; 2]) -> ArcballCamera {
        ArcballCamera {
            look_at: look_at.clone(),
            translation: Transform::one(),
            rotation: Quaternion::new(1.0, 0.0, 0.0, 0.0),
            camera: look_at.clone(),
            inv_camera: look_at.invert().unwrap(),
            motion_speed: motion_speed,
            zoom_speed: zoom_speed,
            inv_screen: [1.0 / screen[0], 1.0 / screen[1]],
        }
    }
    /// Get the view matrix computed by the camera.
    pub fn get_mat4(&self) -> Matrix4<f32> {
        self.camera
    }
    /// Rotate the camera, mouse positions should be in pixel coordinates.
    ///
    /// Rotates starting from the orientation at the previous mouse position, `mouse_prev`,
    /// and rotating to desired orientation at the current mouse position, `mouse_cur`.
    pub fn rotate(&mut self, mouse_prev: Vector2<f32>, mouse_cur: Vector2<f32>) {
        let m_cur = Vector2::new(clamp(mouse_cur.x * 2.0 * self.inv_screen[0] - 1.0, -1.0, 1.0),
                                    clamp(1.0 - 2.0 * mouse_cur.y * self.inv_screen[1], -1.0, 1.0));
        let m_prev = Vector2::new(clamp(mouse_prev.x * 2.0 * self.inv_screen[0] - 1.0, -1.0, 1.0),
                                    clamp(1.0 - 2.0 * mouse_prev.y * self.inv_screen[1], -1.0, 1.0));
        let mouse_cur_ball = ArcballCamera::screen_to_arcball(m_cur);
        let mouse_prev_ball = ArcballCamera::screen_to_arcball(m_prev);
        self.rotation = mouse_cur_ball * mouse_prev_ball * self.rotation;
        self.camera = self.translation * self.look_at * Matrix4::from(self.rotation);
        self.inv_camera = self.camera.invert().unwrap();
    }
    /// Zoom the camera in by some amount, positive values zoom in, negative zoom out.
    pub fn zoom(&mut self, amount: f32, elapsed: f32) {
        let motion = Vector3::new(0.0, 0.0, amount);
        self.translation = Matrix4::from_translation(motion * self.zoom_speed * elapsed) * self.translation;
        self.camera = self.translation * self.look_at * Matrix4::from(self.rotation);
        self.inv_camera = self.camera.invert().unwrap();
    }
    /// Pan the camera following the delta motion of the mouse. Mouse delta should be in pixels.
    pub fn pan(&mut self, mouse_delta: Vector2<f32>, elapsed: f32) {
        let motion = Vector3::new(mouse_delta.x, mouse_delta.y, 0.0) * self.motion_speed * elapsed;
        self.translation = Matrix4::from_translation(motion) * self.translation;
        self.camera = self.translation * self.look_at * Matrix4::from(self.rotation);
        self.inv_camera = self.camera.invert().unwrap();
    }
    /// Update the screen dimensions if the window has resized.
    pub fn update_screen(&mut self, width: f32, height: f32) {
        self.inv_screen[0] = 1.0 / width;
        self.inv_screen[1] = 1.0 / height;
    }
    fn screen_to_arcball(p: Vector2<f32>) -> Quaternion<f32> {
        let dist = cgmath::dot(p, p);
        // If we're on/in the sphere return the point on it
        if dist <= 1.0 {
            Quaternion::new(0.0, p.x, p.y, f32::sqrt(1.0 - dist))
        } else {
            let unit_p = p.normalize();
            Quaternion::new(0.0, unit_p.x, unit_p.y, 0.0)
        }
    }
}

fn clamp(x: f32, min: f32, max: f32) -> f32 {
    if x < min {
        min
    } else if x > max {
        max
    } else {
        x
    }
}

<commit_msg>Clippy lint fixes<commit_after>#![cfg_attr(feature = "unstable", feature(plugin))]
#![cfg_attr(feature = "unstable", plugin(clippy))]

//! An implementation of the [Shoemake Arcball Camera](http://dl.acm.org/citation.cfm?id=155312)
//! using [cgmath](https://crates.io/crates/cgmath). See the
//! [cube example](https://github.com/Twinklebear/arcball/blob/master/examples/cube.rs) for an example
//! of use with [glium](https://crates.io/crates/glium).
extern crate cgmath;

use cgmath::prelude::*;
use cgmath::{Matrix4, Quaternion, Vector2, Vector3};

/// The Shoemake Arcball camera.
pub struct ArcballCamera {
    look_at: Matrix4<f32>,
    translation: Matrix4<f32>,
    rotation: Quaternion<f32>,
    camera: Matrix4<f32>,
    inv_camera: Matrix4<f32>,
    motion_speed: f32,
    zoom_speed: f32,
    inv_screen: [f32; 2],
}

impl ArcballCamera {
    /// Create a new Arcball camera starting from the look at matrix `look_at`. The `motion_speed`
    /// sets the speed for panning and `zoom_speed` the speed for zooming the camera. `screen` should be
    /// `[screen_width, screen_height]`
    pub fn new(look_at: &Matrix4<f32>, motion_speed: f32, zoom_speed: f32, screen: [f32; 2]) -> ArcballCamera {
        ArcballCamera {
            look_at: *look_at,
            translation: Transform::one(),
            rotation: Quaternion::new(1.0, 0.0, 0.0, 0.0),
            camera: *look_at,
            inv_camera: look_at.invert().unwrap(),
            motion_speed: motion_speed,
            zoom_speed: zoom_speed,
            inv_screen: [1.0 / screen[0], 1.0 / screen[1]],
        }
    }
    /// Get the view matrix computed by the camera.
    pub fn get_mat4(&self) -> Matrix4<f32> {
        self.camera
    }
    /// Rotate the camera, mouse positions should be in pixel coordinates.
    ///
    /// Rotates starting from the orientation at the previous mouse position, `mouse_prev`,
    /// and rotating to desired orientation at the current mouse position, `mouse_cur`.
    pub fn rotate(&mut self, mouse_prev: Vector2<f32>, mouse_cur: Vector2<f32>) {
        let m_cur = Vector2::new(clamp(mouse_cur.x * 2.0 * self.inv_screen[0] - 1.0, -1.0, 1.0),
                                    clamp(1.0 - 2.0 * mouse_cur.y * self.inv_screen[1], -1.0, 1.0));
        let m_prev = Vector2::new(clamp(mouse_prev.x * 2.0 * self.inv_screen[0] - 1.0, -1.0, 1.0),
                                    clamp(1.0 - 2.0 * mouse_prev.y * self.inv_screen[1], -1.0, 1.0));
        let mouse_cur_ball = ArcballCamera::screen_to_arcball(m_cur);
        let mouse_prev_ball = ArcballCamera::screen_to_arcball(m_prev);
        self.rotation = mouse_cur_ball * mouse_prev_ball * self.rotation;
        self.camera = self.translation * self.look_at * Matrix4::from(self.rotation);
        self.inv_camera = self.camera.invert().unwrap();
    }
    /// Zoom the camera in by some amount, positive values zoom in, negative zoom out.
    pub fn zoom(&mut self, amount: f32, elapsed: f32) {
        let motion = Vector3::new(0.0, 0.0, amount);
        self.translation = Matrix4::from_translation(motion * self.zoom_speed * elapsed) * self.translation;
        self.camera = self.translation * self.look_at * Matrix4::from(self.rotation);
        self.inv_camera = self.camera.invert().unwrap();
    }
    /// Pan the camera following the delta motion of the mouse. Mouse delta should be in pixels.
    pub fn pan(&mut self, mouse_delta: Vector2<f32>, elapsed: f32) {
        let motion = Vector3::new(mouse_delta.x, mouse_delta.y, 0.0) * self.motion_speed * elapsed;
        self.translation = Matrix4::from_translation(motion) * self.translation;
        self.camera = self.translation * self.look_at * Matrix4::from(self.rotation);
        self.inv_camera = self.camera.invert().unwrap();
    }
    /// Update the screen dimensions if the window has resized.
    pub fn update_screen(&mut self, width: f32, height: f32) {
        self.inv_screen[0] = 1.0 / width;
        self.inv_screen[1] = 1.0 / height;
    }
    fn screen_to_arcball(p: Vector2<f32>) -> Quaternion<f32> {
        let dist = cgmath::dot(p, p);
        // If we're on/in the sphere return the point on it
        if dist <= 1.0 {
            Quaternion::new(0.0, p.x, p.y, f32::sqrt(1.0 - dist))
        } else {
            let unit_p = p.normalize();
            Quaternion::new(0.0, unit_p.x, unit_p.y, 0.0)
        }
    }
}

fn clamp(x: f32, min: f32, max: f32) -> f32 {
    if x < min {
        min
    } else if x > max {
        max
    } else {
        x
    }
}

<|endoftext|>


<commit_before>//! Toy Math Library

use std::ops::{Add, Mul};

/// Calculate sine function with Taylor series as approximation approach
///
///
/// ```raw
///              x^3   x^5   x^7   x^9   x^11   x^13
/// sin(x) = x - --- + --- - --- + --- - ---- + ---- - ...
///               3!    5!    7!    9!    11!    13!
/// ```
///
/// Error Function :
///
/// ```raw
/// Error(x) = | sin(x) - taylor_sin(x) |
/// ```
///
/// * the error getting smaller when x getting close to 0
/// * the error getting greater when x getting far from 0
///
/// limit the x will make precision greater
///
/// trigonometric identities we can use :
///
/// * sin(2π+β) = sin(β)
/// * sin(π+β) = -sin(β)
/// * sin(-π/2+β) = -cos(β)
///
/// `sin(x) = sin(απ+β) = (-1)^α sin(β), ∀ α ∈ ℤ, β ∈ ℝ, 0 ≦ β < π`
///
pub fn taylor_sin<T>(x: T) -> T
    where T: Mul<T, Output=T> + Mul<f64, Output=T> +
             Add<T, Output=T> + Add<f64, Output=T> +
             Copy
{

    const A0: f64 =  1.0;                                   //  1/1!
    const A1: f64 = -1.666666666666666666666666666666E-1;   // -1/3!
    const A2: f64 =  8.333333333333333333333333333333E-3;   //  1/5!
    const A3: f64 = -1.984126984126984126984126984126E-4;   // -1/7!
    const A4: f64 =  2.755731922398589065255731922398E-6;   //  1/9!
    const A5: f64 = -2.505210838544171877505210838544E-8;   // -1/11!
    const A6: f64 =  1.605904383682161459939237717015E-10;  //  1/13!

    let x2 = x * x;

    ((((((
        x2 * A6
           + A5) * x2
           + A4) * x2
           + A3) * x2
           + A2) * x2
           + A1) * x2
           + A0) * x

}

/// Calculate cosine function with Taylor series as approximation approach
///
///
/// ```raw
///              x^2   x^4   x^6   x^8   x^10   x^12
/// sin(x) = 1 - --- + --- - --- + --- - ---- + ---- - ...
///               2!    4!    6!    8!    10!    12!
/// ```
///
/// Error Function :
///
/// ```raw
/// Error(x) = | cos(x) - taylor_cos(x) |
/// ```
///
/// * the error getting smaller when x getting close to 0
/// * the error getting greater when x getting far from 0
///
/// limit the x will make precision greater
///
/// trigonometric identities we can use :
///
/// * cos(2π+β) = cos(β)
/// * cos(π+β) = -cos(β)
/// * cos(-π/2+β) = sin(β)
///
/// `sin(x) = sin(απ+β) = (-1)^α sin(β), ∀ α ∈ ℤ, β ∈ ℝ, 0 ≦ β < π`
///
pub fn taylor_cos<T>(x: T) -> T
    where T: Mul<T, Output=T> + Mul<f64, Output=T> +
             Add<T, Output=T> + Add<f64, Output=T> +
             Copy
{

    const A0: f64 =  1.0;                                   //  1/0!
    const A1: f64 = -0.5;                                   // -1/2!
    const A2: f64 =  4.166666666666666666666666666666E-2;   //  1/4!
    const A3: f64 = -1.388888888888888888888888888888E-3;   // -1/6!
    const A4: f64 =  2.480158730158730158730158730158E-5;   //  1/8!
    const A5: f64 = -2.755731922398589065255731922398E-7;   // -1/10!
    const A6: f64 =  2.087675698786809897921009032120E-9;   //  1/12!

    let x2 = x * x;

    ((((((
        x2 * A6
           + A5) * x2
           + A4) * x2
           + A3) * x2
           + A2) * x2
           + A1) * x2
           + A0)

}

/// sine function for f64
///
/// Currently, we call [taylor_sin] and [taylor_cos] as implementation.
///
/// [taylor_sin]: fn.taylor_sin.html
/// [taylor_cos]: fn.taylor_cos.html
///
pub fn sin(data: f64) -> f64 {
    use std::f64::consts::{PI, FRAC_PI_2, FRAC_PI_4};

    // [-∞, ∞] => (-π, π)
    // sin(θ) = -sin(θ-π)
    let (data, neg_flag) = (data % PI, ((data / PI) as u8) % 2 != 0);
    // (-π, π) => (0, π)
    // sin(θ) = -sin(-θ)
    let (data, neg_flag) = (data.abs(), neg_flag ^ (data < 0.));

    let ret = match data {
        data if ((0. <= data) && (data < FRAC_PI_4)) => {
            // sin(θ)
            taylor_sin(data)
        },
        data if ((FRAC_PI_4 <= data) && (data < (PI - FRAC_PI_4))) => {
            // sin(θ) = cos(θ-π/2)
            taylor_cos(data - FRAC_PI_2)
        },
        data if (((PI - FRAC_PI_4) <= data) && (data < PI)) => {
            // sin(θ) = sin(π-θ)
            taylor_sin(PI - data)
        },
        _ => { panic!("why are you here ?") }
    };

    if neg_flag {
        return -ret;
    }

    ret
}

/// sine function for f32
///
/// Currently, we call [sin] as implementation.
///
/// [sin]: fn.sin.html
pub fn sinf(data: f32) -> f32 {
    sin(data as f64) as f32
}

/// cosine function for f64
///
/// Currently, we call [sin] as implementation.
///
/// [sin]: fn.sin.html
pub fn cos(data: f64) -> f64 {
    use std::f64::consts::FRAC_PI_2;

    sin(FRAC_PI_2 - data)
}

/// cosine function for f32
///
/// Currently, we call [cos] as implementation.
///
/// [cos]: fn.cos.html
pub fn cosf(data: f32) -> f32 {
    cos(data as f64) as f32
}
<commit_msg>update polynomial coefficients<commit_after>//! Toy Math Library

use std::ops::{Add, Mul};

/// Calculate sine function with modified Taylor series as approximation approach
///
///
/// ```raw
///              x^3   x^5   x^7   x^9   x^11   x^13
/// sin(x) = x - --- + --- - --- + --- - ---- + ---- - ...
///               3!    5!    7!    9!    11!    13!
/// ```
///
/// Error Function :
///
/// ```raw
/// Error(x) = | sin(x) - poly_sin(x) |
/// ```
///
/// * the error getting smaller when x getting close to 0
/// * the error getting greater when x getting far from 0
///
/// limit the x will make precision greater
///
/// trigonometric identities we can use :
///
/// * sin(2π+β) = sin(β)
/// * sin(π+β) = -sin(β)
/// * sin(-π/2+β) = -cos(β)
///
/// `sin(x) = sin(απ+β) = (-1)^α sin(β), ∀ α ∈ ℤ, β ∈ ℝ, 0 ≦ β < π`
///
pub fn poly_sin<T>(x: T) -> T
    where T: Mul<T, Output=T> + Mul<f64, Output=T> +
             Add<T, Output=T> + Add<f64, Output=T> +
             Copy
{

    // taylor
    // const A0: f64 =  1.0;                                   //  1/1!
    // const A1: f64 = -1.666666666666666666666666666666E-1;   // -1/3!
    // const A2: f64 =  8.333333333333333333333333333333E-3;   //  1/5!
    // const A3: f64 = -1.984126984126984126984126984126E-4;   // -1/7!
    // const A4: f64 =  2.755731922398589065255731922398E-6;   //  1/9!
    // const A5: f64 = -2.505210838544171877505210838544E-8;   // -1/11!
    // const A6: f64 =  1.605904383682161459939237717015E-10;  //  1/13!

    // modified
    const A0: f64 =  1.0;
    const A1: f64 = -1.66666666666666324348E-1;
    const A2: f64 =  8.33333333332248946124E-3;
    const A3: f64 = -1.98412698298579493134E-4;
    const A4: f64 =  2.75573137070700676789E-6;
    const A5: f64 = -2.50507602534068634195E-8;
    const A6: f64 =  1.58969099521155010221E-10;

    let x2 = x * x;

    ((((((
        x2 * A6
           + A5) * x2
           + A4) * x2
           + A3) * x2
           + A2) * x2
           + A1) * x2
           + A0) * x

}

/// Calculate cosine function with modified Taylor series as approximation approach
///
///
/// ```raw
///              x^2   x^4   x^6   x^8   x^10   x^12
/// sin(x) = 1 - --- + --- - --- + --- - ---- + ---- - ...
///               2!    4!    6!    8!    10!    12!
/// ```
///
/// Error Function :
///
/// ```raw
/// Error(x) = | cos(x) - poly_cos(x) |
/// ```
///
/// * the error getting smaller when x getting close to 0
/// * the error getting greater when x getting far from 0
///
/// limit the x will make precision greater
///
/// trigonometric identities we can use :
///
/// * cos(2π+β) = cos(β)
/// * cos(π+β) = -cos(β)
/// * cos(-π/2+β) = sin(β)
///
/// `sin(x) = sin(απ+β) = (-1)^α sin(β), ∀ α ∈ ℤ, β ∈ ℝ, 0 ≦ β < π`
///
pub fn poly_cos<T>(x: T) -> T
    where T: Mul<T, Output=T> + Mul<f64, Output=T> +
             Add<T, Output=T> + Add<f64, Output=T> +
             Copy
{

    // taylor
    // const A0: f64 =  1.0;                                   //  1/0!
    // const A1: f64 = -0.5;                                   // -1/2!
    // const A2: f64 =  4.166666666666666666666666666666E-2;   //  1/4!
    // const A3: f64 = -1.388888888888888888888888888888E-3;   // -1/6!
    // const A4: f64 =  2.480158730158730158730158730158E-5;   //  1/8!
    // const A5: f64 = -2.755731922398589065255731922398E-7;   // -1/10!
    // const A6: f64 =  2.087675698786809897921009032120E-9;   //  1/12!

    // modified
    const A0: f64 =  1.0;
    const A1: f64 = -0.5;
    const A2: f64 =  4.16666666666666019037E-2;
    const A3: f64 = -1.38888888888741095749E-3;
    const A4: f64 =  2.48015872894767294178E-05;
    const A5: f64 = -2.75573143513906633035E-7;
    const A6: f64 =  2.08757232129817482790E-9;
    //const A7: f64 = -1.13596475577881948265E-11;

    let x2 = x * x;

    ((((((
        x2 * A6
           + A5) * x2
           + A4) * x2
           + A3) * x2
           + A2) * x2
           + A1) * x2
           + A0)

}

/// sine function for f64
///
/// Currently, we call [poly_sin] and [poly_cos] as implementation.
///
/// [poly_sin]: fn.poly_sin.html
/// [poly_cos]: fn.poly_cos.html
///
pub fn sin(data: f64) -> f64 {
    use std::f64;
    use std::f64::consts::{PI, FRAC_PI_2, FRAC_PI_4};

    if data.is_nan() || data.is_infinite() {
        return f64::NAN;
    }

    // [-∞, ∞] => (-π, π)
    // sin(θ) = -sin(θ-π)
    let (data, neg_flag) = (data % PI, ((data / PI) as u8) % 2 != 0);
    // (-π, π) => (0, π)
    // sin(θ) = -sin(-θ)
    let (data, neg_flag) = (data.abs(), neg_flag ^ (data < 0.));

    let ret = match data {
        data if ((0. <= data) && (data < FRAC_PI_4)) => {
            // sin(θ)
            poly_sin(data)
        },
        data if ((FRAC_PI_4 <= data) && (data < (PI - FRAC_PI_4))) => {
            // sin(θ) = cos(θ-π/2)
            poly_cos(data - FRAC_PI_2)
        },
        data if (((PI - FRAC_PI_4) <= data) && (data < PI)) => {
            // sin(θ) = sin(π-θ)
            poly_sin(PI - data)
        },
        _ => { panic!("why are you here ?") }
    };

    if neg_flag {
        return -ret;
    }

    ret
}

/// sine function for f32
///
/// Currently, we call [sin] as implementation.
///
/// [sin]: fn.sin.html
pub fn sinf(data: f32) -> f32 {
    sin(data as f64) as f32
}

/// cosine function for f64
///
/// Currently, we call [sin] as implementation.
///
/// cos(θ) = sin(π/2 - θ)
///
/// [sin]: fn.sin.html
pub fn cos(data: f64) -> f64 {
    use std::f64::consts::FRAC_PI_2;

    sin(FRAC_PI_2 - data)
}

/// cosine function for f32
///
/// Currently, we call [cos] as implementation.
///
/// [cos]: fn.cos.html
pub fn cosf(data: f32) -> f32 {
    cos(data as f64) as f32
}
<|endoftext|>


<commit_before>// Module for parsing 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/.

/// Basic ISO box structure.
pub struct Mp4BoxHeader {
    /// Four character box type
    name: u32,
    /// Size of the box in bytes
    size: u64,
}

/// File type box 'ftyp'.
pub struct Mp4FileTypeBox {
    name: u32,
    size: u64,
    major_brand: u32,
    minor_version: u32,
    compatible_brands: Vec<u32>,
}

extern crate byteorder;
use byteorder::{BigEndian, ReadBytesExt};

/// Parse a box out of a data buffer.
pub fn read_box_header<T: ReadBytesExt>(src: &mut T) -> Option<Mp4BoxHeader> {
    let tmp_size = src.read_u32::<BigEndian>().unwrap();
    let name = src.read_u32::<BigEndian>().unwrap();
    let size = match tmp_size {
        1 => src.read_u64::<BigEndian>().unwrap(),
        _ => tmp_size as u64,
    };
    Some(Mp4BoxHeader{
        name: name,
        size: size,
    })
}

/// Parse an ftype box.
pub fn read_ftyp<T: ReadBytesExt>(src: &mut T) -> Option<Mp4FileTypeBox> {
    let head = read_box_header(src).unwrap();
    let major = src.read_u32::<BigEndian>().unwrap();
    let minor = src.read_u32::<BigEndian>().unwrap();
    let brand_count = (head.size - 8 - 8) /4;
    let mut brands = Vec::new();
    for _ in 0..brand_count {
        brands.push(src.read_u32::<BigEndian>().unwrap());
    }
    Some(Mp4FileTypeBox{
        name: head.name,
        size: head.size,
        major_brand: major,
        minor_version: minor,
        compatible_brands: brands,
    })
}

/// Split a u32 box type into a [u8].
fn u32_to_vec(x: u32) -> Vec<u8> {
    vec!((x >> 24 & 0xffu32) as u8,
         (x >> 16 & 0xffu32) as u8,
         (x >>  8 & 0xffu32) as u8,
         (x & 0xffu32) as u8)
}

use std::fmt;
impl fmt::Display for Mp4BoxHeader {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name_bytes = u32_to_vec(self.name);
        let name = String::from_utf8_lossy(&name_bytes);
        write!(f, "'{}' {} bytes", name, self.size)
    }
}

impl fmt::Display for Mp4FileTypeBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name_bytes = u32_to_vec(self.name);
        let name = String::from_utf8_lossy(&name_bytes);
        let brand_bytes = u32_to_vec(self.major_brand);
        let brand = String::from_utf8_lossy(&brand_bytes);
        write!(f, "'{}' {} bytes '{}' v{}", name, self.size,
            brand, self.minor_version)
    }
}

#[test]
fn test_read_box_header() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 8];  // minimal box length
    write!(&mut test, "test").unwrap(); // box type
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1952805748);
    assert_eq!(parsed.size, 8);
    println!("box {}", parsed);
}

#[test]
fn test_read_box_header_long() {
    use std::io::Cursor;
    let mut test: Vec<u8> = vec![0, 0, 0, 1]; // long box extension code
    test.extend("long".to_string().into_bytes()); // box type
    test.extend(vec![0, 0, 0, 0, 0, 0, 16, 0]); // 64 bit size
    // Skip generating box content.
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1819242087);
    assert_eq!(parsed.size, 4096);
    println!("box {}", parsed);
}

#[test]
fn test_read_ftyp() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 24]; // size
    write!(&mut test, "ftyp").unwrap(); // type
    write!(&mut test, "mp42").unwrap(); // major brand
    test.extend(vec![0, 0, 0, 0]);      // minor version
    write!(&mut test, "isom").unwrap(); // compatible brands...
    write!(&mut test, "mp42").unwrap();
    assert_eq!(test.len(), 24);

    let mut stream = Cursor::new(test);
    let parsed = read_ftyp(&mut stream).unwrap();
    assert_eq!(parsed.name, 1718909296);
    assert_eq!(parsed.size, 24);
    assert_eq!(parsed.major_brand, 1836069938);
    assert_eq!(parsed.minor_version, 0);
    assert_eq!(parsed.compatible_brands.len(), 2);
    println!("box {}", parsed);
}
<commit_msg>Add asserts on the box length.<commit_after>// Module for parsing 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/.

/// Basic ISO box structure.
pub struct Mp4BoxHeader {
    /// Four character box type
    name: u32,
    /// Size of the box in bytes
    size: u64,
}

/// File type box 'ftyp'.
pub struct Mp4FileTypeBox {
    name: u32,
    size: u64,
    major_brand: u32,
    minor_version: u32,
    compatible_brands: Vec<u32>,
}

extern crate byteorder;
use byteorder::{BigEndian, ReadBytesExt};

/// Parse a box out of a data buffer.
pub fn read_box_header<T: ReadBytesExt>(src: &mut T) -> Option<Mp4BoxHeader> {
    let tmp_size = src.read_u32::<BigEndian>().unwrap();
    let name = src.read_u32::<BigEndian>().unwrap();
    let size = match tmp_size {
        1 => src.read_u64::<BigEndian>().unwrap(),
        _ => tmp_size as u64,
    };
    assert!(size >= 8);
    if tmp_size == 1 {
        assert!(size >= 16);
    }
    Some(Mp4BoxHeader{
        name: name,
        size: size,
    })
}

/// Parse an ftype box.
pub fn read_ftyp<T: ReadBytesExt>(src: &mut T) -> Option<Mp4FileTypeBox> {
    let head = read_box_header(src).unwrap();
    let major = src.read_u32::<BigEndian>().unwrap();
    let minor = src.read_u32::<BigEndian>().unwrap();
    let brand_count = (head.size - 8 - 8) /4;
    let mut brands = Vec::new();
    for _ in 0..brand_count {
        brands.push(src.read_u32::<BigEndian>().unwrap());
    }
    Some(Mp4FileTypeBox{
        name: head.name,
        size: head.size,
        major_brand: major,
        minor_version: minor,
        compatible_brands: brands,
    })
}

/// Split a u32 box type into a [u8].
fn u32_to_vec(x: u32) -> Vec<u8> {
    vec!((x >> 24 & 0xffu32) as u8,
         (x >> 16 & 0xffu32) as u8,
         (x >>  8 & 0xffu32) as u8,
         (x & 0xffu32) as u8)
}

use std::fmt;
impl fmt::Display for Mp4BoxHeader {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name_bytes = u32_to_vec(self.name);
        let name = String::from_utf8_lossy(&name_bytes);
        write!(f, "'{}' {} bytes", name, self.size)
    }
}

impl fmt::Display for Mp4FileTypeBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name_bytes = u32_to_vec(self.name);
        let name = String::from_utf8_lossy(&name_bytes);
        let brand_bytes = u32_to_vec(self.major_brand);
        let brand = String::from_utf8_lossy(&brand_bytes);
        write!(f, "'{}' {} bytes '{}' v{}", name, self.size,
            brand, self.minor_version)
    }
}

#[test]
fn test_read_box_header() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 8];  // minimal box length
    write!(&mut test, "test").unwrap(); // box type
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1952805748);
    assert_eq!(parsed.size, 8);
    println!("box {}", parsed);
}

#[test]
fn test_read_box_header_long() {
    use std::io::Cursor;
    let mut test: Vec<u8> = vec![0, 0, 0, 1]; // long box extension code
    test.extend("long".to_string().into_bytes()); // box type
    test.extend(vec![0, 0, 0, 0, 0, 0, 16, 0]); // 64 bit size
    // Skip generating box content.
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1819242087);
    assert_eq!(parsed.size, 4096);
    println!("box {}", parsed);
}

#[test]
fn test_read_ftyp() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 24]; // size
    write!(&mut test, "ftyp").unwrap(); // type
    write!(&mut test, "mp42").unwrap(); // major brand
    test.extend(vec![0, 0, 0, 0]);      // minor version
    write!(&mut test, "isom").unwrap(); // compatible brands...
    write!(&mut test, "mp42").unwrap();
    assert_eq!(test.len(), 24);

    let mut stream = Cursor::new(test);
    let parsed = read_ftyp(&mut stream).unwrap();
    assert_eq!(parsed.name, 1718909296);
    assert_eq!(parsed.size, 24);
    assert_eq!(parsed.major_brand, 1836069938);
    assert_eq!(parsed.minor_version, 0);
    assert_eq!(parsed.compatible_brands.len(), 2);
    println!("box {}", parsed);
}
<|endoftext|>


<commit_before>#[derive(PartialEq, Debug)]
pub enum Direction {
    North,
    East,
    South,
    West,
}

pub fn distance(input: &str) -> u32 {
    let mut location: (i32, i32) = (0, 0);
    let mut direction = Direction::North;

    for instruction in input.split_whitespace() {
        let mut chars = instruction.chars();
        if let (Some(turn_dir), Some(num_blocks)) = (chars.next(), chars.next()) {
            direction = turn(direction, turn_dir);
            let num_blocks: i32 = num_blocks.to_string()
                                            .parse()
                                            .expect("Cannot parse");
            match direction {
                Direction::North => location.1 += num_blocks,
                Direction::East => location.0 += num_blocks,
                Direction::South => location.1 -= num_blocks,
                Direction::West => location.0 -= num_blocks,
            }

        } else {
            panic!("Could not get instructions out of {}", instruction);
        }

    }
    (location.0.abs() + location.1.abs()) as u32
}

pub fn turn(initial_direction: Direction, turn_command: char) -> Direction {
    match (turn_command, initial_direction) {
        ('L', Direction::North) => Direction::West,
        ('L', Direction::West) => Direction::South,
        ('L', Direction::South) => Direction::East,
        ('L', Direction::East) => Direction::North,

        ('R', Direction::North) => Direction::East,
        ('R', Direction::East) => Direction::South,
        ('R', Direction::South) => Direction::West,
        ('R', Direction::West) => Direction::North,

        (unknown_turn_command, dir) => panic!("\
            I don't know how to turn {} from {:?}!",
            unknown_turn_command,
            dir
        ),
    }
}

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

    #[test]
    fn r1_is_one() {
        assert_eq!(distance("R1"), 1);
    }

    #[test]
    fn r1_r1_is_two() {
        assert_eq!(distance("R1 R1"), 2);
    }

    #[test]
    fn turn_left() {
        let mut dir = Direction::North;
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::West);
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::South);
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::East);
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::North);
    }

    #[test]
    fn turn_right() {
        let mut dir = Direction::North;
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::East);
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::South);
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::West);
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::North);
    }
}<commit_msg>Extract a point struct since i already almost messed up tuple indexing<commit_after>#[derive(PartialEq, Debug)]
pub enum Direction {
    North,
    East,
    South,
    West,
}

pub struct Point {
    x: i32,
    y: i32,
}

pub fn distance(input: &str) -> u32 {
    let mut location = Point { x: 0, y: 0 };
    let mut direction = Direction::North;

    for instruction in input.split_whitespace() {
        let mut chars = instruction.chars();
        if let (Some(turn_dir), Some(num_blocks)) = (chars.next(), chars.next()) {
            direction = turn(direction, turn_dir);
            let num_blocks: i32 = num_blocks.to_string()
                                            .parse()
                                            .expect("Cannot parse");
            match direction {
                Direction::North => location.y += num_blocks,
                Direction::East  => location.x += num_blocks,
                Direction::South => location.y -= num_blocks,
                Direction::West  => location.x -= num_blocks,
            }
        } else {
            panic!("Could not get instructions out of {}", instruction);
        }

    }
    (location.x.abs() + location.y.abs()) as u32
}

pub fn turn(initial_direction: Direction, turn_command: char) -> Direction {
    match (turn_command, initial_direction) {
        ('L', Direction::North) => Direction::West,
        ('L', Direction::West) => Direction::South,
        ('L', Direction::South) => Direction::East,
        ('L', Direction::East) => Direction::North,

        ('R', Direction::North) => Direction::East,
        ('R', Direction::East) => Direction::South,
        ('R', Direction::South) => Direction::West,
        ('R', Direction::West) => Direction::North,

        (unknown_turn_command, dir) => panic!("\
            I don't know how to turn {} from {:?}!",
            unknown_turn_command,
            dir
        ),
    }
}

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

    #[test]
    fn r1_is_one() {
        assert_eq!(distance("R1"), 1);
    }

    #[test]
    fn r1_r1_is_two() {
        assert_eq!(distance("R1 R1"), 2);
    }

    #[test]
    fn turn_left() {
        let mut dir = Direction::North;
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::West);
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::South);
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::East);
        dir = turn(dir, 'L');
        assert_eq!(dir, Direction::North);
    }

    #[test]
    fn turn_right() {
        let mut dir = Direction::North;
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::East);
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::South);
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::West);
        dir = turn(dir, 'R');
        assert_eq!(dir, Direction::North);
    }
}<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use std::ops::Deref;
use std::marker::PhantomData;

// What does this do? You'll never guess!
type HeapId<'a> = PhantomData<std::cell::Cell<&'a mut ()>>;

// Pair is the only type that is actually allocated inside the heap (private)
struct Pair<'a> {
    mark: bool,
    head: XValue<'a>,
    tail: XValue<'a>
}

// Values inside the heap (GC heap-to-heap cross-references) (private)
enum XValue<'a> { Null, Int(i32), Str(Rc<String>), Pair(*mut Pair<'a>, HeapId<'a>) }

// The heap is (for now) just a big Vec of Pairs
pub struct Heap<'a> {
    id: HeapId<'a>,
    storage: Vec<Pair<'a>>,
    freelist: *mut Pair<'a>,
    pins: RefCell<HashMap<*mut Pair<'a>, usize>>
}

pub const HEAP_SIZE: usize = 10000;

pub fn with_heap<F, O>(f: F) -> O
    where F: for<'a> FnOnce(Heap<'a>) -> O
{
    f(Heap::new())
}

impl<'a> Heap<'a> {
    fn new() -> Heap<'a> {
        // Allocate with the full capacity so that allocated Pairs never move
        let mut h = Heap {
            id: PhantomData,
            storage: Vec::with_capacity(HEAP_SIZE),
            freelist: std::ptr::null_mut(),
            pins: RefCell::new(HashMap::new())
        };
        for i in 0 .. HEAP_SIZE {
            h.storage.push(Pair {
                mark: false,
                head: XValue::Null,
                tail: XValue::Null
            });
            let p = &mut h.storage[i] as *mut Pair<'a>;
            unsafe {
                h.add_to_free_list(p);
            }
        }
        h
    }

    fn pin(&self, p: *mut Pair<'a>) {
        let mut pins = self.pins.borrow_mut();
        let entry = pins.entry(p).or_insert(0);
        *entry += 1;
    }

    fn unpin(&self, p: *mut Pair<'a>) {
        let mut pins = self.pins.borrow_mut();
        if {
            let entry = pins.entry(p).or_insert(0);
            assert!(*entry != 0);
            *entry -= 1;
            *entry == 0
        } {
            pins.remove(&p);
        }
    }

    unsafe fn add_to_free_list(&mut self, p: *mut Pair<'a>) {
        let listp: *mut *mut Pair<'a> = std::mem::transmute(p);
        *listp = self.freelist;
        assert_eq!(*listp, self.freelist);
        self.freelist = p;
    }

    pub fn try_alloc(&mut self, pair: (Value<'a>, Value<'a>)) -> Option<PairRoot<'a>> {
        if self.freelist.is_null() {
            unsafe {
                self.gc();
            }
            if self.freelist.is_null() {
                return None;
            }
        }

        let p = self.freelist;
        unsafe {
            let listp: *mut *mut Pair<'a> = std::mem::transmute(p);
            self.freelist = *listp;

            let (h, t) = pair;
            *p = Pair {
                mark: false,
                head: value_to_heap(h),
                tail: value_to_heap(t)
            };
            Some(PairRoot::new(self, p))
        }
    }

    pub fn alloc(&mut self, pair: (Value<'a>, Value<'a>)) -> PairRoot<'a> {
        self.try_alloc(pair).expect("out of memory (gc did not collect anything)")
    }

    pub fn alloc_null(&mut self) -> PairRoot<'a> {
        self.alloc((Value::Null, Value::Null))
    }

    unsafe fn mark(p: *mut Pair<'a>) {
        if !p.is_null() && !(*p).mark {
            (*p).mark = true;
            Heap::mark_value(&(*p).head);
            Heap::mark_value(&(*p).tail);
        }
    }

    unsafe fn mark_value(v: &XValue<'a>) {
        match v {
            &XValue::Pair(p, _) => Heap::mark(p),
            _ => {}
        }
    }

    unsafe fn gc(&mut self) {
        // clear mark bits
        for p in &mut self.storage {
            p.mark = false;
        }

        // mark phase
        for (&p, _) in self.pins.borrow().deref() {
            Heap::mark(p);
        }

        // sweep phase
        self.freelist = std::ptr::null_mut();
        for i in 0 .. HEAP_SIZE {
            let p = &mut self.storage[i] as *mut Pair<'a>;
            if !(*p).mark {
                self.add_to_free_list(p);
            }
        }
    }

    #[cfg(test)]
    pub fn force_gc(&mut self) {
        unsafe { self.gc(); }
    }
}

// === Values outside the heap that may refer to heap values

// Handle to a Pair that lives in the heap.
#[allow(raw_pointer_derive)]
#[derive(Debug, PartialEq)]
pub struct PairRoot<'a>(*mut Pair<'a>, *const Heap<'a>, HeapId<'a>);

impl<'a> Drop for PairRoot<'a> {
    fn drop(&mut self) {
        unsafe {
            (*self.1).unpin(self.0);
        }
    }
}

impl<'a> Clone for PairRoot<'a> {
    fn clone(&self) -> PairRoot<'a> {
        let p = self.0;
        let heap = self.1;
        unsafe {
            (*heap).pin(p);
        }
        PairRoot(p, heap, self.2)
    }
}

impl<'a> PairRoot<'a> {
    unsafe fn new(heap: &Heap<'a>, p: *mut Pair<'a>) -> PairRoot<'a> {
        heap.pin(p);
        PairRoot(p, heap as *const Heap<'a>, heap.id)
    }

    pub fn head(&self) -> Value<'a> {
        let p = self.0;
        unsafe { value_from_heap(&*self.1, &(*p).head) }
    }

    pub fn tail(&self) -> Value<'a> {
        let p = self.0;
        unsafe { value_from_heap(&*self.1, &(*p).tail) }
    }

    pub fn set_head(&self, v: Value<'a>) {
        let p = self.0;
        unsafe { (*p).head = value_to_heap(v); }
    }

    pub fn set_tail(&self, v: Value<'a>) {
        let p = self.0;
        unsafe { (*p).tail = value_to_heap(v); }
    }

    #[cfg(test)]
    pub fn address(&self) -> usize {
        unsafe { std::mem::transmute(self.0) }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum Value<'a> {
    Null,
    Int(i32),
    Str(Rc<String>),  // <-- equality is by value
    Pair(PairRoot<'a>)  // <-- equality is by pointer
}

// === Getting data into and out of the heap

fn value_to_heap<'a>(v: Value<'a>) -> XValue<'a> {
    match v {
        Value::Null => XValue::Null,
        Value::Int(n) => XValue::Int(n),
        Value::Str(rcstr) => XValue::Str(rcstr),
        Value::Pair(PairRoot(p, _, heap_id)) => XValue::Pair(p, heap_id)
    }
}

unsafe fn value_from_heap<'a>(heap: &Heap<'a>, v: &XValue<'a>) -> Value<'a> {
    match v {
        &XValue::Null => Value::Null,
        &XValue::Int(n) => Value::Int(n),
        &XValue::Str(ref rcstr) => Value::Str(rcstr.clone()),
        &XValue::Pair(p, _) => Value::Pair(PairRoot::new(heap, p))
    }
}

#[cfg(test)]
mod test {
    use super::with_heap;
    use super::Value;
    use super::HEAP_SIZE;
    use std::rc::Rc;

    /// Test that a Heap can at least allocate two objects.
    #[test]
    fn can_allocate_twice() {
        with_heap(|mut heap| {
            let obj1 = heap.alloc((Value::Int(1), Value::Null));
            let obj2 = heap.alloc((Value::Int(2), Value::Null));
            assert_eq!(obj1.head(), Value::Int(1));
            assert_eq!(obj2.head(), Value::Int(2));
        });
    }

    /// Test that rooted objects are not collected and reused.
    #[test]
    fn root_is_not_recycled() {
        with_heap(|mut heap| {
            // Create and root one object.
            let root = heap.alloc((Value::Int(1), Value::Str(Rc::new("hello world".to_string()))));

            // Subsequent allocations never return root.
            for _ in 0 .. HEAP_SIZE * 2 {
                let tmp = heap.alloc_null();
                assert!(tmp != root);
            }
        });
    }

    /// Test try_alloc()'s behavior when the heap is full and every Object is
    /// reachable.
    #[test]
    fn full_heap() {
        with_heap(|mut heap| {
            // Fill up the heap by allocating HEAP_SIZE objects.
            let mut v = Value::Null;
            for _ in 0 .. HEAP_SIZE {
                v = Value::Pair(heap.alloc((Value::Null, v)));
            }

            // The whole heap is reachable.  Now try_alloc() should return null every
            // time it's called.
            for _ in 0 .. 4 {
                assert_eq!(heap.try_alloc((Value::Null, Value::Null)), None);
            }
        });
    }

    /// Test allocate()'s behavior when the heap is only almost full.
    #[test]
    fn nearly_full_heap() {
        with_heap(|mut heap| {
            // Make the heap nearly full by allocating (HEAP_SIZE - 1) objects.
            let mut v = Value::Null;
            for _ in 0 .. HEAP_SIZE - 1 {
                v = Value::Pair(heap.alloc((Value::Null, v)));
            }

            // Now the entire heap is reachable except for one Object.  We should
            // be able to call allocate() successfully, repeatedly.  It returns
            // that one object every time it's called!
            let last = heap.alloc_null().address();
            for _ in 0 .. 10 {
                assert_eq!(heap.alloc_null().address(), last);
            }
        });
    }

    /// Test that objects reachable from a root's `.head` or `.tail` are not
    /// collected.
    #[test]
    fn reachable_objects_not_collected() {
        with_heap(|mut heap| {
            let obj1 = heap.alloc_null();
            let (p2, p3, p4, p5);
            {
                let obj2 = heap.alloc_null();
                p2 = obj2.address();
                obj1.set_head(Value::Pair(obj2.clone()));
                let obj3 = heap.alloc_null();
                p3 = obj3.address();
                obj1.set_tail(Value::Pair(obj3));
                let obj4 = heap.alloc_null();
                p4 = obj4.address();
                obj2.set_head(Value::Pair(obj4));
                let obj5 = heap.alloc_null();
                p5 = obj5.address();
                obj2.set_tail(Value::Pair(obj5));
            }

            heap.force_gc();

            let h = match obj1.head() {
                Value::Pair(p) => p,
                _ => panic!("expected pair in obj1.head")
            };
            assert_eq!(h.address(), p2);

            let t = match obj1.tail() {
                Value::Pair(p) => p,
                _ => panic!("expected pair in obj1.tail")
            };
            assert_eq!(t.address(), p3);

            let hh = match h.head() {
                Value::Pair(p) => p,
                _ => panic!("expected pair in obj1.head.head")
            };
            assert_eq!(hh.address(), p4);

            let ht = match h.tail() {
                Value::Pair(p) => p,
                _ => panic!("expected pair in obj1.head.tail")
            };
            assert_eq!(ht.address(), p5);
        });
    }

    /// Test that the GC is not confused by an object that contains pointers to
    /// itself.
    #[test]
    fn root_self_references() {
        with_heap(|mut heap| {
            // Create a root object that contains pointers to itself.
            let root = heap.alloc_null();
            root.set_head(Value::Pair(root.clone()));
            root.set_tail(Value::Pair(root.clone()));

            heap.force_gc();

            // After GC, the root object should be unchanged.
            assert_eq!(root.head(), Value::Pair(root.clone()));
            assert_eq!(root.tail(), Value::Pair(root.clone()));
        });
    }

    /// Test that the GC is not confused by cycles in the reachable object graph.
    #[test]
    fn test_root_cycle() {
        with_heap(|mut heap| {
            // Set up obj1 and obj2 to point to each other.
            let obj1 = heap.alloc_null();
            let obj2 = heap.alloc((Value::Pair(obj1.clone()),
                                   Value::Pair(obj1.clone())));  // obj2 points to obj1
            obj1.set_head(Value::Pair(obj2.clone()));  // and vice versa
            obj1.set_tail(Value::Pair(obj2.clone()));

            heap.force_gc();

            // After GC, the two objects are unchanged.
            assert_eq!(obj1.head(), Value::Pair(obj2.clone()));
            assert_eq!(obj1.tail(), Value::Pair(obj2.clone()));
            assert_eq!(obj2.head(), Value::Pair(obj1.clone()));
            assert_eq!(obj2.tail(), Value::Pair(obj1.clone()));
        });
    }

    /// Test that the GC is not confused by cycles that are garbage.
    #[test]
    fn unreachable_cycle() {
        with_heap(|mut heap| {
            // Make a cycle.
            let (p1, p2);
            {
                let obj1 = heap.alloc_null();
                p1 = obj1.address();
                let obj2 = heap.alloc_null();
                p2 = obj2.address();
                obj2.set_tail(Value::Pair(obj1.clone()));
                obj1.set_tail(Value::Pair(obj2.clone()));
            }  // Make the cycle unreachable.

            // Allocation should eventually recycle both objects.
            let mut recycled1 = 0;
            let mut recycled2 = 0;
            let mut root = Value::Null;
            for _ in 0 .. HEAP_SIZE {
                let p = heap.alloc((Value::Null, root));
                root = Value::Pair(p.clone());
                if p.address() == p1 {
                    recycled1 += 1;
                }
                if p.address() == p2 {
                    recycled2 += 1;
                }
            }
            assert_eq!(recycled1, 1);
            assert_eq!(recycled2, 1);
        });
    }

    // Tests that you can't share values across separate heaps.
    // Try uncommenting the tests below: if any of them compile successfully,
    // consider it a test failure!
    /*
    #[test]
    fn bug_swapping() {
        with_heap(|heap1| {
            with_heap(|mut heap2| {
                let obj1 = heap1.alloc_null();  // error: cannot infer an appropriate lifetime parameter
                let obj2 = heap2.alloc((Value::Null, Value::Pair(obj1)));
            });
        });
    }

    #[test]
    fn bug_swapping_2() {
        let heap1 = with_heap(|h| h);  // error: cannot infer an appropriate lifetime
        let heap2 = with_heap(|h| h);
        let obj1 = heap1.alloc_null();
        let obj2 = heap2.alloc((Value::Null, Value::Pair(obj1)));
    }

    #[test]
    fn bug_swapping_3() {
        with_heap(|heap1| {
            let heap2 = with_heap(|h| h);  // error: cannot infer an appropriate lifetime
            let obj1 = heap1.alloc_null();
            let obj2 = heap2.alloc((Value::Null, Value::Pair(obj1)));
        });
    }
    */
}
<commit_msg>It is nicer to use iter() than deref().<commit_after>use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use std::marker::PhantomData;

// What does this do? You'll never guess!
type HeapId<'a> = PhantomData<std::cell::Cell<&'a mut ()>>;

// Pair is the only type that is actually allocated inside the heap (private)
struct Pair<'a> {
    mark: bool,
    head: XValue<'a>,
    tail: XValue<'a>
}

// Values inside the heap (GC heap-to-heap cross-references) (private)
enum XValue<'a> { Null, Int(i32), Str(Rc<String>), Pair(*mut Pair<'a>, HeapId<'a>) }

// The heap is (for now) just a big Vec of Pairs
pub struct Heap<'a> {
    id: HeapId<'a>,
    storage: Vec<Pair<'a>>,
    freelist: *mut Pair<'a>,
    pins: RefCell<HashMap<*mut Pair<'a>, usize>>
}

pub const HEAP_SIZE: usize = 10000;

pub fn with_heap<F, O>(f: F) -> O
    where F: for<'a> FnOnce(Heap<'a>) -> O
{
    f(Heap::new())
}

impl<'a> Heap<'a> {
    fn new() -> Heap<'a> {
        // Allocate with the full capacity so that allocated Pairs never move
        let mut h = Heap {
            id: PhantomData,
            storage: Vec::with_capacity(HEAP_SIZE),
            freelist: std::ptr::null_mut(),
            pins: RefCell::new(HashMap::new())
        };
        for i in 0 .. HEAP_SIZE {
            h.storage.push(Pair {
                mark: false,
                head: XValue::Null,
                tail: XValue::Null
            });
            let p = &mut h.storage[i] as *mut Pair<'a>;
            unsafe {
                h.add_to_free_list(p);
            }
        }
        h
    }

    fn pin(&self, p: *mut Pair<'a>) {
        let mut pins = self.pins.borrow_mut();
        let entry = pins.entry(p).or_insert(0);
        *entry += 1;
    }

    fn unpin(&self, p: *mut Pair<'a>) {
        let mut pins = self.pins.borrow_mut();
        if {
            let entry = pins.entry(p).or_insert(0);
            assert!(*entry != 0);
            *entry -= 1;
            *entry == 0
        } {
            pins.remove(&p);
        }
    }

    unsafe fn add_to_free_list(&mut self, p: *mut Pair<'a>) {
        let listp: *mut *mut Pair<'a> = std::mem::transmute(p);
        *listp = self.freelist;
        assert_eq!(*listp, self.freelist);
        self.freelist = p;
    }

    pub fn try_alloc(&mut self, pair: (Value<'a>, Value<'a>)) -> Option<PairRoot<'a>> {
        if self.freelist.is_null() {
            unsafe {
                self.gc();
            }
            if self.freelist.is_null() {
                return None;
            }
        }

        let p = self.freelist;
        unsafe {
            let listp: *mut *mut Pair<'a> = std::mem::transmute(p);
            self.freelist = *listp;

            let (h, t) = pair;
            *p = Pair {
                mark: false,
                head: value_to_heap(h),
                tail: value_to_heap(t)
            };
            Some(PairRoot::new(self, p))
        }
    }

    pub fn alloc(&mut self, pair: (Value<'a>, Value<'a>)) -> PairRoot<'a> {
        self.try_alloc(pair).expect("out of memory (gc did not collect anything)")
    }

    pub fn alloc_null(&mut self) -> PairRoot<'a> {
        self.alloc((Value::Null, Value::Null))
    }

    unsafe fn mark(p: *mut Pair<'a>) {
        if !p.is_null() && !(*p).mark {
            (*p).mark = true;
            Heap::mark_value(&(*p).head);
            Heap::mark_value(&(*p).tail);
        }
    }

    unsafe fn mark_value(v: &XValue<'a>) {
        match v {
            &XValue::Pair(p, _) => Heap::mark(p),
            _ => {}
        }
    }

    unsafe fn gc(&mut self) {
        // clear mark bits
        for p in &mut self.storage {
            p.mark = false;
        }

        // mark phase
        for (&p, _) in self.pins.borrow().iter() {
            Heap::mark(p);
        }

        // sweep phase
        self.freelist = std::ptr::null_mut();
        for i in 0 .. HEAP_SIZE {
            let p = &mut self.storage[i] as *mut Pair<'a>;
            if !(*p).mark {
                self.add_to_free_list(p);
            }
        }
    }

    #[cfg(test)]
    pub fn force_gc(&mut self) {
        unsafe { self.gc(); }
    }
}

// === Values outside the heap that may refer to heap values

// Handle to a Pair that lives in the heap.
#[allow(raw_pointer_derive)]
#[derive(Debug, PartialEq)]
pub struct PairRoot<'a>(*mut Pair<'a>, *const Heap<'a>, HeapId<'a>);

impl<'a> Drop for PairRoot<'a> {
    fn drop(&mut self) {
        unsafe {
            (*self.1).unpin(self.0);
        }
    }
}

impl<'a> Clone for PairRoot<'a> {
    fn clone(&self) -> PairRoot<'a> {
        let p = self.0;
        let heap = self.1;
        unsafe {
            (*heap).pin(p);
        }
        PairRoot(p, heap, self.2)
    }
}

impl<'a> PairRoot<'a> {
    unsafe fn new(heap: &Heap<'a>, p: *mut Pair<'a>) -> PairRoot<'a> {
        heap.pin(p);
        PairRoot(p, heap as *const Heap<'a>, heap.id)
    }

    pub fn head(&self) -> Value<'a> {
        let p = self.0;
        unsafe { value_from_heap(&*self.1, &(*p).head) }
    }

    pub fn tail(&self) -> Value<'a> {
        let p = self.0;
        unsafe { value_from_heap(&*self.1, &(*p).tail) }
    }

    pub fn set_head(&self, v: Value<'a>) {
        let p = self.0;
        unsafe { (*p).head = value_to_heap(v); }
    }

    pub fn set_tail(&self, v: Value<'a>) {
        let p = self.0;
        unsafe { (*p).tail = value_to_heap(v); }
    }

    #[cfg(test)]
    pub fn address(&self) -> usize {
        unsafe { std::mem::transmute(self.0) }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum Value<'a> {
    Null,
    Int(i32),
    Str(Rc<String>),  // <-- equality is by value
    Pair(PairRoot<'a>)  // <-- equality is by pointer
}

// === Getting data into and out of the heap

fn value_to_heap<'a>(v: Value<'a>) -> XValue<'a> {
    match v {
        Value::Null => XValue::Null,
        Value::Int(n) => XValue::Int(n),
        Value::Str(rcstr) => XValue::Str(rcstr),
        Value::Pair(PairRoot(p, _, heap_id)) => XValue::Pair(p, heap_id)
    }
}

unsafe fn value_from_heap<'a>(heap: &Heap<'a>, v: &XValue<'a>) -> Value<'a> {
    match v {
        &XValue::Null => Value::Null,
        &XValue::Int(n) => Value::Int(n),
        &XValue::Str(ref rcstr) => Value::Str(rcstr.clone()),
        &XValue::Pair(p, _) => Value::Pair(PairRoot::new(heap, p))
    }
}

#[cfg(test)]
mod test {
    use super::with_heap;
    use super::Value;
    use super::HEAP_SIZE;
    use std::rc::Rc;

    /// Test that a Heap can at least allocate two objects.
    #[test]
    fn can_allocate_twice() {
        with_heap(|mut heap| {
            let obj1 = heap.alloc((Value::Int(1), Value::Null));
            let obj2 = heap.alloc((Value::Int(2), Value::Null));
            assert_eq!(obj1.head(), Value::Int(1));
            assert_eq!(obj2.head(), Value::Int(2));
        });
    }

    /// Test that rooted objects are not collected and reused.
    #[test]
    fn root_is_not_recycled() {
        with_heap(|mut heap| {
            // Create and root one object.
            let root = heap.alloc((Value::Int(1), Value::Str(Rc::new("hello world".to_string()))));

            // Subsequent allocations never return root.
            for _ in 0 .. HEAP_SIZE * 2 {
                let tmp = heap.alloc_null();
                assert!(tmp != root);
            }
        });
    }

    /// Test try_alloc()'s behavior when the heap is full and every Object is
    /// reachable.
    #[test]
    fn full_heap() {
        with_heap(|mut heap| {
            // Fill up the heap by allocating HEAP_SIZE objects.
            let mut v = Value::Null;
            for _ in 0 .. HEAP_SIZE {
                v = Value::Pair(heap.alloc((Value::Null, v)));
            }

            // The whole heap is reachable.  Now try_alloc() should return null every
            // time it's called.
            for _ in 0 .. 4 {
                assert_eq!(heap.try_alloc((Value::Null, Value::Null)), None);
            }
        });
    }

    /// Test allocate()'s behavior when the heap is only almost full.
    #[test]
    fn nearly_full_heap() {
        with_heap(|mut heap| {
            // Make the heap nearly full by allocating (HEAP_SIZE - 1) objects.
            let mut v = Value::Null;
            for _ in 0 .. HEAP_SIZE - 1 {
                v = Value::Pair(heap.alloc((Value::Null, v)));
            }

            // Now the entire heap is reachable except for one Object.  We should
            // be able to call allocate() successfully, repeatedly.  It returns
            // that one object every time it's called!
            let last = heap.alloc_null().address();
            for _ in 0 .. 10 {
                assert_eq!(heap.alloc_null().address(), last);
            }
        });
    }

    /// Test that objects reachable from a root's `.head` or `.tail` are not
    /// collected.
    #[test]
    fn reachable_objects_not_collected() {
        with_heap(|mut heap| {
            let obj1 = heap.alloc_null();
            let (p2, p3, p4, p5);
            {
                let obj2 = heap.alloc_null();
                p2 = obj2.address();
                obj1.set_head(Value::Pair(obj2.clone()));
                let obj3 = heap.alloc_null();
                p3 = obj3.address();
                obj1.set_tail(Value::Pair(obj3));
                let obj4 = heap.alloc_null();
                p4 = obj4.address();
                obj2.set_head(Value::Pair(obj4));
                let obj5 = heap.alloc_null();
                p5 = obj5.address();
                obj2.set_tail(Value::Pair(obj5));
            }

            heap.force_gc();

            let h = match obj1.head() {
                Value::Pair(p) => p,
                _ => panic!("expected pair in obj1.head")
            };
            assert_eq!(h.address(), p2);

            let t = match obj1.tail() {
                Value::Pair(p) => p,
                _ => panic!("expected pair in obj1.tail")
            };
            assert_eq!(t.address(), p3);

            let hh = match h.head() {
                Value::Pair(p) => p,
                _ => panic!("expected pair in obj1.head.head")
            };
            assert_eq!(hh.address(), p4);

            let ht = match h.tail() {
                Value::Pair(p) => p,
                _ => panic!("expected pair in obj1.head.tail")
            };
            assert_eq!(ht.address(), p5);
        });
    }

    /// Test that the GC is not confused by an object that contains pointers to
    /// itself.
    #[test]
    fn root_self_references() {
        with_heap(|mut heap| {
            // Create a root object that contains pointers to itself.
            let root = heap.alloc_null();
            root.set_head(Value::Pair(root.clone()));
            root.set_tail(Value::Pair(root.clone()));

            heap.force_gc();

            // After GC, the root object should be unchanged.
            assert_eq!(root.head(), Value::Pair(root.clone()));
            assert_eq!(root.tail(), Value::Pair(root.clone()));
        });
    }

    /// Test that the GC is not confused by cycles in the reachable object graph.
    #[test]
    fn test_root_cycle() {
        with_heap(|mut heap| {
            // Set up obj1 and obj2 to point to each other.
            let obj1 = heap.alloc_null();
            let obj2 = heap.alloc((Value::Pair(obj1.clone()),
                                   Value::Pair(obj1.clone())));  // obj2 points to obj1
            obj1.set_head(Value::Pair(obj2.clone()));  // and vice versa
            obj1.set_tail(Value::Pair(obj2.clone()));

            heap.force_gc();

            // After GC, the two objects are unchanged.
            assert_eq!(obj1.head(), Value::Pair(obj2.clone()));
            assert_eq!(obj1.tail(), Value::Pair(obj2.clone()));
            assert_eq!(obj2.head(), Value::Pair(obj1.clone()));
            assert_eq!(obj2.tail(), Value::Pair(obj1.clone()));
        });
    }

    /// Test that the GC is not confused by cycles that are garbage.
    #[test]
    fn unreachable_cycle() {
        with_heap(|mut heap| {
            // Make a cycle.
            let (p1, p2);
            {
                let obj1 = heap.alloc_null();
                p1 = obj1.address();
                let obj2 = heap.alloc_null();
                p2 = obj2.address();
                obj2.set_tail(Value::Pair(obj1.clone()));
                obj1.set_tail(Value::Pair(obj2.clone()));
            }  // Make the cycle unreachable.

            // Allocation should eventually recycle both objects.
            let mut recycled1 = 0;
            let mut recycled2 = 0;
            let mut root = Value::Null;
            for _ in 0 .. HEAP_SIZE {
                let p = heap.alloc((Value::Null, root));
                root = Value::Pair(p.clone());
                if p.address() == p1 {
                    recycled1 += 1;
                }
                if p.address() == p2 {
                    recycled2 += 1;
                }
            }
            assert_eq!(recycled1, 1);
            assert_eq!(recycled2, 1);
        });
    }

    // Tests that you can't share values across separate heaps.
    // Try uncommenting the tests below: if any of them compile successfully,
    // consider it a test failure!
    /*
    #[test]
    fn bug_swapping() {
        with_heap(|heap1| {
            with_heap(|mut heap2| {
                let obj1 = heap1.alloc_null();  // error: cannot infer an appropriate lifetime parameter
                let obj2 = heap2.alloc((Value::Null, Value::Pair(obj1)));
            });
        });
    }

    #[test]
    fn bug_swapping_2() {
        let heap1 = with_heap(|h| h);  // error: cannot infer an appropriate lifetime
        let heap2 = with_heap(|h| h);
        let obj1 = heap1.alloc_null();
        let obj2 = heap2.alloc((Value::Null, Value::Pair(obj1)));
    }

    #[test]
    fn bug_swapping_3() {
        with_heap(|heap1| {
            let heap2 = with_heap(|h| h);  // error: cannot infer an appropriate lifetime
            let obj1 = heap1.alloc_null();
            let obj2 = heap2.alloc((Value::Null, Value::Pair(obj1)));
        });
    }
    */
}
<|endoftext|>


<commit_before>extern crate piston_window;
extern crate interpolation;
extern crate rand;

// Re-exported for the convenience of library users
pub use rand::*;

mod turtle_window;

mod turtle;
mod speed;
mod radians;
mod animation;
mod extensions;
mod renderer;
mod state;

pub mod color;
pub mod event;

pub use turtle::{Turtle, Point, Distance, Angle};
pub use speed::{Speed};
pub use color::{Color};
pub use event::Event;
<commit_msg>Added some documentation to the root module<commit_after>//! The API Documentation below will help you learn about the various things you can do with this
//! library.
//!
//! **If this is your first time using Rust or using this library, read the Guide on
//! [turtle.rs](http://turtle.rs) to learn how to start.**
//!
//! The [`Turtle` struct](struct.Turtle.html) documentation contains information about the various
//! things you can do with the `Turtle` instances you create. The [`color` module](color/index.html)
//! and its submodules contain hundreds of constants that you can use as color values.
//! As a convenience, you can use the color name listed with each constant in a string instead of the
//! constant itself. See that module for more information about how to use different colors.
//!
//! ## Event Handling
//!
//! For advanced users, the [`Event` struct](event/enum.Event.html) documentation provides information
//! about how you can create an event loop. This allows you to draw things in response to
//! certain events like the mouse moving, keys being pressed, and more.
//!
//! The `Turtle` struct contains a few convenience methods so you can do some common event-related
//! things without creating the entire event loop.
//!
//! * Use [`wait_for_click()`](struct.Turtle.html#method.wait_for_click) to wait for the user to click
//!   anywhere on the screen before continuing

extern crate piston_window;
extern crate interpolation;
extern crate rand;

// Re-exported for the convenience of library users
pub use rand::*;

mod turtle_window;

mod turtle;
mod speed;
mod radians;
mod animation;
mod extensions;
mod renderer;
mod state;

pub mod color;
pub mod event;

pub use turtle::{Turtle, Point, Distance, Angle};
pub use speed::{Speed};
pub use color::{Color};
pub use event::Event;
<|endoftext|>