<commit_before>// xfail-fast

// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Ping-pong is a bounded protocol. This is place where I can
// experiment with what code the compiler should generate for bounded
// protocols.

// This was generated initially by the pipe compiler, but it's been
// modified in hopefully straightforward ways.
#[legacy_records];

mod pingpong {
    use core::pipes::*;
    use core::ptr;

    pub type packets = {
        ping: Packet<ping>,
        pong: Packet<pong>,
    };

    pub fn init() -> (client::ping, server::ping) {
        let buffer = ~Buffer {
            header: BufferHeader(),
            data: {
                ping: mk_packet::<ping>(),
                pong: mk_packet::<pong>()
            }
        };
        do pipes::entangle_buffer(move buffer) |buffer, data| {
            data.ping.set_buffer_(buffer);
            data.pong.set_buffer_(buffer);
            ptr::addr_of(&(data.ping))
        }
    }
    pub enum ping = server::pong;
    pub enum pong = client::ping;
    pub mod client {
        use core::pipes::*;
        use core::ptr;

        pub fn ping(+pipe: ping) -> pong {
            {
                let b = pipe.reuse_buffer();
                let s = SendPacketBuffered(ptr::addr_of(&(b.buffer.data.pong)));
                let c = RecvPacketBuffered(ptr::addr_of(&(b.buffer.data.pong)));
                let message = ::pingpong::ping(move s);
                ::pipes::send(move pipe, move message);
                move c
            }
        }
        pub type ping = pipes::SendPacketBuffered<::pingpong::ping,
                                                  ::pingpong::packets>;
        pub type pong = pipes::RecvPacketBuffered<::pingpong::pong,
                                                  ::pingpong::packets>;
    }
    pub mod server {
        use core::pipes::*;
        use core::ptr;

        pub type ping = pipes::RecvPacketBuffered<::pingpong::ping,
        ::pingpong::packets>;
        pub fn pong(+pipe: pong) -> ping {
            {
                let b = pipe.reuse_buffer();
                let s = SendPacketBuffered(ptr::addr_of(&(b.buffer.data.ping)));
                let c = RecvPacketBuffered(ptr::addr_of(&(b.buffer.data.ping)));
                let message = ::pingpong::pong(move s);
                ::pipes::send(move pipe, move message);
                move c
            }
        }
        pub type pong = pipes::SendPacketBuffered<::pingpong::pong,
                                                  ::pingpong::packets>;
    }
}

mod test {
    use pipes::recv;
    use pingpong::{ping, pong};

    pub fn client(-chan: ::pingpong::client::ping) {
        use pingpong::client;

        let chan = client::ping(move chan); return;
        log(error, "Sent ping");
        let pong(_chan) = recv(move chan);
        log(error, "Received pong");
    }

    pub fn server(-chan: ::pingpong::server::ping) {
        use pingpong::server;

        let ping(chan) = recv(move chan); return;
        log(error, "Received ping");
        let _chan = server::pong(move chan);
        log(error, "Sent pong");
    }
}

fn main() {
    let (client_, server_) = ::pingpong::init();
    let client_ = ~mut Some(move client_);
    let server_ = ~mut Some(move server_);
    do task::spawn |move client_| {
        let mut client__ = None;
        *client_ <-> client__;
        test::client(option::unwrap(move client__));
    };
    do task::spawn |move server_| {
        let mut server_ˊ = None;
        *server_ <-> server_ˊ;
        test::server(option::unwrap(move server_ˊ));
    };
}
<commit_msg>testsuite: Remove call to set_buffer_, use set_buffer<commit_after>// xfail-fast

// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Ping-pong is a bounded protocol. This is place where I can
// experiment with what code the compiler should generate for bounded
// protocols.

// This was generated initially by the pipe compiler, but it's been
// modified in hopefully straightforward ways.
#[legacy_records];

mod pingpong {
    use core::pipes::*;
    use core::ptr;

    pub type packets = {
        ping: Packet<ping>,
        pong: Packet<pong>,
    };

    pub fn init() -> (client::ping, server::ping) {
        let buffer = ~Buffer {
            header: BufferHeader(),
            data: {
                ping: mk_packet::<ping>(),
                pong: mk_packet::<pong>()
            }
        };
        do pipes::entangle_buffer(move buffer) |buffer, data| {
            data.ping.set_buffer(buffer);
            data.pong.set_buffer(buffer);
            ptr::addr_of(&(data.ping))
        }
    }
    pub enum ping = server::pong;
    pub enum pong = client::ping;
    pub mod client {
        use core::pipes::*;
        use core::ptr;

        pub fn ping(+pipe: ping) -> pong {
            {
                let b = pipe.reuse_buffer();
                let s = SendPacketBuffered(ptr::addr_of(&(b.buffer.data.pong)));
                let c = RecvPacketBuffered(ptr::addr_of(&(b.buffer.data.pong)));
                let message = ::pingpong::ping(move s);
                ::pipes::send(move pipe, move message);
                move c
            }
        }
        pub type ping = pipes::SendPacketBuffered<::pingpong::ping,
                                                  ::pingpong::packets>;
        pub type pong = pipes::RecvPacketBuffered<::pingpong::pong,
                                                  ::pingpong::packets>;
    }
    pub mod server {
        use core::pipes::*;
        use core::ptr;

        pub type ping = pipes::RecvPacketBuffered<::pingpong::ping,
        ::pingpong::packets>;
        pub fn pong(+pipe: pong) -> ping {
            {
                let b = pipe.reuse_buffer();
                let s = SendPacketBuffered(ptr::addr_of(&(b.buffer.data.ping)));
                let c = RecvPacketBuffered(ptr::addr_of(&(b.buffer.data.ping)));
                let message = ::pingpong::pong(move s);
                ::pipes::send(move pipe, move message);
                move c
            }
        }
        pub type pong = pipes::SendPacketBuffered<::pingpong::pong,
                                                  ::pingpong::packets>;
    }
}

mod test {
    use pipes::recv;
    use pingpong::{ping, pong};

    pub fn client(-chan: ::pingpong::client::ping) {
        use pingpong::client;

        let chan = client::ping(move chan); return;
        log(error, "Sent ping");
        let pong(_chan) = recv(move chan);
        log(error, "Received pong");
    }

    pub fn server(-chan: ::pingpong::server::ping) {
        use pingpong::server;

        let ping(chan) = recv(move chan); return;
        log(error, "Received ping");
        let _chan = server::pong(move chan);
        log(error, "Sent pong");
    }
}

fn main() {
    let (client_, server_) = ::pingpong::init();
    let client_ = ~mut Some(move client_);
    let server_ = ~mut Some(move server_);
    do task::spawn |move client_| {
        let mut client__ = None;
        *client_ <-> client__;
        test::client(option::unwrap(move client__));
    };
    do task::spawn |move server_| {
        let mut server_ˊ = None;
        *server_ <-> server_ˊ;
        test::server(option::unwrap(move server_ˊ));
    };
}
<|endoftext|>


<commit_before>extern crate svg;

pub mod circle;
pub mod fx32;
pub mod ray2;
pub mod raytrace;
pub mod vec2;

#[cfg(test)]
mod tests {
	use super::circle::Circle;
	use super::fx32::Fx32;
	use super::ray2::Ray2;
	use super::raytrace;
	use super::vec2::Vec2;
	use super::svg::Document;
	use super::svg::node::element::Path;
	use super::svg::node::element::path::Data;

	#[test]
	fn svg () {
		let mut document = Document::new()
			.set("viewBox", (0, 0, 512, 512));

		let scale = 1;
		let scale_fx = Fx32::from_int (scale);

		let obstacle = vec! [
		Circle {
			center: Vec2 {x: Fx32::from_q (256, scale), y: Fx32::from_q (500, scale)},
			radius: Fx32::from_q (50, scale),
		},
		Circle {
			center: Vec2 {x: Fx32::from_q (81, scale), y: Fx32::from_q (512 - 232, scale)},
			radius: Fx32::from_q (40, scale),
		},
		Circle {
			center: Vec2 {x: Fx32::from_q (404, scale), y: Fx32::from_q (512 - 41, scale)},
			radius: Fx32::from_q (60, scale),
		},
		];

		for x in 512 - 110..512 + 110 {
			let mut particle = Ray2 {
				start: Vec2 {
					x: Fx32::from_q (x, scale * 2),
					y: Fx32::from_q (0, scale)
				},
				dir: Vec2 {
					x: Fx32::from_q (0, scale),
					y: Fx32::from_q (100, scale),
				},
			};

			let mut data = Data::new().move_to(((particle.start.x * scale_fx).to_i32 (), (particle.start.y * scale_fx).to_i32 ()));

			for step in 0..10 {
				let trace_result = obstacle.iter ().map(|obstacle: &Circle| raytrace::ray_trace_circle_2 (&particle, obstacle)).fold ( raytrace::Ray2TraceResult::Miss, raytrace::fold_closer_result);

				match trace_result {
					raytrace::Ray2TraceResult::Miss => {
						particle.start = particle.start + particle.dir;
					},
					raytrace::Ray2TraceResult::Hit (t, ccd_pos, normal) => {
						particle.start = ccd_pos;
						particle.dir = particle.dir.reflect (&normal);
						//particle.dir = normal;
					},
				};

				data = data.line_to(((particle.start.x * scale_fx).to_i32 (), (particle.start.y * scale_fx).to_i32 ()));
			}

			//data = data.close ();

			let path = Path::new()
				.set("fill", "none")
				.set("stroke", "black")
				.set("stroke-width", 0.5)
				.set("d", data);

			document = document.add(path);
		}

		super::svg::save("image.svg", &document).unwrap();
	}

