<commit_before>extern crate rand;

extern crate intmap;

use intmap::{Entry, IntMap};

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

    fn get_random_range(count: usize) -> Vec<u64> {
        use rand::prelude::StdRng;
        use rand::{Rng, SeedableRng};

        let mut vec = Vec::new();
        let mut rng = StdRng::seed_from_u64(4242);

        for _ in 0..count {
            vec.push(rng.gen::<u64>());
        }

        vec.sort();
        vec.dedup();

        vec
    }

    #[test]
    fn intmap_get_insert_impl() {
        let count = 20_000;
        let data = get_random_range(count as usize);
        let mut map: IntMap<u64> = IntMap::new();

        println!("");
        println!("Starting test");

        for s in data.iter() {
            assert!(map.insert(*s, *s), "intmap insert failed! ix: {:?}", s);
        }

        assert_eq!(map.len(), count);
        assert!(map.assert_count());

        for s in data.iter() {
            assert_eq!(*map.get(*s).unwrap(), *s, "intmap get failed! key: {:?}", s);
        }

        assert_eq!(map.len(), count);

        for s in data.iter() {
            assert!(
                map.contains_key(*s),
                "intmap contains_key failed! key: {:?}",
                s
            );
        }

        assert_eq!(map.len(), count);

        for s in data.iter() {
            let val = map.remove(*s).unwrap();
            assert_eq!(val, *s, "intmap remove failed! key: {:?}", s);
        }

        assert_eq!(map.len(), 0);
        assert!(map.assert_count());
    }

    #[test]
    fn reserve() {
        let mut map: IntMap<bool> = IntMap::new();
        map.reserve(9001);
    }

    #[test]
    fn add_duplicate() {
        let mut map = IntMap::new();

        for i in 0..20_000 {
            assert_eq!(map.insert(i, format!("item: {:?}", i)), true);
            assert_eq!(map.insert(i, format!("item: {:?}", i)), false);
        }
    }

    #[test]
    fn get_value_map() {
        let mut map = IntMap::new();

        for i in 0..20_000 {
            assert_eq!(map.insert(i, i + 1), true);
        }

        for i in 0..20_000 {
            assert_eq!(map.contains_key(i), true);
            assert_eq!(*map.get(i).unwrap(), i + 1);
            assert_eq!(*map.get_mut(i).unwrap(), i + 1);
            assert_eq!(map.remove(i).unwrap(), i + 1);
        }

        for i in 0..20_000 {
            assert_eq!(map.contains_key(i), false);
            assert_eq!(map.remove(i), None);
        }

        assert!(map.is_empty());
    }

    #[test]
    fn get_value_not_in_map() {
        let mut map = IntMap::new();

        for i in 0..20_000 {
            assert_eq!(map.insert(i, format!("item: {:?}", i)), true);
        }

        for i in 20_000..40_000 {
            assert_eq!(map.get(i), None);
            assert_eq!(map.get_mut(i), None);
        }
    }

    #[test]
    fn add_string() {
        let mut map = IntMap::new();

        for i in 0..20_000 {
            map.insert(i, format!("item: {:?}", i));
        }
    }

    #[test]
    fn retain() {
        let mut map = IntMap::new();

        for i in 0..20_000 {
            map.insert(i, format!("item: {:?}", i));
        }

        map.retain(|k, _v| k > 10_000);

        for i in 10_001..20_000 {
            assert_eq!(map.contains_key(i), true);
        }
    }

    #[test]
    fn single_add_get() {
        let mut map: IntMap<u64> = IntMap::new();
        map.insert(21, 42);
        let val = map.get(21);
        assert!(val.is_some());
        assert_eq!(*val.unwrap(), 42);
    }

    #[test]
    fn map_iter() {
        let count = 20_000;
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for (k, v) in map.iter() {
            assert_eq!(*k, *v);
        }
    }

    #[test]
    fn map_iter_keys() {
        let count = 20_000;
        let data: Vec<_> = (0..count).collect();
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for k in map.keys() {
            assert_eq!(*k, data[*k as usize]);
        }
    }

    #[test]
    fn map_iter_values() {
        let count = 20_000;
        let data: Vec<_> = (0..count).collect();
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for v in map.values() {
            assert_eq!(*v, data[*v as usize]);
        }
    }

    #[test]
    fn map_iter_values_mut() {
        let count = 20_000;
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for value in map.values_mut() {
            *value += 1;
        }

        for n in 0..count {
            assert_eq!(n + 1, *map.get(n).expect("Failed to get number!"));
        }
    }

    #[test]
    fn map_mut_iter() {
        let count = 20_000;
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for kv in map.iter_mut() {
            *kv.1 += 1;
        }

        for n in 0..count {
            assert_eq!(n + 1, *map.get(n).expect("Failed to get number!"));
        }
    }

    #[test]
    fn map_iter_empty() {
        let mut map: IntMap<u64> = IntMap::new();
        map.clear();

        for kv in map.iter() {
            panic!("Not printing: {:?}", kv);
        }
    }

    #[test]
    fn map_mut_iter_empty() {
        let mut map: IntMap<u64> = IntMap::new();
        map.clear();

        for _ in map.iter_mut() {
            panic!();
        }
    }

    #[test]
    fn map_into_iter() {
        let count = 20_000;
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for (k, v) in map.into_iter() {
            assert_eq!(k, v);
        }
    }

    #[test]
    fn map_drain() {
        let count = 20_000;
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for (k, v) in map.drain() {
            assert_eq!(k, v);
        }
        assert_eq!(map.len(), 0);
    }

    #[test]
    fn map_into_iter_empty() {
        let mut map: IntMap<u64> = IntMap::new();
        map.clear();

        for kv in map.into_iter() {
            panic!("Not printing: {:?}", kv);
        }
    }

    #[test]
    fn extend_two_maps() {
        let count = 20_000;
        let mut map_1: IntMap<u64> = IntMap::new();
        let mut map_2: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map_1.insert(i, i);
        }

        for i in count..(count * 2) {
            map_2.insert(i, i);
        }

        map_1.extend(map_2.into_iter());

        assert_eq!(map_1.len(), (count * 2) as usize);

        for (k, v) in map_1.iter() {
            assert_eq!(k, v);
        }
    }

    #[test]
    fn from_iter_collect() {
        let count = 20_000;

        let map = (0..count).map(|i| (i, i * i)).collect::<IntMap<_>>();

        for k in 0..count {
            assert!(map.contains_key(k));
        }

        for (&k, &v) in map.iter() {
            assert_eq!(k * k, v);
        }
    }

    #[test]
    fn map_equality() {
        let count = 5_000;

        let map_1 = (0..count).map(|i| (i, i * i)).collect::<IntMap<_>>();

        let map_2 = (0..count).rev().map(|i| (i, i * i)).collect::<IntMap<_>>();

        assert_eq!(map_1, map_2);
    }

    #[test]
    fn entry_api() {
        let count = 20_000;
        let data: Vec<u64> = (0..count).collect();
        let mut map: IntMap<u64> = IntMap::new();

        // Insert values 0..19999
        for i in 0..count {
            match map.entry(i) {
                Entry::Occupied(_) => panic!("unexpected while insert, i = {}", i),
                Entry::Vacant(entry) => entry.insert(i),
            };
        }

        assert_eq!(map.len(), count as usize);

        for (k, v) in map.iter() {
            assert_eq!(*v, data[*k as usize]);
        }

        // Replace values 0..19999 with 20000..39999
        for i in 0..count {
            match map.entry(i) {
                Entry::Occupied(mut entry) => {
                    assert_eq!(*entry.get(), i);
                    assert_eq!(*entry.get_mut(), i);
                    assert_eq!(entry.insert(count + i), i);
                    assert_eq!(*entry.into_mut(), count + i);
                }
                Entry::Vacant(_) => panic!("unexpected while replace, i = {}", i),
            };
        }

        assert_eq!(map.len(), count as usize);

        for (k, v) in map.iter() {
            assert_eq!(*v, count + data[*k as usize]);
        }

        // Remove values 20000..39999
        for i in 0..count {
            match map.entry(i) {
                Entry::Occupied(entry) => {
                    assert_eq!(entry.remove(), count + i);
                }
                Entry::Vacant(_) => panic!("unexpected while remove, i = {}", i),
            };
        }

        assert_eq!(map.len(), 0);
    }

    #[test]
    fn test_debug_features() {
        let count = 20_000;
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        assert_eq!(map.load(), 20_000);
        assert_eq!(map.capacity(), 32_768);
        assert!(map.load_rate() > 0.70);
        assert!(map.collisions().is_empty());

        let mut map: IntMap<u64> = IntMap::new();
        for i in 0..3 {
            map.insert(i, i + 1);
        }

        assert_eq!(format!("{:?}", map), "{0: 1, 1: 2, 2: 3}");
    }

    #[test]
    fn load_factor() {
        let mut map: IntMap<u64> = IntMap::new();

        map.set_load_factor(0.1);
        assert_eq!(map.get_load_factor(), 0.1);

        for i in 0..12 {
            map.insert(i, i);
        }

        assert_eq!(map.capacity(), 128);
        assert!(map.load_rate() <= 10.);
        assert!(map.collisions().is_empty());

        let mut map: IntMap<u64> = IntMap::new();

        map.set_load_factor(2.);
        assert_eq!(map.get_load_factor(), 2.);

        for i in 0..16 {
            map.insert(i, i);
        }

        println!("Load {}", map.load_rate());
        println!("factor {:?}", map.collisions());

        assert_eq!(map.capacity(), 8);
        assert!(map.load_rate() <= 200.);
        assert_eq!(format!("{:?}", map.collisions()), "{2: 8}");
    }

    #[test]
    fn failing_test() {
        assert_eq!(true, false);
    }
}
<commit_msg>Remove failing test<commit_after>extern crate rand;

extern crate intmap;

