<commit_before>extern crate rand;

use std::ops::IndexMut;
use std::cmp::max;

type Flt = f64;
type Flt2 = (Flt, Flt);

pub struct RaytraceState<'a> {
    buffer: Vec<(Flt, Flt, Flt)>,
    size: (u32, u32),
    orig_buf: &'a [u8],
    blur_buf: &'a [u8],
    bytes_per_pixel: usize,
    origin: Flt2,
}

impl<'a> RaytraceState<'a> {
    pub fn new(size: (u32, u32), orig_buf: &'a [u8], blur_buf: &'a [u8], origin: (f64, f64)) -> RaytraceState<'a> {
        RaytraceState {
            buffer: vec![(0.0, 0.0, 0.0); (size.0 * size.1) as usize],
            size: size,
            orig_buf: orig_buf,
            blur_buf: blur_buf,
            origin: origin,
            bytes_per_pixel: 4,
        }
    }
}

struct RaytraceParams {
    iters_per_frame: u32,
}

const PARAMS: RaytraceParams = RaytraceParams { iters_per_frame: 1000 };

/// Progresses on to the next pixel along the specified direction.
fn next_voxel(pos: Flt2, dir: Flt2) -> Flt2 {
    fn max_inf(x: Flt, y: Flt) -> Flt {
        if x.is_finite() && y.is_finite() {
            x.max(y)
        } else {
            (2.0 as Flt).sqrt()
        }
    }
    let pos_frac = (pos.0.fract(), pos.1.fract());
    let tx1 = (1.0 - pos_frac.0) / dir.0;
    let tx2 = -pos_frac.0 / dir.0;
    let ty1 = (1.0 - pos_frac.1) / dir.1;
    let ty2 = -pos_frac.1 / dir.1;
    let tx = max_inf(tx1, tx2);
    let ty = max_inf(ty1, ty2);
    let dist = tx.min(ty) + 0.01;
    (pos.0 + dir.0 * dist, pos.1 + dir.1 * dist)
}

fn validate_bounds(point: (i32, i32), size: (u32, u32)) -> Option<(u32, u32)> {
    if point.0 < 0 || point.0 >= size.0 as i32 || point.1 < 0 || point.1 >= size.1 as i32 {
        None
    } else {
        Some((point.0 as u32, point.1 as u32))
    }
}

/// Convert from a hue (0-1) to a an RGB triplet
/// Colors are maximum saturation.
fn hue_to_rgb(hue: Flt) -> (Flt, Flt, Flt) {
    let hue3 = hue * 3.0;
    let fract = hue3.fract();
    let color = match hue3 as i32 {
        0 => (fract, 0.0, 1.0 - fract),
        1 => (1.0 - fract, fract, 0.0),
        2 => (0.0, 1.0 - fract, fract),
        _ => panic!("Invalid hue {}", hue),
    };
    (color.0.sqrt(), color.1.sqrt(), color.2.sqrt())
}

fn normalize(val: Flt2) -> Flt2 {
    let len = dot(val, val).sqrt();
    (val.0 / len, val.1 / len)
}

fn dot(left: Flt2, right: Flt2) -> Flt {
    left.0 * right.0 + left.1 * right.1
}

fn buf_to_pix(val: Flt) -> u8 {
    let val = val.powf(1.0 / 2.2);
    if val >= 1.0 {
        255
    } else if val < 0.0 {
        0
    } else {
        (val * 255.0) as u8
    }
}

impl<'a> RaytraceState<'a> {
    /// Raytrace multiple rays originating from the origin
    pub fn raytrace(&mut self, data: &mut [u8], frame: u32) {
        // (x + o * frame) / (1 + frame)
        // x / (1 + frame) + o * frame / (1 + frame);

        // Take into account weighting of previous frames when adding current
        // frame.
        let mulby = (frame - 1) as Flt / (frame as Flt);
        self.mul(mulby);
        let multiplier = 100.0;
        let weight = multiplier / ((PARAMS.iters_per_frame * frame) as Flt);

        // Cast out a bunch of rays!
        for _ in 0..PARAMS.iters_per_frame {
            self.raytrace_single(weight);
        }

        // Write pixel data back into shared buffer.
        self.blit(data);
    }

    /// Maximum length of a ray, as a function of the size of the image. This
    /// keeps a ray from reflecting around inside of an object infinitely.
    fn max_ray_length(&self) -> u32 {
        2 * max(self.size.0, self.size.1)
    }

    /// Trace out a single ray in the environment. The ray is cast, leaving
    /// behind a trail of colored light which is then averaged with the paths
    /// left by other rays.
    fn raytrace_single(&mut self, weight: Flt) {
        // Start at origin with a random starting direction
        let mut pos = self.origin;
        let mut dir = {
            let theta: Flt = rand::random::<Flt>() * 6.28318530718;
            (theta.cos(), theta.sin())
        };

        // Choose a random color for the current ray
        let hue = rand::random::<Flt>();
        let rgb = hue_to_rgb(hue);

        // Keep track of the number of refractions this ray has had
        let mut num_refracts = 0;
        let mut old_value = -1.0;
        let mut max_iters = self.max_ray_length();

        // Keep following this ray until we end out of bounds
        while let Some(ipos) = validate_bounds((pos.0.floor() as i32, pos.1.floor() as i32),
                                               self.size) {
            if max_iters == 0 {
                break;
            }
            max_iters -= 1;
            if num_refracts != 0 {
                num_refracts -= 1;
            } else {
                if self.refract(&mut dir, &mut old_value, ipos, hue) {
                    num_refracts = 3;
                }
            }
            self.put_pixel(ipos, rgb, weight);
            pos = next_voxel(pos, dir);
        }
    }

    /// Bend a beam of light as it crosses the boundary between two materials, the
    /// intensity depending on the wavelength (color) of the ray.
    fn refract(&self, dir: &mut Flt2, old: &mut Flt, coords: (u32, u32), hue: Flt) -> bool {
        // Implemented based on the following papers
        // http://steve.hollasch.net/cgindex/render/refraction.txt
        // http://graphics.stanford.edu/courses/cs148-10-summer/docs/2006--degreve--reflection_refraction.pdf
        let new = self.orig_value_at(coords);
        if !dir.0.is_finite() {
            panic!("non-finite dir");
        }
        // old >= 0 to not do first iteration
        let result = if *old >= 0.0 && (new > 0.5) != (*old > 0.5) {
            let eta = 1.1 + hue * 0.2;
            let normal = self.normal_at(coords);
            if !normal.0.is_finite() {
                *old = new;
                return false;
            }
            let c1 = -dot(*dir, normal);
            let under_sqrt = 1.0 - eta * eta * (1.0 - c1 * c1);
            *dir = if under_sqrt < 0.0 {
                (dir.0 + 2.0 * c1 * normal.0, dir.1 + 2.0 * c1 * normal.1)
            } else {
                let normal_mul = eta * c1 - under_sqrt.sqrt();
                let refract_i = (dir.0 * eta, dir.1 * eta);
                let refract_n = (normal.0 * normal_mul, normal.1 * normal_mul);
                (refract_i.0 + refract_n.0, refract_i.1 + refract_n.1)
            };
            *dir = normalize(*dir);
            true
        } else {
            false
        };
        *old = new;
        result
    }

    fn blur_at(&self, coords: (u32, u32)) -> (u8, u8, u8) {
        let idx = (coords.1 * self.size.0 + coords.0) as usize;
        let red = self.blur_buf[idx * self.bytes_per_pixel + 0];
        let green = self.blur_buf[idx * self.bytes_per_pixel + 1];
        let blue = self.blur_buf[idx * self.bytes_per_pixel + 2];
        return (red, green, blue);
    }

    fn blur_value_at(&self, coords: (u32, u32)) -> Flt {
        let blur = self.blur_at(coords);
        return (blur.0 as Flt + blur.1 as Flt + blur.2 as Flt) / (255.0 * 3.0);
    }

    /// Returns the RGB pixel values of the specified coordinate.
    fn orig_at(&self, coords: (u32, u32)) -> (u8, u8, u8) {
        let idx = (coords.1 * self.size.0 + coords.0) as usize;
        let red = self.orig_buf[idx * self.bytes_per_pixel + 0];
        let green = self.orig_buf[idx * self.bytes_per_pixel + 1];
        let blue = self.orig_buf[idx * self.bytes_per_pixel + 2];
        return (red, green, blue);
    }

    /// Calculate the value of the original image at the specified coordinate.
    /// This uses a standard average of the RGB values.
    fn orig_value_at(&self, coords: (u32, u32)) -> Flt {
        let orig = self.orig_at(coords);
        return (orig.0 as Flt + orig.1 as Flt + orig.2 as Flt) / (255.0 * 3.0);
    }

    /// Calculate the normal at the specified coordinate, using the blur mapped
    /// image.
    fn normal_at(&self, coords: (u32, u32)) -> Flt2 {
        let left = if coords.0 == 0 {
            0
        } else {
            coords.0 - 1
        };
        let right = if coords.0 == self.size.0 - 1 {
            self.size.0 - 1
        } else {
            coords.0 + 1
        };
        let up = if coords.1 == 0 {
            0
        } else {
            coords.1 - 1
        };
        let down = if coords.1 == self.size.1 - 1 {
            self.size.1 - 1
        } else {
            coords.1 + 1
        };
        // Grab a diagonal of values from the current poing
        let c00 = self.blur_value_at((left, up));
        let c01 = self.blur_value_at((left, down));
        let c10 = self.blur_value_at((right, up));
        let c11 = self.blur_value_at((right, down));
        // Calculate a (very approximate) gradient
        let x = (c10 - c00) + (c11 - c01);
        let y = (c01 - c00) + (c11 - c10);
        normalize((x, y))
    }

    /// Push a value to the specified pixel coordinate, taking into account the
    /// weight of the previous values pushed.
    fn put_pixel(&mut self, coords: (u32, u32), value: (Flt, Flt, Flt), weight: Flt) {
        let index = coords.1 * self.size.0 + coords.0;
        let arr = self.buffer.index_mut(index as usize);
        arr.0 = arr.0 + value.0 * weight;
        arr.1 = arr.1 + value.1 * weight;
        arr.2 = arr.2 + value.2 * weight;
    }

    fn mul(&mut self, value: Flt) {
        for v in self.buffer.iter_mut() {
            v.0 *= value;
            v.1 *= value;
            v.2 *= value;
        }
    }

    /// Write pixel data to buffer
    fn blit(&self, data: &mut [u8]) {
        for (i, v) in self.buffer.iter().enumerate() {
            data[i * 4 + 0] = buf_to_pix(v.0);
            data[i * 4 + 1] = buf_to_pix(v.1);
            data[i * 4 + 2] = buf_to_pix(v.2);
            data[i * 4 + 3] = 255;
        }
    }
}
<commit_msg>I fixed refraction!... I think<commit_after>extern crate rand;

use std::ops::{Add, Sub, Mul, Div, Neg};
use std::ops::IndexMut;
use std::cmp::max;

type Flt = f64;

#[derive(Debug, Copy, Clone)]
struct Flt2 {
    x: Flt,
    y: Flt,
}

pub struct RaytraceState<'a> {
    buffer: Vec<(Flt, Flt, Flt)>,
    size: (u32, u32),
    orig_buf: &'a [u8],
    blur_buf: &'a [u8],
    bytes_per_pixel: usize,
    origin: (Flt, Flt),
    iters_per_frame: u32,
}

impl<'a> RaytraceState<'a> {
    pub fn new(size: (u32, u32),
               orig_buf: &'a [u8],
               blur_buf: &'a [u8],
               origin: (f64, f64))
               -> RaytraceState<'a> {
        RaytraceState {
            buffer: vec![(0.0, 0.0, 0.0); (size.0 * size.1) as usize],
            size: size,
            orig_buf: orig_buf,
            blur_buf: blur_buf,
            origin: origin,
            bytes_per_pixel: 4,
            iters_per_frame: 1000,
        }
    }
}