	#[test]
	fn vec () {
		let a = Vec2 {x: Fx32::from_int (2), y: Fx32::from_int (3)};
		let b = Vec2 {x: Fx32::from_int (4), y: Fx32::from_int (5)};
		let c = Vec2 {x: Fx32::from_int (6), y: Fx32::from_int (8)};

		assert_eq! (a + b, c, "Vector add");

		assert_eq! (
			Vec2 {x: Fx32::from_int (3), y: Fx32::from_int (4)}.length (),
			Fx32::from_int (5),
			"pythagorean triple");

		assert_eq! (
			Vec2 {x: Fx32::from_int (10), y: Fx32::from_int (1)}.cross (),
			Vec2 {x: Fx32::from_int (-1), y: Fx32::from_int (10)},
			"2D cross product");

		assert_eq! (
			Vec2 {x: Fx32::from_int (5), y: Fx32::from_int (5)}.reflect (&Vec2 {x: Fx32::from_int (0), y: Fx32::from_int (-1)}),
			Vec2 {x: Fx32::from_int (5), y: Fx32::from_int (-5)},
			"reflect");
	}

	#[test]
	fn it_works() {
		let a = Fx32::new (5000);
		let b = Fx32::new (4000);

		assert! (a == a, "eq");
		assert! (b == b, "eq");
		assert! (a != b, "eq");

		assert_eq! ((a + b).x, 9000, "Fx32 add failed");
		assert_eq! ((a - b).x, 1000, "Fx32 sub failed");
		assert_eq! (-a.x, -5000, "Fx32 neg failed");

		//assert_eq! (65536, super::fx32::DENOMINATOR, "Denominator is wrong");
		//assert_eq! (65536, Fx32::from_float (1.0f32).x, "Denominator applied wrong");

		let half = Fx32::from_float (0.5f32);
		let quarter = Fx32::from_float (0.25f32);
		let three_quarters = Fx32::from_float (0.75f32);

		assert_eq! (half + quarter, three_quarters, "from_float / add failed");

		assert! (half * half == quarter, "mul");
		assert! (Fx32::from_float (1.0f32 / 64.0f32) * Fx32::from_float (128.0f32) == Fx32::from_float (2.0f32), "mul");

		let biggest_root = 181.0f32;
		assert_eq! (
			Fx32::from_float (biggest_root) * Fx32::from_float (biggest_root),
			Fx32::from_float (biggest_root * biggest_root),
			"big * big mul");

		assert_eq! (
			Fx32::from_float (1.0f32 / 64.0f32) * Fx32::from_float (1.0f32 / 32.0f32),
			Fx32::from_float (1.0f32 / 32.0f32 / 64.0f32),
			"small * small mul");

		assert_eq! (
			Fx32::mul_precise (Fx32::from_float (1.0f32 / 1024.0f32), Fx32::from_float (1024.0f32)),
			Fx32::from_float (1.0f32),
			"small * big mul");

		/*
		Remember, i32 is signed, so our 16.16 is really 15.16
		plus one sign bit
		If we scale this to meters, we have no more than
		32 km negative and positive, with 1/65 millimeter granularity.
		For my plan, this is fine, if I stay within 10 km each way the
		math should be fine and that's a bigger world than I could create.

		Update: Our 20.12 is actually 1.19.12
		We have no more than 524,288 meters negative and positive, with
		1/4 millimeter granularity.

		I am trying 20.12 not because I need a bigger world but because
		I want more headroom for multiplying large numbers.
		*/
		assert_eq! (
			Fx32::mul_64 (Fx32::from_float (1.0f32 / 2048.0f32), Fx32::from_float (16384.0f32)),
			Fx32::from_float (8.0f32),
			"mul_64");

		assert_eq! (
			Fx32::from_float (1.0f32 / 1024.0f32).mul_small (
			Fx32::from_float (0.5f32)),
			Fx32::from_float (1.0f32 / 2048.0f32),
			"mul_small");

		assert_eq! (
			Fx32::from_float (1.0f32).mul_small (
			Fx32::from_float (1.5f32)),
			Fx32::from_float (1.5f32),
			"mul_small");

		assert_eq! (
			Fx32::from_int (512) / Fx32::from_int (8),
			Fx32::from_int (64),
			"div_64");

		assert_eq! (
			Fx32::from_int (1).square_64 (),
			Fx32::from_int (1),
			"square");
		assert_eq! (
			Fx32::from_int (1).sqrt_64 (),
			Fx32::from_int (1),
			"square_root");

		assert_eq! (
			Fx32::from_int (9).square_64 (),
			Fx32::from_int (81),
			"square");
		assert_eq! (
			Fx32::from_int (9).sqrt_64 (),
			Fx32::from_int (3),
			"sqrt");

		// Biggest POT I can square with 20.12 is 512
		// With 16.16 is 128
		assert_eq! (
			Fx32::from_int (128).square_64 (),
			Fx32::from_int (128 * 128),
			"big square");

		assert_eq! (
			Fx32::from_int (128 * 128).sqrt_64 (),
			Fx32::from_int (128),
			"big sqrt");

		assert_eq! (
			Fx32::from_int (511) * Fx32::from_q (1, 10).to_small (),
			Fx32::from_q (3348583, 65536),
			"Fx32 * Fx32Small");
    }
}
<commit_msg>Tweaking big * small multiplication<commit_after>extern crate svg;

pub mod circle;
pub mod fx32;
pub mod ray2;
pub mod raytrace;
pub mod vec2;

#[cfg(test)]
mod tests {
	use super::circle::Circle;
	use super::fx32::Fx32;
	use super::ray2::Ray2;
	use super::raytrace;
	use super::vec2::Vec2;
	use super::svg::Document;
	use super::svg::node::element::Path;
	use super::svg::node::element::path::Data;

	#[test]
	fn svg () {
		let mut document = Document::new()
			.set("viewBox", (0, 0, 512, 512));

		let scale = 1;
		let scale_fx = Fx32::from_int (scale);

		let obstacle = vec! [
		Circle {
			center: Vec2 {x: Fx32::from_q (256, scale), y: Fx32::from_q (500, scale)},
			radius: Fx32::from_q (50, scale),
		},
		Circle {
			center: Vec2 {x: Fx32::from_q (81, scale), y: Fx32::from_q (512 - 232, scale)},
			radius: Fx32::from_q (40, scale),
		},
		Circle {
			center: Vec2 {x: Fx32::from_q (404, scale), y: Fx32::from_q (512 - 41, scale)},
			radius: Fx32::from_q (60, scale),
		},
		];

		for x in 512 - 110..512 + 110 {
			let mut particle = Ray2 {
				start: Vec2 {
					x: Fx32::from_q (x, scale * 2),
					y: Fx32::from_q (0, scale)
				},
				dir: Vec2 {
					x: Fx32::from_q (0, scale),
					y: Fx32::from_q (100, scale),
				},
			};

			let mut data = Data::new().move_to(((particle.start.x * scale_fx).to_i32 (), (particle.start.y * scale_fx).to_i32 ()));

			for step in 0..10 {
				let trace_result = obstacle.iter ().map(|obstacle: &Circle| raytrace::ray_trace_circle_2 (&particle, obstacle)).fold ( raytrace::Ray2TraceResult::Miss, raytrace::fold_closer_result);

				match trace_result {
					raytrace::Ray2TraceResult::Miss => {
						particle.start = particle.start + particle.dir;
					},
					raytrace::Ray2TraceResult::Hit (t, ccd_pos, normal) => {
						particle.start = ccd_pos;
						particle.dir = particle.dir.reflect (&normal);
						//particle.dir = normal;
					},
				};

				data = data.line_to(((particle.start.x * scale_fx).to_i32 (), (particle.start.y * scale_fx).to_i32 ()));
			}

			//data = data.close ();

			let path = Path::new()
				.set("fill", "none")
				.set("stroke", "black")
				.set("stroke-width", 0.5)
				.set("d", data);

			document = document.add(path);
		}

		super::svg::save("image.svg", &document).unwrap();
	}

	#[test]
	fn vec () {
		let a = Vec2 {x: Fx32::from_int (2), y: Fx32::from_int (3)};
		let b = Vec2 {x: Fx32::from_int (4), y: Fx32::from_int (5)};
		let c = Vec2 {x: Fx32::from_int (6), y: Fx32::from_int (8)};

		assert_eq! (a + b, c, "Vector add");

		assert_eq! (
			Vec2 {x: Fx32::from_int (3), y: Fx32::from_int (4)}.length (),
			Fx32::from_int (5),
			"pythagorean triple");

		assert_eq! (
			Vec2 {x: Fx32::from_int (10), y: Fx32::from_int (1)}.cross (),
			Vec2 {x: Fx32::from_int (-1), y: Fx32::from_int (10)},
			"2D cross product");

		assert_eq! (
			Vec2 {x: Fx32::from_int (5), y: Fx32::from_int (5)}.reflect (&Vec2 {x: Fx32::from_int (0), y: Fx32::from_int (-1)}),
			Vec2 {x: Fx32::from_int (5), y: Fx32::from_int (-5)},
			"reflect");
	}