use intmap::{Entry, IntMap};

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

    fn get_random_range(count: usize) -> Vec<u64> {
        use rand::prelude::StdRng;
        use rand::{Rng, SeedableRng};

        let mut vec = Vec::new();
        let mut rng = StdRng::seed_from_u64(4242);

        for _ in 0..count {
            vec.push(rng.gen::<u64>());
        }

        vec.sort();
        vec.dedup();

        vec
    }

    #[test]
    fn intmap_get_insert_impl() {
        let count = 20_000;
        let data = get_random_range(count as usize);
        let mut map: IntMap<u64> = IntMap::new();

        println!("");
        println!("Starting test");

        for s in data.iter() {
            assert!(map.insert(*s, *s), "intmap insert failed! ix: {:?}", s);
        }

        assert_eq!(map.len(), count);
        assert!(map.assert_count());

        for s in data.iter() {
            assert_eq!(*map.get(*s).unwrap(), *s, "intmap get failed! key: {:?}", s);
        }

        assert_eq!(map.len(), count);

        for s in data.iter() {
            assert!(
                map.contains_key(*s),
                "intmap contains_key failed! key: {:?}",
                s
            );
        }

        assert_eq!(map.len(), count);

        for s in data.iter() {
            let val = map.remove(*s).unwrap();
            assert_eq!(val, *s, "intmap remove failed! key: {:?}", s);
        }

        assert_eq!(map.len(), 0);
        assert!(map.assert_count());
    }

    #[test]
    fn reserve() {
        let mut map: IntMap<bool> = IntMap::new();
        map.reserve(9001);
    }

    #[test]
    fn add_duplicate() {
        let mut map = IntMap::new();

        for i in 0..20_000 {
            assert_eq!(map.insert(i, format!("item: {:?}", i)), true);
            assert_eq!(map.insert(i, format!("item: {:?}", i)), false);
        }
    }

    #[test]
    fn get_value_map() {
        let mut map = IntMap::new();

        for i in 0..20_000 {
            assert_eq!(map.insert(i, i + 1), true);
        }

        for i in 0..20_000 {
            assert_eq!(map.contains_key(i), true);
            assert_eq!(*map.get(i).unwrap(), i + 1);
            assert_eq!(*map.get_mut(i).unwrap(), i + 1);
            assert_eq!(map.remove(i).unwrap(), i + 1);
        }

        for i in 0..20_000 {
            assert_eq!(map.contains_key(i), false);
            assert_eq!(map.remove(i), None);
        }

        assert!(map.is_empty());
    }

    #[test]
    fn get_value_not_in_map() {
        let mut map = IntMap::new();

        for i in 0..20_000 {
            assert_eq!(map.insert(i, format!("item: {:?}", i)), true);
        }

        for i in 20_000..40_000 {
            assert_eq!(map.get(i), None);
            assert_eq!(map.get_mut(i), None);
        }
    }

    #[test]
    fn add_string() {
        let mut map = IntMap::new();

        for i in 0..20_000 {
            map.insert(i, format!("item: {:?}", i));
        }
    }

    #[test]
    fn retain() {
        let mut map = IntMap::new();

        for i in 0..20_000 {
            map.insert(i, format!("item: {:?}", i));
        }

        map.retain(|k, _v| k > 10_000);

        for i in 10_001..20_000 {
            assert_eq!(map.contains_key(i), true);
        }
    }

    #[test]
    fn single_add_get() {
        let mut map: IntMap<u64> = IntMap::new();
        map.insert(21, 42);
        let val = map.get(21);
        assert!(val.is_some());
        assert_eq!(*val.unwrap(), 42);
    }

    #[test]
    fn map_iter() {
        let count = 20_000;
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for (k, v) in map.iter() {
            assert_eq!(*k, *v);
        }
    }

    #[test]
    fn map_iter_keys() {
        let count = 20_000;
        let data: Vec<_> = (0..count).collect();
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for k in map.keys() {
            assert_eq!(*k, data[*k as usize]);
        }
    }

    #[test]
    fn map_iter_values() {
        let count = 20_000;
        let data: Vec<_> = (0..count).collect();
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for v in map.values() {
            assert_eq!(*v, data[*v as usize]);
        }
    }

    #[test]
    fn map_iter_values_mut() {
        let count = 20_000;
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for value in map.values_mut() {
            *value += 1;
        }

        for n in 0..count {
            assert_eq!(n + 1, *map.get(n).expect("Failed to get number!"));
        }
    }

    #[test]
    fn map_mut_iter() {
        let count = 20_000;
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for kv in map.iter_mut() {
            *kv.1 += 1;
        }

        for n in 0..count {
            assert_eq!(n + 1, *map.get(n).expect("Failed to get number!"));
        }
    }

    #[test]
    fn map_iter_empty() {
        let mut map: IntMap<u64> = IntMap::new();
        map.clear();

        for kv in map.iter() {
            panic!("Not printing: {:?}", kv);
        }
    }

    #[test]
    fn map_mut_iter_empty() {
        let mut map: IntMap<u64> = IntMap::new();
        map.clear();

        for _ in map.iter_mut() {
            panic!();
        }
    }

    #[test]
    fn map_into_iter() {
        let count = 20_000;
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for (k, v) in map.into_iter() {
            assert_eq!(k, v);
        }
    }

    #[test]
    fn map_drain() {
        let count = 20_000;
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        for (k, v) in map.drain() {
            assert_eq!(k, v);
        }
        assert_eq!(map.len(), 0);
    }

    #[test]
    fn map_into_iter_empty() {
        let mut map: IntMap<u64> = IntMap::new();
        map.clear();

        for kv in map.into_iter() {
            panic!("Not printing: {:?}", kv);
        }
    }

    #[test]
    fn extend_two_maps() {
        let count = 20_000;
        let mut map_1: IntMap<u64> = IntMap::new();
        let mut map_2: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map_1.insert(i, i);
        }

        for i in count..(count * 2) {
            map_2.insert(i, i);
        }

        map_1.extend(map_2.into_iter());

        assert_eq!(map_1.len(), (count * 2) as usize);

        for (k, v) in map_1.iter() {
            assert_eq!(k, v);
        }
    }

    #[test]
    fn from_iter_collect() {
        let count = 20_000;

        let map = (0..count).map(|i| (i, i * i)).collect::<IntMap<_>>();

        for k in 0..count {
            assert!(map.contains_key(k));
        }

        for (&k, &v) in map.iter() {
            assert_eq!(k * k, v);
        }
    }

    #[test]
    fn map_equality() {
        let count = 5_000;

        let map_1 = (0..count).map(|i| (i, i * i)).collect::<IntMap<_>>();

        let map_2 = (0..count).rev().map(|i| (i, i * i)).collect::<IntMap<_>>();

        assert_eq!(map_1, map_2);
    }

    #[test]
    fn entry_api() {
        let count = 20_000;
        let data: Vec<u64> = (0..count).collect();
        let mut map: IntMap<u64> = IntMap::new();

        // Insert values 0..19999
        for i in 0..count {
            match map.entry(i) {
                Entry::Occupied(_) => panic!("unexpected while insert, i = {}", i),
                Entry::Vacant(entry) => entry.insert(i),
            };
        }

        assert_eq!(map.len(), count as usize);

        for (k, v) in map.iter() {
            assert_eq!(*v, data[*k as usize]);
        }

        // Replace values 0..19999 with 20000..39999
        for i in 0..count {
            match map.entry(i) {
                Entry::Occupied(mut entry) => {
                    assert_eq!(*entry.get(), i);
                    assert_eq!(*entry.get_mut(), i);
                    assert_eq!(entry.insert(count + i), i);
                    assert_eq!(*entry.into_mut(), count + i);
                }
                Entry::Vacant(_) => panic!("unexpected while replace, i = {}", i),
            };
        }

        assert_eq!(map.len(), count as usize);

        for (k, v) in map.iter() {
            assert_eq!(*v, count + data[*k as usize]);
        }

        // Remove values 20000..39999
        for i in 0..count {
            match map.entry(i) {
                Entry::Occupied(entry) => {
                    assert_eq!(entry.remove(), count + i);
                }
                Entry::Vacant(_) => panic!("unexpected while remove, i = {}", i),
            };
        }

        assert_eq!(map.len(), 0);
    }

    #[test]
    fn test_debug_features() {
        let count = 20_000;
        let mut map: IntMap<u64> = IntMap::new();

        for i in 0..count {
            map.insert(i, i);
        }

        assert_eq!(map.load(), 20_000);
        assert_eq!(map.capacity(), 32_768);
        assert!(map.load_rate() > 0.70);
        assert!(map.collisions().is_empty());

        let mut map: IntMap<u64> = IntMap::new();
        for i in 0..3 {
            map.insert(i, i + 1);
        }

        assert_eq!(format!("{:?}", map), "{0: 1, 1: 2, 2: 3}");
    }

    #[test]
    fn load_factor() {
        let mut map: IntMap<u64> = IntMap::new();

        map.set_load_factor(0.1);
        assert_eq!(map.get_load_factor(), 0.1);

        for i in 0..12 {
            map.insert(i, i);
        }

        assert_eq!(map.capacity(), 128);
        assert!(map.load_rate() <= 10.);
        assert!(map.collisions().is_empty());

        let mut map: IntMap<u64> = IntMap::new();

        map.set_load_factor(2.);
        assert_eq!(map.get_load_factor(), 2.);

        for i in 0..16 {
            map.insert(i, i);
        }

        println!("Load {}", map.load_rate());
        println!("factor {:?}", map.collisions());

        assert_eq!(map.capacity(), 8);
        assert!(map.load_rate() <= 200.);
        assert_eq!(format!("{:?}", map.collisions()), "{2: 8}");
    }
}
<|endoftext|>


<commit_before>use std::num::{Float};
use std::ops::{Neg};
use std::vec::{Vec};

use geometry::{Vector3D, AsVector, Direction3D, Ray3D};
use color::{ColorRGB};

pub use self::scene_object::{SceneObject};
pub use self::scene_light::{SceneLight};
pub use self::plane::{Plane};
pub use self::sphere::{Sphere};
pub use self::camera::{Camera};

mod scene_object;
mod scene_light;
mod plane;
mod sphere;
mod camera;

const BIAS: f32 = 1.0e-4;

pub struct Scene {
    background_color: ColorRGB,
    refractive_index: f32,
    max_ray_depth: u32,

    items: Vec<InternalObject>,
    lights: Vec<InternalLight>
}

impl Scene {
    pub fn new(background_color: &ColorRGB, refractive_index: f32, max_ray_depth: u32) -> Scene {
        Scene {
            background_color: background_color.clone(),
            refractive_index: refractive_index,
            max_ray_depth: max_ray_depth,
            items: Vec::new(),
            lights: Vec::new()
        }
    }

    pub fn add_light_source(&mut self, light: Box<SceneLight>) {
        let index = self.items.len();
        self.items.push(InternalObject {
            index: index,
            object: light.clone(),
            is_light: true
        });
        self.lights.push(InternalLight {
            index: index,
            light: light
        });
    }

    pub fn add_object(&mut self, object: Box<SceneObject+Sync+Send>) {
        let index = self.items.len();
        self.items.push(InternalObject {
            index: index,
            object: object,
            is_light: false
        });
    }