impl Flt2 {
    fn new(x: Flt, y: Flt) -> Flt2 {
        Flt2 { x: x, y: y }
    }

    fn fract(self) -> Flt2 {
        Self::new(self.x.fract(), self.y.fract())
    }

    fn floor(self) -> Flt2 {
        Self::new(self.x.floor(), self.y.floor())
    }

    fn floori(self) -> (i32, i32) {
        let floor = self.floor();
        (floor.x as i32, floor.y as i32)
    }

    fn normalized(self) -> Flt2 {
        self / dot(self, self).sqrt()
    }
}

impl PartialEq for Flt2 {
    fn eq(&self, other: &Self) -> bool {
        self.x == other.x && self.y == other.y
    }
}

impl Eq for Flt2 {}

impl Add for Flt2 {
    type Output = Flt2;

    fn add(self, other: Flt2) -> Flt2 {
        Flt2::new(self.x + other.x, self.y + other.y)
    }
}

impl Sub for Flt2 {
    type Output = Flt2;

    fn sub(self, other: Flt2) -> Flt2 {
        Flt2::new(self.x - other.x, self.y - other.y)
    }
}

impl Neg for Flt2 {
    type Output = Flt2;

    fn neg(self) -> Flt2 {
        Flt2::new(-self.x, -self.y)
    }
}

impl Mul<Flt> for Flt2 {
    type Output = Flt2;

    fn mul(self, other: Flt) -> Flt2 {
        Flt2::new(self.x * other, self.y * other)
    }
}

impl Div for Flt2 {
    type Output = Flt2;

    fn div(self, other: Flt2) -> Flt2 {
        Flt2::new(self.x / other.x, self.y / other.y)
    }
}

impl Div<Flt> for Flt2 {
    type Output = Flt2;

    fn div(self, other: Flt) -> Flt2 {
        Flt2::new(self.x / other, self.y / other)
    }
}

#[test]
fn test_flt2_ops() {
    fn vecis(v: Flt2, x: Flt, y: Flt) {
        assert!(v.x == x && v.y == y);
    }
    let v11 = Flt2::new(1.0, 1.0);
    let v15 = Flt2::new(1.0, 5.0);
    let add = v11 + v15;
    vecis(add, 2.0, 6.0);
    let sub = v15 - v11;
    vecis(sub, 0.0, 4.0);
    let mul = v15 * 2.0;
    vecis(mul, 2.0, 10.0);
    let div = v15 / 2.0;
    vecis(div, 0.5, 2.5);
    let div2 = v15 / v11;
    vecis(div2, 1.0, 5.0);
}

/// Progresses on to the next pixel along the specified direction.
fn next_voxel(pos: Flt2, dir: Flt2) -> Flt2 {
    fn max_inf(x: Flt, y: Flt) -> Flt {
        if x.is_finite() && y.is_finite() {
            x.max(y)
        } else {
            (2.0 as Flt).sqrt()
        }
    }
    let pos_frac = pos.fract();
    let t1 = (Flt2::new(1.0, 1.0) - pos_frac) / dir;
    let t2 = -pos_frac / dir;
    let tx = max_inf(t1.x, t2.x);
    let ty = max_inf(t1.y, t2.y);
    let dist = tx.min(ty) + 0.01;
    pos + dir * dist
}

fn validate_bounds(point: (i32, i32), size: (u32, u32)) -> Option<(u32, u32)> {
    if point.0 < 0 || point.0 >= size.0 as i32 || point.1 < 0 || point.1 >= size.1 as i32 {
        None
    } else {
        Some((point.0 as u32, point.1 as u32))
    }
}

/// Convert from a hue (0-1) to a an RGB triplet
/// Colors are maximum saturation.
fn hue_to_rgb(hue: Flt) -> (Flt, Flt, Flt) {
    let hue3 = hue * 3.0;
    let fract = hue3.fract();
    let color = match hue3 as i32 {
        0 => (fract, 0.0, 1.0 - fract),
        1 => (1.0 - fract, fract, 0.0),
        2 => (0.0, 1.0 - fract, fract),
        _ => panic!("Invalid hue {}", hue),
    };
    (color.0.sqrt(), color.1.sqrt(), color.2.sqrt())
}

fn dot(left: Flt2, right: Flt2) -> Flt {
    left.x * right.x + left.y * right.y
}

fn buf_to_pix(val: Flt) -> u8 {
    // gamma correction
    let val = val.powf(1.0 / 2.2);
    // clamp
    if val >= 1.0 {
        255
    } else if val < 0.0 {
        0
    } else {
        (val * 255.0) as u8
    }
}

// Calculates new ray direction according to diffuse laws
fn diffuse_dir(incoming: Flt2, normal: Flt2) -> Flt2 {
    let result = Flt2::new(rand::random::<Flt>() * 2.0 - 1.0,
                           rand::random::<Flt>() * 2.0 - 1.0)
                     .normalized();
    if (dot(result, normal) < 0.0) != (dot(normal, incoming) < 0.0) {
        -result
    } else {
        result
    }
}

// Calculates new ray direction according to reflection laws
fn reflect_dir(incoming: Flt2, normal: Flt2) -> Flt2 {
    incoming - normal * (2.0 * dot(incoming, normal))
}

// Calculates new ray direction according to refraction laws
fn refract_dir(mut eta: Flt, incoming: Flt2, mut normal: Flt2) -> Option<Flt2> {
    let mut c1 = -dot(incoming, normal);
    if c1 < 0.0 {
        c1 = -c1;
        normal = -normal;
        eta = 1.0 / eta;
    }
    let cs2 = 1.0 - eta * eta * (1.0 - c1 * c1);
    if cs2 < 0.0 {
        None
    } else {
        let normal_mul = eta * c1 - cs2.sqrt();
        let result = incoming * eta + normal * normal_mul;
        Some(result)
    }
}

#[test]
fn test_refract() {
    assert_eq!(refract_dir(2.0, Flt2::new(1.0, 0.0), Flt2::new(-1.0, 0.0)).unwrap(),
               Flt2::new(1.0, 0.0));
    assert_eq!(refract_dir(2.0, Flt2::new(0.0, 1.0), Flt2::new(0.0, 1.0)).unwrap(),
               Flt2::new(0.0, 1.0));
}

impl<'a> RaytraceState<'a> {
    /// Raytrace multiple rays originating from the origin
    pub fn raytrace(&mut self, data: &mut [u8], frame: u32) {
        // (x + o * frame) / (1 + frame)
        // x / (1 + frame) + o * frame / (1 + frame);

        // Take into account weighting of previous frames when adding current
        // frame.
        let mulby = (frame - 1) as Flt / (frame as Flt);
        self.mul(mulby);
        let multiplier = 100.0;
        let weight = multiplier / ((self.iters_per_frame * frame) as Flt);

        // Cast out a bunch of rays!
        for _ in 0..self.iters_per_frame {
            self.raytrace_single(weight);
        }

        // Write pixel data back into shared buffer.
        self.blit(data);
    }

    /// Maximum length of a ray, as a function of the size of the image. This
    /// keeps a ray from reflecting around inside of an object infinitely.
    fn max_ray_length(&self) -> u32 {
        2 * max(self.size.0, self.size.1)
    }

    /// Trace out a single ray in the environment. The ray is cast, leaving
    /// behind a trail of colored light which is then averaged with the paths
    /// left by other rays.
    fn raytrace_single(&mut self, weight: Flt) {
        // Start at origin with a random starting direction
        let mut pos = Flt2::new(self.origin.0, self.origin.1);
        let mut dir = {
            let theta: Flt = rand::random::<Flt>() * 6.28318530718;
            Flt2::new(theta.cos(), theta.sin())
        };

        // Choose a random color for the current ray
        let hue = rand::random::<Flt>();
        let rgb = hue_to_rgb(hue);

        // Keep track of the number of refractions this ray has had
        let mut num_refracts = 0;
        let mut old_value = -1.0; // sentinel value detected in refract for first iteration
        let mut max_iters = self.max_ray_length();

        // Keep following this ray until we end out of bounds
        while let Some(ipos) = validate_bounds(pos.floori(), self.size) {
            if max_iters == 0 {
                break;
            }
            max_iters -= 1;
            if num_refracts != 0 {
                num_refracts -= 1;
            } else {
                match self.refract(&mut dir, &mut old_value, ipos, hue) {
                    Some(true) => num_refracts = 0,
                    Some(false) => (),
                    None => {
                        self.put_pixel(ipos, (10.0, -10.0, -10.0), 1.0);
                        break;
                    }
                }
            }
            self.put_pixel(ipos, rgb, weight);
            pos = next_voxel(pos, dir);
        }
    }

    /// Bend a beam of light as it crosses the boundary between two materials, the
    /// intensity depending on the wavelength (color) of the ray.
    fn refract(&self, dir: &mut Flt2, old: &mut Flt, coords: (u32, u32), hue: Flt) -> Option<bool> {
        // Implemented based on the following papers
        // http://steve.hollasch.net/cgindex/render/refraction.txt
        // http://graphics.stanford.edu/courses/cs148-10-summer/docs/2006--degreve--reflection_refraction.pdf
        let new = self.orig_value_at(coords);
        if !dir.x.is_finite() {
            panic!("non-finite dir");
        }
        // old >= 0 to not do first iteration
        let result = if *old >= 0.0 && (new > 0.5) != (*old > 0.5) {
            let eta = 1.3 + hue * 0.2;
            if let Some(normal) = self.normal_at(coords) {
                let rand_bounce = rand::random::<Flt>();
                let thresh_diffuse = 0.75;
                *dir = if new < 0.5 && rand_bounce > thresh_diffuse {
                    diffuse_dir(*dir, normal)
                } else {
                    refract_dir(eta, *dir, normal).unwrap_or(reflect_dir(*dir, normal))
                };
                *dir = dir.normalized();
            } else {
                *old = new;
                return None;
            }
            true
        } else {
            false
        };
        *old = new;
        Some(result)
    }

    fn blur_at(&self, coords: (u32, u32)) -> (u8, u8, u8) {
        let idx = (coords.1 * self.size.0 + coords.0) as usize;
        let red = self.blur_buf[idx * self.bytes_per_pixel + 0];
        let green = self.blur_buf[idx * self.bytes_per_pixel + 1];
        let blue = self.blur_buf[idx * self.bytes_per_pixel + 2];
        return (red, green, blue);
    }

    fn blur_value_at(&self, coords: (u32, u32)) -> Flt {
        let blur = self.blur_at(coords);
        return (blur.0 as Flt + blur.1 as Flt + blur.2 as Flt) / (255.0 * 3.0);
    }

    /// Returns the RGB pixel values of the specified coordinate.
    fn orig_at(&self, coords: (u32, u32)) -> (u8, u8, u8) {
        let idx = (coords.1 * self.size.0 + coords.0) as usize;
        let red = self.orig_buf[idx * self.bytes_per_pixel + 0];
        let green = self.orig_buf[idx * self.bytes_per_pixel + 1];
        let blue = self.orig_buf[idx * self.bytes_per_pixel + 2];
        return (red, green, blue);
    }

    /// Calculate the value of the original image at the specified coordinate.
    /// This uses a standard average of the RGB values.
    fn orig_value_at(&self, coords: (u32, u32)) -> Flt {
        let orig = self.orig_at(coords);
        return (orig.0 as Flt + orig.1 as Flt + orig.2 as Flt) / (255.0 * 3.0);
    }