	#[test]
	fn it_works() {
		let a = Fx32::new (5000);
		let b = Fx32::new (4000);

		assert! (a == a, "eq");
		assert! (b == b, "eq");
		assert! (a != b, "eq");

		assert_eq! ((a + b).x, 9000, "Fx32 add failed");
		assert_eq! ((a - b).x, 1000, "Fx32 sub failed");
		assert_eq! (-a.x, -5000, "Fx32 neg failed");

		//assert_eq! (65536, super::fx32::DENOMINATOR, "Denominator is wrong");
		//assert_eq! (65536, Fx32::from_float (1.0f32).x, "Denominator applied wrong");

		let half = Fx32::from_float (0.5f32);
		let quarter = Fx32::from_float (0.25f32);
		let three_quarters = Fx32::from_float (0.75f32);

		assert_eq! (half + quarter, three_quarters, "from_float / add failed");

		assert! (half * half == quarter, "mul");
		assert! (Fx32::from_float (1.0f32 / 64.0f32) * Fx32::from_float (128.0f32) == Fx32::from_float (2.0f32), "mul");

		let biggest_root = 181.0f32;
		assert_eq! (
			Fx32::from_float (biggest_root) * Fx32::from_float (biggest_root),
			Fx32::from_float (biggest_root * biggest_root),
			"big * big mul");

		assert_eq! (
			Fx32::from_float (1.0f32 / 64.0f32) * Fx32::from_float (1.0f32 / 32.0f32),
			Fx32::from_float (1.0f32 / 32.0f32 / 64.0f32),
			"small * small mul");

		assert_eq! (
			Fx32::mul_precise (Fx32::from_float (1.0f32 / 1024.0f32), Fx32::from_float (1024.0f32)),
			Fx32::from_float (1.0f32),
			"small * big mul");

		/*
		Remember, i32 is signed, so our 16.16 is really 15.16
		plus one sign bit
		If we scale this to meters, we have no more than
		32 km negative and positive, with 1/65 millimeter granularity.
		For my plan, this is fine, if I stay within 10 km each way the
		math should be fine and that's a bigger world than I could create.

		Update: Our 20.12 is actually 1.19.12
		We have no more than 524,288 meters negative and positive, with
		1/4 millimeter granularity.

		I am trying 20.12 not because I need a bigger world but because
		I want more headroom for multiplying large numbers.
		*/
		assert_eq! (
			Fx32::mul_64 (Fx32::from_float (1.0f32 / 2048.0f32), Fx32::from_float (16384.0f32)),
			Fx32::from_float (8.0f32),
			"mul_64");

		assert_eq! (
			Fx32::from_float (1.0f32 / 1024.0f32).mul_small (
			Fx32::from_float (0.5f32)),
			Fx32::from_float (1.0f32 / 2048.0f32),
			"mul_small");

		assert_eq! (
			Fx32::from_float (1.0f32).mul_small (
			Fx32::from_float (1.5f32)),
			Fx32::from_float (1.5f32),
			"mul_small");

		assert_eq! (
			Fx32::from_int (512) / Fx32::from_int (8),
			Fx32::from_int (64),
			"div_64");

		assert_eq! (
			Fx32::from_int (1).square_64 (),
			Fx32::from_int (1),
			"square");
		assert_eq! (
			Fx32::from_int (1).sqrt_64 (),
			Fx32::from_int (1),
			"square_root");

		assert_eq! (
			Fx32::from_int (9).square_64 (),
			Fx32::from_int (81),
			"square");
		assert_eq! (
			Fx32::from_int (9).sqrt_64 (),
			Fx32::from_int (3),
			"sqrt");

		// Biggest POT I can square with 20.12 is 512
		// With 16.16 is 128
		assert_eq! (
			Fx32::from_int (128).square_64 (),
			Fx32::from_int (128 * 128),
			"big square");

		assert_eq! (
			Fx32::from_int (128 * 128).sqrt_64 (),
			Fx32::from_int (128),
			"big sqrt");

		assert_eq! (
			Fx32::from_int (511) * Fx32::from_q (1, 10).to_small (),
			Fx32::from_q (3348583, 65536),
			"Fx32 * Fx32Small");

		assert_eq! (
			Fx32::from_int (16383) * Fx32::from_q (1, 10).to_small (),
			Fx32::from_q (107357799, 65536),
			"Fx32 * Fx32Small");
    }
}
<|endoftext|>


<commit_before>use hyper;
use iron::prelude::{IronError, IronResult, Request, Response};
use iron::status;
use iron::typemap::Key;
use persistent;
use persistent::State;
use postgres;
use postgres::error::SqlState;
use potboiler_common::{db, url_from_body};
use potboiler_common::string_error::StringError;

use r2d2;
use r2d2_postgres;
use serde_json;
use serde_types::Log;
use std::collections::HashMap;
use std::collections::HashSet;
use std::io::Read;
use std::iter::FromIterator;

use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use url::Url;
use uuid::Uuid;
pub type PostgresConnection = r2d2::PooledConnection<r2d2_postgres::PostgresConnectionManager>;
pub type PostgresPool = r2d2::Pool<r2d2_postgres::PostgresConnectionManager>;
use clock;
use hybrid_clocks::{Clock, Timestamp, Wall, WallT};
use std::sync::RwLock;
pub type SyncClock = Arc<RwLock<Clock<Wall>>>;

#[derive(Copy, Clone)]
pub struct Nodes;

pub struct NodeInfo {
}

pub struct NodeList {
    nodes: HashMap<String, NodeInfo>,
    pool: PostgresPool,
    clock: SyncClock,
}

impl Key for Nodes {
    type Value = NodeList;
}

fn parse_json_from_request(raw_result: Result<hyper::client::Response, hyper::Error>)
                           -> Result<serde_json::value::Value, StringError> {
    let mut res = match raw_result {
        Ok(val) => val,
        Err(val) => {
            return Err(StringError(format!("Failed to get logs: {:?}", val)));
        }
    };
    let body_string = {
        let mut body = String::new();
        res.read_to_string(&mut body).expect("could read from body");
        body
    };
    return match serde_json::de::from_str(&body_string) {
        Ok(val) => {
            debug!("Good data back {:?}", val);
            Ok(val)
        }
        Err(_) => Err(StringError(format!("Got crappy data back: {:?}", body_string))),
    };
}

fn parse_object_from_request(raw_result: Result<hyper::client::Response, hyper::Error>)
                             -> Result<serde_json::value::Map<String, serde_json::Value>, StringError> {
    let json: serde_json::Value = match parse_json_from_request(raw_result) {
        Ok(val) => val,
        Err(err) => return Err(err),
    };
    return match json.as_object() {
        Some(val) => Ok(val.clone()),
        None => Err(StringError(format!("Info isn't a map: {:?}", json))),
    };
}

fn check_host_once(host_url: &String, conn: &PostgresConnection, clock_state: SyncClock) {
    let client = hyper::client::Client::new();
    let check_url = format!("{}/log", &host_url);
    info!("Checking {} ({})", host_url, check_url);
    let raw_result = client.get(&check_url).send();
    let kv = match parse_object_from_request(raw_result) {
        Ok(val) => val,
        Err(err) => {
            warn!("Error while getting from {:?}: {:?}", host_url, err);
            return;
        }
    };
    let stmt = conn.prepare("SELECT 1 from log where id=$1")
        .expect("prepare failure");
    for (key, value) in kv.iter() {
        let value_uuid = match Uuid::parse_str(value.as_str().unwrap()) {
            Ok(val) => val,
            Err(_) => {
                warn!("Value {} isn't a UUID!", value);
                continue;
            }
        };
        let key_uuid = match Uuid::parse_str(key) {
            Ok(val) => val,
            Err(_) => {
                warn!("Key {} isn't a UUID!", key);
                continue;
            }
        };
        let single_item = stmt.query(&[&value_uuid]).expect("bad single query");
        if !single_item.is_empty() {
            debug!("Already have {} locally", value_uuid);
            continue;
        }

        let first_item = conn.query("SELECT id from log WHERE prev is null and owner=$1 limit 1",
                   &[&key_uuid])
            .expect("bad first query");
        let start_uuid = if first_item.is_empty() {
            let first_url = format!("{}/log/first", &host_url);
            debug!("Get first from {:?}", host_url);
            let res = client.get(&first_url).send();
            let first_entry = match parse_object_from_request(res) {
                Ok(val) => val,
                Err(err) => {
                    warn!("Error while getting first item from {:?}: {:?}",
                          host_url,
                          err);
                    return;
                }
            };
            info!("First entry: {:?}", first_entry);
            first_entry.get(key).unwrap().clone()
        } else {
            info!("Already have an entry from the list with server id {:?}",
                  key);
            let last_items = conn.query("SELECT id from log WHERE next is null and owner=$1 limit 1",
                       &[&key_uuid])
                .expect("bad last query");
            if last_items.is_empty() {
                warn!("Can't find end entry for server id {:?}", key);
                return;
            }
            let last_item = last_items.get(0);
            let last_item_id: Uuid = last_item.get("id");
            info!("Last item: {:?}", last_item_id);
            let last_url = format!("{}/log/{}", &host_url, last_item_id);
            debug!("Get last from {:?}", host_url);
            let res = client.get(&last_url).send();
            let last_entry = match parse_object_from_request(res) {
                Ok(val) => val,
                Err(err) => {
                    warn!("Error while getting first item from {:?}: {:?}",
                          host_url,
                          err);
                    return;
                }
            };
            info!("Last entry: {:?}", last_entry);
            last_entry.get("next").unwrap().clone()
        };
        let mut current_uuid = start_uuid;
        loop {
            let real_uuid = {
                let str_uuid = current_uuid.as_str();
                String::from(str_uuid.expect("UUID unwrap"))
            };
            let current_url = format!("{}/log/{}", &host_url, real_uuid);
            debug!("Get {} from {}", real_uuid, host_url);
            let res = client.get(&current_url).send();
            let current_entry = match parse_object_from_request(res) {
                Ok(val) => val,
                Err(err) => {
                    warn!("Error while getting first item from {:?}: {:?}",
                          host_url,
                          err);
                    return;
                }
            };
            let next = current_entry.get("next").expect("has next key");
            let timestamp: Timestamp<WallT> =
                serde_json::value::from_value(current_entry.get("when").expect(" has when key").clone())
                    .expect("is byte string");
            clock::observe_timestamp(&clock_state, timestamp);
            let log = Log {
                id: Uuid::parse_str(&real_uuid).unwrap(),
                owner: key_uuid,
                next: get_uuid_from_map(&current_entry, "next"),
                prev: get_uuid_from_map(&current_entry, "prev"),
                data: current_entry.get("data").unwrap().clone(),
                when: clock::get_timestamp_from_state(&clock_state),
            };
            insert_log(conn, &log);
            if next.is_null() {
                break;
            }
            current_uuid = next.clone();
        }
    }
}