    pub fn trace(&self, ray: &Ray3D, depth: u32) -> TraceResult {

        // Find the nearest object that the ray intersects.
        let mut optional_nearest: Option<(&InternalObject, f32)> = None;
        for current_item in self.items.iter() {
            let optional_intersection = current_item.object.intersect(ray);
            if let Some(current_distance) = optional_intersection {
                match optional_nearest {
                    Some((_, nearest_distance)) => {
                        if current_distance < nearest_distance {
                            optional_nearest = Some((current_item, current_distance));
                        }
                    },
                    None => {
                        optional_nearest = Some((current_item, current_distance));
                    }
                }
            }
        }

        // If the ray doesn't hit any objects, return the background color.
        if optional_nearest.is_none() {
            return TraceResult {
                color: self.background_color.clone(),
                distance: 0.0
            };
        }

        // Get the information about the nearest intersection.
        let (nearest_item, nearest_distance) = optional_nearest.unwrap();

        // Get the point where the ray intersects the object.
        let point = ray.point(nearest_distance);

        // If the ray intersects a light source, simply return the color of the light.
        if nearest_item.is_light {
            return TraceResult {
                color: nearest_item.object.get_material(&point).color,
                distance: nearest_distance
            };
        }

        // Get the surface normal and color at the intersection point.
        let normal = nearest_item.object.get_normal(&point);
        let surface_material = nearest_item.object.get_material(&point);

        // Calculate the color at the intersection point.
        let mut total_ray_color = ColorRGB::black().clone();

        if depth < self.max_ray_depth {
            // TODO: Add Fresnel effects (?)

            // Calculate the color from the reflected ray.
            let reflection = surface_material.reflection;
            if reflection > 0.0 {
                let reflected_direction = (&ray.direction - &normal * 2.0 * Vector3D::dot(&ray.direction, &normal)).to_unit();
                let nearby_point = point.translate_dist(&reflected_direction, BIAS);
                let reflected_result = self.trace(&Ray3D::new(&nearby_point, &reflected_direction), depth + 1);
                total_ray_color = &total_ray_color + &reflected_result.color * reflection * &surface_material.color;
            }

            // Calculate the color from the refracted ray.
            let refraction = surface_material.refraction;
            if refraction > 0.0 {
                let n;
                let cos_i;
                if Vector3D::dot(&ray.direction, &normal) > 0.0 {
                    // Internal refraction
                    n = surface_material.refractive_index / self.refractive_index;
                    cos_i = -Vector3D::dot(&ray.direction, &(-&normal));
                } else {
                    // External refraction
                    n = self.refractive_index / surface_material.refractive_index;
                    cos_i = -Vector3D::dot(&ray.direction, &normal);
                }

                let cos2_t = 1.0 - n * n * (1.0 - cos_i * cos_i);
                if cos2_t > 0.0 {
                    let refracted_direction = (&ray.direction * n + &normal * (n * cos_i - (cos2_t).sqrt())).to_unit();
                    let nearby_point = point.translate_dist(&refracted_direction, BIAS);
                    let refracted_result = self.trace(&Ray3D::new(&nearby_point, &refracted_direction), depth + 1);

                    // Beer's Law
                    let absorbance = &surface_material.color * (0.15 * -refracted_result.distance);
                    let transparency = ColorRGB::from_rgb(absorbance.red.exp(), absorbance.green.exp(), absorbance.blue.exp());
                    total_ray_color = &total_ray_color + &refracted_result.color * transparency;
                }
            }
        }

        // Calculate the color from each light in the scene.
        for light_item in self.lights.iter() {
            let light = &light_item.light;
            let light_color = light.get_material(&point).color;
            let vector_to_light = Vector3D::between_points(&point, light.get_center());
            let distance_to_light = vector_to_light.magnitude();
            let direction_to_light = vector_to_light.to_unit();

            // Calculate the shading from the light.
            let mut shade: f32 = 1.0;
            let nearby_point = point.translate_dist(&direction_to_light, BIAS);
            let shadow_ray = Ray3D::new(&nearby_point, &direction_to_light);
            for shadow_item in self.items.iter() {
                if shadow_item.index != light_item.index {
                    let shadow_result = shadow_item.object.intersect(&shadow_ray);
                    if let Some(distance) = shadow_result {
                        if distance < distance_to_light {
                            shade = 0.0;
                            break;
                        }
                    }
                }
            }

            if shade != 0.0 {
                // Calculate the diffusive lighting from the light.
                let diffuse = surface_material.diffuse;
                if diffuse > 0.0 {
                    let percentage_of_light = Vector3D::dot(&normal, &direction_to_light);
                    if percentage_of_light > 0.0 {
                        total_ray_color = &total_ray_color + (&light_color * &surface_material.color) * (shade * diffuse * percentage_of_light);
                    }
                }

                // Calculate the specular lighting from the light.
                let specular = surface_material.specular;
                let shininess = surface_material.shininess;
                if specular > 0.0 && shininess > 0 {
                    let reflected_direction = (&direction_to_light - &normal * 2.0 * Vector3D::dot(&direction_to_light, &normal)).to_unit();
                    let percentage_of_light = Vector3D::dot(&ray.direction, &reflected_direction);
                    if percentage_of_light > 0.0 {
                        total_ray_color = &total_ray_color + &light_color * (shade * specular * percentage_of_light.powi(shininess as i32));
                    }
                }
            }
        }

        TraceResult {
            color: total_ray_color,
            distance: nearest_distance
        }
    }
}

struct InternalObject {
    pub index: usize,
    pub object: Box<SceneObject+Sync+Send>,
    pub is_light: bool
}

struct InternalLight {
    pub index: usize,
    pub light: Box<SceneLight>
}

#[derive(Show)]
pub struct TraceResult {
    pub color: ColorRGB,
    pub distance: f32
}
<commit_msg>Removes unused `use` statements.<commit_after>use std::num::{Float};
use std::vec::{Vec};

use geometry::{Vector3D, Ray3D};
use color::{ColorRGB};

pub use self::scene_object::{SceneObject};
pub use self::scene_light::{SceneLight};
pub use self::plane::{Plane};
pub use self::sphere::{Sphere};
pub use self::camera::{Camera};

mod scene_object;
mod scene_light;
mod plane;
mod sphere;
mod camera;

const BIAS: f32 = 1.0e-4;

pub struct Scene {
    background_color: ColorRGB,
    refractive_index: f32,
    max_ray_depth: u32,

    items: Vec<InternalObject>,
    lights: Vec<InternalLight>
}

impl Scene {
    pub fn new(background_color: &ColorRGB, refractive_index: f32, max_ray_depth: u32) -> Scene {
        Scene {
            background_color: background_color.clone(),
            refractive_index: refractive_index,
            max_ray_depth: max_ray_depth,
            items: Vec::new(),
            lights: Vec::new()
        }
    }

    pub fn add_light_source(&mut self, light: Box<SceneLight>) {
        let index = self.items.len();
        self.items.push(InternalObject {
            index: index,
            object: light.clone(),
            is_light: true
        });
        self.lights.push(InternalLight {
            index: index,
            light: light
        });
    }

    pub fn add_object(&mut self, object: Box<SceneObject+Sync+Send>) {
        let index = self.items.len();
        self.items.push(InternalObject {
            index: index,
            object: object,
            is_light: false
        });
    }

    pub fn trace(&self, ray: &Ray3D, depth: u32) -> TraceResult {

        // Find the nearest object that the ray intersects.
        let mut optional_nearest: Option<(&InternalObject, f32)> = None;
        for current_item in self.items.iter() {
            let optional_intersection = current_item.object.intersect(ray);
            if let Some(current_distance) = optional_intersection {
                match optional_nearest {
                    Some((_, nearest_distance)) => {
                        if current_distance < nearest_distance {
                            optional_nearest = Some((current_item, current_distance));
                        }
                    },
                    None => {
                        optional_nearest = Some((current_item, current_distance));
                    }
                }
            }
        }

        // If the ray doesn't hit any objects, return the background color.
        if optional_nearest.is_none() {
            return TraceResult {
                color: self.background_color.clone(),
                distance: 0.0
            };
        }

        // Get the information about the nearest intersection.
        let (nearest_item, nearest_distance) = optional_nearest.unwrap();

        // Get the point where the ray intersects the object.
        let point = ray.point(nearest_distance);

        // If the ray intersects a light source, simply return the color of the light.
        if nearest_item.is_light {
            return TraceResult {
                color: nearest_item.object.get_material(&point).color,
                distance: nearest_distance
            };
        }

        // Get the surface normal and color at the intersection point.
        let normal = nearest_item.object.get_normal(&point);
        let surface_material = nearest_item.object.get_material(&point);

        // Calculate the color at the intersection point.
        let mut total_ray_color = ColorRGB::black().clone();

        if depth < self.max_ray_depth {
            // TODO: Add Fresnel effects (?)

            // Calculate the color from the reflected ray.
            let reflection = surface_material.reflection;
            if reflection > 0.0 {
                let reflected_direction = (&ray.direction - &normal * 2.0 * Vector3D::dot(&ray.direction, &normal)).to_unit();
                let nearby_point = point.translate_dist(&reflected_direction, BIAS);
                let reflected_result = self.trace(&Ray3D::new(&nearby_point, &reflected_direction), depth + 1);
                total_ray_color = &total_ray_color + &reflected_result.color * reflection * &surface_material.color;
            }

            // Calculate the color from the refracted ray.
            let refraction = surface_material.refraction;
            if refraction > 0.0 {
                let n;
                let cos_i;
                if Vector3D::dot(&ray.direction, &normal) > 0.0 {
                    // Internal refraction
                    n = surface_material.refractive_index / self.refractive_index;
                    cos_i = -Vector3D::dot(&ray.direction, &(-&normal));
                } else {
                    // External refraction
                    n = self.refractive_index / surface_material.refractive_index;
                    cos_i = -Vector3D::dot(&ray.direction, &normal);
                }

                let cos2_t = 1.0 - n * n * (1.0 - cos_i * cos_i);
                if cos2_t > 0.0 {
                    let refracted_direction = (&ray.direction * n + &normal * (n * cos_i - (cos2_t).sqrt())).to_unit();
                    let nearby_point = point.translate_dist(&refracted_direction, BIAS);
                    let refracted_result = self.trace(&Ray3D::new(&nearby_point, &refracted_direction), depth + 1);

                    // Beer's Law
                    let absorbance = &surface_material.color * (0.15 * -refracted_result.distance);
                    let transparency = ColorRGB::from_rgb(absorbance.red.exp(), absorbance.green.exp(), absorbance.blue.exp());
                    total_ray_color = &total_ray_color + &refracted_result.color * transparency;
                }
            }
        }

        // Calculate the color from each light in the scene.
        for light_item in self.lights.iter() {
            let light = &light_item.light;
            let light_color = light.get_material(&point).color;
            let vector_to_light = Vector3D::between_points(&point, light.get_center());
            let distance_to_light = vector_to_light.magnitude();
            let direction_to_light = vector_to_light.to_unit();

            // Calculate the shading from the light.
            let mut shade: f32 = 1.0;
            let nearby_point = point.translate_dist(&direction_to_light, BIAS);
            let shadow_ray = Ray3D::new(&nearby_point, &direction_to_light);
            for shadow_item in self.items.iter() {
                if shadow_item.index != light_item.index {
                    let shadow_result = shadow_item.object.intersect(&shadow_ray);
                    if let Some(distance) = shadow_result {
                        if distance < distance_to_light {
                            shade = 0.0;
                            break;
                        }
                    }
                }
            }

            if shade != 0.0 {
                // Calculate the diffusive lighting from the light.
                let diffuse = surface_material.diffuse;
                if diffuse > 0.0 {
                    let percentage_of_light = Vector3D::dot(&normal, &direction_to_light);
                    if percentage_of_light > 0.0 {
                        total_ray_color = &total_ray_color + (&light_color * &surface_material.color) * (shade * diffuse * percentage_of_light);
                    }
                }

                // Calculate the specular lighting from the light.
                let specular = surface_material.specular;
                let shininess = surface_material.shininess;
                if specular > 0.0 && shininess > 0 {
                    let reflected_direction = (&direction_to_light - &normal * 2.0 * Vector3D::dot(&direction_to_light, &normal)).to_unit();
                    let percentage_of_light = Vector3D::dot(&ray.direction, &reflected_direction);
                    if percentage_of_light > 0.0 {
                        total_ray_color = &total_ray_color + &light_color * (shade * specular * percentage_of_light.powi(shininess as i32));
                    }
                }
            }
        }

        TraceResult {
            color: total_ray_color,
            distance: nearest_distance
        }
    }
}

struct InternalObject {
    pub index: usize,
    pub object: Box<SceneObject+Sync+Send>,
    pub is_light: bool
}

struct InternalLight {
    pub index: usize,
    pub light: Box<SceneLight>
}

#[derive(Show)]
pub struct TraceResult {
    pub color: ColorRGB,
    pub distance: f32
}
<|endoftext|>


<commit_before>//! A collection of serialization and deserialization functions
//! that use the `serde` crate for the serializable and deserializable
//! implementation.

use std::io::{Write, Read};
use ::SizeLimit;

pub use self::reader::{
    Deserializer,
    DeserializeResult,
    DeserializeError,
    InvalidEncoding
};

pub use self::writer::{
    Serializer,
    SerializeResult,
    SerializeError,
};

use self::writer::SizeChecker;

use serde_crate as serde;

mod reader;
mod writer;

/// Serializes an object directly into a `Writer`.
///
/// If the serialization would take more bytes than allowed by `size_limit`, an error
/// is returned and *no bytes* will be written into the `Writer`.
///
/// If this returns an `SerializeError` (other than SizeLimit), assume that the
/// writer is in an invalid state, as writing could bail out in the middle of
/// serializing.
pub fn serialize_into<W, T>(writer: &mut W, value: &T, size_limit: SizeLimit) -> SerializeResult<()>
    where W: Write, T: serde::Serialize,
{
    match size_limit {
        SizeLimit::Infinite => { }
        SizeLimit::Bounded(x) => {
            let mut size_checker = SizeChecker::new(x);
            try!(value.serialize(&mut size_checker))
        }
    }

    let mut serializer = Serializer::new(writer);
    serde::Serialize::serialize(value, &mut serializer)
}