    /// Calculate the normal at the specified coordinate, using the blur mapped
    /// image.
    fn normal_at(&self, coords: (u32, u32)) -> Option<Flt2> {
        let left = if coords.0 == 0 {
            0
        } else {
            coords.0 - 1
        };
        let right = if coords.0 == self.size.0 - 1 {
            self.size.0 - 1
        } else {
            coords.0 + 1
        };
        let up = if coords.1 == 0 {
            0
        } else {
            coords.1 - 1
        };
        let down = if coords.1 == self.size.1 - 1 {
            self.size.1 - 1
        } else {
            coords.1 + 1
        };
        // Grab a diagonal of values from the current poing
        let c00 = self.blur_value_at((left, up));
        let c01 = self.blur_value_at((left, coords.1));
        let c02 = self.blur_value_at((left, down));
        let c10 = self.blur_value_at((coords.0, up));
        let c12 = self.blur_value_at((coords.0, down));
        let c20 = self.blur_value_at((right, up));
        let c21 = self.blur_value_at((right, coords.1));
        let c22 = self.blur_value_at((right, down));
        // Calculate a (very approximate) gradient using Sobel filter
        let x = (c20 + 2.0 * c21 + c22) - (c00 + 2.0 * c01 + c02);
        let y = (c02 + 2.0 * c12 + c22) - (c00 + 2.0 * c10 + c20);
        if x == 0.0 && y == 0.0 {
            None
        } else {
            Some(Flt2::new(x, y).normalized())
        }
    }

    /// Push a value to the specified pixel coordinate, taking into account the
    /// weight of the previous values pushed.
    fn put_pixel(&mut self, coords: (u32, u32), value: (Flt, Flt, Flt), weight: Flt) {
        let index = coords.1 * self.size.0 + coords.0;
        let arr = self.buffer.index_mut(index as usize);
        arr.0 = arr.0 + value.0 * weight;
        arr.1 = arr.1 + value.1 * weight;
        arr.2 = arr.2 + value.2 * weight;
    }

    fn mul(&mut self, value: Flt) {
        for v in self.buffer.iter_mut() {
            v.0 *= value;
            v.1 *= value;
            v.2 *= value;
        }
    }

    /// Write pixel data to buffer
    fn blit(&self, data: &mut [u8]) {
        for (i, v) in self.buffer.iter().enumerate() {
            data[i * 4 + 0] = buf_to_pix(v.0);
            data[i * 4 + 1] = buf_to_pix(v.1);
            data[i * 4 + 2] = buf_to_pix(v.2);
            data[i * 4 + 3] = 255;
        }
    }
}
<|endoftext|>


<commit_before>use crate::{
    exchange::ExchangeKind,
    options::{ExchangeDeclareOptions, QueueDeclareOptions},
    topology::{BindingDefinition, ExchangeDefinition, QueueDefinition},
    types::{FieldTable, ShortString},
};
use parking_lot::Mutex;
use std::{collections::HashMap, sync::Arc};

#[derive(Clone, Default)]
pub(crate) struct Registry(Arc<Mutex<Inner>>);

impl Registry {
    pub(crate) fn exchanges_topology(&self) -> Vec<ExchangeDefinition> {
        self.0.lock().exchanges.values().cloned().collect()
    }

    pub(crate) fn queues_topology(&self) -> Vec<QueueDefinition> {
        self.0
            .lock()
            .queues
            .values()
            .filter(|q| q.options.map(|o| !o.exclusive).unwrap_or(false))
            .cloned()
            .collect()
    }

    pub(crate) fn register_exchange(
        &self,
        name: ShortString,
        kind: ExchangeKind,
        options: ExchangeDeclareOptions,
        arguments: FieldTable,
    ) {
        let mut inner = self.0.lock();
        if let Some(exchange) = inner.exchanges.get_mut(&name) {
            exchange.kind = Some(kind);
            exchange.options = Some(options);
            exchange.arguments = Some(arguments);
        } else {
            inner.exchanges.insert(
                name.clone(),
                ExchangeDefinition {
                    name,
                    kind: Some(kind),
                    options: Some(options),
                    arguments: Some(arguments),
                    bindings: Vec::new(),
                },
            );
        }
    }

    pub(crate) fn deregister_exchange(&self, name: ShortString) {
        self.0.lock().exchanges.remove(&name);
    }

    pub(crate) fn register_exchange_binding(
        &self,
        destination: ShortString,
        source: ShortString,
        routing_key: ShortString,
        arguments: FieldTable,
    ) {
        self.0
            .lock()
            .exchanges
            .entry(destination.clone())
            .or_insert_with(|| ExchangeDefinition {
                name: destination,
                kind: None,
                options: None,
                arguments: None,
                bindings: Vec::new(),
            })
            .bindings
            .push(BindingDefinition {
                source,
                routing_key,
                arguments,
            });
    }

    pub(crate) fn deregister_exchange_binding(
        &self,
        destination: ShortString,
        source: ShortString,
        routing_key: ShortString,
        arguments: FieldTable,
    ) {
        if let Some(destination) = self.0.lock().exchanges.get_mut(&destination) {
            destination.bindings.retain(|binding| {
                binding.source != source
                    || binding.routing_key != routing_key
                    || binding.arguments != arguments
            });
        }
    }

    pub(crate) fn register_queue(
        &self,
        name: ShortString,
        options: QueueDeclareOptions,
        arguments: FieldTable,
    ) {
        let mut inner = self.0.lock();
        if let Some(queue) = inner.queues.get_mut(&name) {
            queue.options = Some(options);
            queue.arguments = Some(arguments);
        } else {
            inner.queues.insert(
                name.clone(),
                QueueDefinition {
                    name,
                    options: Some(options),
                    arguments: Some(arguments),
                    bindings: Vec::new(),
                },
            );
        }
    }

    pub(crate) fn deregister_queue(&self, name: ShortString) {
        self.0.lock().queues.remove(&name);
    }

    pub(crate) fn register_queue_binding(
        &self,
        destination: ShortString,
        source: ShortString,
        routing_key: ShortString,
        arguments: FieldTable,
    ) {
        self.0
            .lock()
            .queues
            .entry(destination.clone())
            .or_insert_with(|| QueueDefinition {
                name: destination,
                options: None,
                arguments: None,
                bindings: Vec::new(),
            })
            .bindings
            .push(BindingDefinition {
                source,
                routing_key,
                arguments,
            });
    }

    pub(crate) fn deregister_queue_binding(
        &self,
        destination: ShortString,
        source: ShortString,
        routing_key: ShortString,
        arguments: FieldTable,
    ) {
        if let Some(destination) = self.0.lock().queues.get_mut(&destination) {
            destination.bindings.retain(|binding| {
                binding.source != source
                    || binding.routing_key != routing_key
                    || binding.arguments != arguments
            });
        }
    }
}

#[derive(Default)]
struct Inner {
    exchanges: HashMap<ShortString, ExchangeDefinition>,
    queues: HashMap<ShortString, QueueDefinition>,
}
<commit_msg>registry: simplifications<commit_after>use crate::{
    exchange::ExchangeKind,
    options::{ExchangeDeclareOptions, QueueDeclareOptions},
    topology::{BindingDefinition, ExchangeDefinition, QueueDefinition},
    types::{FieldTable, ShortString},
};
use parking_lot::Mutex;
use std::{collections::HashMap, sync::Arc};

#[derive(Clone, Default)]
pub(crate) struct Registry(Arc<Mutex<Inner>>);

impl Registry {
    pub(crate) fn exchanges_topology(&self) -> Vec<ExchangeDefinition> {
        self.0.lock().exchanges.values().cloned().collect()
    }

    pub(crate) fn queues_topology(&self) -> Vec<QueueDefinition> {
        self.0
            .lock()
            .queues
            .values()
            .filter(|q| q.options.map(|o| !o.exclusive).unwrap_or(false))
            .cloned()
            .collect()
    }

    pub(crate) fn register_exchange(
        &self,
        name: ShortString,
        kind: ExchangeKind,
        options: ExchangeDeclareOptions,
        arguments: FieldTable,
    ) {
        let mut inner = self.0.lock();
        if let Some(exchange) = inner.exchanges.get_mut(&name) {
            exchange.kind = Some(kind);
            exchange.options = Some(options);
            exchange.arguments = Some(arguments);
        } else {
            inner.exchanges.insert(
                name.clone(),
                ExchangeDefinition {
                    name,
                    kind: Some(kind),
                    options: Some(options),
                    arguments: Some(arguments),
                    bindings: Vec::new(),
                },
            );
        }
    }

    pub(crate) fn deregister_exchange(&self, name: ShortString) {
        self.0.lock().exchanges.remove(&name);
    }

    pub(crate) fn register_exchange_binding(
        &self,
        destination: ShortString,
        source: ShortString,
        routing_key: ShortString,
        arguments: FieldTable,
    ) {
        self.0
            .lock()
            .exchanges
            .entry(destination.clone())
            .or_insert_with(|| ExchangeDefinition {
                name: destination,
                kind: None,
                options: None,
                arguments: None,
                bindings: Vec::new(),
            })
            .bindings
            .push(BindingDefinition {
                source,
                routing_key,
                arguments,
            });
    }

    pub(crate) fn deregister_exchange_binding(
        &self,
        destination: ShortString,
        source: ShortString,
        routing_key: ShortString,
        arguments: FieldTable,
    ) {
        if let Some(destination) = self.0.lock().exchanges.get_mut(&destination) {
            destination.bindings.retain(|binding| {
                binding.source != source
                    || binding.routing_key != routing_key
                    || binding.arguments != arguments
            });
        }
    }

    pub(crate) fn register_queue(
        &self,
        name: ShortString,
        options: QueueDeclareOptions,
        arguments: FieldTable,
    ) {
        let mut inner = self.0.lock();
        if let Some(queue) = inner.queues.get_mut(&name) {
            queue.options = Some(options);
            queue.arguments = Some(arguments);
        } else {
            inner.queues.insert(
                name.clone(),
                QueueDefinition::new(name, Some(options), Some(arguments)),
            );
        }
    }

    pub(crate) fn deregister_queue(&self, name: ShortString) {
        self.0.lock().queues.remove(&name);
    }

    pub(crate) fn register_queue_binding(
        &self,
        destination: ShortString,
        source: ShortString,
        routing_key: ShortString,
        arguments: FieldTable,
    ) {
        self.0
            .lock()
            .queues
            .entry(destination.clone())
            .or_insert_with(|| QueueDefinition {
                name: destination,
                options: None,
                arguments: None,
                bindings: Vec::new(),
            })
            .register_binding(source, routing_key, arguments);
    }

    pub(crate) fn deregister_queue_binding(
        &self,
        destination: ShortString,
        source: ShortString,
        routing_key: ShortString,
        arguments: FieldTable,
    ) {
        if let Some(destination) = self.0.lock().queues.get_mut(&destination) {
            destination.deregister_binding(source, routing_key, arguments);
        }
    }
}

#[derive(Default)]
struct Inner {
    exchanges: HashMap<ShortString, ExchangeDefinition>,
    queues: HashMap<ShortString, QueueDefinition>,
}
<|endoftext|>


<commit_before>#[cfg(feature = "hot-resource")]
mod hot {
  use notify::{self, RecommendedWatcher, Watcher};
  use std::collections::BTreeMap;
  use std::path::{Path, PathBuf};
  use std::sync::{Arc, Mutex};
  use std::sync::mpsc;
  use std::thread;

  /// Time to await after a resource update to establish that it should be reloaded.
  pub const UPDATE_AWAIT_TIME: f64 = 0.1; // 100ms

  pub struct ResourceManager {
    receivers: Arc<Mutex<BTreeMap<PathBuf, mpsc::Sender<()>>>>
  }

  impl ResourceManager {
    pub fn new<P>(root: P) -> Self where P: AsRef<Path> {
      let (wsx, wrx) = mpsc::channel();
      let mut watcher: RecommendedWatcher = Watcher::new(wsx).unwrap();
      let receivers: Arc<Mutex<BTreeMap<PathBuf, mpsc::Sender<()>>>> = Arc::new(Mutex::new(BTreeMap::new()));
      let receivers_ = receivers.clone();
      let root = root.as_ref().to_path_buf();

      let _ = thread::spawn(move || {
        let _ = watcher.watch(root);

        for event in wrx.iter() {
          match event {
            notify::Event { path: Some(path), op: Ok(notify::op::WRITE) } => {
              if let Some(sx) = receivers_.lock().unwrap().get(&path) {
                sx.send(()).unwrap();
              }
            },
            _ => {}
          }
        }
      });

      ResourceManager {
        receivers: receivers
      }
    }