fn get_uuid_from_map(map: &serde_json::value::Map<String, serde_json::Value>, key: &str) -> Option<Uuid> {
    let value = map.get(key).unwrap();
    if value.is_null() {
        None
    } else {
        Some(Uuid::parse_str(value.as_str().unwrap()).unwrap())
    }
}

pub fn insert_log(conn: &PostgresConnection, log: &Log) {
    debug!("Inserting {:?}", log);
    if log.prev.is_some() {
        conn.execute("UPDATE log set next = $1 where owner = $2 and id = $3",
                     &[&log.id, &log.owner, &log.prev])
            .expect("update worked");
    }
    let raw_timestamp = clock::get_raw_timestamp(&log.when);
    conn.execute("INSERT INTO log (id, owner, data, prev, hlc_tstamp) VALUES ($1, $2, $3, $4, $5)",
                 &[&log.id, &log.owner, &log.data, &log.prev, &raw_timestamp])
        .expect("insert worked");
}

fn check_new_nodes(host_url: &String, conn: &PostgresConnection) {
    let client = hyper::client::Client::new();
    let check_url = format!("{}/nodes", &host_url);
    info!("Checking {} ({})", host_url, check_url);
    let raw_result = client.get(&check_url).send();
    let nodes = match parse_json_from_request(raw_result) {
        Ok(val) => val,
        Err(err) => {
            warn!("Error while getting from {:?}: {:?}", host_url, err);
            return;
        }
    };
    let new_nodes: HashSet<String> =
        HashSet::from_iter(nodes.as_array().unwrap().iter().map(|x| String::from(x.as_str().unwrap())));
    let existing_nodes = conn.query("SELECT url from nodes", &[])
        .expect("prepare failure");
    let existing_nodes_set: HashSet<String> = HashSet::from_iter(existing_nodes.iter()
        .map(|x| x.get::<&str, String>("url")));
    let extra_nodes = new_nodes.difference(&existing_nodes_set).collect::<Vec<&String>>();
    debug!("existing nodes: {:?}; remote nodes: {:?}",
           existing_nodes_set,
           new_nodes);
    info!("extra nodes: {:?}", extra_nodes);
}

fn check_host(host_url: String, conn: PostgresConnection, clock_state: SyncClock) {
    let sleep_time = Duration::from_secs(5);
    loop {
        check_host_once(&host_url, &conn, clock_state.clone());
        check_new_nodes(&host_url, &conn);
        thread::sleep(sleep_time);
    }
}

pub fn initial_nodes(pool: PostgresPool, clock_state: SyncClock) -> NodeList {
    let conn = pool.get().unwrap();
    let mut nodes = HashMap::new();
    let stmt = conn.prepare("select url from nodes").expect("prepare failure");
    for row in &stmt.query(&[]).expect("nodes select works") {
        let url: String = row.get("url");
        nodes.insert(url.clone(), NodeInfo {});
        let conn = pool.get().unwrap();
        let cs = clock_state.clone();
        thread::spawn(move || check_host(url.clone(), conn, cs));
    }
    return NodeList {
        nodes: nodes,
        pool: pool,
        clock: clock_state,
    };
}

fn get_nodes_list(req: &Request) -> Vec<String> {
    let state_ref = req.extensions.get::<State<Nodes>>().unwrap().read().unwrap();
    let nodelist = state_ref.deref();
    let mut vec = Vec::with_capacity(nodelist.nodes.len());
    for key in nodelist.nodes.keys() {
        vec.push(key.clone());
    }
    return vec;
}

fn insert_node(req: &mut Request, to_notify: &String) {
    let (conn, clock_state) = {
        let mut nodelist = req.extensions
            .get_mut::<State<Nodes>>()
            .unwrap()
            .write()
            .unwrap();
        let nodelist_dm = nodelist.deref_mut();
        nodelist_dm.nodes.insert(to_notify.clone(), NodeInfo {});
        (nodelist_dm.pool.get().unwrap(), nodelist_dm.clock.clone())
    };

    let url = to_notify.clone();
    thread::spawn(move || check_host(url, conn, clock_state));
}

pub fn notify_everyone(req: &Request, log_arc: Arc<Log>) {
    let nodes = get_nodes_list(req);
    for node in nodes {
        let local_log = log_arc.clone();
        thread::spawn(move || {
            let client = hyper::client::Client::new();
            let notify_url = format!("{}/log/other", node);
            debug!("Notifying (node) {}", notify_url);
            let res = client.post(&notify_url)
                .body(&serde_json::ser::to_string(&local_log).unwrap())
                .send();
            match res {
                Ok(val) => {
                    if val.status != hyper::status::StatusCode::Ok {
                        warn!("Failed to notify {:?}: {:?}", &node, val.status);
                    }
                }
                Err(val) => {
                    warn!("Failed to notify {:?}: {:?}", &node, val);
                }
            };
        });
    }
}

pub fn node_add(req: &mut Request) -> IronResult<Response> {
    let conn = get_pg_connection!(&req);
    let url = url_from_body(req).unwrap().unwrap();
    debug!("Registering node {}", url);
    match Url::parse(&url) {
        Err(err) => Err(IronError::new(err, (status::BadRequest, "Bad URL"))),
        Ok(_) => {
            match conn.execute("INSERT INTO nodes (url) VALUES ($1)", &[&url]) {
                Ok(_) => {
                    insert_node(req, &url);
                    Ok(Response::with((status::NoContent)))
                }
                Err(err) => {
                    if let postgres::error::Error::Db(dberr) = err {
                        match dberr.code {
                            SqlState::UniqueViolation => Ok(Response::with((status::NoContent))),
                            _ => Err(IronError::new(dberr, (status::BadRequest, "Some other error"))),
                        }
                    } else {
                        Err(IronError::new(err, (status::BadRequest, "Some other error")))
                    }
                }
            }
        }
    }
}

pub fn node_remove(req: &mut Request) -> IronResult<Response> {
    let conn = get_pg_connection!(&req);
    conn.execute("DELETE from nodes where url = $1",
                 &[&url_from_body(req).unwrap().unwrap()])
        .expect("delete worked");
    Ok(Response::with((status::NoContent)))
}

pub fn node_list(req: &mut Request) -> IronResult<Response> {
    let conn = get_pg_connection!(&req);
    let stmt = conn.prepare("select url from nodes").expect("prepare failure");
    let mut nodes = Vec::new();
    for row in &stmt.query(&[]).expect("last select works") {
        let url: String = row.get("url");
        nodes.push(url);
    }
    Ok(Response::with((status::Ok, serde_json::ser::to_string(&nodes).unwrap())))
}
<commit_msg>Create new node entries when we find items on other hosts<commit_after>use hyper;
use iron::prelude::{IronError, IronResult, Request, Response};
use iron::status;
use iron::typemap::Key;
use persistent;
use persistent::State;
use postgres;
use postgres::error::SqlState;
use potboiler_common::{db, url_from_body};
use potboiler_common::string_error::StringError;

use r2d2;
use r2d2_postgres;
use serde_json;
use serde_types::Log;
use std::collections::HashMap;
use std::collections::HashSet;
use std::io::Read;
use std::iter::FromIterator;

use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use url::Url;
use uuid::Uuid;
pub type PostgresConnection = r2d2::PooledConnection<r2d2_postgres::PostgresConnectionManager>;
pub type PostgresPool = r2d2::Pool<r2d2_postgres::PostgresConnectionManager>;
use clock;
use hybrid_clocks::{Clock, Timestamp, Wall, WallT};
use std::sync::RwLock;
pub type SyncClock = Arc<RwLock<Clock<Wall>>>;
pub type LockedNode = Arc<RwLock<HashMap<String, NodeInfo>>>;

#[derive(Copy, Clone)]
pub struct Nodes;

pub struct NodeInfo {
}

#[derive(Clone)]
pub struct NodeList {
    nodes: LockedNode,
    pool: PostgresPool,
    clock: SyncClock,
}

impl Key for Nodes {
    type Value = NodeList;
}

fn parse_json_from_request(raw_result: Result<hyper::client::Response, hyper::Error>)
                           -> Result<serde_json::value::Value, StringError> {
    let mut res = match raw_result {
        Ok(val) => val,
        Err(val) => {
            return Err(StringError(format!("Failed to get logs: {:?}", val)));
        }
    };
    let body_string = {
        let mut body = String::new();
        res.read_to_string(&mut body).expect("could read from body");
        body
    };
    return match serde_json::de::from_str(&body_string) {
        Ok(val) => {
            debug!("Good data back {:?}", val);
            Ok(val)
        }
        Err(_) => Err(StringError(format!("Got crappy data back: {:?}", body_string))),
    };
}

fn parse_object_from_request(raw_result: Result<hyper::client::Response, hyper::Error>)
                             -> Result<serde_json::value::Map<String, serde_json::Value>, StringError> {
    let json: serde_json::Value = match parse_json_from_request(raw_result) {
        Ok(val) => val,
        Err(err) => return Err(err),
    };
    return match json.as_object() {
        Some(val) => Ok(val.clone()),
        None => Err(StringError(format!("Info isn't a map: {:?}", json))),
    };
}