/// Serializes a serializable object into a `Vec` of bytes.
///
/// If the serialization would take more bytes than allowed by `size_limit`,
/// an error is returned.
pub fn serialize<T>(value: &T, size_limit: SizeLimit) -> SerializeResult<Vec<u8>>
    where T: serde::Serialize,
{
    // Since we are putting values directly into a vector, we can do size
    // computation out here and pre-allocate a buffer of *exactly*
    // the right size.
    let mut writer = match size_limit {
        SizeLimit::Bounded(size_limit) => {
            let actual_size = match serialized_size_bounded(value, size_limit) {
                Some(actual_size) => actual_size,
                None => { return Err(SerializeError::SizeLimit); }
            };
            Vec::with_capacity(actual_size as usize)
        }
        SizeLimit::Infinite => Vec::new()
    };

    try!(serialize_into(&mut writer, value, SizeLimit::Infinite));
    Ok(writer)
}

/// Returns the size that an object would be if serialized using bincode.
///
/// This is used internally as part of the check for encode_into, but it can
/// be useful for preallocating buffers if thats your style.
pub fn serialized_size<T: serde::Serialize>(value: &T) -> u64 {
    use std::u64::MAX;
    let mut size_checker = SizeChecker::new(MAX);
    value.serialize(&mut size_checker).ok();
    size_checker.written
}

/// Given a maximum size limit, check how large an object would be if it
/// were to be serialized.
///
/// If it can be serialized in `max` or fewer bytes, that number will be returned
/// inside `Some`.  If it goes over bounds, then None is returned.
pub fn serialized_size_bounded<T: serde::Serialize>(value: &T, max: u64) -> Option<u64> {
    let mut size_checker = SizeChecker::new(max);
    value.serialize(&mut size_checker).ok().map(|_| size_checker.written)
}

/// Deserializes an object directly from a `Buffer`ed Reader.
///
/// If the provided `SizeLimit` is reached, the deserialization will bail immediately.
/// A SizeLimit can help prevent an attacker from flooding your server with
/// a neverending stream of values that runs your server out of memory.
///
/// If this returns an `DeserializeError`, assume that the buffer that you passed
/// in is in an invalid state, as the error could be returned during any point
/// in the reading.
pub fn deserialize_from<R, T>(reader: &mut R, size_limit: SizeLimit) -> DeserializeResult<T>
    where R: Read,
          T: serde::Deserialize,
{
    let mut deserializer = Deserializer::new(reader, size_limit);
    serde::Deserialize::deserialize(&mut deserializer)
}

/// Deserializes a slice of bytes into an object.
///
/// This method does not have a size-limit because if you already have the bytes
/// in memory, then you don't gain anything by having a limiter.
pub fn deserialize<T>(bytes: &[u8]) -> DeserializeResult<T>
    where T: serde::Deserialize,
{
    let mut reader = bytes;
    deserialize_from(&mut reader, SizeLimit::Infinite)
}
<commit_msg>Remove sized bounds where appropriate (#101)<commit_after>//! A collection of serialization and deserialization functions
//! that use the `serde` crate for the serializable and deserializable
//! implementation.

use std::io::{Write, Read};
use ::SizeLimit;

pub use self::reader::{
    Deserializer,
    DeserializeResult,
    DeserializeError,
    InvalidEncoding
};

pub use self::writer::{
    Serializer,
    SerializeResult,
    SerializeError,
};

use self::writer::SizeChecker;

use serde_crate as serde;

mod reader;
mod writer;

/// Serializes an object directly into a `Writer`.
///
/// If the serialization would take more bytes than allowed by `size_limit`, an error
/// is returned and *no bytes* will be written into the `Writer`.
///
/// If this returns an `SerializeError` (other than SizeLimit), assume that the
/// writer is in an invalid state, as writing could bail out in the middle of
/// serializing.
pub fn serialize_into<W: ?Sized, T: ?Sized>(writer: &mut W, value: &T, size_limit: SizeLimit) -> SerializeResult<()>
    where W: Write,
          T: serde::Serialize,
{
    match size_limit {
        SizeLimit::Infinite => { }
        SizeLimit::Bounded(x) => {
            let mut size_checker = SizeChecker::new(x);
            try!(value.serialize(&mut size_checker))
        }
    }

    let mut serializer = Serializer::new(writer);
    serde::Serialize::serialize(value, &mut serializer)
}

/// Serializes a serializable object into a `Vec` of bytes.
///
/// If the serialization would take more bytes than allowed by `size_limit`,
/// an error is returned.
pub fn serialize<T: ?Sized>(value: &T, size_limit: SizeLimit) -> SerializeResult<Vec<u8>>
    where T: serde::Serialize
{
    // Since we are putting values directly into a vector, we can do size
    // computation out here and pre-allocate a buffer of *exactly*
    // the right size.
    let mut writer = match size_limit {
        SizeLimit::Bounded(size_limit) => {
            let actual_size = match serialized_size_bounded(value, size_limit) {
                Some(actual_size) => actual_size,
                None => { return Err(SerializeError::SizeLimit); }
            };
            Vec::with_capacity(actual_size as usize)
        }
        SizeLimit::Infinite => Vec::new()
    };

    try!(serialize_into(&mut writer, value, SizeLimit::Infinite));
    Ok(writer)
}

/// Returns the size that an object would be if serialized using bincode.
///
/// This is used internally as part of the check for encode_into, but it can
/// be useful for preallocating buffers if thats your style.
pub fn serialized_size<T: ?Sized>(value: &T) -> u64
    where T: serde::Serialize
{
    use std::u64::MAX;
    let mut size_checker = SizeChecker::new(MAX);
    value.serialize(&mut size_checker).ok();
    size_checker.written
}

/// Given a maximum size limit, check how large an object would be if it
/// were to be serialized.
///
/// If it can be serialized in `max` or fewer bytes, that number will be returned
/// inside `Some`.  If it goes over bounds, then None is returned.
pub fn serialized_size_bounded<T: ?Sized>(value: &T, max: u64) -> Option<u64>
    where T: serde::Serialize
{
    let mut size_checker = SizeChecker::new(max);
    value.serialize(&mut size_checker).ok().map(|_| size_checker.written)
}

/// Deserializes an object directly from a `Buffer`ed Reader.
///
/// If the provided `SizeLimit` is reached, the deserialization will bail immediately.
/// A SizeLimit can help prevent an attacker from flooding your server with
/// a neverending stream of values that runs your server out of memory.
///
/// If this returns an `DeserializeError`, assume that the buffer that you passed
/// in is in an invalid state, as the error could be returned during any point
/// in the reading.
pub fn deserialize_from<R: ?Sized, T>(reader: &mut R, size_limit: SizeLimit) -> DeserializeResult<T>
    where R: Read,
          T: serde::Deserialize,
{
    let mut deserializer = Deserializer::new(reader, size_limit);
    serde::Deserialize::deserialize(&mut deserializer)
}

/// Deserializes a slice of bytes into an object.
///
/// This method does not have a size-limit because if you already have the bytes
/// in memory, then you don't gain anything by having a limiter.
pub fn deserialize<T>(bytes: &[u8]) -> DeserializeResult<T>
    where T: serde::Deserialize,
{
    let mut reader = bytes;
    deserialize_from(&mut reader, SizeLimit::Infinite)
}
<|endoftext|>


<commit_before>//! AWS API request signatures.
//!
//! Follows [AWS Signature 4](http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)
//! algorithm.
//!
//! If needed, the request will be re-issued to a temporary redirect endpoint.  This can happen with
//! newly created S3 buckets not in us-standard/us-east-1.

use std::ascii::AsciiExt;
use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use std::str;

use hyper::status::StatusCode;
use openssl::crypto::hash::Type::SHA256;
use openssl::crypto::hash::hash;
use openssl::crypto::hmac::hmac;
use rustc_serialize::hex::ToHex;
use time::Tm;
use time::now_utc;
use url::percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET, QUERY_ENCODE_SET};

use credential::AwsCredentials;
use param::Params;
use region::Region;

const HTTP_TEMPORARY_REDIRECT: StatusCode = StatusCode::TemporaryRedirect;

/// A data structure for all the elements of an HTTP request that are involved in
/// the Amazon Signature Version 4 signing process
#[derive(Debug)]
pub struct SignedRequest<'a> {
    method: String,
    service: String,
    region: Region,
    path: String,
    headers: BTreeMap<String, Vec<Vec<u8>>>,
    params: Params,
    hostname: Option<String>,
    payload: Option<&'a [u8]>,
    content_type: Option<String>,
    canonical_query_string: String,
    canonical_uri: String,
}

impl <'a> SignedRequest <'a> {
    /// Default constructor
    pub fn new(method: &str, service: &str, region: Region, path: &str) -> SignedRequest<'a> {
        SignedRequest {
            method: method.to_string(),
            service: service.to_string(),
            region: region,
            path: path.to_string(),
            headers: BTreeMap::new(),
            params: Params::new(),
            hostname: None,
            payload: None,
            content_type: None,
            canonical_query_string: String::new(),
            canonical_uri: String::new(),
         }
    }

    pub fn set_content_type(&mut self, content_type: String) {
        self.content_type = Some(content_type);
    }

    pub fn set_hostname(&mut self, hostname: Option<String>) {
        self.hostname = hostname;
    }

    pub fn set_endpoint_prefix(&mut self, endpoint_prefix: String) {
        self.hostname = Some(build_hostname(&endpoint_prefix, self.region));
    }

    pub fn set_payload(&mut self, payload: Option<&'a [u8]>) {
        self.payload = payload;
    }

    pub fn method(&self) -> &str {
        &self.method
    }

    pub fn path(&self) -> &str {
        &self.path
    }

    pub fn canonical_uri(&self) -> &str {
        &self.canonical_uri
    }

    pub fn canonical_query_string(&self) -> &str {
        &self.canonical_query_string
    }

    pub fn payload(&self) -> Option<&'a [u8]> {
        self.payload
    }

    pub fn headers(&'a self) -> &'a BTreeMap<String, Vec<Vec<u8>>> {
        &self.headers
    }

    pub fn hostname(&self) -> String {
        match self.hostname {
            Some(ref h) => h.to_string(),
            None => build_hostname(&self.service, self.region)
        }
    }

    // If the key exists in headers, set it to blank/unoccupied:
    pub fn remove_header(&mut self, key: &str) {
        let key_lower = key.to_ascii_lowercase().to_string();
        self.headers.remove(&key_lower);
    }

    /// Add a value to the array of headers for the specified key.
    /// Headers are kept sorted by key name for use at signing (BTreeMap)
    pub fn add_header(&mut self, key: &str, value: &str) {
        let key_lower = key.to_ascii_lowercase().to_string();
        let value_vec = value.as_bytes().to_vec();

        match self.headers.entry(key_lower) {
            Entry::Vacant(entry) => {
                let mut values = Vec::new();
                values.push(value_vec);
                entry.insert(values);
            }
            Entry::Occupied(entry) => {
                entry.into_mut().push(value_vec);
            }
        }
    }

    pub fn add_param<S>(&mut self, key: S, value: S)  where S: Into<String> {
        self.params.insert(key.into(), value.into());
    }

    pub fn set_params(&mut self, params: Params){
        self.params = params;
    }

    pub fn sign(&mut self, creds: &AwsCredentials) {
        debug!("Creating request to send to AWS.");
        let hostname = match self.hostname {
            Some(ref h) => h.to_string(),
            None => build_hostname(&self.service, self.region)
        };

        // Gotta remove and re-add headers since by default they append the value.  If we're following
        // a 307 redirect we end up with Three Stooges in the headers with duplicate values.
        self.remove_header("host");
        self.add_header("host", &hostname);

        if let Some(ref token) = *creds.token() {
            self.remove_header("X-Amz-Security-Token");
            self.add_header("X-Amz-Security-Token", token);
        }

        self.canonical_query_string = build_canonical_query_string(&self.params);

        let date = now_utc();
        self.remove_header("x-amz-date");
        self.add_header("x-amz-date", &date.strftime("%Y%m%dT%H%M%SZ").unwrap().to_string());

        // build the canonical request
        let signed_headers = signed_headers(&self.headers);
        self.canonical_uri = canonical_uri(&self.path);
        let canonical_headers = canonical_headers(&self.headers);

        let canonical_request : String;

        match self.payload {
            None => {
                canonical_request = format!("{}\n{}\n{}\n{}\n{}\n{}",
                    &self.method,
                    self.canonical_uri,
                    self.canonical_query_string,
                    canonical_headers,
                    signed_headers,
                    &to_hexdigest_from_string(""));
                self.remove_header("x-amz-content-sha256");
                self.add_header("x-amz-content-sha256", &to_hexdigest_from_string(""));
            }
            Some(payload) => {
                // This is hashing the payload twice, booo:
                canonical_request = format!("{}\n{}\n{}\n{}\n{}\n{}",
                    &self.method,
                    self.canonical_uri,
                    self.canonical_query_string,
                    canonical_headers,
                    signed_headers,
                    &to_hexdigest_from_bytes(payload));
                self.remove_header("x-amz-content-sha256");
                self.add_header("x-amz-content-sha256", &to_hexdigest_from_bytes(payload));
                self.remove_header("content-length");
                self.add_header("content-length", &format!("{}", payload.len()));
            }
        }

        self.remove_header("content-type");
        let ct = match self.content_type {
            Some(ref h) => h.to_string(),
            None => String::from("application/octet-stream")
        };

        self.add_header("content-type", &ct);

        // use the hashed canonical request to build the string to sign
        let hashed_canonical_request = to_hexdigest_from_string(&canonical_request);
        let scope = format!("{}/{}/{}/aws4_request", date.strftime("%Y%m%d").unwrap(), self.region, &self.service);
        let string_to_sign = string_to_sign(date, &hashed_canonical_request, &scope);

        // construct the signing key and sign the string with it
        let signing_key = signing_key(creds.aws_secret_access_key(), date, &self.region.to_string(), &self.service);
        let signature = signature(&string_to_sign, signing_key);

        // build the actual auth header
        let auth_header = format!("AWS4-HMAC-SHA256 Credential={}/{}, SignedHeaders={}, Signature={}",
                   &creds.aws_access_key_id(), scope, signed_headers, signature);
        self.remove_header("authorization");
        self.add_header("authorization", &auth_header);
    }

}