    pub fn monitor<P>(&mut self, path: P, sx: mpsc::Sender<()>) where P: AsRef<Path> {
      let mut receivers = self.receivers.lock().unwrap();

      receivers.insert(path.as_ref().to_path_buf(), sx);
    }
  }
}

#[cfg(not(feature = "hot-resource"))]
mod cold {
  use std::path::Path;
  use std::sync::mpsc;

  pub struct ResourceManager {}

  impl ResourceManager {
    pub fn new<P>(_: P) -> Self where P: AsRef<Path> {
      ResourceManager {}
    }

    pub fn monitor<P>(&mut self, _: P, _: mpsc::Sender<()>) where P: AsRef<Path> {}
  }
}

#[cfg(feature = "hot-resource")]
pub use self::hot::*;
#[cfg(not(feature = "hot-resource"))]
pub use self::cold::*;

/// Sync all the resources passed in as arguments.
#[macro_export]
macro_rules! sync {
  ($( $r:ident ),*) => {
    $( $r.sync(); )*
  }
}

/// A helper macro to declare a `sync` public method for a resource. The resource must
/// have a `last_update_time: f64` and a `reload(&mut self)` function.
#[cfg(feature = "hot-resource")]
#[macro_export]
macro_rules! decl_sync_hot {
  () => {
    pub fn sync(&mut self) {
      if self.rx.try_recv().is_ok() {
        self.last_update_time = Some(::time::precise_time_s());
      }

      match self.last_update_time {
        Some(last_update_time) if ::time::precise_time_s() - last_update_time >= ::resource::UPDATE_AWAIT_TIME => {
          self.reload();
          self.last_update_time = None;
        },
        _ => {}
      }
    }
  }
}
<commit_msg>Typo.<commit_after>#[cfg(feature = "hot-resource")]
mod hot {
  use notify::{self, RecommendedWatcher, Watcher};
  use std::collections::BTreeMap;
  use std::path::{Path, PathBuf};
  use std::sync::{Arc, Mutex};
  use std::sync::mpsc;
  use std::thread;

  /// Time to await after a resource update to establish that it should be reloaded.
  pub const UPDATE_AWAIT_TIME: f64 = 0.1; // 100ms

  pub struct ResourceManager {
    receivers: Arc<Mutex<BTreeMap<PathBuf, mpsc::Sender<()>>>>
  }

  impl ResourceManager {
    pub fn new<P>(root: P) -> Self where P: AsRef<Path> {
      let (wsx, wrx) = mpsc::channel();
      let mut watcher: RecommendedWatcher = Watcher::new(wsx).unwrap();
      let receivers: Arc<Mutex<BTreeMap<PathBuf, mpsc::Sender<()>>>> = Arc::new(Mutex::new(BTreeMap::new()));
      let receivers_ = receivers.clone();
      let root = root.as_ref().to_path_buf();

      let _ = thread::spawn(move || {
        let _ = watcher.watch(root);

        for event in wrx.iter() {
          match event {
            notify::Event { path: Some(path), op: Ok(notify::op::WRITE) } => {
              if let Some(sx) = receivers_.lock().unwrap().get(&path) {
                sx.send(()).unwrap();
              }
            },
            _ => {}
          }
        }
      });

      ResourceManager {
        receivers: receivers
      }
    }

    pub fn monitor<P>(&mut self, path: P, sx: mpsc::Sender<()>) where P: AsRef<Path> {
      let mut receivers = self.receivers.lock().unwrap();

      receivers.insert(path.as_ref().to_path_buf(), sx);
    }
  }
}

#[cfg(not(feature = "hot-resource"))]
mod cold {
  use std::path::Path;
  use std::sync::mpsc;

  pub struct ResourceManager {}

  impl ResourceManager {
    pub fn new<P>(_: P) -> Self where P: AsRef<Path> {
      ResourceManager {}
    }

    pub fn monitor<P>(&mut self, _: P, _: mpsc::Sender<()>) where P: AsRef<Path> {}
  }
}

#[cfg(feature = "hot-resource")]
pub use self::hot::*;
#[cfg(not(feature = "hot-resource"))]
pub use self::cold::*;

/// Sync all the resources passed in as arguments.
#[macro_export]
macro_rules! sync {
  ($( $r:ident ),*) => {
    $( $r.sync(); )*
  }
}

/// A helper macro to declare a `sync` public method for a resource. The resource must
/// have a `last_update_time: Option<f64>` and a `reload(&mut self)` function.
#[cfg(feature = "hot-resource")]
#[macro_export]
macro_rules! decl_sync_hot {
  () => {
    pub fn sync(&mut self) {
      if self.rx.try_recv().is_ok() {
        self.last_update_time = Some(::time::precise_time_s());
      }

      match self.last_update_time {
        Some(last_update_time) if ::time::precise_time_s() - last_update_time >= ::resource::UPDATE_AWAIT_TIME => {
          self.reload();
          self.last_update_time = None;
        },
        _ => {}
      }
    }
  }
}
<|endoftext|>


<commit_before>//! jsonrpc response
use std::collections::BTreeMap;
use serde::de::{Deserialize, Deserializer, Error as DeError};
use serde::ser::{Serialize, Serializer};
use serde_json::value::{from_value, to_value};
use super::{Id, Value, Error, Version, Params};

/// Response from subscription
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct SubscriptionOutput {
	/// Notification method
	pub method: String,
	/// Id of notification
	pub notification_id: Value,
	/// Result
	pub result: Result<Value, Error>,
}

// TODO [ToDr] Test serialization!
impl From<SubscriptionOutput> for Params {
	fn from(output: SubscriptionOutput) -> Self {
		let mut map = BTreeMap::new();
		map.insert("subscription".into(), output.notification_id);
		match output.result {
			Ok(result) => map.insert("result".into(), result),
			Err(error) => map.insert("error".into(), to_value(error)),
		};
		Params::Map(map)
	}
}

/// Successful response
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Success {
	/// Protocol version
	pub jsonrpc: Version,
	/// Result
	pub result: Value,
	/// Correlation id
	pub id: Id
}

/// Unsuccessful response
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Failure {
	/// Protocol Version
	pub jsonrpc: Version,
	/// Error
	pub error: Error,
	/// Correlation id
	pub id: Id
}

/// Represents synchronous output - failure or success
#[derive(Debug, PartialEq)]
pub enum Output {
	/// Success
	Success(Success),
	/// Failure
	Failure(Failure),
}

impl Output {
	/// Creates new synchronous output given `Result`, `Id` and `Version`.
	pub fn from(result: Result<Value, Error>, id: Id, jsonrpc: Version) -> Self {
		match result {
			Ok(result) => Output::Success(Success {
				id: id,
				jsonrpc: jsonrpc,
				result: result,
			}),
			Err(error) => Output::Failure(Failure {
				id: id,
				jsonrpc: jsonrpc,
				error: error,
			}),
		}
	}
}

impl Deserialize for Output {
	fn deserialize<D>(deserializer: &mut D) -> Result<Output, D::Error>
	where D: Deserializer {
		let v = try!(Value::deserialize(deserializer));
		from_value(v.clone()).map(Output::Failure)
			.or_else(|_| from_value(v).map(Output::Success))
			.map_err(|_| D::Error::custom("")) // types must match
	}
}

impl Serialize for Output {
	fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
	where S: Serializer {
		match *self {
			Output::Success(ref s) => s.serialize(serializer),
			Output::Failure(ref f) => f.serialize(serializer)
		}
	}
}

/// Synchronous response
#[derive(Debug, PartialEq)]
pub enum Response {
	/// Single response
	Single(Output),
	/// Response to batch request (batch of responses)
	Batch(Vec<Output>)
}

impl Deserialize for Response {
	fn deserialize<D>(deserializer: &mut D) -> Result<Response, D::Error>
	where D: Deserializer {
		let v = try!(Value::deserialize(deserializer));
		from_value(v.clone()).map(Response::Batch)
			.or_else(|_| from_value(v).map(Response::Single))
			.map_err(|_| D::Error::custom("")) // types must match
	}
}

impl Serialize for Response {
	fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
	where S: Serializer {
		match *self {
			Response::Single(ref o) => o.serialize(serializer),
			Response::Batch(ref b) => b.serialize(serializer)
		}
	}
}

impl From<Failure> for Response {
	fn from(failure: Failure) -> Self {
		Response::Single(Output::Failure(failure))
	}
}

impl From<Success> for Response {
	fn from(success: Success) -> Self {
		Response::Single(Output::Success(success))
	}
}