fn check_host_once(host_url: &String, conn: &PostgresConnection, clock_state: SyncClock) {
    let client = hyper::client::Client::new();
    let check_url = format!("{}/log", &host_url);
    info!("Checking {} ({})", host_url, check_url);
    let raw_result = client.get(&check_url).send();
    let kv = match parse_object_from_request(raw_result) {
        Ok(val) => val,
        Err(err) => {
            warn!("Error while getting from {:?}: {:?}", host_url, err);
            return;
        }
    };
    let stmt = conn.prepare("SELECT 1 from log where id=$1")
        .expect("prepare failure");
    for (key, value) in kv.iter() {
        let value_uuid = match Uuid::parse_str(value.as_str().unwrap()) {
            Ok(val) => val,
            Err(_) => {
                warn!("Value {} isn't a UUID!", value);
                continue;
            }
        };
        let key_uuid = match Uuid::parse_str(key) {
            Ok(val) => val,
            Err(_) => {
                warn!("Key {} isn't a UUID!", key);
                continue;
            }
        };
        let single_item = stmt.query(&[&value_uuid]).expect("bad single query");
        if !single_item.is_empty() {
            debug!("Already have {} locally", value_uuid);
            continue;
        }

        let first_item = conn.query("SELECT id from log WHERE prev is null and owner=$1 limit 1",
                   &[&key_uuid])
            .expect("bad first query");
        let start_uuid = if first_item.is_empty() {
            let first_url = format!("{}/log/first", &host_url);
            debug!("Get first from {:?}", host_url);
            let res = client.get(&first_url).send();
            let first_entry = match parse_object_from_request(res) {
                Ok(val) => val,
                Err(err) => {
                    warn!("Error while getting first item from {:?}: {:?}",
                          host_url,
                          err);
                    return;
                }
            };
            info!("First entry: {:?}", first_entry);
            first_entry.get(key).unwrap().clone()
        } else {
            info!("Already have an entry from the list with server id {:?}",
                  key);
            let last_items = conn.query("SELECT id from log WHERE next is null and owner=$1 limit 1",
                       &[&key_uuid])
                .expect("bad last query");
            if last_items.is_empty() {
                warn!("Can't find end entry for server id {:?}", key);
                return;
            }
            let last_item = last_items.get(0);
            let last_item_id: Uuid = last_item.get("id");
            info!("Last item: {:?}", last_item_id);
            let last_url = format!("{}/log/{}", &host_url, last_item_id);
            debug!("Get last from {:?}", host_url);
            let res = client.get(&last_url).send();
            let last_entry = match parse_object_from_request(res) {
                Ok(val) => val,
                Err(err) => {
                    warn!("Error while getting first item from {:?}: {:?}",
                          host_url,
                          err);
                    return;
                }
            };
            info!("Last entry: {:?}", last_entry);
            last_entry.get("next").unwrap().clone()
        };
        let mut current_uuid = start_uuid;
        loop {
            let real_uuid = {
                let str_uuid = current_uuid.as_str();
                String::from(str_uuid.expect("UUID unwrap"))
            };
            let current_url = format!("{}/log/{}", &host_url, real_uuid);
            debug!("Get {} from {}", real_uuid, host_url);
            let res = client.get(&current_url).send();
            let current_entry = match parse_object_from_request(res) {
                Ok(val) => val,
                Err(err) => {
                    warn!("Error while getting first item from {:?}: {:?}",
                          host_url,
                          err);
                    return;
                }
            };
            let next = current_entry.get("next").expect("has next key");
            let timestamp: Timestamp<WallT> =
                serde_json::value::from_value(current_entry.get("when").expect(" has when key").clone())
                    .expect("is byte string");
            clock::observe_timestamp(&clock_state, timestamp);
            let log = Log {
                id: Uuid::parse_str(&real_uuid).unwrap(),
                owner: key_uuid,
                next: get_uuid_from_map(&current_entry, "next"),
                prev: get_uuid_from_map(&current_entry, "prev"),
                data: current_entry.get("data").unwrap().clone(),
                when: clock::get_timestamp_from_state(&clock_state),
            };
            insert_log(conn, &log);
            if next.is_null() {
                break;
            }
            current_uuid = next.clone();
        }
    }
}

fn get_uuid_from_map(map: &serde_json::value::Map<String, serde_json::Value>, key: &str) -> Option<Uuid> {
    let value = map.get(key).unwrap();
    if value.is_null() {
        None
    } else {
        Some(Uuid::parse_str(value.as_str().unwrap()).unwrap())
    }
}

pub fn insert_log(conn: &PostgresConnection, log: &Log) {
    debug!("Inserting {:?}", log);
    if log.prev.is_some() {
        conn.execute("UPDATE log set next = $1 where owner = $2 and id = $3",
                     &[&log.id, &log.owner, &log.prev])
            .expect("update worked");
    }
    let raw_timestamp = clock::get_raw_timestamp(&log.when);
    conn.execute("INSERT INTO log (id, owner, data, prev, hlc_tstamp) VALUES ($1, $2, $3, $4, $5)",
                 &[&log.id, &log.owner, &log.data, &log.prev, &raw_timestamp])
        .expect("insert worked");
}

fn check_new_nodes(host_url: &String, conn: &PostgresConnection, nodelist: NodeList) {
    let client = hyper::client::Client::new();
    let check_url = format!("{}/nodes", &host_url);
    info!("Checking {} ({})", host_url, check_url);
    let raw_result = client.get(&check_url).send();
    let remote_nodes = match parse_json_from_request(raw_result) {
        Ok(val) => val,
        Err(err) => {
            warn!("Error while getting from {:?}: {:?}", host_url, err);
            return;
        }
    };
    let remote_node_set: HashSet<String> = HashSet::from_iter(remote_nodes.as_array()
        .unwrap()
        .iter()
        .map(|x| String::from(x.as_str().unwrap())));
    let existing_nodes = conn.query("SELECT url from nodes", &[])
        .expect("prepare failure");
    let existing_nodes_set: HashSet<String> = HashSet::from_iter(existing_nodes.iter()
        .map(|x| x.get::<&str, String>("url")));
    let extra_nodes = remote_node_set.difference(&existing_nodes_set)
        .map(|x| x.clone())
        .collect::<Vec<String>>();
    debug!("existing nodes: {:?}; remote nodes: {:?}",
           existing_nodes_set,
           remote_node_set);
    info!("extra nodes: {:?}", extra_nodes);
    let mut nodes = nodelist.nodes.write().unwrap();
    for extra in extra_nodes {
        nodes.insert(extra.clone(), NodeInfo {});
        let nodeslist = nodelist.clone();
        thread::spawn(move || check_host(extra.clone(), nodeslist));
    }
}

fn check_host(host_url: String, nodelist: NodeList) {
    let sleep_time = Duration::from_secs(5);
    let conn = nodelist.pool.get().unwrap();
    loop {
        check_host_once(&host_url, &conn, nodelist.clock.clone());
        check_new_nodes(&host_url, &conn, nodelist.clone());
        thread::sleep(sleep_time);
    }
}

pub fn initial_nodes(pool: PostgresPool, clock_state: SyncClock) -> NodeList {
    let conn = pool.get().unwrap();
    let stmt = conn.prepare("select url from nodes").expect("prepare failure");
    let locked_nodes = Arc::new(RwLock::new(HashMap::new()));
    let mut nodes = locked_nodes.write().unwrap();
    for row in &stmt.query(&[]).expect("nodes select works") {
        let url: String = row.get("url");
        nodes.insert(url.clone(), NodeInfo {});
        let nodeslist = NodeList {
            nodes: locked_nodes.clone(),
            pool: pool.clone(),
            clock: clock_state.clone(),
        };
        thread::spawn(move || check_host(url.clone(), nodeslist));
    }
    return NodeList {
        nodes: locked_nodes.clone(),
        pool: pool,
        clock: clock_state,
    };
}

fn get_nodes_list(req: &Request) -> Vec<String> {
    let state_ref = req.extensions.get::<State<Nodes>>().unwrap().read().unwrap();
    let nodes = state_ref.deref().nodes.read().unwrap();
    let mut vec = Vec::with_capacity(nodes.len());
    for key in nodes.keys() {
        vec.push(key.clone());
    }
    return vec;
}

fn insert_node(req: &mut Request, to_notify: &String) {
    let nodelist = {
        let mut nodelist = req.extensions
            .get_mut::<State<Nodes>>()
            .unwrap()
            .write()
            .unwrap();
        let nodelist_dm = nodelist.deref_mut();
        nodelist_dm.nodes.write().unwrap().insert(to_notify.clone(), NodeInfo {});
        NodeList {
            nodes: nodelist_dm.nodes.clone(),
            pool: nodelist_dm.pool.clone(),
            clock: nodelist_dm.clock.clone(),
        }
    };

    let url = to_notify.clone();
    thread::spawn(move || check_host(url, nodelist));
}

pub fn notify_everyone(req: &Request, log_arc: Arc<Log>) {
    let nodes = get_nodes_list(req);
    for node in nodes {
        let local_log = log_arc.clone();
        thread::spawn(move || {
            let client = hyper::client::Client::new();
            let notify_url = format!("{}/log/other", node);
            debug!("Notifying (node) {}", notify_url);
            let res = client.post(&notify_url)
                .body(&serde_json::ser::to_string(&local_log).unwrap())
                .send();
            match res {
                Ok(val) => {
                    if val.status != hyper::status::StatusCode::Ok {
                        warn!("Failed to notify {:?}: {:?}", &node, val.status);
                    }
                }
                Err(val) => {
                    warn!("Failed to notify {:?}: {:?}", &node, val);
                }
            };
        });
    }
}

pub fn node_add(req: &mut Request) -> IronResult<Response> {
    let conn = get_pg_connection!(&req);
    let url = url_from_body(req).unwrap().unwrap();
    debug!("Registering node {}", url);
    match Url::parse(&url) {
        Err(err) => Err(IronError::new(err, (status::BadRequest, "Bad URL"))),
        Ok(_) => {
            match conn.execute("INSERT INTO nodes (url) VALUES ($1)", &[&url]) {
                Ok(_) => {
                    insert_node(req, &url);
                    Ok(Response::with((status::NoContent)))
                }
                Err(err) => {
                    if let postgres::error::Error::Db(dberr) = err {
                        match dberr.code {
                            SqlState::UniqueViolation => Ok(Response::with((status::NoContent))),
                            _ => Err(IronError::new(dberr, (status::BadRequest, "Some other error"))),
                        }
                    } else {
                        Err(IronError::new(err, (status::BadRequest, "Some other error")))
                    }
                }
            }
        }
    }
}