fn signature(string_to_sign: &str, signing_key: Vec<u8>) -> String {
    hmac(SHA256, &signing_key, string_to_sign.as_bytes()).to_hex().to_string()
}

fn signing_key(secret: &str, date: Tm, region: &str, service: &str) -> Vec<u8> {
    let k_date = hmac(SHA256, format!("AWS4{}", secret).as_bytes(), date.strftime("%Y%m%d").unwrap().to_string().as_bytes());
    let k_region = hmac(SHA256, &k_date, region.as_bytes());
    let k_service = hmac(SHA256, &k_region, service.as_bytes());
    hmac(SHA256, &k_service, b"aws4_request")
}

/// Mark string as AWS4-HMAC-SHA256 hashed
pub fn string_to_sign(date: Tm, hashed_canonical_request: &str, scope: &str) -> String {
    format!("AWS4-HMAC-SHA256\n{}\n{}\n{}",
        date.strftime("%Y%m%dT%H%M%SZ").unwrap(),
        scope,
        hashed_canonical_request)
}

fn signed_headers(headers: &BTreeMap<String, Vec<Vec<u8>>>) -> String {
    let mut signed = String::new();

    for (key,_) in headers.iter() {
        if !signed.is_empty() {
            signed.push(';')
        }

        if skipped_headers(key) {
            continue;
        }
        signed.push_str(&key.to_ascii_lowercase());
    }
    signed
}

fn canonical_headers(headers: &BTreeMap<String, Vec<Vec<u8>>>) -> String {
    let mut canonical = String::new();

    for item in headers.iter() {
        if skipped_headers(item.0) {
            continue;
        }
        canonical.push_str(format!("{}:{}\n", item.0.to_ascii_lowercase(), canonical_values(item.1)).as_ref());
    }
    canonical
}

fn canonical_values(values: &[Vec<u8>]) -> String {
    let mut st = String::new();
    for v in values {
        let s = str::from_utf8(v).unwrap();
        if !st.is_empty() {
            st.push(',')
        }
        if s.starts_with('\"') {
            st.push_str(s);
        } else {
            st.push_str(s.replace("  ", " ").trim());
        }
    }
    st
}

fn skipped_headers(header: &str) -> bool {
    ["authorization", "content-length", "user-agent"].contains(&header)
}

fn canonical_uri(path: &str) -> String {
    match path {
        "" => "/".to_string(),
        _ => encode_uri(path)
    }
}

fn build_canonical_query_string(params: &Params) -> String {
    if params.is_empty() {
        return String::new();
    }

    let mut output = String::new();
    for item in params.iter() {
        if !output.is_empty() {
            output.push_str("&");
        }
        output.push_str(&byte_serialize(item.0));
        output.push_str("=");
        output.push_str(&byte_serialize(item.1));
    }

    output
}

#[inline]
fn encode_uri(uri: &str) -> String {
    utf8_percent_encode(uri, QUERY_ENCODE_SET).collect::<String>()
}

#[inline]
fn byte_serialize(input: &str) -> String {
    utf8_percent_encode(input, DEFAULT_ENCODE_SET).collect::<String>()
}

// TODO: consolidate these functions
fn to_hexdigest_from_string(val: &str) -> String {
    let h = hash(SHA256, val.as_bytes());
    h.to_hex().to_string()
}

fn to_hexdigest_from_bytes(val: &[u8]) -> String {
    let h = hash(SHA256, val);
    h.to_hex().to_string()
}

fn build_hostname(service: &str, region: Region) -> String {
    //iam has only 1 endpoint, other services have region-based endpoints
    match service {
        "iam" => {
                match region {
                    Region::CnNorth1 => format!("{}.{}.amazonaws.com.cn", service, region),
                    _ => format!("{}.amazonaws.com", service),
                }
            }
        "s3" => {
                match region {
                    Region::UsEast1 => "s3.amazonaws.com".to_string(),
                    Region::CnNorth1 => format!("s3.{}.amazonaws.com.cn", region),
                    _ => format!("s3-{}.amazonaws.com", region),
                }
            }
        _ => {
                match region {
                    Region::CnNorth1 => format!("{}.{}.amazonaws.com.cn", service, region),
                    _ => format!("{}.{}.amazonaws.com", service, region),
                }
            }
    }
}

#[cfg(test)]
mod tests {
    use region::Region;

    use super::SignedRequest;

    use super::super::ProfileProvider;
    use super::super::credential::ProvideAwsCredentials;

    #[test]
    fn get_hostname_none_present() {
        let request = SignedRequest::new("POST", "sqs", Region::UsEast1, "/");
        assert_eq!("sqs.us-east-1.amazonaws.com", request.hostname());
    }

    #[test]
    fn get_hostname_happy_path() {
        let mut request = SignedRequest::new("POST", "sqs", Region::UsEast1, "/");
        request.set_hostname(Some("test-hostname".to_string()));
        assert_eq!("test-hostname", request.hostname());
    }
    #[test]
    fn path_percent_encoded() {
        let provider = ProfileProvider::with_configuration(
            "tests/sample-data/multiple_profile_credentials",
            "foo",
        );
        let mut request = SignedRequest::new("GET", "s3", Region::UsEast1, "/path with spaces");
        request.sign(provider.credentials().as_ref().unwrap());
        assert_eq!("/path%20with%20spaces", request.canonical_uri());
    }
}
<commit_msg>Cleanup code when digesting string slices and bytes.<commit_after>//! AWS API request signatures.
//!
//! Follows [AWS Signature 4](http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)
//! algorithm.
//!
//! If needed, the request will be re-issued to a temporary redirect endpoint.  This can happen with
//! newly created S3 buckets not in us-standard/us-east-1.

use std::ascii::AsciiExt;
use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use std::str;

use hyper::status::StatusCode;
use openssl::crypto::hash::Type::SHA256;
use openssl::crypto::hash::hash;
use openssl::crypto::hmac::hmac;
use rustc_serialize::hex::ToHex;
use time::Tm;
use time::now_utc;
use url::percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET, QUERY_ENCODE_SET};

use credential::AwsCredentials;
use param::Params;
use region::Region;

const HTTP_TEMPORARY_REDIRECT: StatusCode = StatusCode::TemporaryRedirect;

/// A data structure for all the elements of an HTTP request that are involved in
/// the Amazon Signature Version 4 signing process
#[derive(Debug)]
pub struct SignedRequest<'a> {
    method: String,
    service: String,
    region: Region,
    path: String,
    headers: BTreeMap<String, Vec<Vec<u8>>>,
    params: Params,
    hostname: Option<String>,
    payload: Option<&'a [u8]>,
    content_type: Option<String>,
    canonical_query_string: String,
    canonical_uri: String,
}