#[test]
fn success_output_serialize() {
	use serde_json;
	use serde_json::Value;

	let so = Output::Success(Success {
		jsonrpc: Version::V2,
		result: Value::U64(1),
		id: Id::Num(1)
	});

	let serialized = serde_json::to_string(&so).unwrap();
	assert_eq!(serialized, r#"{"jsonrpc":"2.0","result":1,"id":1}"#);
}

#[test]
fn success_output_deserialize() {
	use serde_json;
	use serde_json::Value;

	let dso = r#"{"jsonrpc":"2.0","result":1,"id":1}"#;

	let deserialized: Output = serde_json::from_str(dso).unwrap();
	assert_eq!(deserialized, Output::Success(Success {
		jsonrpc: Version::V2,
		result: Value::U64(1),
		id: Id::Num(1)
	}));
}

#[test]
fn failure_output_serialize() {
	use serde_json;

	let fo = Output::Failure(Failure {
		jsonrpc: Version::V2,
		error: Error::parse_error(),
		id: Id::Num(1)
	});

	let serialized = serde_json::to_string(&fo).unwrap();
	assert_eq!(serialized, r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error","data":null},"id":1}"#);
}

#[test]
fn failure_output_deserialize() {
	use serde_json;

	let dfo = r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":1}"#;

	let deserialized: Output = serde_json::from_str(dfo).unwrap();
	assert_eq!(deserialized, Output::Failure(Failure {
		jsonrpc: Version::V2,
		error: Error::parse_error(),
		id: Id::Num(1)
	}));
}

#[test]
fn single_response_deserialize() {
	use serde_json;
	use serde_json::Value;

	let dsr = r#"{"jsonrpc":"2.0","result":1,"id":1}"#;

	let deserialized: Response = serde_json::from_str(dsr).unwrap();
	assert_eq!(deserialized, Response::Single(Output::Success(Success {
		jsonrpc: Version::V2,
		result: Value::U64(1),
		id: Id::Num(1)
	})));
}

#[test]
fn batch_response_deserialize() {
	use serde_json;
	use serde_json::Value;

	let dbr = r#"[{"jsonrpc":"2.0","result":1,"id":1},{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":1}]"#;

	let deserialized: Response = serde_json::from_str(dbr).unwrap();
	assert_eq!(deserialized, Response::Batch(vec![
		Output::Success(Success {
			jsonrpc: Version::V2,
			result: Value::U64(1),
			id: Id::Num(1)
		}),
		Output::Failure(Failure {
			jsonrpc: Version::V2,
			error: Error::parse_error(),
			id: Id::Num(1)
		})
	]));
}
<commit_msg>to_value fix<commit_after>//! jsonrpc response
use std::collections::BTreeMap;
use serde::de::{Deserialize, Deserializer, Error as DeError};
use serde::ser::{Serialize, Serializer};
use serde_json::value::{from_value, to_value};
use super::{Id, Value, Error, Version, Params};

/// Response from subscription
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct SubscriptionOutput {
	/// Notification method
	pub method: String,
	/// Id of notification
	pub notification_id: Value,
	/// Result
	pub result: Result<Value, Error>,
}

// TODO [ToDr] Test serialization!
impl From<SubscriptionOutput> for Params {
	fn from(output: SubscriptionOutput) -> Self {
		let mut map = BTreeMap::new();
		map.insert("subscription".into(), output.notification_id);
		match output.result {
			Ok(result) => map.insert("result".into(), result),
			Err(error) => map.insert("error".into(), to_value(&error)),
		};
		Params::Map(map)
	}
}

/// Successful response
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Success {
	/// Protocol version
	pub jsonrpc: Version,
	/// Result
	pub result: Value,
	/// Correlation id
	pub id: Id
}

/// Unsuccessful response
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Failure {
	/// Protocol Version
	pub jsonrpc: Version,
	/// Error
	pub error: Error,
	/// Correlation id
	pub id: Id
}

/// Represents synchronous output - failure or success
#[derive(Debug, PartialEq)]
pub enum Output {
	/// Success
	Success(Success),
	/// Failure
	Failure(Failure),
}

impl Output {
	/// Creates new synchronous output given `Result`, `Id` and `Version`.
	pub fn from(result: Result<Value, Error>, id: Id, jsonrpc: Version) -> Self {
		match result {
			Ok(result) => Output::Success(Success {
				id: id,
				jsonrpc: jsonrpc,
				result: result,
			}),
			Err(error) => Output::Failure(Failure {
				id: id,
				jsonrpc: jsonrpc,
				error: error,
			}),
		}
	}
}

impl Deserialize for Output {
	fn deserialize<D>(deserializer: &mut D) -> Result<Output, D::Error>
	where D: Deserializer {
		let v = try!(Value::deserialize(deserializer));
		from_value(v.clone()).map(Output::Failure)
			.or_else(|_| from_value(v).map(Output::Success))
			.map_err(|_| D::Error::custom("")) // types must match
	}
}

impl Serialize for Output {
	fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
	where S: Serializer {
		match *self {
			Output::Success(ref s) => s.serialize(serializer),
			Output::Failure(ref f) => f.serialize(serializer)
		}
	}
}

/// Synchronous response
#[derive(Debug, PartialEq)]
pub enum Response {
	/// Single response
	Single(Output),
	/// Response to batch request (batch of responses)
	Batch(Vec<Output>)
}

impl Deserialize for Response {
	fn deserialize<D>(deserializer: &mut D) -> Result<Response, D::Error>
	where D: Deserializer {
		let v = try!(Value::deserialize(deserializer));
		from_value(v.clone()).map(Response::Batch)
			.or_else(|_| from_value(v).map(Response::Single))
			.map_err(|_| D::Error::custom("")) // types must match
	}
}

impl Serialize for Response {
	fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
	where S: Serializer {
		match *self {
			Response::Single(ref o) => o.serialize(serializer),
			Response::Batch(ref b) => b.serialize(serializer)
		}
	}
}

impl From<Failure> for Response {
	fn from(failure: Failure) -> Self {
		Response::Single(Output::Failure(failure))
	}
}

impl From<Success> for Response {
	fn from(success: Success) -> Self {
		Response::Single(Output::Success(success))
	}
}

#[test]
fn success_output_serialize() {
	use serde_json;
	use serde_json::Value;

	let so = Output::Success(Success {
		jsonrpc: Version::V2,
		result: Value::U64(1),
		id: Id::Num(1)
	});

	let serialized = serde_json::to_string(&so).unwrap();
	assert_eq!(serialized, r#"{"jsonrpc":"2.0","result":1,"id":1}"#);
}

#[test]
fn success_output_deserialize() {
	use serde_json;
	use serde_json::Value;

	let dso = r#"{"jsonrpc":"2.0","result":1,"id":1}"#;

	let deserialized: Output = serde_json::from_str(dso).unwrap();
	assert_eq!(deserialized, Output::Success(Success {
		jsonrpc: Version::V2,
		result: Value::U64(1),
		id: Id::Num(1)
	}));
}

#[test]
fn failure_output_serialize() {
	use serde_json;

	let fo = Output::Failure(Failure {
		jsonrpc: Version::V2,
		error: Error::parse_error(),
		id: Id::Num(1)
	});

	let serialized = serde_json::to_string(&fo).unwrap();
	assert_eq!(serialized, r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error","data":null},"id":1}"#);
}

#[test]
fn failure_output_deserialize() {
	use serde_json;

	let dfo = r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":1}"#;

	let deserialized: Output = serde_json::from_str(dfo).unwrap();
	assert_eq!(deserialized, Output::Failure(Failure {
		jsonrpc: Version::V2,
		error: Error::parse_error(),
		id: Id::Num(1)
	}));
}

#[test]
fn single_response_deserialize() {
	use serde_json;
	use serde_json::Value;

	let dsr = r#"{"jsonrpc":"2.0","result":1,"id":1}"#;

	let deserialized: Response = serde_json::from_str(dsr).unwrap();
	assert_eq!(deserialized, Response::Single(Output::Success(Success {
		jsonrpc: Version::V2,
		result: Value::U64(1),
		id: Id::Num(1)
	})));
}

#[test]
fn batch_response_deserialize() {
	use serde_json;
	use serde_json::Value;

	let dbr = r#"[{"jsonrpc":"2.0","result":1,"id":1},{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":1}]"#;

	let deserialized: Response = serde_json::from_str(dbr).unwrap();
	assert_eq!(deserialized, Response::Batch(vec![
		Output::Success(Success {
			jsonrpc: Version::V2,
			result: Value::U64(1),
			id: Id::Num(1)
		}),
		Output::Failure(Failure {
			jsonrpc: Version::V2,
			error: Error::parse_error(),
			id: Id::Num(1)
		})
	]));
}
<|endoftext|>


<commit_before>use rustc_serialize::json::{self, Json, ToJson};

use common::{Nullable, Date};
use cookie;
use time;

#[derive(Debug)]
pub enum WebDriverResponse {
    CloseWindow(CloseWindowResponse),
    Cookie(CookieResponse),
    DeleteSession,
    ElementRect(RectResponse),
    Generic(ValueResponse),
    NewSession(NewSessionResponse),
    Timeouts(TimeoutsResponse),
    Void,
    WindowRect(RectResponse),
}

impl WebDriverResponse {
    pub fn to_json_string(self) -> String {
        let obj = match self {
            WebDriverResponse::CloseWindow(ref x) => json::encode(&x.to_json()),
            WebDriverResponse::Cookie(ref x) => json::encode(x),
            WebDriverResponse::DeleteSession => Ok("{}".to_string()),
            WebDriverResponse::ElementRect(ref x) => json::encode(x),
            WebDriverResponse::Generic(ref x) => json::encode(x),
            WebDriverResponse::NewSession(ref x) => json::encode(x),
            WebDriverResponse::Timeouts(ref x) => json::encode(x),
            WebDriverResponse::Void => Ok("{}".to_string()),
            WebDriverResponse::WindowRect(ref x) => json::encode(x),
        }.unwrap();

        match self {
            WebDriverResponse::Generic(_) |
            WebDriverResponse::Cookie(_) => obj,
            _ => {
                let mut data = String::with_capacity(11 + obj.len());
                data.push_str("{\"value\": ");
                data.push_str(&*obj);
                data.push_str("}");
                data
            }
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct CloseWindowResponse {
    pub window_handles: Vec<String>,
}

impl CloseWindowResponse {
    pub fn new(handles: Vec<String>) -> CloseWindowResponse {
        CloseWindowResponse { window_handles: handles }
    }
}

impl ToJson for CloseWindowResponse {
    fn to_json(&self) -> Json {
        Json::Array(self.window_handles
                    .iter()
                    .map(|x| Json::String(x.clone()))
                    .collect::<Vec<Json>>())
    }
}

#[derive(RustcEncodable, Debug)]
pub struct NewSessionResponse {
    pub sessionId: String,
    pub capabilities: json::Json
}

impl NewSessionResponse {
    pub fn new(session_id: String, capabilities: json::Json) -> NewSessionResponse {
        NewSessionResponse {
            capabilities: capabilities,
            sessionId: session_id
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct TimeoutsResponse {
    pub script: u64,
    pub pageLoad: u64,
    pub implicit: u64,
}

impl TimeoutsResponse {
    pub fn new(script: u64, page_load: u64, implicit: u64) -> TimeoutsResponse {
        TimeoutsResponse {
            script: script,
            pageLoad: page_load,
            implicit: implicit,
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct ValueResponse {
    pub value: json::Json
}

impl ValueResponse {
    pub fn new(value: json::Json) -> ValueResponse {
        ValueResponse {
            value: value
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct RectResponse {
    pub x: f64,
    pub y: f64,
    pub width: f64,
    pub height: f64
}

impl RectResponse {
    pub fn new(x: f64, y: f64, width: f64, height: f64) -> RectResponse {
        RectResponse {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

//TODO: some of these fields are probably supposed to be optional
#[derive(RustcEncodable, PartialEq, Debug, Clone)]
pub struct Cookie {
    pub name: String,
    pub value: String,
    pub path: Nullable<String>,
    pub domain: Nullable<String>,
    pub expiry: Nullable<Date>,
    pub secure: bool,
    pub httpOnly: bool
}

impl Cookie {
    pub fn new(name: String, value: String, path: Nullable<String>, domain: Nullable<String>,
               expiry: Nullable<Date>, secure: bool, http_only: bool) -> Cookie {
        Cookie {
            name: name,
            value: value,
            path: path,
            domain: domain,
            expiry: expiry,
            secure: secure,
            httpOnly: http_only
        }
    }
}

impl Into<cookie::Cookie<'static>> for Cookie {
    fn into(self) -> cookie::Cookie<'static> {
        let cookie = cookie::Cookie::build(self.name, self.value)
            .secure(self.secure)
            .http_only(self.httpOnly);
        let cookie = match self.domain {
            Nullable::Value(domain) => cookie.domain(domain),
            Nullable::Null => cookie,
        };
        let cookie = match self.path {
            Nullable::Value(path) => cookie.path(path),
            Nullable::Null => cookie,
        };
        let cookie = match self.expiry {
            Nullable::Value(Date(expiry)) => {
                cookie.expires(time::at(time::Timespec::new(expiry as i64, 0)))
            },
            Nullable::Null => cookie,
        };
        cookie.finish()
    }
}

#[derive(RustcEncodable, Debug)]
pub struct CookieResponse {
    pub value: Vec<Cookie>
}

impl CookieResponse {
    pub fn new(value: Vec<Cookie>) -> CookieResponse {
        CookieResponse {
            value: value
        }
    }
}

#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;
    use rustc_serialize::json::Json;
    use super::{WebDriverResponse,
                CloseWindowResponse,
                CookieResponse,
                RectResponse,
                NewSessionResponse,
                ValueResponse,
                TimeoutsResponse,
                Cookie,
                Nullable};

    fn test(resp: WebDriverResponse, expected_str: &str) {
        let data = resp.to_json_string();
        let actual = Json::from_str(&*data).unwrap();
        let expected = Json::from_str(expected_str).unwrap();
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_close_window() {
        let resp = WebDriverResponse::CloseWindow(
            CloseWindowResponse::new(vec!["test".into()]));
        let expected = r#"{"value": ["test"]}"#;
        test(resp, expected);
    }

    #[test]
    fn test_cookie() {
        let resp = WebDriverResponse::Cookie(CookieResponse::new(
            vec![
                Cookie::new("test".into(),
                            "test_value".into(),
                            Nullable::Value("/".into()),
                            Nullable::Null,
                            Nullable::Null,
                            true,
                            false)
            ]));
        let expected = r#"{"value": [{"name": "test", "value": "test_value", "path": "/",
"domain": null, "expiry": null, "secure": true, "httpOnly": false}]}"#;
        test(resp, expected);
    }

    #[test]
    fn test_element_rect() {
        let resp = WebDriverResponse::ElementRect(RectResponse::new(
            0f64, 1f64, 2f64, 3f64));
        let expected = r#"{"value": {"x": 0.0, "y": 1.0, "width": 2.0, "height": 3.0}}"#;
        test(resp, expected);
    }

    #[test]
    fn test_window_rect() {
        let resp = WebDriverResponse::WindowRect(RectResponse {
            x: 0f64,
            y: 1f64,
            width: 2f64,
            height: 3f64,
        });
        let expected = r#"{"value": {"x": 0.0, "y": 1.0, "width": 2.0, "height": 3.0}}"#;
        test(resp, expected);
    }

    #[test]
    fn test_new_session() {
        let resp = WebDriverResponse::NewSession(
            NewSessionResponse::new("test".into(),
                                    Json::Object(BTreeMap::new())));
        let expected = r#"{"value": {"sessionId": "test", "capabilities": {}}}"#;
        test(resp, expected);
    }

    #[test]
    fn test_timeouts() {
         let resp = WebDriverResponse::Timeouts(TimeoutsResponse::new(
            1, 2, 3));
        let expected = r#"{"value": {"script": 1, "pageLoad": 2, "implicit": 3}}"#;
        test(resp, expected);
    }

    #[test]
    fn test_value() {
        let mut value = BTreeMap::new();
        value.insert("example".into(), Json::Array(vec![Json::String("test".into())]));
        let resp = WebDriverResponse::Generic(ValueResponse::new(
            Json::Object(value)));
        let expected = r#"{"value": {"example": ["test"]}}"#;
        test(resp, expected);
    }
}
<commit_msg>response: add single cookie response type (#102)<commit_after>use rustc_serialize::json::{self, Json, ToJson};

use common::{Nullable, Date};
use cookie;
use time;

#[derive(Debug)]
pub enum WebDriverResponse {
    CloseWindow(CloseWindowResponse),
    Cookie(CookieResponse),
    Cookies(CookiesResponse),
    DeleteSession,
    ElementRect(RectResponse),
    Generic(ValueResponse),
    NewSession(NewSessionResponse),
    Timeouts(TimeoutsResponse),
    Void,
    WindowRect(RectResponse),
}

impl WebDriverResponse {
    pub fn to_json_string(self) -> String {
        use response::WebDriverResponse::*;

        let obj = match self {
            CloseWindow(ref x) => json::encode(&x.to_json()),
            Cookie(ref x) => json::encode(x),
            Cookies(ref x) => json::encode(x),
            DeleteSession => Ok("{}".to_string()),
            ElementRect(ref x) => json::encode(x),
            Generic(ref x) => json::encode(x),
            NewSession(ref x) => json::encode(x),
            Timeouts(ref x) => json::encode(x),
            Void => Ok("{}".to_string()),
            WindowRect(ref x) => json::encode(x),
        }.unwrap();

        match self {
            Generic(_) | Cookie(_) | Cookies(_) => obj,
            _ => {
                let mut data = String::with_capacity(11 + obj.len());
                data.push_str("{\"value\": ");
                data.push_str(&*obj);
                data.push_str("}");
                data
            }
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct CloseWindowResponse {
    pub window_handles: Vec<String>,
}

impl CloseWindowResponse {
    pub fn new(handles: Vec<String>) -> CloseWindowResponse {
        CloseWindowResponse { window_handles: handles }
    }
}

impl ToJson for CloseWindowResponse {
    fn to_json(&self) -> Json {
        Json::Array(self.window_handles
                    .iter()
                    .map(|x| Json::String(x.clone()))
                    .collect::<Vec<Json>>())
    }
}

#[derive(RustcEncodable, Debug)]
pub struct NewSessionResponse {
    pub sessionId: String,
    pub capabilities: json::Json
}

impl NewSessionResponse {
    pub fn new(session_id: String, capabilities: json::Json) -> NewSessionResponse {
        NewSessionResponse {
            capabilities: capabilities,
            sessionId: session_id
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct TimeoutsResponse {
    pub script: u64,
    pub pageLoad: u64,
    pub implicit: u64,
}

impl TimeoutsResponse {
    pub fn new(script: u64, page_load: u64, implicit: u64) -> TimeoutsResponse {
        TimeoutsResponse {
            script: script,
            pageLoad: page_load,
            implicit: implicit,
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct ValueResponse {
    pub value: json::Json
}

impl ValueResponse {
    pub fn new(value: json::Json) -> ValueResponse {
        ValueResponse {
            value: value
        }
    }
}

#[derive(RustcEncodable, Debug)]
pub struct RectResponse {
    pub x: f64,
    pub y: f64,
    pub width: f64,
    pub height: f64
}

impl RectResponse {
    pub fn new(x: f64, y: f64, width: f64, height: f64) -> RectResponse {
        RectResponse {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

#[derive(RustcEncodable, PartialEq, Debug, Clone)]
pub struct Cookie {
    pub name: String,
    pub value: String,
    pub path: Nullable<String>,
    pub domain: Nullable<String>,
    pub expiry: Nullable<Date>,
    pub secure: bool,
    pub httpOnly: bool,
}

impl Into<cookie::Cookie<'static>> for Cookie {
    fn into(self) -> cookie::Cookie<'static> {
        let cookie = cookie::Cookie::build(self.name, self.value)
            .secure(self.secure)
            .http_only(self.httpOnly);
        let cookie = match self.domain {
            Nullable::Value(domain) => cookie.domain(domain),
            Nullable::Null => cookie,
        };
        let cookie = match self.path {
            Nullable::Value(path) => cookie.path(path),
            Nullable::Null => cookie,
        };
        let cookie = match self.expiry {
            Nullable::Value(Date(expiry)) => {
                cookie.expires(time::at(time::Timespec::new(expiry as i64, 0)))
            }
            Nullable::Null => cookie,
        };
        cookie.finish()
    }
}

#[derive(RustcEncodable, Debug)]
pub struct CookieResponse {
    pub value: Cookie,
}

#[derive(RustcEncodable, Debug)]
pub struct CookiesResponse {
    pub value: Vec<Cookie>,
}

#[cfg(test)]
mod tests {
    use super::{CloseWindowResponse, Cookie, CookieResponse, CookiesResponse, NewSessionResponse,
                Nullable, RectResponse, TimeoutsResponse, ValueResponse, WebDriverResponse};
    use rustc_serialize::json::Json;
    use std::collections::BTreeMap;

    fn test(resp: WebDriverResponse, expected_str: &str) {
        let data = resp.to_json_string();
        let actual = Json::from_str(&*data).unwrap();
        let expected = Json::from_str(expected_str).unwrap();
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_close_window() {
        let resp = WebDriverResponse::CloseWindow(
            CloseWindowResponse::new(vec!["test".into()]));
        let expected = r#"{"value": ["test"]}"#;
        test(resp, expected);
    }

    #[test]
    fn test_cookie() {
        let cookie = Cookie {
            name: "name".into(),
            value: "value".into(),
            path: Nullable::Value("/".into()),
            domain: Nullable::Null,
            expiry: Nullable::Null,
            secure: true,
            httpOnly: false,
        };
        let resp = WebDriverResponse::Cookie(CookieResponse { value: cookie });
        let expected = r#"{"value": {"name": "name", "expiry": null, "value": "value",
"path": "/", "domain": null, "secure": true, "httpOnly": false}}"#;
        test(resp, expected);
    }

    #[test]
    fn test_cookies() {
        let resp = WebDriverResponse::Cookies(CookiesResponse {
            value: vec![
                Cookie {
                    name: "name".into(),
                    value: "value".into(),
                    path: Nullable::Value("/".into()),
                    domain: Nullable::Null,
                    expiry: Nullable::Null,
                    secure: true,
                    httpOnly: false,
                }
            ]});
        let expected = r#"{"value": [{"name": "name", "value": "value", "path": "/",
"domain": null, "expiry": null, "secure": true, "httpOnly": false}]}"#;
        test(resp, expected);
    }

    #[test]
    fn test_element_rect() {
        let resp = WebDriverResponse::ElementRect(RectResponse::new(
            0f64, 1f64, 2f64, 3f64));
        let expected = r#"{"value": {"x": 0.0, "y": 1.0, "width": 2.0, "height": 3.0}}"#;
        test(resp, expected);
    }

    #[test]
    fn test_window_rect() {
        let resp = WebDriverResponse::WindowRect(RectResponse {
            x: 0f64,
            y: 1f64,
            width: 2f64,
            height: 3f64,
        });
        let expected = r#"{"value": {"x": 0.0, "y": 1.0, "width": 2.0, "height": 3.0}}"#;
        test(resp, expected);
    }

    #[test]
    fn test_new_session() {
        let resp = WebDriverResponse::NewSession(
            NewSessionResponse::new("test".into(),
                                    Json::Object(BTreeMap::new())));
        let expected = r#"{"value": {"sessionId": "test", "capabilities": {}}}"#;
        test(resp, expected);
    }

    #[test]
    fn test_timeouts() {
         let resp = WebDriverResponse::Timeouts(TimeoutsResponse::new(
            1, 2, 3));
        let expected = r#"{"value": {"script": 1, "pageLoad": 2, "implicit": 3}}"#;
        test(resp, expected);
    }

    #[test]
    fn test_value() {
        let mut value = BTreeMap::new();
        value.insert("example".into(), Json::Array(vec![Json::String("test".into())]));
        let resp = WebDriverResponse::Generic(ValueResponse::new(
            Json::Object(value)));
        let expected = r#"{"value": {"example": ["test"]}}"#;
        test(resp, expected);
    }
}
<|endoftext|>


<commit_before>pub struct PLPWriter
{
	pub use_tabs: bool,
	pub indent_level: u16,
	pub code: String,
}

impl PLPWriter
{
	// TODO: implement indentation writing
	pub fn new() -> PLPWriter
	{
		PLPWriter {
			use_tabs: true,
			indent_level: 0,
			code: String::new(),
			}
	}

	pub fn reset(&mut self)
	{
		self.indent_level = 0;
		self.code = String::new();
	}

	pub fn li(&mut self, register: &str, value: &str) -> String
	{
		let mut code = String::new();
		code.push_str("li ");
		code.push_str(register);
		code.push_str(", ");
		code.push_str(value);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn mov(&mut self, register_to: &str, register_from: &str) -> String
	{
		let mut code = String::new();
		code.push_str("move ");
		code.push_str(register_to);
		code.push_str(", ");
		code.push_str(register_from);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn addu(&mut self, register_sum: &str, register_addend1: &str, register_addend2: &str) -> String
	{
		let mut code = String::new();
		code.push_str("addu ");
		code.push_str(register_sum);
		code.push_str(", ");
		code.push_str(register_addend1);
		code.push_str(", ");
		code.push_str(register_addend2);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn subu(&mut self, register_difference: &str, register_addend1: &str, register_addend2: &str) -> String
	{
		let mut code = String::new();
		code.push_str("subu ");
		code.push_str(register_difference);
		code.push_str(", ");
		code.push_str(register_addend1);
		code.push_str(", ");
		code.push_str(register_addend2);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn mullo(&mut self, register_product: &str, register_multiplicand1: &str, register_multiplicand2: &str) -> String
	{
		let mut code = String::new();
		code.push_str("subu ");
		code.push_str(register_product);
		code.push_str(", ");
		code.push_str(register_multiplicand1);
		code.push_str(", ");
		code.push_str(register_multiplicand2);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn sw(&mut self, register_target: &str, offset: u16, register_address: &str) -> String
	{
		let mut code = String::new();
		code.push_str("sw ");
		code.push_str(register_target);
		code.push_str(", ");
		code.push_str(&*offset.to_string());
		code.push_str(" (");
		code.push_str(register_address);
		code.push_str(")\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn lw(&mut self, register_target: &str, offset: u16, register_address: &str) -> String
	{
		let mut code = String::new();
		code.push_str("lw ");
		code.push_str(register_target);
		code.push_str(", ");
		code.push_str(&*offset.to_string());
		code.push_str(" (");
		code.push_str(register_address);
		code.push_str(")\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn push(&mut self, register_target: &str) -> String
	{
		let mut code = String::new();
		code.push_str("push ");
		code.push_str(register_target);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn pop(&mut self, register_target: &str) -> String
	{
		let mut code = String::new();
		code.push_str("pop ");
		code.push_str(register_target);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn call(&mut self, function_label: &str) -> String
	{
		let mut code = String::new();
		code.push_str("call ");
		code.push_str(function_label);
		code.push_str("\n");
		code.push_str("nop");
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn nop(&mut self) -> String
	{
		let mut code = String::new();
		code.push_str("nop");
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}
}
<commit_msg>Documentation<commit_after>pub struct PLPWriter
{
	/// If true, tabs will be used to indent. Else, spaces will be used to indent
	pub use_tabs: bool,

	/// Number of indent characters to prefix each line of code with.
	/// Adjusting this value will not affect code that has already been written
	pub indent_level: u16,

	/// PLP output of this writer
	pub code: String,
}

impl PLPWriter
{
	// TODO: implement indentation writing
	pub fn new() -> PLPWriter
	{
		PLPWriter {
			use_tabs: true,
			indent_level: 0,
			code: String::new(),
			}
	}

	pub fn reset(&mut self)
	{
		self.indent_level = 0;
		self.code = String::new();
	}

	pub fn li(&mut self, register: &str, value: &str) -> String
	{
		let mut code = String::new();
		code.push_str("li ");
		code.push_str(register);
		code.push_str(", ");
		code.push_str(value);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn mov(&mut self, register_to: &str, register_from: &str) -> String
	{
		let mut code = String::new();
		code.push_str("move ");
		code.push_str(register_to);
		code.push_str(", ");
		code.push_str(register_from);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn addu(&mut self, register_sum: &str, register_addend1: &str, register_addend2: &str) -> String
	{
		let mut code = String::new();
		code.push_str("addu ");
		code.push_str(register_sum);
		code.push_str(", ");
		code.push_str(register_addend1);
		code.push_str(", ");
		code.push_str(register_addend2);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn subu(&mut self, register_difference: &str, register_addend1: &str, register_addend2: &str) -> String
	{
		let mut code = String::new();
		code.push_str("subu ");
		code.push_str(register_difference);
		code.push_str(", ");
		code.push_str(register_addend1);
		code.push_str(", ");
		code.push_str(register_addend2);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn mullo(&mut self, register_product: &str, register_multiplicand1: &str, register_multiplicand2: &str) -> String
	{
		let mut code = String::new();
		code.push_str("subu ");
		code.push_str(register_product);
		code.push_str(", ");
		code.push_str(register_multiplicand1);
		code.push_str(", ");
		code.push_str(register_multiplicand2);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn sw(&mut self, register_target: &str, offset: u16, register_address: &str) -> String
	{
		let mut code = String::new();
		code.push_str("sw ");
		code.push_str(register_target);
		code.push_str(", ");
		code.push_str(&*offset.to_string());
		code.push_str(" (");
		code.push_str(register_address);
		code.push_str(")\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn lw(&mut self, register_target: &str, offset: u16, register_address: &str) -> String
	{
		let mut code = String::new();
		code.push_str("lw ");
		code.push_str(register_target);
		code.push_str(", ");
		code.push_str(&*offset.to_string());
		code.push_str(" (");
		code.push_str(register_address);
		code.push_str(")\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn push(&mut self, register_target: &str) -> String
	{
		let mut code = String::new();
		code.push_str("push ");
		code.push_str(register_target);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn pop(&mut self, register_target: &str) -> String
	{
		let mut code = String::new();
		code.push_str("pop ");
		code.push_str(register_target);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn call(&mut self, function_label: &str) -> String
	{
		let mut code = String::new();
		code.push_str("call ");
		code.push_str(function_label);
		code.push_str("\n");
		code.push_str("nop");
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn nop(&mut self) -> String
	{
		let mut code = String::new();
		code.push_str("nop");
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}
}
<|endoftext|>


<commit_before>use std::ops::Add;
use std::ops::Sub;

use super::rect::Rect;

#[derive(Debug, Copy, Clone)]
pub enum RelativePos<T> {
    FromStart(T),
    FromEnd(T),
}

#[derive(Debug, Copy, Clone)]
pub enum RelativeSize<T> {
    Absolute(T),
    Relative(T),
}

#[derive(Debug, Copy, Clone)]
pub struct RelativeRect<T> {
    pub top: RelativePos<T>,
    pub left: RelativePos<T>,
    pub width: RelativeSize<T>,
    pub height: RelativeSize<T>,
}

impl<T: Copy + Add<T, Output=T> + Sub<T, Output=T>> RelativePos<T> {
    fn relative_to(&self, start: T, end: T) -> T {
        match *self {
            RelativePos::FromStart(n) => start + n,
            RelativePos::FromEnd(n) => end - n
        }
    }
}

impl<T: Copy + Add<T, Output=T> + Sub<T, Output=T>> RelativeSize<T> {
    fn relative_to(&self, size: T) -> T {
        match *self {
            RelativeSize::Absolute(n) => n,
            RelativeSize::Relative(n) => size - n
        }
    }
}

impl<T> RelativeRect<T>
        where T: Copy + Add<T, Output=T> + Sub<T, Output=T>
{
    pub fn get_absolute_to(&self, relative_to: Rect<T>) -> Rect<T> {
        Rect {
            top: self.top.relative_to(relative_to.top, relative_to.bottom()),
            left: self.left.relative_to(relative_to.left, relative_to.right()),
            width: self.width.relative_to(relative_to.width),
            height: self.height.relative_to(relative_to.height)
        }
    }
}
<commit_msg>Add documentation and a unit test for relative_rect<commit_after>//! A rect that has relative values to be calculated from a concrete rect.
use std::ops::Add;
use std::ops::Sub;

use super::rect::Rect;

/// A position (top or left) relative to a parent's position (top or left).
#[derive(Debug, Copy, Clone)]
pub enum RelativePos<T> {
    /// The position is calculated from the start of the parent position.
    FromStart(T),
    /// the position is *substracted* from the parent struct.
    FromEnd(T),
}

/// A size (height or width) relative to a parent size (height or width).
#[derive(Debug, Copy, Clone)]
pub enum RelativeSize<T> {
    /// The size is absolute, it is up to the creator to make sure that it is not larger
    /// than the parent size.
    Absolute(T),
    /// A size that is relative to the parent and is smaller than the parent struct by the given units.
    /// The units are *substracted* from the parent.
    Relative(T),
}

/// A relative rect struct.
///
/// A rect that can be positioned relative to a regular rect. This is geared towards rects that
/// are contained in an other, absolute, rect. As such, the relative fields are geard towards
/// substraction.
#[derive(Debug, Copy, Clone)]
pub struct RelativeRect<T> {
    pub top: RelativePos<T>,
    pub left: RelativePos<T>,
    pub width: RelativeSize<T>,
    pub height: RelativeSize<T>,
}

impl<T: Copy + Add<T, Output=T> + Sub<T, Output=T>> RelativePos<T> {
    fn relative_to(&self, start: T, end: T) -> T {
        match *self {
            RelativePos::FromStart(n) => start + n,
            RelativePos::FromEnd(n) => end - n
        }
    }
}

impl<T: Copy + Add<T, Output=T> + Sub<T, Output=T>> RelativeSize<T> {
    fn relative_to(&self, size: T) -> T {
        match *self {
            RelativeSize::Absolute(n) => n,
            RelativeSize::Relative(n) => size - n
        }
    }
}

impl<T> RelativeRect<T>
        where T: Copy + Add<T, Output=T> + Sub<T, Output=T>
{
    /// Returns an absolute rect resolving the relative values based on the supplied rect.
    ///
    /// # Examples
    ///
    /// ```
    /// use rex_utils::relative_rect::{RelativeRect, RelativePos, RelativeSize};
    /// use rex_utils::rect::Rect;
    ///
    /// let sub_rect = RelativeRect {
    ///     // This is addition on .top
    ///     top: RelativePos::FromStart(5),
    ///     // This is substraction from .right()
    ///     left: RelativePos::FromEnd(10),
    ///     // This is substration from .width
    ///     width: RelativeSize::Absolute(4),
    ///     // This is an absolute values, not modified
    ///     height: RelativeSize::Relative(5)
    /// };
    ///
    /// let abs_rect = Rect {
    ///     top: 10,
    ///     left: 10,
    ///     height: 40,
    ///     width: 40,
    /// };
    ///
    /// assert_eq!(sub_rect.get_absolute_to(abs_rect), Rect {
    ///     top: 15,
    ///     left: 40,
    ///     width: 4,
    ///     height: 35});
    /// ```
    pub fn get_absolute_to(&self, relative_to: Rect<T>) -> Rect<T> {
        Rect {
            top: self.top.relative_to(relative_to.top, relative_to.bottom()),
            left: self.left.relative_to(relative_to.left, relative_to.right()),
            width: self.width.relative_to(relative_to.width),
            height: self.height.relative_to(relative_to.height)
        }
    }
}
<|endoftext|>


<commit_before>use std::io::File;
use std::path::posix::Path;
//use std::option::Option;
use std::vec::Vec;

// Prints the byte length of every underlying packet in the stream

// A bitstream is represented by the stream itself (read to a certain point),
// plus any information needed to process the remainder of the stream at that
// point
struct OggBitstream {
    file : File,
    end_of_stream : bool,
    current_segment_lengths : Vec<u8>
}

impl OggBitstream {
    fn new(f : File) -> OggBitstream {
        OggBitstream {
            end_of_stream : false,
            file : f,
            current_segment_lengths : Vec::new() }
    }

    /*
packet header:
OggS: 4 bytes
version: 1 byte
header type: 1 byte (fresh/continued packet, bos, eos)
absolute granule position: 8 bytes
stream serial number: 4 bytes
page sequence number: 4 bytes
page checksum: 4 bytes
segment count: 1 byte
segment table (variable: 1 byte per segment)
*/

    // Returns the bytes of the next packet in the underlying stream, or a
    // suitable null value
    fn next_packet(&mut self) -> Option<Vec<u8>> {
        let mut packet : Vec<u8> = Vec::new();
        loop {
            let segment = self.next_segment();
            if segment.len() < 255 {
                return Some(packet.append(segment.as_slice()));
            } else {
                packet = packet.append(segment.as_slice());
            }
        }
    }

    // Removes the next segment off of the segment list and return it
    fn next_segment(&mut self) -> Vec<u8> {
        if self.current_segment_lengths.len() == 0 {
            self.read_page();
        }

        // TODO: check end of stream

        let mut segment = Vec::from_elem(self.current_segment_lengths.as_slice()[0].to_uint().unwrap(), 0_u8);
        self.current_segment_lengths = Vec::from_slice(self.current_segment_lengths.tail());
        self.file.read(segment.as_mut_slice());
        segment
    }

    // reads the next page of the bitstream (through the segment table, but not
    // the segments themselve), writing it to the struct
    fn read_page(&mut self) {
        println!("Reading a page")
        // 1. read the static-length body
        // 2. read the variable-length current-segments table, write it to struct

        // TODO: figure out how to create the vector to read into without
        // initializing it first (maybe use a BufferedReader)
        let mut header = Vec::from_elem(27, 0_u8);
        self.file.read(header.as_mut_slice());
        let segment_count = header.as_slice()[26].to_uint().unwrap();
        let mut segment_table : Vec<u8> = Vec::from_elem(segment_count, 0_u8);
        self.file.read(segment_table.as_mut_slice());
        self.current_segment_lengths = segment_table;
    }
}

fn main() {
    println!("starting...");
    let mut maybe_f = File::open(&Path::new("star_wars.ogg"));
    match maybe_f {
        Ok(mut f) => {

            //let mut header : Vec<u8> = Vec::from_elem(27, 0_u8);
            // println!("vector reference length: {}", header.len());
            // println!("vector reference capacity: {}", header.capacity());
            // let mut header_slice = header.mut_slice(0, 27);
            // println!("slice length: {}", header_slice.len());
            // match f.read_at_least(3, header_slice) {
            //     Ok(bytes_read) => { println!("bytes read: {}", bytes_read); }
            //     Err(error) => { println!("error {}", error); }
            // }

            //     //println!("{}", header_slice.len());
            let mut bs = OggBitstream::new(f);
            let mut next_packet = bs.next_packet();
            while next_packet.is_some() {
                println!("Packet: {}", next_packet.unwrap().len());
                next_packet = bs.next_packet();
            }
        }
        _ => ()
    }
}
<commit_msg>Add check for end-of-stream<commit_after>use std::io::File;
use std::path::posix::Path;
//use std::option::Option;
use std::vec::Vec;

// Prints the byte length of every underlying packet in the stream

// A bitstream is represented by the stream itself (read to a certain point),
// plus any information needed to process the remainder of the stream at that
// point
struct OggBitstream {
    file : File,
    end_of_stream : bool,
    current_segment_lengths : Vec<u8>
}

impl OggBitstream {
    fn new(f : File) -> OggBitstream {
        OggBitstream {
            end_of_stream : false,
            file : f,
            current_segment_lengths : Vec::new() }
    }

    /*
packet header:
OggS: 4 bytes
version: 1 byte
header type: 1 byte (fresh/continued packet, bos, eos)
absolute granule position: 8 bytes
stream serial number: 4 bytes
page sequence number: 4 bytes
page checksum: 4 bytes
segment count: 1 byte
segment table (variable: 1 byte per segment)
*/

    // Returns the bytes of the next packet in the underlying stream, or a
    // suitable null value
    fn next_packet(&mut self) -> Option<Vec<u8>> {
        let mut packet : Vec<u8> = Vec::new();
        loop {

            match self.next_segment() {
                None => { return None }
                Some(segment) => {
                    if segment.len() < 255 {
                        return Some(packet.append(segment.as_slice()));
                    } else {
                        packet = packet.append(segment.as_slice());
                    }
                }
            }
        }
    }

    // Removes the next segment off of the segment list and return it
    fn next_segment(&mut self) -> Option<Vec<u8>> {
        if self.current_segment_lengths.len() == 0 {
            if self.end_of_stream {
                return None;
            } else {
            self.read_page();
            }
        }

        let mut segment = Vec::from_elem(self.current_segment_lengths.as_slice()[0].to_uint().unwrap(), 0_u8);
        self.current_segment_lengths = Vec::from_slice(self.current_segment_lengths.tail());
        self.file.read(segment.as_mut_slice());
        Some(segment)
    }

    // reads the next page of the bitstream (through the segment table, but not
    // the segments themselve), writing it to the struct
    fn read_page(&mut self) {
        println!("Reading a page")
        // 1. read the static-length body
        // 2. read the variable-length current-segments table, write it to struct

        // TODO: figure out how to create the vector to read into without
        // initializing it first (maybe use a BufferedReader)
        let mut header = Vec::from_elem(27, 0_u8);
        self.file.read(header.as_mut_slice());
        let header_type = header.get(5);
        self.end_of_stream = (*header_type == 0x04_u8);
        let segment_count = header.as_slice()[26].to_uint().unwrap();
        let mut segment_table : Vec<u8> = Vec::from_elem(segment_count, 0_u8);
        self.file.read(segment_table.as_mut_slice());
        self.current_segment_lengths = segment_table;
    }
}

fn main() {
    println!("starting...");
    let mut maybe_f = File::open(&Path::new("star_wars.ogg"));
    match maybe_f {
        Ok(mut f) => {
            let mut bs = OggBitstream::new(f);
            let mut next_packet = bs.next_packet();
            while next_packet.is_some() {
                println!("Packet: {}", next_packet.unwrap().len());
                next_packet = bs.next_packet();
            }
        }
        _ => ()
    }
}
<|endoftext|>


<commit_before>extern crate tcod;
use tcod::RootConsole;
use tcod::{Console};
use tcod::console::{FontLayout, FontType, Offscreen};
use tcod::input::{Key, KeyCode};

mod traits;
use traits::{Renderable, Movable, Position};

mod units;

const SCREEN_WIDTH: u8 = 80;
const SCREEN_HEIGHT: u8 = 50;

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right
}

#[derive(Debug)]
enum KeyType {
    Movement(Direction),
    Exit,
    Other,
}

fn key_type(key: &Key) -> KeyType {
    match key.code {
        KeyCode::Right  =>  KeyType::Movement(Direction::Right),
        KeyCode::Left   =>  KeyType::Movement(Direction::Left),
        KeyCode::Up     =>  KeyType::Movement(Direction::Up),
        KeyCode::Down   =>  KeyType::Movement(Direction::Down),
        KeyCode::Escape =>  KeyType::Exit,
        _ => KeyType::Other,
    }
}

fn main() {
    let mut root = RootConsole::initializer()
                    .size(SCREEN_WIDTH as i32, SCREEN_HEIGHT as i32)
                    .title("Roguelike Tutorial")
                    .fullscreen(false)
                    .font("arial10x10.png", FontLayout::Tcod)
                    .font_type(FontType::Greyscale)
                    .init();

    let mut buffer_console = Offscreen::new(SCREEN_WIDTH as i32, SCREEN_HEIGHT as i32);

    root.set_default_foreground(tcod::colors::WHITE);

    let mut player = units::Unit::new(1, 1, '@', tcod::colors::WHITE);

    while !root.window_closed() {
        buffer_console.clear();

        player.render(&mut buffer_console);

        tcod::console::blit(&buffer_console, (0,0), (0,0), &mut root, (0,0), 1.0, 1.0);
        root.flush();

        let key = root.wait_for_keypress(true);

        match key_type(&key) {
            KeyType::Movement(dir)  => {
                let (x,y) = player.get_position();
                match dir {
                    Direction::Up    if y > 0                 => player.nudge(dir),
                    Direction::Down  if y < SCREEN_HEIGHT-1   => player.nudge(dir),
                    Direction::Left  if x > 0                 => player.nudge(dir),
                    Direction::Right if x < SCREEN_WIDTH-1    => player.nudge(dir),
                    _ => {}
                }
            },
            KeyType::Exit           => break,
            KeyType::Other          => println!("{:?}", key),
        }
    }
}
<commit_msg>Added NPC vector, and dummy NPC.<commit_after>extern crate tcod;
use tcod::RootConsole;
use tcod::{Console};
use tcod::console::{FontLayout, FontType, Offscreen};
use tcod::input::{Key, KeyCode};

mod traits;
use traits::{Renderable, Movable, Position};

mod units;

const SCREEN_WIDTH: u8 = 80;
const SCREEN_HEIGHT: u8 = 50;

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right
}

#[derive(Debug)]
enum KeyType {
    Movement(Direction),
    Exit,
    Other,
}

fn key_type(key: &Key) -> KeyType {
    match key.code {
        KeyCode::Right  =>  KeyType::Movement(Direction::Right),
        KeyCode::Left   =>  KeyType::Movement(Direction::Left),
        KeyCode::Up     =>  KeyType::Movement(Direction::Up),
        KeyCode::Down   =>  KeyType::Movement(Direction::Down),
        KeyCode::Escape =>  KeyType::Exit,
        _ => KeyType::Other,
    }
}

fn main() {
    let mut root = RootConsole::initializer()
                    .size(SCREEN_WIDTH as i32, SCREEN_HEIGHT as i32)
                    .title("Roguelike Tutorial")
                    .fullscreen(false)
                    .font("arial10x10.png", FontLayout::Tcod)
                    .font_type(FontType::Greyscale)
                    .init();

    let mut buffer_console = Offscreen::new(SCREEN_WIDTH as i32, SCREEN_HEIGHT as i32);

    root.set_default_foreground(tcod::colors::WHITE);

    let mut player = units::Unit::new(1, 1, '@', tcod::colors::WHITE);

    let mut npcs = vec![];
    npcs.push(units::Unit::new(5, 5, '@', tcod::colors::YELLOW));

    while !root.window_closed() {
        buffer_console.clear();

        for unit in &npcs {
            unit.render(&mut buffer_console);
        }

        player.render(&mut buffer_console);

        tcod::console::blit(&buffer_console, (0,0), (0,0), &mut root, (0,0), 1.0, 1.0);
        root.flush();

        let key = root.wait_for_keypress(true);

        match key_type(&key) {
            KeyType::Movement(dir)  => {
                let (x,y) = player.get_position();
                match dir {
                    Direction::Up    if y > 0                 => player.nudge(dir),
                    Direction::Down  if y < SCREEN_HEIGHT-1   => player.nudge(dir),
                    Direction::Left  if x > 0                 => player.nudge(dir),
                    Direction::Right if x < SCREEN_WIDTH-1    => player.nudge(dir),
                    _ => {}
                }
            },
            KeyType::Exit           => break,
            KeyType::Other          => println!("{:?}", key),
        }
    }
}
<|endoftext|>


<commit_before>use lapin::{executor::Executor, ConnectionProperties, Result};
use std::{future::Future, pin::Pin};

// ConnectionProperties extension

pub trait LapinAsyncGlobalExecutorExt {
    fn with_async_global_executor(self) -> Self
    where
        Self: Sized;
}

impl LapinAsyncGlobalExecutorExt for ConnectionProperties {
    fn with_async_global_executor(self) -> Self {
        self.with_executor(AsyncGlobalExecutorExecutor)
    }
}

// Executor

#[derive(Debug)]
struct AsyncGlobalExecutorExecutor;

impl Executor for AsyncGlobalExecutorExecutor {
    fn spawn(&self, f: Pin<Box<dyn Future<Output = ()> + Send>>) -> Result<()> {
        async_global_executor::spawn(f).detach();
        Ok(())
    }
}
<commit_msg>lapin-async-executor: export executor<commit_after>use lapin::{executor::Executor, ConnectionProperties, Result};
use std::{future::Future, pin::Pin};

// ConnectionProperties extension

pub trait LapinAsyncGlobalExecutorExt {
    fn with_async_global_executor(self) -> Self
    where
        Self: Sized;
}

impl LapinAsyncGlobalExecutorExt for ConnectionProperties {
    fn with_async_global_executor(self) -> Self {
        self.with_executor(AsyncGlobalExecutorExecutor)
    }
}

// Executor

#[derive(Debug)]
// this needs to be public until lapin passes the executor itself to reactors
pub struct AsyncGlobalExecutorExecutor;

impl Executor for AsyncGlobalExecutorExecutor {
    fn spawn(&self, f: Pin<Box<dyn Future<Output = ()> + Send>>) -> Result<()> {
        async_global_executor::spawn(f).detach();
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! Logging support for the test framework.
//!
//! https://stackoverflow.com/questions/30177845/how-to-initialize-the-logger-for-integration-tests
//!
//! The test framework runs the tests, possibly simultaneously, and in various orders.  This helper
//! function, which should be called at the beginning of each test, will setup logging for all of
//! the tests.

use env_logger;
use std::sync::{Once, ONCE_INIT};

static INIT: Once = ONCE_INIT;

/// Setup the logging system.  Intended to be called at the beginning of each test.
pub fn setup() {
    INIT.call_once(|| {
        env_logger::init();
    });
}
<commit_msg>sim: remove deprecated usage of sync::ONCE_INIT<commit_after>//! Logging support for the test framework.
//!
//! https://stackoverflow.com/questions/30177845/how-to-initialize-the-logger-for-integration-tests
//!
//! The test framework runs the tests, possibly simultaneously, and in various orders.  This helper
//! function, which should be called at the beginning of each test, will setup logging for all of
//! the tests.

use env_logger;
use std::sync::Once;

static INIT: Once = Once::new();

/// Setup the logging system.  Intended to be called at the beginning of each test.
pub fn setup() {
    INIT.call_once(|| {
        env_logger::init();
    });
}
<|endoftext|>