pub fn node_remove(req: &mut Request) -> IronResult<Response> {
    let conn = get_pg_connection!(&req);
    conn.execute("DELETE from nodes where url = $1",
                 &[&url_from_body(req).unwrap().unwrap()])
        .expect("delete worked");
    Ok(Response::with((status::NoContent)))
}

pub fn node_list(req: &mut Request) -> IronResult<Response> {
    let conn = get_pg_connection!(&req);
    let stmt = conn.prepare("select url from nodes").expect("prepare failure");
    let mut nodes = Vec::new();
    for row in &stmt.query(&[]).expect("last select works") {
        let url: String = row.get("url");
        nodes.push(url);
    }
    Ok(Response::with((status::Ok, serde_json::ser::to_string(&nodes).unwrap())))
}
<|endoftext|>


<commit_before>use collections::VecDeque;
// Temporary hack until libredox get hashmaps
use redox::*;

#[derive(Clone, PartialEq, Copy, Hash)]
pub enum InsertMode {
    Append,
    Insert,
    Replace,
}

#[derive(Clone, PartialEq, Copy, Hash)]
pub struct InsertOptions {
    mode: InsertMode,
}

/// A mode
#[derive(Clone, PartialEq, Copy, Hash)]
pub enum Mode {
    /// A primitive mode (no repeat, no delimiters, no preprocessing)
    Primitive(PrimitiveMode),
    /// Command mode
    Command(CommandMode),
}

#[derive(Clone, PartialEq, Copy, Hash)]
/// A command mode
pub enum CommandMode {
//    Visual(VisualOptions),
    /// Normal mode
    Normal,
}

#[derive(Clone, PartialEq, Copy, Hash)]
/// A primitive mode
pub enum PrimitiveMode {
    /// Insert mode
    Insert(InsertOptions),
}

#[derive(Clone, PartialEq, Hash)]
/// The state of the editor
pub struct Editor {
    /// The current cursor
    pub current_cursor: u8,
    /// The cursors
    pub cursors: Vec<Cursor>,
    /// The text (document)
    pub text: VecDeque<VecDeque<char>>,
    /// The x coordinate of the scroll
    pub scroll_x: u32,
    /// The y coordinate of the scroll
    pub scroll_y: u32,
    /// Number of repeation entered
    pub n: u16,
}

impl Editor {

    /// Execute a instruction n times
    pub fn exec(&mut self, n: u16, cmd: char) {

        match cmd {

        }
    }

    /// Feed a char to the editor (as input)
    fn feed(&mut self, c: char) {
        match self.cursors[self.current_cursor as usize].mode {
            Mode::Primitive(_) => {
                self.exec(0, c);
            },
            Mode::Command(_) => {
                self.n = match c {
                    '0' if self.n != 0 => self.n * 10,
                    '1'           => self.n * 10 + 1,
                    '2'           => self.n * 10 + 2,
                    '3'           => self.n * 10 + 3,
                    '4'           => self.n * 10 + 4,
                    '5'           => self.n * 10 + 5,
                    '6'           => self.n * 10 + 6,
                    '7'           => self.n * 10 + 7,
                    '8'           => self.n * 10 + 8,
                    '9'           => self.n * 10 + 9,
                    _             => {
                        self.exec(if self.n == 0 { 1 } else { self.n }, c);
                        self.n
                    }
                }

            }
        }
    }

    /// Insert text
    fn insert(&mut self, c: char) {

    }

    /// Create new default state editor
    fn new() -> Editor {
        Editor {
            current_cursor: 0,
            cursors: Vec::new(),
            text: VecDeque::new(),
            scroll_x: 0,
            scroll_y: 0,
            n: 0,
        }
    }
}

/// A command char
#[derive(Clone, Copy, Hash, PartialEq)]
pub enum CommandChar {
    /// A char
    Char(char),
    /// A wildcard
    Wildcard,
}

#[derive(Clone, PartialEq, Hash)]
/// A cursor
pub struct Cursor {
    /// The x coordinate of the cursor
    pub x: u32,
    /// The y coordinate of the cursor
    pub y: u32,
    /// The mode of the cursor
    pub mode: Mode,
    /// The history of the cursor
    pub history: Vec<Unit>,

<commit_msg>More refactoring<commit_after>use collections::VecDeque;
// Temporary hack until libredox get hashmaps
use redox::*;

#[derive(Clone)]
/// An instruction
pub Inst(i16, char)

#[derive(Clone, PartialEq, Copy, Hash)]
pub enum InsertMode {
    Append,
    Insert,
    Replace,
}

#[derive(Clone, PartialEq, Copy, Hash)]
pub struct InsertOptions {
    mode: InsertMode,
}

/// A mode
#[derive(Clone, PartialEq, Copy, Hash)]
pub enum Mode {
    /// A primitive mode (no repeat, no delimiters, no preprocessing)
    Primitive(PrimitiveMode),
    /// Command mode
    Command(CommandMode),
}

#[derive(Clone, PartialEq, Copy, Hash)]
/// A command mode
pub enum CommandMode {
//    Visual(VisualOptions),
    /// Normal mode
    Normal,
}

#[derive(Clone, PartialEq, Copy, Hash)]
/// A primitive mode
pub enum PrimitiveMode {
    /// Insert mode
    Insert(InsertOptions),
}

#[derive(Clone, PartialEq, Hash)]
/// The state of the editor
pub struct Editor<I: Iterator<Item = char>> {
    /// The current cursor
    pub current_cursor: u8,
    /// The cursors
    pub cursors: Vec<Cursor>,
    /// The text (document)
    pub text: VecDeque<VecDeque<char>>,
    /// The x coordinate of the scroll
    pub scroll_x: u32,
    /// The y coordinate of the scroll
    pub scroll_y: u32,
    /// Number of repeation entered
    pub n: u16,
    /// The input iterator
    pub iter: I,
}

impl Editor {

    /// Execute a instruction
    pub fn exec(&mut self, inst: Inst) {

    }

    /// Feed a char to the editor (as input)
    pub fn feed(&mut self, c: char) {
        match self.cursors[self.current_cursor as usize].mode {
            Mode::Primitive(_) => {
                self.exec(Inst(0, c));
            },
            Mode::Command(_) => {
                self.n = match c {
                    '0' if self.n != 0 => self.n * 10,
                    '1'                => self.n * 10 + 1,
                    '2'                => self.n * 10 + 2,
                    '3'                => self.n * 10 + 3,
                    '4'                => self.n * 10 + 4,
                    '5'                => self.n * 10 + 5,
                    '6'                => self.n * 10 + 6,
                    '7'                => self.n * 10 + 7,
                    '8'                => self.n * 10 + 8,
                    '9'                => self.n * 10 + 9,
                    _                  => {
                        self.exec(Inst(if self.n == 0 { 1 } else { self.n },
                                       c));
                        self.n
                    },
                }

            }
        }
    }

    /// Initialize the editor
    pub fn init(&mut self) {
        for c in self.iter {
            self.feed(c);
        }
    }

    /// Insert text
    pub fn insert(&mut self, c: char) {

    }