impl <'a> SignedRequest <'a> {
    /// Default constructor
    pub fn new(method: &str, service: &str, region: Region, path: &str) -> SignedRequest<'a> {
        SignedRequest {
            method: method.to_string(),
            service: service.to_string(),
            region: region,
            path: path.to_string(),
            headers: BTreeMap::new(),
            params: Params::new(),
            hostname: None,
            payload: None,
            content_type: None,
            canonical_query_string: String::new(),
            canonical_uri: String::new(),
         }
    }

    pub fn set_content_type(&mut self, content_type: String) {
        self.content_type = Some(content_type);
    }

    pub fn set_hostname(&mut self, hostname: Option<String>) {
        self.hostname = hostname;
    }

    pub fn set_endpoint_prefix(&mut self, endpoint_prefix: String) {
        self.hostname = Some(build_hostname(&endpoint_prefix, self.region));
    }

    pub fn set_payload(&mut self, payload: Option<&'a [u8]>) {
        self.payload = payload;
    }

    pub fn method(&self) -> &str {
        &self.method
    }

    pub fn path(&self) -> &str {
        &self.path
    }

    pub fn canonical_uri(&self) -> &str {
        &self.canonical_uri
    }

    pub fn canonical_query_string(&self) -> &str {
        &self.canonical_query_string
    }

    pub fn payload(&self) -> Option<&'a [u8]> {
        self.payload
    }

    pub fn headers(&'a self) -> &'a BTreeMap<String, Vec<Vec<u8>>> {
        &self.headers
    }

    pub fn hostname(&self) -> String {
        match self.hostname {
            Some(ref h) => h.to_string(),
            None => build_hostname(&self.service, self.region)
        }
    }

    // If the key exists in headers, set it to blank/unoccupied:
    pub fn remove_header(&mut self, key: &str) {
        let key_lower = key.to_ascii_lowercase().to_string();
        self.headers.remove(&key_lower);
    }

    /// Add a value to the array of headers for the specified key.
    /// Headers are kept sorted by key name for use at signing (BTreeMap)
    pub fn add_header(&mut self, key: &str, value: &str) {
        let key_lower = key.to_ascii_lowercase().to_string();
        let value_vec = value.as_bytes().to_vec();

        match self.headers.entry(key_lower) {
            Entry::Vacant(entry) => {
                let mut values = Vec::new();
                values.push(value_vec);
                entry.insert(values);
            }
            Entry::Occupied(entry) => {
                entry.into_mut().push(value_vec);
            }
        }
    }

    pub fn add_param<S>(&mut self, key: S, value: S)  where S: Into<String> {
        self.params.insert(key.into(), value.into());
    }

    pub fn set_params(&mut self, params: Params){
        self.params = params;
    }

    pub fn sign(&mut self, creds: &AwsCredentials) {
        debug!("Creating request to send to AWS.");
        let hostname = match self.hostname {
            Some(ref h) => h.to_string(),
            None => build_hostname(&self.service, self.region)
        };

        // Gotta remove and re-add headers since by default they append the value.  If we're following
        // a 307 redirect we end up with Three Stooges in the headers with duplicate values.
        self.remove_header("host");
        self.add_header("host", &hostname);

        if let Some(ref token) = *creds.token() {
            self.remove_header("X-Amz-Security-Token");
            self.add_header("X-Amz-Security-Token", token);
        }

        self.canonical_query_string = build_canonical_query_string(&self.params);

        let date = now_utc();
        self.remove_header("x-amz-date");
        self.add_header("x-amz-date", &date.strftime("%Y%m%dT%H%M%SZ").unwrap().to_string());

        // build the canonical request
        let signed_headers = signed_headers(&self.headers);
        self.canonical_uri = canonical_uri(&self.path);
        let canonical_headers = canonical_headers(&self.headers);

        let canonical_request : String;

        match self.payload {
            None => {
                canonical_request = format!("{}\n{}\n{}\n{}\n{}\n{}",
                    &self.method,
                    self.canonical_uri,
                    self.canonical_query_string,
                    canonical_headers,
                    signed_headers,
                    &to_hexdigest(""));
                self.remove_header("x-amz-content-sha256");
                self.add_header("x-amz-content-sha256", &to_hexdigest(""));
            }
            Some(payload) => {
                // This is hashing the payload twice, booo:
                canonical_request = format!("{}\n{}\n{}\n{}\n{}\n{}",
                    &self.method,
                    self.canonical_uri,
                    self.canonical_query_string,
                    canonical_headers,
                    signed_headers,
                    &to_hexdigest(payload));
                self.remove_header("x-amz-content-sha256");
                self.add_header("x-amz-content-sha256", &to_hexdigest(payload));
                self.remove_header("content-length");
                self.add_header("content-length", &format!("{}", payload.len()));
            }
        }

        self.remove_header("content-type");
        let ct = match self.content_type {
            Some(ref h) => h.to_string(),
            None => String::from("application/octet-stream")
        };

        self.add_header("content-type", &ct);

        // use the hashed canonical request to build the string to sign
        let hashed_canonical_request = to_hexdigest(&canonical_request);
        let scope = format!("{}/{}/{}/aws4_request", date.strftime("%Y%m%d").unwrap(), self.region, &self.service);
        let string_to_sign = string_to_sign(date, &hashed_canonical_request, &scope);

        // construct the signing key and sign the string with it
        let signing_key = signing_key(creds.aws_secret_access_key(), date, &self.region.to_string(), &self.service);
        let signature = signature(&string_to_sign, signing_key);

        // build the actual auth header
        let auth_header = format!("AWS4-HMAC-SHA256 Credential={}/{}, SignedHeaders={}, Signature={}",
                   &creds.aws_access_key_id(), scope, signed_headers, signature);
        self.remove_header("authorization");
        self.add_header("authorization", &auth_header);
    }

}

fn signature(string_to_sign: &str, signing_key: Vec<u8>) -> String {
    hmac(SHA256, &signing_key, string_to_sign.as_bytes()).to_hex().to_string()
}

fn signing_key(secret: &str, date: Tm, region: &str, service: &str) -> Vec<u8> {
    let k_date = hmac(SHA256, format!("AWS4{}", secret).as_bytes(), date.strftime("%Y%m%d").unwrap().to_string().as_bytes());
    let k_region = hmac(SHA256, &k_date, region.as_bytes());
    let k_service = hmac(SHA256, &k_region, service.as_bytes());
    hmac(SHA256, &k_service, b"aws4_request")
}

/// Mark string as AWS4-HMAC-SHA256 hashed
pub fn string_to_sign(date: Tm, hashed_canonical_request: &str, scope: &str) -> String {
    format!("AWS4-HMAC-SHA256\n{}\n{}\n{}",
        date.strftime("%Y%m%dT%H%M%SZ").unwrap(),
        scope,
        hashed_canonical_request)
}

fn signed_headers(headers: &BTreeMap<String, Vec<Vec<u8>>>) -> String {
    let mut signed = String::new();

    for (key,_) in headers.iter() {
        if !signed.is_empty() {
            signed.push(';')
        }

        if skipped_headers(key) {
            continue;
        }
        signed.push_str(&key.to_ascii_lowercase());
    }
    signed
}

fn canonical_headers(headers: &BTreeMap<String, Vec<Vec<u8>>>) -> String {
    let mut canonical = String::new();

    for item in headers.iter() {
        if skipped_headers(item.0) {
            continue;
        }
        canonical.push_str(format!("{}:{}\n", item.0.to_ascii_lowercase(), canonical_values(item.1)).as_ref());
    }
    canonical
}

fn canonical_values(values: &[Vec<u8>]) -> String {
    let mut st = String::new();
    for v in values {
        let s = str::from_utf8(v).unwrap();
        if !st.is_empty() {
            st.push(',')
        }
        if s.starts_with('\"') {
            st.push_str(s);
        } else {
            st.push_str(s.replace("  ", " ").trim());
        }
    }
    st
}

fn skipped_headers(header: &str) -> bool {
    ["authorization", "content-length", "user-agent"].contains(&header)
}

fn canonical_uri(path: &str) -> String {
    match path {
        "" => "/".to_string(),
        _ => encode_uri(path)
    }
}

fn build_canonical_query_string(params: &Params) -> String {
    if params.is_empty() {
        return String::new();
    }

    let mut output = String::new();
    for item in params.iter() {
        if !output.is_empty() {
            output.push_str("&");
        }
        output.push_str(&byte_serialize(item.0));
        output.push_str("=");
        output.push_str(&byte_serialize(item.1));
    }

    output
}

#[inline]
fn encode_uri(uri: &str) -> String {
    utf8_percent_encode(uri, QUERY_ENCODE_SET).collect::<String>()
}

#[inline]
fn byte_serialize(input: &str) -> String {
    utf8_percent_encode(input, DEFAULT_ENCODE_SET).collect::<String>()
}

fn to_hexdigest<T: AsRef<[u8]>>(t: T) -> String {
    let h = hash(SHA256, t.as_ref());
    h.to_hex().to_string()
}

fn build_hostname(service: &str, region: Region) -> String {
    //iam has only 1 endpoint, other services have region-based endpoints
    match service {
        "iam" => {
                match region {
                    Region::CnNorth1 => format!("{}.{}.amazonaws.com.cn", service, region),
                    _ => format!("{}.amazonaws.com", service),
                }
            }
        "s3" => {
                match region {
                    Region::UsEast1 => "s3.amazonaws.com".to_string(),
                    Region::CnNorth1 => format!("s3.{}.amazonaws.com.cn", region),
                    _ => format!("s3-{}.amazonaws.com", region),
                }
            }
        _ => {
                match region {
                    Region::CnNorth1 => format!("{}.{}.amazonaws.com.cn", service, region),
                    _ => format!("{}.{}.amazonaws.com", service, region),
                }
            }
    }
}

#[cfg(test)]
mod tests {
    use region::Region;

    use super::SignedRequest;

    use super::super::ProfileProvider;
    use super::super::credential::ProvideAwsCredentials;

    #[test]
    fn get_hostname_none_present() {
        let request = SignedRequest::new("POST", "sqs", Region::UsEast1, "/");
        assert_eq!("sqs.us-east-1.amazonaws.com", request.hostname());
    }

    #[test]
    fn get_hostname_happy_path() {
        let mut request = SignedRequest::new("POST", "sqs", Region::UsEast1, "/");
        request.set_hostname(Some("test-hostname".to_string()));
        assert_eq!("test-hostname", request.hostname());
    }
    #[test]
    fn path_percent_encoded() {
        let provider = ProfileProvider::with_configuration(
            "tests/sample-data/multiple_profile_credentials",
            "foo",
        );
        let mut request = SignedRequest::new("GET", "s3", Region::UsEast1, "/path with spaces");
        request.sign(provider.credentials().as_ref().unwrap());
        assert_eq!("/path%20with%20spaces", request.canonical_uri());
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

#[macro_use] extern crate adapton ;
extern crate test ;

use std::rc::Rc;
use adapton::adapton_sigs::* ;
use adapton::engine::* ;
use adapton::macros::* ;

/// Direction Graph where each node has exactly two outgoing edges
#[derive(Debug,PartialEq,Eq,Hash,Clone)]
pub struct BiDiGraph {
  id:usize,
  lsucc:Artic<BiDiGraph>,
  rsucc:Artic<BiDiGraph>,
}

pub fn count_forever (g:BiDiGraph) -> usize {
  let cl = eageric!(count_forever, g:force(&g.lsucc));
  let cr = eageric!(count_forever, g:force(&g.rsucc));
  1 + cl.1 + cr.1
}

pub fn count_visit_cases (g:BiDiGraph) -> usize {
  fn visit (g:BiDiGraph,
            visit_flag:bool,
            rec:&(Fn(BiDiGraph)-> usize)) -> usize {
    if visit_flag { 0 } else {
      let gl = force(&g.lsucc);
      let gr = force(&g.rsucc);
      match (g.id == gl.id, g.id == gr.id, gl.id == gr.id) {
        (false, false, false) => 1 + rec(gl) + rec(gr),
        (true,  false, false) => 1 + 0       + rec(gr),
        (false, true,  false) => 1 + rec(gl) + 0,
        (false, false, true)  => 1 + rec(gl) + 0,
        (true,  true,  true)  => 1 + 0       + 0,
        (true,  true,  false) => unreachable!(),
        (true,  false, true)  => unreachable!(),
        (false, true,  true)  => unreachable!(),
      }
    }
  };
  let t = cothunk(prog_pt!(stringify!(visit)),
                  Rc::new(Box::new(visit)), g);
  force(&t)
}

pub fn count_visit (g:BiDiGraph) -> usize {
  fn visit (g:BiDiGraph,
            visit_flag:bool,
            rec:&(Fn(BiDiGraph)-> usize)) -> usize {
    if visit_flag { 0 } else {
      let gl = force(&g.lsucc);
      let gr = force(&g.rsucc);
      1 + rec(gl) + rec(gr)
    }
  };
  let t = cothunk(prog_pt!(stringify!(visit)),
                  Rc::new(Box::new(visit)), g);
  force(&t)
}

pub fn count_visit_trip (g:BiDiGraph) -> usize {
  fn visit (g:BiDiGraph,
            visit_flag:bool, st:Trip,
            rec:&(Fn(BiDiGraph,Trip)-> (usize,Trip))) -> (usize,Trip) {
    if visit_flag { (0,st) } else {
      let gl      = force(&g.lsucc);
      let gr      = force(&g.rsucc);
      let (cl,st) = rec(gl,st);
      let (cr,st) = rec(gr,st);
      (1 + cr + cl, st)
    }
  };
  let t = cothunk2(prog_pt!(stringify!(visit)),
                   Rc::new(Box::new(visit)), g);
  force(&t)
}

pub fn bomb (_x:usize) -> BiDiGraph { panic!("BOMB!") }

// graph_RGB:
//
//      R
//    /  \
//   Y -- G
//
// Creates a directed K3 graph shown above, with nodes {R,G,B}.
// Each node has two successors: The other two nodes in the set.
// We show undirected edges above, due to limitations of ASCII.
//
pub fn graph_RGB () -> BiDiGraph {
  use std::mem;
  let nr = name_of_str("r");
  let ng = name_of_str("g");
  let ny = name_of_str("y");

  let ag : Artic<BiDiGraph> = thunkic!(ng.clone() =>> bomb, _x:0);
  let ay : Artic<BiDiGraph> = thunkic!(ny.clone() =>> bomb, _x:0);

  let r  = BiDiGraph{id:0, lsucc:ay.clone(), rsucc:ag.clone()};
  let ar = cell(nr, r.clone());

  let g  = BiDiGraph{id:1, lsucc:ar.clone(), rsucc:ay};
  let ag = cell(ng, g);

  let y  = BiDiGraph{id:2, lsucc:ag, rsucc:ar};
  let ay = cell(ny, y);

  return r
}

#[test]
pub fn count_graph() {

}
<commit_msg>avoid rustc warnings<commit_after>#![feature(test)]

#[macro_use] extern crate adapton ;
extern crate test ;

use std::rc::Rc;
use adapton::adapton_sigs::* ;
use adapton::engine::* ;
use adapton::macros::* ;

/// Direction Graph where each node has exactly two outgoing edges
#[derive(Debug,PartialEq,Eq,Hash,Clone)]
pub struct BiDiGraph {
  id:usize,
  lsucc:Artic<BiDiGraph>,
  rsucc:Artic<BiDiGraph>,
}

pub fn count_forever (g:BiDiGraph) -> usize {
  let cl = eageric!(count_forever, g:force(&g.lsucc));
  let cr = eageric!(count_forever, g:force(&g.rsucc));
  1 + cl.1 + cr.1
}

pub fn count_visit_cases (g:BiDiGraph) -> usize {
  fn visit (g:BiDiGraph,
            visit_flag:bool,
            rec:&(Fn(BiDiGraph)-> usize)) -> usize {
    if visit_flag { 0 } else {
      let gl = force(&g.lsucc);
      let gr = force(&g.rsucc);
      match (g.id == gl.id, g.id == gr.id, gl.id == gr.id) {
        (false, false, false) => 1 + rec(gl) + rec(gr),
        (true,  false, false) => 1 + 0       + rec(gr),
        (false, true,  false) => 1 + rec(gl) + 0,
        (false, false, true)  => 1 + rec(gl) + 0,
        (true,  true,  true)  => 1 + 0       + 0,
        (true,  true,  false) => unreachable!(),
        (true,  false, true)  => unreachable!(),
        (false, true,  true)  => unreachable!(),
      }
    }
  };
  let t = cothunk(prog_pt!(stringify!(visit)),
                  Rc::new(Box::new(visit)), g);
  force(&t)
}

pub fn count_visit (g:BiDiGraph) -> usize {
  fn visit (g:BiDiGraph,
            visit_flag:bool,
            rec:&(Fn(BiDiGraph)-> usize)) -> usize {
    if visit_flag { 0 } else {
      let gl = force(&g.lsucc);
      let gr = force(&g.rsucc);
      1 + rec(gl) + rec(gr)
    }
  };
  let t = cothunk(prog_pt!(stringify!(visit)),
                  Rc::new(Box::new(visit)), g);
  force(&t)
}

pub fn count_visit_trip (g:BiDiGraph) -> usize {
  fn visit (g:BiDiGraph,
            visit_flag:bool, st:Trip,
            rec:&(Fn(BiDiGraph,Trip)-> (usize,Trip))) -> (usize,Trip) {
    if visit_flag { (0,st) } else {
      let gl      = force(&g.lsucc);
      let gr      = force(&g.rsucc);
      let (cl,st) = rec(gl,st);
      let (cr,st) = rec(gr,st);
      (1 + cr + cl, st)
    }
  };
  let t = cothunk2(prog_pt!(stringify!(visit)),
                   Rc::new(Box::new(visit)), g);
  force(&t)
}

pub fn bomb (_x:usize) -> BiDiGraph { panic!("BOMB!") }

// graph_RGB:
//
//      R
//    /  \
//   Y -- G
//
// Creates a directed K3 graph shown above, with nodes {R,G,B}.
// Each node has two successors: The other two nodes in the set.
// We show undirected edges above, due to limitations of ASCII.
//
pub fn graph_rgb () -> BiDiGraph {
  let nr = name_of_str("r");
  let ng = name_of_str("g");
  let ny = name_of_str("y");

  let ag : Artic<BiDiGraph> = thunkic!(ng.clone() =>> bomb, _x:0);
  let ay : Artic<BiDiGraph> = thunkic!(ny.clone() =>> bomb, _x:0);

  let r  = BiDiGraph{id:0, lsucc:ay.clone(), rsucc:ag.clone()};
  let ar = cell(nr, r.clone());

  let g  = BiDiGraph{id:1, lsucc:ar.clone(), rsucc:ay};
  let ag = cell(ng, g);

  let y  = BiDiGraph{id:2, lsucc:ag, rsucc:ar};
  let _  = cell(ny, y);

  return r
}

#[test]
pub fn count_graph() {

}
<|endoftext|>


<commit_before>use super::super::RW;
use super::super::thread::{Handler, Message};
use super::super::evented::{EventSourceTrait, RcEventSource, Evented, EventedImpl};
use mio_orig::{EventLoop, Token, EventSet};
use std::sync::Arc;
use spin::Mutex;
use super::super::thread::MioSender;
use super::super::{sender_retry, in_coroutine, yield_now};

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc;
type ArcChannelShared = Arc<Mutex<ChannelShared>>;
type ArcCounter = Arc<AtomicUsize>;

/// State shared between senders and receiver.
struct ChannelShared {
    token: Option<Token>,
    sender: Option<MioSender>,
}

/// Channel receiving end
///
/// Create with `channel()`
pub struct Receiver<T>(RcEventSource<ReceiverCore<T>>);

struct ReceiverCore<T> {
    receiver: mpsc::Receiver<T>,
    shared: ArcChannelShared,
    counter: ArcCounter,
}

impl<T> EventedImpl for Receiver<T>
    where T: 'static
{
    type Raw = ReceiverCore<T>;

    fn shared(&self) -> &RcEventSource<ReceiverCore<T>> {
        &self.0
    }
}

impl<T> EventSourceTrait for ReceiverCore<T> {
    fn register(&mut self, event_loop: &mut EventLoop<Handler>, token: Token, interest: EventSet) -> bool {
        debug_assert!(interest.is_readable());
        trace!("Receiver({}): register", token.as_usize());
        let mut lock = self.shared.lock();

        lock.token = Some(token);
        lock.sender = Some(event_loop.channel());

        if self.counter.load(Ordering::SeqCst) != 0 {
            trace!("Receiver({}): not empty; self notify", token.as_usize());
            lock.token = None;
            true
        } else {
            false
        }
    }

    fn reregister(&mut self,
                  _event_loop: &mut EventLoop<Handler>,
                  token: Token,
                  interest: EventSet) -> bool {
        debug_assert!(interest.is_readable());
        trace!("Receiver({}): reregister", token.as_usize());
        let mut lock = self.shared.lock();

        debug_assert!(lock.token.is_some());
        debug_assert!(lock.sender.is_some());

        if self.counter.load(Ordering::SeqCst) != 0 {
            lock.token = None;
            true
        } else {
            false
        }
    }

    fn deregister(&mut self, _event_loop: &mut EventLoop<Handler>, token: Token) {
        trace!("Receiver({}): dereregister", token.as_usize());
        let mut lock = self.shared.lock();
        lock.token = None;
        lock.sender = None;
    }
}

impl<T> Receiver<T> {
    fn new(shared: ArcChannelShared, counter: ArcCounter, receiver: mpsc::Receiver<T>) -> Self {
        let core = ReceiverCore {
            shared: shared,
            counter: counter,
            receiver: receiver,
        };

        Receiver(RcEventSource::new(core))
    }
}

impl<T> Receiver<T>
    where T: 'static
{
    /// Receive `T` sent using corresponding `Sender::send()`.
    ///
    /// Will block coroutine if no elements are available.
    pub fn recv(&self) -> Result<T, mpsc::RecvError> {
        if in_coroutine() {
            loop {
                let recv = self.try_recv();

                match recv {
                    Err(mpsc::TryRecvError::Empty) => self.block_on(RW::read()),
                    Err(mpsc::TryRecvError::Disconnected) => return Err(mpsc::RecvError),
                    Ok(t) => return Ok(t),
                }
                debug_assert!(self.empty_shared_token());
            }
        } else {
            self.shared().io_ref().receiver.recv()
        }
    }

    /// Try reading data from the queue.
    ///
    /// This will not block.
    pub fn try_recv(&self) -> Result<T, mpsc::TryRecvError> {
        let shared = self.shared();
        let io_ref = shared.io_ref();
        let res = io_ref.receiver.try_recv();
        if res.is_ok() {
            let _prev_counter = self.shared().io_ref().counter.fetch_sub(1, Ordering::SeqCst);
            // since send() first sends, then increases the counter, it is
            // possible for _prev_counter to be zero
        }
        res
    }

    fn empty_shared_token(&self) -> bool {
        let shared = self.shared();
        let io_ref = shared.io_ref();
        let lock = io_ref.shared.lock();
        lock.token.is_none()
    }
}

struct SenderShared {
    shared: ArcChannelShared,
    counter: ArcCounter,
}

impl Drop for SenderShared {
    fn drop(&mut self) {
        let prev_counter = self.counter.fetch_add(1, Ordering::SeqCst);
        if prev_counter == 0 {
            maybe_notify_receiver(&self.shared);
        }
    }
}

/// Channel sending end
///
/// Use this inside mioco coroutines or outside of mioco itself to send data
/// asynchronously to the receiving end.
///
/// Create with `channel()`
pub struct Sender<T> {
    shared: Arc<SenderShared>,
    sender: mpsc::Sender<T>,
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Self {
        Sender {
            shared: self.shared.clone(),
            sender: self.sender.clone(),
        }
    }
}

impl<T> Sender<T> {
    fn new(shared: ArcChannelShared, counter: ArcCounter, sender: mpsc::Sender<T>) -> Self {
        Sender {
            shared: Arc::new(SenderShared {
                shared: shared,
                counter: counter,
            }),
            sender: sender,
        }
    }
}

/// Channel sending end
///
/// Use this inside mioco coroutines or outside of mioco itself to send data
/// asynchronously to the receiving end.
///
/// Outside mioco, this is a blocking operation if the channel is full.
///
/// Create with `sync_channel()`
pub struct SyncSender<T> {
    shared: Arc<SenderShared>,
    sender: mpsc::SyncSender<T>,
}

impl<T> SyncSender<T> {
    fn new(shared: ArcChannelShared, counter: ArcCounter, sender: mpsc::SyncSender<T>) -> Self {
        SyncSender {
            shared: Arc::new(SenderShared {
                shared: shared,
                counter: counter,
            }),
            sender: sender,
        }
    }

    /// Deliver `T` to the other end of the channel.
    ///
    /// Channel behaves like a queue.
    ///
    /// When sender is outside mioco, this is a blocking operation (if channel
    /// is full). If the sender is inside mioco, `try_send` will be
    /// called where coroutine is yielded incase of `TrySendError::Full` error.
    pub fn send(&self, mut t: T) -> Result<(), mpsc::SendError<T>> {
       if in_coroutine() {
            loop {
                t = match self.sender.try_send(t) {
                    Err(mpsc::TrySendError::Full(t)) => {
                        println!("Yielding ...");
                        yield_now();
                        t
                    }
                    Err(mpsc::TrySendError::Disconnected(t)) => return Err(mpsc::SendError(t)),
                    Ok(t) => return Ok(t),
                };
            }
        } else {
            try!(self.sender.send(t));
        }

        let prev_counter = self.shared.counter.fetch_add(1, Ordering::SeqCst);

        if prev_counter == 0 {
            maybe_notify_receiver(&self.shared.shared);
        }
        Ok(())
    }
}

fn maybe_notify_receiver(shared: &ArcChannelShared) {
    let mut lock = shared.lock();
    let ChannelShared { ref mut sender, ref mut token } = *lock;

    if let Some(token) = *token {
        trace!("Sender: notifying {:?}", token);
        let sender = sender.as_ref().unwrap();
        sender_retry(&sender, Message::ChannelMsg(token))
    }
}

impl<T> Sender<T> {
    /// Deliver `T` to the other end of the channel.
    ///
    /// Channel behaves like a queue.
    ///
    /// This is non-blocking operation.
    pub fn send(&self, t: T) -> Result<(), mpsc::SendError<T>> {
        try!(self.sender.send(t));
        let prev_counter = self.shared.counter.fetch_add(1, Ordering::SeqCst);

        if prev_counter == 0 {
            maybe_notify_receiver(&self.shared.shared);
        }
        Ok(())
    }
}

/// Create a channel
///
/// Channel can be used to deliver data via MPSC queue.
///
/// Channel is modeled after `std::sync::mpsc::channel()`, only
/// supporting mioco-aware sending and receiving.
///
/// When receiving end is outside of coroutine, channel will behave just
/// like `std::sync::mpsc::channel()`.
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
    let shared = ChannelShared {
        token: None,
        sender: None,
    };

    let shared = Arc::new(Mutex::new(shared));

    let counter = Arc::new(AtomicUsize::new(0));
    let (sender, receiver) = mpsc::channel();
    (Sender::new(shared.clone(), counter.clone(), sender), Receiver::new(shared, counter, receiver))
}

/// Create a channel
///
/// Channel can be used to deliver data via MPSC queue.
///
/// Channel is modeled after `std::sync::mpsc::channel()`, only
/// supporting mioco-aware sending and receiving.
///
/// When receiving end is outside of coroutine, channel will behave just
/// like `std::sync::mpsc::channel()`.
pub fn sync_channel<T>(bound: usize) -> (SyncSender<T>, Receiver<T>) {
    let shared = ChannelShared {
        token: None,
        sender: None,
    };

    let shared = Arc::new(Mutex::new(shared));

    let counter = Arc::new(AtomicUsize::new(0));
    let (sender, receiver) = mpsc::sync_channel(bound);
    (SyncSender::new(shared.clone(), counter.clone(), sender), Receiver::new(shared, counter, receiver))
}

unsafe impl<T : Send> Send for Receiver<T> {}
unsafe impl<T : Send> Send for Sender<T> {}
unsafe impl<T : Send> Send for SyncSender<T> {}
<commit_msg>clone trait for SyncSender<commit_after>use super::super::RW;
use super::super::thread::{Handler, Message};
use super::super::evented::{EventSourceTrait, RcEventSource, Evented, EventedImpl};
use mio_orig::{EventLoop, Token, EventSet};
use std::sync::Arc;
use spin::Mutex;
use super::super::thread::MioSender;
use super::super::{sender_retry, in_coroutine, yield_now};

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc;
type ArcChannelShared = Arc<Mutex<ChannelShared>>;
type ArcCounter = Arc<AtomicUsize>;

/// State shared between senders and receiver.
struct ChannelShared {
    token: Option<Token>,
    sender: Option<MioSender>,
}

/// Channel receiving end
///
/// Create with `channel()`
pub struct Receiver<T>(RcEventSource<ReceiverCore<T>>);

struct ReceiverCore<T> {
    receiver: mpsc::Receiver<T>,
    shared: ArcChannelShared,
    counter: ArcCounter,
}

impl<T> EventedImpl for Receiver<T>
    where T: 'static
{
    type Raw = ReceiverCore<T>;

    fn shared(&self) -> &RcEventSource<ReceiverCore<T>> {
        &self.0
    }
}

impl<T> EventSourceTrait for ReceiverCore<T> {
    fn register(&mut self, event_loop: &mut EventLoop<Handler>, token: Token, interest: EventSet) -> bool {
        debug_assert!(interest.is_readable());
        trace!("Receiver({}): register", token.as_usize());
        let mut lock = self.shared.lock();

        lock.token = Some(token);
        lock.sender = Some(event_loop.channel());

        if self.counter.load(Ordering::SeqCst) != 0 {
            trace!("Receiver({}): not empty; self notify", token.as_usize());
            lock.token = None;
            true
        } else {
            false
        }
    }