    /// Create new default state editor
    pub fn new() -> Editor {
        Editor {
            current_cursor: 0,
            cursors: Vec::new(),
            text: VecDeque::new(),
            scroll_x: 0,
            scroll_y: 0,
            n: 0,
        }
    }
}

/// A command char
#[derive(Clone, Copy, Hash, PartialEq)]
pub enum CommandChar {
    /// A char
    Char(char),
    /// A wildcard
    Wildcard,
}

#[derive(Clone, PartialEq, Hash)]
/// A cursor
pub struct Cursor {
    /// The x coordinate of the cursor
    pub x: u32,
    /// The y coordinate of the cursor
    pub y: u32,
    /// The mode of the cursor
    pub mode: Mode,
    /// The history of the cursor
    pub history: Vec<Inst>,
}
<|endoftext|>


<commit_before>#![cfg(feature = "rblas")]

extern crate rblas;
#[macro_use] extern crate ndarray;

use rblas::Gemm;
use rblas::attribute::Transpose;

use ndarray::{
    OwnedArray,
};

use ndarray::blas::AsBlas;

#[test]
fn strided_matrix() {
    // smoke test, a matrix multiplication of uneven size
    let (n, m) = (45, 33);
    let mut a = OwnedArray::linspace(0., ((n * m) - 1) as f32, n as usize * m as usize ).into_shape((n, m)).unwrap();
    let mut b = ndarray::linalg::eye(m);
    let mut res = OwnedArray::zeros(a.dim());
    Gemm::gemm(&1., Transpose::NoTrans, &a.blas(), Transpose::NoTrans, &b.blas(),
               &0., &mut res.blas());
    assert_eq!(res, a);

    // matrix multiplication, strided
    let mut aprim = a.to_shared();
    aprim.islice(s![0..12, 0..11]);
    println!("{:?}", aprim.shape());
    println!("{:?}", aprim.strides());
    let mut b = ndarray::linalg::eye(aprim.shape()[1]);
    let mut res = OwnedArray::zeros(aprim.dim());
    Gemm::gemm(&1., Transpose::NoTrans, &aprim.blas(), Transpose::NoTrans, &b.blas(),
               &0., &mut res.blas());
    println!("{:?}", aprim);
    println!("{:?}", b);
    println!("{:?}", res);
    println!("{:?}", &res - &aprim);
    assert_eq!(res, aprim);

    // Transposed matrix multiply
    let (np, mp) = aprim.dim();
    let mut res = OwnedArray::zeros((mp, np));
    let mut b = ndarray::linalg::eye(np);
    Gemm::gemm(&1., Transpose::Trans, &aprim.blas(), Transpose::NoTrans, &b.blas(),
               &0., &mut res.blas());
    let mut at = aprim.clone();
    at.swap_axes(0, 1);
    assert_eq!(at, res);

    // strided, needs copy
    let mut abis = a.to_shared();
    abis.islice(s![0..12, ..;2]);
    println!("{:?}", abis.shape());
    println!("{:?}", abis.strides());
    let mut b = ndarray::linalg::eye(abis.shape()[1]);
    let mut res = OwnedArray::zeros(abis.dim());
    Gemm::gemm(&1., Transpose::NoTrans, &abis.blas(), Transpose::NoTrans, &b.blas(),
               &0., &mut res.blas());
    println!("{:?}", abis);
    println!("{:?}", b);
    println!("{:?}", res);
    println!("{:?}", &res - &abis);
    assert_eq!(res, abis);
}
<commit_msg>Fix blas tests<commit_after>#![cfg(feature = "rblas")]

extern crate rblas;
#[macro_use] extern crate ndarray;

use rblas::Gemm;
use rblas::attribute::Transpose;

use ndarray::{
    OwnedArray,
};

use ndarray::blas::AsBlas;

#[test]
fn strided_matrix() {
    // smoke test, a matrix multiplication of uneven size
    let (n, m) = (45, 33);
    let mut a = OwnedArray::linspace(0., ((n * m) - 1) as f32, n as usize * m as usize ).into_shape((n, m)).unwrap();
    let mut b = OwnedArray::eye(m);
    let mut res = OwnedArray::zeros(a.dim());
    Gemm::gemm(&1., Transpose::NoTrans, &a.blas(), Transpose::NoTrans, &b.blas(),
               &0., &mut res.blas());
    assert_eq!(res, a);

    // matrix multiplication, strided
    let mut aprim = a.to_shared();
    aprim.islice(s![0..12, 0..11]);
    println!("{:?}", aprim.shape());
    println!("{:?}", aprim.strides());
    let mut b = OwnedArray::eye(aprim.shape()[1]);
    let mut res = OwnedArray::zeros(aprim.dim());
    Gemm::gemm(&1., Transpose::NoTrans, &aprim.blas(), Transpose::NoTrans, &b.blas(),
               &0., &mut res.blas());
    println!("{:?}", aprim);
    println!("{:?}", b);
    println!("{:?}", res);
    println!("{:?}", &res - &aprim);
    assert_eq!(res, aprim);

    // Transposed matrix multiply
    let (np, mp) = aprim.dim();
    let mut res = OwnedArray::zeros((mp, np));
    let mut b = OwnedArray::eye(np);
    Gemm::gemm(&1., Transpose::Trans, &aprim.blas(), Transpose::NoTrans, &b.blas(),
               &0., &mut res.blas());
    let mut at = aprim.clone();
    at.swap_axes(0, 1);
    assert_eq!(at, res);

    // strided, needs copy
    let mut abis = a.to_shared();
    abis.islice(s![0..12, ..;2]);
    println!("{:?}", abis.shape());
    println!("{:?}", abis.strides());
    let mut b = OwnedArray::eye(abis.shape()[1]);
    let mut res = OwnedArray::zeros(abis.dim());
    Gemm::gemm(&1., Transpose::NoTrans, &abis.blas(), Transpose::NoTrans, &b.blas(),
               &0., &mut res.blas());
    println!("{:?}", abis);
    println!("{:?}", b);
    println!("{:?}", res);
    println!("{:?}", &res - &abis);
    assert_eq!(res, abis);
}
<|endoftext|>


<commit_before>extern crate xattr;
extern crate tempfile;

use xattr::FileExt;

use tempfile::NamedTempFile;

#[test]
#[cfg(target_os = "linux")]
fn test_fd() {
    // Only works on "real" filesystems.
    let tmp = NamedTempFile::new_in("/var/tmp").unwrap();
    assert!(tmp.get_xattr("user.test").is_err());
    assert_eq!(tmp.list_xattr().unwrap().next(), None);

    tmp.set_xattr("user.test", b"my test").unwrap();
    assert_eq!(tmp.get_xattr("user.test").unwrap(), b"my test");
    assert_eq!(&tmp.list_xattr().unwrap().next().unwrap(), "user.test");

    tmp.remove_xattr("user.test").unwrap();
    assert!(tmp.get_xattr("user.test").is_err());
    assert_eq!(tmp.list_xattr().unwrap().next(), None);
}

#[test]
#[cfg(target_os = "linux")]
fn test_path() {
    // Only works on "real" filesystems.
    let tmp = NamedTempFile::new_in("/var/tmp").unwrap();
    assert!(xattr::get(tmp.path(), "user.test").is_err());
    assert_eq!(xattr::list(tmp.path(), ).unwrap().next(), None);

    xattr::set(tmp.path(), "user.test", b"my test").unwrap();
    assert_eq!(xattr::get(tmp.path(), "user.test").unwrap(), b"my test");
    assert_eq!(&xattr::list(tmp.path(), ).unwrap().next().unwrap(), "user.test");

    xattr::remove(tmp.path(), "user.test").unwrap();
    assert!(xattr::get(tmp.path(), "user.test").is_err());
    assert_eq!(xattr::list(tmp.path(), ).unwrap().next(), None);
}

#[test]
#[cfg(target_os = "linux")]
fn test_multi() {
    // Only works on "real" filesystems.
    let tmp = NamedTempFile::new_in("/var/tmp").unwrap();

    xattr::set(tmp.path(), "user.test1", b"first").unwrap();
    xattr::set(tmp.path(), "user.test2", b"second").unwrap();
    xattr::set(tmp.path(), "user.test3", b"third").unwrap();
    let mut attrs = xattr::list(tmp.path()).unwrap();
    assert_eq!(&attrs.next().unwrap(), "user.test1");
    assert_eq!(&attrs.next().unwrap(), "user.test2");
    assert_eq!(&attrs.next().unwrap(), "user.test3");
    assert_eq!(attrs.next(), None);
}
<commit_msg>Fix test<commit_after>extern crate xattr;
extern crate tempfile;

use std::collections::BTreeSet;
use std::ffi::OsStr;
use xattr::FileExt;

use tempfile::NamedTempFile;

#[test]
#[cfg(target_os = "linux")]
fn test_fd() {
    // Only works on "real" filesystems.
    let tmp = NamedTempFile::new_in("/var/tmp").unwrap();
    assert!(tmp.get_xattr("user.test").is_err());
    assert_eq!(tmp.list_xattr().unwrap().next(), None);

    tmp.set_xattr("user.test", b"my test").unwrap();
    assert_eq!(tmp.get_xattr("user.test").unwrap(), b"my test");
    assert_eq!(&tmp.list_xattr().unwrap().next().unwrap(), "user.test");

    tmp.remove_xattr("user.test").unwrap();
    assert!(tmp.get_xattr("user.test").is_err());
    assert_eq!(tmp.list_xattr().unwrap().next(), None);
}

#[test]
#[cfg(target_os = "linux")]
fn test_path() {
    // Only works on "real" filesystems.
    let tmp = NamedTempFile::new_in("/var/tmp").unwrap();
    assert!(xattr::get(tmp.path(), "user.test").is_err());
    assert_eq!(xattr::list(tmp.path(), ).unwrap().next(), None);

    xattr::set(tmp.path(), "user.test", b"my test").unwrap();
    assert_eq!(xattr::get(tmp.path(), "user.test").unwrap(), b"my test");
    assert_eq!(&xattr::list(tmp.path(), ).unwrap().next().unwrap(), "user.test");

    xattr::remove(tmp.path(), "user.test").unwrap();
    assert!(xattr::get(tmp.path(), "user.test").is_err());
    assert_eq!(xattr::list(tmp.path(), ).unwrap().next(), None);
}

#[test]
#[cfg(target_os = "linux")]
fn test_multi() {
    // Only works on "real" filesystems.
    let tmp = NamedTempFile::new_in("/var/tmp").unwrap();
    let mut items: BTreeSet<_> = [
        OsStr::new("user.test1"),
        OsStr::new("user.test2"),
        OsStr::new("user.test3")
    ].iter().cloned().collect();

    for it in &items {
        xattr::set(tmp.path(), it, b"value").unwrap();
    }
    for it in xattr::list(tmp.path()).unwrap() {
        assert!(items.remove(&*it));
    }
    assert!(items.is_empty());
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use texturegl::Texture;

use geom::matrix::{Matrix4, identity};
use geom::size::Size2D;
use geom::rect::Rect;
use std::managed::mut_ptr_eq;

pub enum Format {
    ARGB32Format,
    RGB24Format
}

pub enum Layer {
    ContainerLayerKind(@mut ContainerLayer),
    TextureLayerKind(@mut TextureLayer),
}

impl Layer {
    pub fn with_common<T>(&self, f: |&mut CommonLayer| -> T) -> T {
        match *self {
            ContainerLayerKind(container_layer) => f(&mut container_layer.common),
            TextureLayerKind(texture_layer) => f(&mut texture_layer.common),
        }
    }
}

pub struct CommonLayer {
    parent: Option<Layer>,
    prev_sibling: Option<Layer>,
    next_sibling: Option<Layer>,

    transform: Matrix4<f32>,
}

impl CommonLayer {
    // FIXME: Workaround for cross-crate bug regarding mutability of class fields
    pub fn set_transform(&mut self, new_transform: Matrix4<f32>) {
        self.transform = new_transform;
    }
}

pub fn CommonLayer() -> CommonLayer {
    CommonLayer {
        parent: None,
        prev_sibling: None,
        next_sibling: None,
        transform: identity(),
    }
}

pub struct ContainerLayer {
    common: CommonLayer,
    first_child: Option<Layer>,
    last_child: Option<Layer>,
    scissor: Option<Rect<f32>>,
}

pub fn ContainerLayer() -> ContainerLayer {
    ContainerLayer {
        common: CommonLayer(),
        first_child: None,
        last_child: None,
        scissor: None,
    }
}

struct ChildIterator {
    priv current: Option<Layer>,
}

impl Iterator<Layer> for ChildIterator {
    fn next(&mut self) -> Option<Layer> {
        match self.current {
            None => None,
            Some(child) => {
                self.current = child.with_common(|x| x.next_sibling);
                Some(child)
            }
        }
    }
}

impl ContainerLayer {
    pub fn children(&self) -> ChildIterator {
        ChildIterator { current: self.first_child }
    }

    /// Adds a child to the beginning of the list.
    /// Only works when the child is disconnected from the layer tree.
    pub fn add_child_start(@mut self, new_child: Layer) {
        new_child.with_common(|new_child_common| {
            assert!(new_child_common.parent.is_none());
            assert!(new_child_common.prev_sibling.is_none());
            assert!(new_child_common.next_sibling.is_none());

            new_child_common.parent = Some(ContainerLayerKind(self));

            match self.first_child {
                None => {}
                Some(first_child) => {
                    first_child.with_common(|first_child_common| {
                        assert!(first_child_common.prev_sibling.is_none());
                        first_child_common.prev_sibling = Some(new_child);
                        new_child_common.next_sibling = Some(first_child);
                    })
                }
            }

            self.first_child = Some(new_child);

            match self.last_child {
                None => self.last_child = Some(new_child),
                Some(_) => {}
            }
        })
    }

    /// Adds a child to the end of the list.
    /// Only works when the child is disconnected from the layer tree.
    pub fn add_child_end(@mut self, new_child: Layer) {
        new_child.with_common(|new_child_common| {
            assert!(new_child_common.parent.is_none());
            assert!(new_child_common.prev_sibling.is_none());
            assert!(new_child_common.next_sibling.is_none());

            new_child_common.parent = Some(ContainerLayerKind(self));

            match self.last_child {
                None => {}
                Some(last_child) => {
                    last_child.with_common(|last_child_common| {
                        assert!(last_child_common.next_sibling.is_none());
                        last_child_common.next_sibling = Some(new_child);
                        new_child_common.prev_sibling = Some(last_child);
                    })
                }
            }

            self.last_child = Some(new_child);

            match self.first_child {
                None => self.first_child = Some(new_child),
                Some(_) => {}
            }
        })
    }

    pub fn remove_child(@mut self, child: Layer) {
        child.with_common(|child_common| {
            assert!(child_common.parent.is_some());
            match child_common.parent.unwrap() {
                ContainerLayerKind(ref container) => {
                    assert!(mut_ptr_eq(*container, self));
                },
                _ => fail!(~"Invalid parent of child in layer tree"),
            }

            match child_common.next_sibling {
                None => { // this is the last child
                    self.last_child = child_common.prev_sibling;
                },
                Some(ref sibling) => {
                    sibling.with_common(|sibling_common| {
                        sibling_common.prev_sibling = child_common.prev_sibling;
                    })
                }
            }
            match child_common.prev_sibling {
                None => { // this is the first child
                    self.first_child = child_common.next_sibling;
                },
                Some(ref sibling) => {
                    sibling.with_common(|sibling_common| {
                        sibling_common.next_sibling = child_common.next_sibling;
                    })
                }
            }
        })
    }
}

/// Whether a texture should be flipped.
#[deriving(Eq)]
pub enum Flip {
    /// The texture should not be flipped.
    NoFlip,
    /// The texture should be flipped vertically.
    VerticalFlip,
}

pub struct TextureLayer {
    common: CommonLayer,
    /// A handle to the GPU texture.
    texture: Texture,
    /// The size of the texture in pixels.
    size: Size2D<uint>,
    /// Whether this texture is flipped vertically.
    flip: Flip,
}

impl TextureLayer {
    pub fn new(texture: Texture, size: Size2D<uint>, flip: Flip) -> TextureLayer {
        TextureLayer {
            common: CommonLayer(),
            texture: texture,
            size: size,
            flip: flip,
        }
    }
}

<commit_msg>Partial revert of rust upgrade.<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use texturegl::Texture;

use geom::matrix::{Matrix4, identity};
use geom::size::Size2D;
use geom::rect::Rect;
use std::managed::mut_ptr_eq;

pub enum Format {
    ARGB32Format,
    RGB24Format
}

pub enum Layer {
    ContainerLayerKind(@mut ContainerLayer),
    TextureLayerKind(@mut TextureLayer),
}

impl Layer {
    pub fn with_common<T>(&self, f: &fn(&mut CommonLayer) -> T) -> T {
        match *self {
            ContainerLayerKind(container_layer) => f(&mut container_layer.common),
            TextureLayerKind(texture_layer) => f(&mut texture_layer.common),
        }
    }
}

pub struct CommonLayer {
    parent: Option<Layer>,
    prev_sibling: Option<Layer>,
    next_sibling: Option<Layer>,

    transform: Matrix4<f32>,
}

impl CommonLayer {
    // FIXME: Workaround for cross-crate bug regarding mutability of class fields
    pub fn set_transform(&mut self, new_transform: Matrix4<f32>) {
        self.transform = new_transform;
    }
}

pub fn CommonLayer() -> CommonLayer {
    CommonLayer {
        parent: None,
        prev_sibling: None,
        next_sibling: None,
        transform: identity(),
    }
}

pub struct ContainerLayer {
    common: CommonLayer,
    first_child: Option<Layer>,
    last_child: Option<Layer>,
    scissor: Option<Rect<f32>>,
}

pub fn ContainerLayer() -> ContainerLayer {
    ContainerLayer {
        common: CommonLayer(),
        first_child: None,
        last_child: None,
        scissor: None,
    }
}

struct ChildIterator {
    priv current: Option<Layer>,
}

impl Iterator<Layer> for ChildIterator {
    fn next(&mut self) -> Option<Layer> {
        match self.current {
            None => None,
            Some(child) => {
                self.current = child.with_common(|x| x.next_sibling);
                Some(child)
            }
        }
    }
}

impl ContainerLayer {
    pub fn children(&self) -> ChildIterator {
        ChildIterator { current: self.first_child }
    }

    /// Adds a child to the beginning of the list.
    /// Only works when the child is disconnected from the layer tree.
    pub fn add_child_start(@mut self, new_child: Layer) {
        new_child.with_common(|new_child_common| {
            assert!(new_child_common.parent.is_none());
            assert!(new_child_common.prev_sibling.is_none());
            assert!(new_child_common.next_sibling.is_none());

            new_child_common.parent = Some(ContainerLayerKind(self));

            match self.first_child {
                None => {}
                Some(first_child) => {
                    first_child.with_common(|first_child_common| {
                        assert!(first_child_common.prev_sibling.is_none());
                        first_child_common.prev_sibling = Some(new_child);
                        new_child_common.next_sibling = Some(first_child);
                    })
                }
            }

            self.first_child = Some(new_child);

            match self.last_child {
                None => self.last_child = Some(new_child),
                Some(_) => {}
            }
        })
    }

    /// Adds a child to the end of the list.
    /// Only works when the child is disconnected from the layer tree.
    pub fn add_child_end(@mut self, new_child: Layer) {
        new_child.with_common(|new_child_common| {
            assert!(new_child_common.parent.is_none());
            assert!(new_child_common.prev_sibling.is_none());
            assert!(new_child_common.next_sibling.is_none());

            new_child_common.parent = Some(ContainerLayerKind(self));

            match self.last_child {
                None => {}
                Some(last_child) => {
                    last_child.with_common(|last_child_common| {
                        assert!(last_child_common.next_sibling.is_none());
                        last_child_common.next_sibling = Some(new_child);
                        new_child_common.prev_sibling = Some(last_child);
                    })
                }
            }

            self.last_child = Some(new_child);

            match self.first_child {
                None => self.first_child = Some(new_child),
                Some(_) => {}
            }
        })
    }

    pub fn remove_child(@mut self, child: Layer) {
        child.with_common(|child_common| {
            assert!(child_common.parent.is_some());
            match child_common.parent.unwrap() {
                ContainerLayerKind(ref container) => {
                    assert!(mut_ptr_eq(*container, self));
                },
                _ => fail!(~"Invalid parent of child in layer tree"),
            }

            match child_common.next_sibling {
                None => { // this is the last child
                    self.last_child = child_common.prev_sibling;
                },
                Some(ref sibling) => {
                    sibling.with_common(|sibling_common| {
                        sibling_common.prev_sibling = child_common.prev_sibling;
                    })
                }
            }
            match child_common.prev_sibling {
                None => { // this is the first child
                    self.first_child = child_common.next_sibling;
                },
                Some(ref sibling) => {
                    sibling.with_common(|sibling_common| {
                        sibling_common.next_sibling = child_common.next_sibling;
                    })
                }
            }
        })
    }
}

/// Whether a texture should be flipped.
#[deriving(Eq)]
pub enum Flip {
    /// The texture should not be flipped.
    NoFlip,
    /// The texture should be flipped vertically.
    VerticalFlip,
}

pub struct TextureLayer {
    common: CommonLayer,
    /// A handle to the GPU texture.
    texture: Texture,
    /// The size of the texture in pixels.
    size: Size2D<uint>,
    /// Whether this texture is flipped vertically.
    flip: Flip,
}

impl TextureLayer {
    pub fn new(texture: Texture, size: Size2D<uint>, flip: Flip) -> TextureLayer {
        TextureLayer {
            common: CommonLayer(),
            texture: texture,
            size: size,
            flip: flip,
        }
    }
}

<|endoftext|>