    fn reregister(&mut self,
                  _event_loop: &mut EventLoop<Handler>,
                  token: Token,
                  interest: EventSet) -> bool {
        debug_assert!(interest.is_readable());
        trace!("Receiver({}): reregister", token.as_usize());
        let mut lock = self.shared.lock();

        debug_assert!(lock.token.is_some());
        debug_assert!(lock.sender.is_some());

        if self.counter.load(Ordering::SeqCst) != 0 {
            lock.token = None;
            true
        } else {
            false
        }
    }

    fn deregister(&mut self, _event_loop: &mut EventLoop<Handler>, token: Token) {
        trace!("Receiver({}): dereregister", token.as_usize());
        let mut lock = self.shared.lock();
        lock.token = None;
        lock.sender = None;
    }
}

impl<T> Receiver<T> {
    fn new(shared: ArcChannelShared, counter: ArcCounter, receiver: mpsc::Receiver<T>) -> Self {
        let core = ReceiverCore {
            shared: shared,
            counter: counter,
            receiver: receiver,
        };

        Receiver(RcEventSource::new(core))
    }
}

impl<T> Receiver<T>
    where T: 'static
{
    /// Receive `T` sent using corresponding `Sender::send()`.
    ///
    /// Will block coroutine if no elements are available.
    pub fn recv(&self) -> Result<T, mpsc::RecvError> {
        if in_coroutine() {
            loop {
                let recv = self.try_recv();

                match recv {
                    Err(mpsc::TryRecvError::Empty) => self.block_on(RW::read()),
                    Err(mpsc::TryRecvError::Disconnected) => return Err(mpsc::RecvError),
                    Ok(t) => return Ok(t),
                }
                debug_assert!(self.empty_shared_token());
            }
        } else {
            self.shared().io_ref().receiver.recv()
        }
    }

    /// Try reading data from the queue.
    ///
    /// This will not block.
    pub fn try_recv(&self) -> Result<T, mpsc::TryRecvError> {
        let shared = self.shared();
        let io_ref = shared.io_ref();
        let res = io_ref.receiver.try_recv();
        if res.is_ok() {
            let _prev_counter = self.shared().io_ref().counter.fetch_sub(1, Ordering::SeqCst);
            // since send() first sends, then increases the counter, it is
            // possible for _prev_counter to be zero
        }
        res
    }

    fn empty_shared_token(&self) -> bool {
        let shared = self.shared();
        let io_ref = shared.io_ref();
        let lock = io_ref.shared.lock();
        lock.token.is_none()
    }
}

struct SenderShared {
    shared: ArcChannelShared,
    counter: ArcCounter,
}

impl Drop for SenderShared {
    fn drop(&mut self) {
        let prev_counter = self.counter.fetch_add(1, Ordering::SeqCst);
        if prev_counter == 0 {
            maybe_notify_receiver(&self.shared);
        }
    }
}

/// Channel sending end
///
/// Use this inside mioco coroutines or outside of mioco itself to send data
/// asynchronously to the receiving end.
///
/// Create with `channel()`
pub struct Sender<T> {
    shared: Arc<SenderShared>,
    sender: mpsc::Sender<T>,
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Self {
        Sender {
            shared: self.shared.clone(),
            sender: self.sender.clone(),
        }
    }
}

impl<T> Sender<T> {
    fn new(shared: ArcChannelShared, counter: ArcCounter, sender: mpsc::Sender<T>) -> Self {
        Sender {
            shared: Arc::new(SenderShared {
                shared: shared,
                counter: counter,
            }),
            sender: sender,
        }
    }
}

/// Channel sending end
///
/// Use this inside mioco coroutines or outside of mioco itself to send data
/// asynchronously to the receiving end.
///
/// Outside mioco, this is a blocking operation if the channel is full.
///
/// Create with `sync_channel()`
pub struct SyncSender<T> {
    shared: Arc<SenderShared>,
    sender: mpsc::SyncSender<T>,
}

impl<T> Clone for SyncSender<T> {
    fn clone(&self) -> Self {
        SyncSender {
            shared: self.shared.clone(),
            sender: self.sender.clone(),
        }
    }
}

impl<T> SyncSender<T> {
    fn new(shared: ArcChannelShared, counter: ArcCounter, sender: mpsc::SyncSender<T>) -> Self {
        SyncSender {
            shared: Arc::new(SenderShared {
                shared: shared,
                counter: counter,
            }),
            sender: sender,
        }
    }

    /// Deliver `T` to the other end of the channel.
    ///
    /// Channel behaves like a queue.
    ///
    /// When sender is outside mioco, this is a blocking operation (if channel
    /// is full). If the sender is inside mioco, `try_send` will be
    /// called where coroutine is yielded incase of `TrySendError::Full` error.
    pub fn send(&self, mut t: T) -> Result<(), mpsc::SendError<T>> {
       if in_coroutine() {
            loop {
                t = match self.sender.try_send(t) {
                    Err(mpsc::TrySendError::Full(t)) => {
                        println!("Yielding ...");
                        yield_now();
                        t
                    }
                    Err(mpsc::TrySendError::Disconnected(t)) => return Err(mpsc::SendError(t)),
                    Ok(t) => return Ok(t),
                };
            }
        } else {
            try!(self.sender.send(t));
        }

        let prev_counter = self.shared.counter.fetch_add(1, Ordering::SeqCst);

        if prev_counter == 0 {
            maybe_notify_receiver(&self.shared.shared);
        }
        Ok(())
    }
}

fn maybe_notify_receiver(shared: &ArcChannelShared) {
    let mut lock = shared.lock();
    let ChannelShared { ref mut sender, ref mut token } = *lock;

    if let Some(token) = *token {
        trace!("Sender: notifying {:?}", token);
        let sender = sender.as_ref().unwrap();
        sender_retry(&sender, Message::ChannelMsg(token))
    }
}

impl<T> Sender<T> {
    /// Deliver `T` to the other end of the channel.
    ///
    /// Channel behaves like a queue.
    ///
    /// This is non-blocking operation.
    pub fn send(&self, t: T) -> Result<(), mpsc::SendError<T>> {
        try!(self.sender.send(t));
        let prev_counter = self.shared.counter.fetch_add(1, Ordering::SeqCst);

        if prev_counter == 0 {
            maybe_notify_receiver(&self.shared.shared);
        }
        Ok(())
    }
}

/// Create a channel
///
/// Channel can be used to deliver data via MPSC queue.
///
/// Channel is modeled after `std::sync::mpsc::channel()`, only
/// supporting mioco-aware sending and receiving.
///
/// When receiving end is outside of coroutine, channel will behave just
/// like `std::sync::mpsc::channel()`.
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
    let shared = ChannelShared {
        token: None,
        sender: None,
    };

    let shared = Arc::new(Mutex::new(shared));

    let counter = Arc::new(AtomicUsize::new(0));
    let (sender, receiver) = mpsc::channel();
    (Sender::new(shared.clone(), counter.clone(), sender), Receiver::new(shared, counter, receiver))
}

/// Create a channel
///
/// Channel can be used to deliver data via MPSC queue.
///
/// Channel is modeled after `std::sync::mpsc::channel()`, only
/// supporting mioco-aware sending and receiving.
///
/// When receiving end is outside of coroutine, channel will behave just
/// like `std::sync::mpsc::channel()`.
pub fn sync_channel<T>(bound: usize) -> (SyncSender<T>, Receiver<T>) {
    let shared = ChannelShared {
        token: None,
        sender: None,
    };

    let shared = Arc::new(Mutex::new(shared));

    let counter = Arc::new(AtomicUsize::new(0));
    let (sender, receiver) = mpsc::sync_channel(bound);
    (SyncSender::new(shared.clone(), counter.clone(), sender), Receiver::new(shared, counter, receiver))
}

unsafe impl<T : Send> Send for Receiver<T> {}
unsafe impl<T : Send> Send for Sender<T> {}
unsafe impl<T : Send> Send for SyncSender<T> {}
<|endoftext|>